Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
push:
branches:
- main
schedule:
- cron: "17 4 * * *"
workflow_dispatch:

permissions:
contents: read
Expand All @@ -25,8 +28,50 @@ jobs:
node-version: "24"
cache: npm

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- run: npm ci

- run: npm run check

- run: npm test

- name: Verify Bun can load the plugin
run: bun -e "await import('./src/index.js')"

opencode-peer-compat:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
plugin-version: ["1.4.0", "latest"]

steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "24"
cache: npm

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- run: npm ci

- name: Install OpenCode plugin compatibility target
shell: bash
run: npm install --no-save --package-lock=false "@opencode-ai/plugin@${{ matrix.plugin-version }}"

- name: Show tested OpenCode plugin version
run: node -p "require('./node_modules/@opencode-ai/plugin/package.json').version"

- run: npm run check

- run: npm test

- name: Verify Bun can load with this OpenCode plugin
run: bun -e "await import('./src/index.js')"
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.5.22

- Hardened compatibility with current OpenCode 1.18.15 while preserving the existing `>=1.4.0` peer range.
- Handled loop commands now also set `output.noReply = true`; OpenCode 1.18.x safely ignores the unknown field, while hosts that add the proposed `noReply` hook support can skip the acknowledgement model turn automatically.
- Added Bun runtime loading coverage so CI exercises the runtime OpenCode actually uses to load plugins, not only Node syntax/tests.
- Added explicit minimum-peer coverage against `@opencode-ai/plugin@1.4.0` and scheduled testing against the latest published OpenCode plugin package.
- Kept the v0.5.21 server-plugin acknowledgement fallback for current OpenCode versions where `command.execute.before` cannot cancel the prompt turn.

## 0.5.21

- Verified server-plugin compatibility against OpenCode 1.18.15 and updated the development plugin dependency accordingly.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ v0.5.11 includes a referenced heartbeat scheduler. This is important in OpenCode

## Current status

**v0.5.21 targets current OpenCode 1.18.x compatibility and safer releases.** Server-plugin control commands keep their locked-down acknowledgement prompt instead of creating an empty command message, `/compact` prefers the current `session.compact` TUI command, and CI now covers Ubuntu and Windows before publishing. **v0.5.20 fixes Windows TUI state writes.** Session job state is written through the OS temp directory with rename plus copy/unlink fallback and short retries, so antivirus locks and OpenCode snapshots no longer drop `/loop` jobs with `EPERM` on rename. **v0.5.19** hardens Goal Mode, package updates, and the background daemon: package installs are pinned to the installed version so OpenCode cannot keep loading an older cached release, scheduler-created goal messages no longer self-interrupt on delayed updates, finite daemon failures return nonzero, model/agent selection is supported, Windows scheduled tasks use a short launcher that stays below the `/TR` limit, and asynchronous release verification is reliable under load.
**v0.5.22 adds forward-compatible OpenCode command handling plus Bun and peer-range compatibility CI.** **v0.5.21 targets current OpenCode 1.18.x compatibility and safer releases.** Server-plugin control commands keep their locked-down acknowledgement prompt instead of creating an empty command message, `/compact` prefers the current `session.compact` TUI command, and CI now covers Ubuntu and Windows before publishing. **v0.5.20 fixes Windows TUI state writes.** Session job state is written through the OS temp directory with rename plus copy/unlink fallback and short retries, so antivirus locks and OpenCode snapshots no longer drop `/loop` jobs with `EPERM` on rename. **v0.5.19** hardens Goal Mode, package updates, and the background daemon: package installs are pinned to the installed version so OpenCode cannot keep loading an older cached release, scheduler-created goal messages no longer self-interrupt on delayed updates, finite daemon failures return nonzero, model/agent selection is supported, Windows scheduled tasks use a short launcher that stays below the `/TR` limit, and asynchronous release verification is reliable under load.

The known update-related symptoms from older builds are fixed:

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bybrawe/opencode-loop",
"version": "0.5.21",
"version": "0.5.22",
"description": "Claude Code/Codex style /loop and experimental goal mode for OpenCode: heartbeat scheduler, idle-safe loops, scheduled commands, compact scheduling, verification, checkpoints, and persistent coding goals.",
"type": "module",
"main": "src/index.js",
Expand Down
1 change: 1 addition & 0 deletions scripts/smoke-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ try {
}, output)
assert.equal(output.parts.length, 1, "a locally handled slash command must keep a valid acknowledgement prompt")
assert.equal(output.parts[0].text, "original command body")
assert.equal(output.noReply, true, "handled commands should request noReply for compatible OpenCode hosts")

await hooks["command.execute.before"]({ command: "loop-now", sessionID, arguments: "goal" }, { parts: [] })
assert.equal(
Expand Down
7 changes: 4 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2220,9 +2220,10 @@ async function handleCommand(directory, client, input, fallbackName, fallbackArg
if (isLoopCommandName(name)) guardLoopOwnedUserMessage(sessionID)

const handled = () => {
// OpenCode server plugins cannot currently cancel the command prompt turn.
// Keep the command markdown acknowledgement intact so opencode-loop-local
// receives a valid, tool-denied message instead of an empty parts array.
// OpenCode 1.18.x ignores unknown hook output fields, while proposed/newer
// hosts can honor noReply to skip the otherwise unavoidable model turn.
// Keep acknowledgement parts intact as the compatibility fallback.
if (output && typeof output === "object") output.noReply = true
return true
}

Expand Down