Repository navigation
Support OpenCode 2 and keep OpenCode 1 - #4
Merged
Merged
Conversation
OpenCode 2 does not run v1 plugin code. The plugin now has one default export with id and setup() for v2, and server() for v1. The named SidePulse export is gone, because a v1 loader can load it as a second instance. OpenCode 2 ends a turn with session.execution.succeeded, .failed or .interrupted, and sends no session.idle or session.error. Event data moved from properties to data. The self-check replays three traces captured from OpenCode 2.1.2. Closes #2
Owner
Author
|
Hi @MathisHammel, Apologies for the delay of me getting to this. thanks for flagging v2 support :) |
The plugin loads on OpenCode 1.17.20: server() runs once. The migration guide names 1.18.29 as the minimum, but that is more conservative than the loader.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The plugin did not load on OpenCode 2. This change makes one package work on OpenCode 2 and on OpenCode 1. Closes #2.
Problem
OpenCode 2 does not run v1 plugin code. It requires a default export with an
idand asetup()function, so it rejected the plugin function. OpenCode 2 also changed the events that the plugin reads:event.propertiestoevent.data.session.execution.succeeded,session.execution.failed, orsession.execution.interrupted.session.idleand nosession.error.Without the new events, the device stays on the busy animation after every turn.
Fix
One default export serves both APIs. OpenCode 1 calls
server(). OpenCode 2 callssetup().chat.messagectx.session.hook("prompt")tool.execute.beforeandtool.execute.afterctx.tool.hook("execute.before" / "execute.after")eventctx.event.subscribe(), aborted in cleanupsession.idlesession.execution.succeededsession.error(MessageAbortedErrormeans cancel)session.execution.failed/session.execution.interruptedThe named
SidePulseexport is gone. A v1 loader can load a named export as a second instance, and two instances fight over the device. The package stays free of dependencies, and it does not import@opencode/plugin.The self-check replays three traces that I captured from OpenCode 2.1.2 with a logging probe plugin: a normal finish, a cancel, and a failure. It also makes sure that the default export has
id,server(), andsetup().Compatibility
The migration guide says that v1 object entrypoints need OpenCode 1.18.29 or newer. I tested older: on 1.17.20,
server()runs once and the plugin works. The README states 1.17.20 or newer, and it tells users of older releases to pinopencode-sidepulse@0.1.7. The version goes to 0.2.0, because the named export is gone. The merge publishes it.How to test
The self-check needs no device:
The first line must be
ok: 5 programs, 7 transitions. If you remove thesession.execution.succeededline fromsignalForEvent(), the command must fail withv2 normal finish: after session.execution.succeeded state is busy, want done.I also ran real turns on two Macs: a Mac mini (macOS 26.4.1, Apple Silicon, Node v26.12.1) with a SidePulse Dot, and a MacBook (macOS 15.8.1, Apple Silicon, Node v26.5.0) with a SidePulse in the SD card reader. Each OpenCode version ran with its own XDG folders, and it loaded only this plugin from a local path.
echo hithrough the shell tool#00ff22sleep 20opencode/no-such-model-xyz#ff2000onceafter 4 s#ffb000while it waits, then ends greenUserPromptSubmit,PreToolUse shell,PermissionRequest,UserPromptSubmit,PostToolUse shell,Stop. No write toLEDS.LEDecho hithrough the bash tool#00ff22server()runs onceserver()runs once, the plugin writes the deviceopencode runrejects a permission prompt at once, so a test plugin drove the permission turn from inside the service withctx.session.promptand answered it withctx.permission.reply. The app-mode test used a Unix socket server at the probed path that logged each message. It was not the real SidePulse app.Known limits, not changed here
Stopfrom another session arrives during a turn, the plugin drops that turn's tool events. In my app-mode run, a resumed earlier session caused exactly this. v1 has the same flag.