Conversation
vheins
force-pushed
the
feat/opencode-v2-support
branch
from
September 26, 2026 11:43
45250d1 to
4b5390e
Compare
vheins
force-pushed
the
feat/opencode-v2-support
branch
from
September 26, 2026 11:45
4b5390e to
a237941
Compare
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.
Summary
Adds OpenCode V2 support to
opencode-smart-voice-notifywhile keeping full V1 backward compatibility.OpenCode
v2.0.xloads plugins through the new@opencode/pluginAPI and requires the module's default export to be an object withidplussetup(oreffect). The current1.4.0default export is a V1 async function, so V2 fails to load the plugin with:This PR makes the plugin load and work on both V1 (1.18.29+) and V2 (2.0.x).
What changed
src/index.ts): default export is now{ id, setup, server }— V2 readsid/setup, V1 readsserver. The original V1 implementation is preserved verbatim as a named export insrc/plugin.ts.src/v2.ts):$shell runner on top ofnode:child_process(V2 has no shell runner) with.quiet()/.nothrow()/.timeout().clientshim (session.get→ctx.session.get; toast is a no-op since V2 exposes no plugin toast API).{ type, data }) into the V1{ type, properties }shape so the battle-tested notification engine is reused unchanged.ctx.event.subscribe()and disposes cleanly.session.idlein its schema but never emits it — the real completion signal issession.execution.succeeded. Mapping:session.execution.succeeded→session.idle(agent finished)session.execution.failed→session.errorpermission.asked→permission.v2.askedform.created/form.replied/form.cancelled→question.v2.asked/question.v2.replied/question.v2.rejectedsession.inbox.enqueued(user item) →message.updated(user-activity signal)session.execution.succeeded) are routed to the correct instance.server.jsre-export bridge +./serverexport (V2 resolves an absolute plugin directory via itsserverentrypoint).build/build:typesscripts →compile/compile:typesso pacote's git-dependency preparation no longer triggers a failingnpm install --force(theprepare-triggeringbuildscript was the cause).msedge-ttstooptionalDependencies(itspreinstall: only-allow pnpmbreaks npm-based git installs; it is only used as a lazy fallback for theedgeengine).dist/stays git-ignored and is produced by the existingcompilescript as before.tests/unit/v2-adapter.test.tscovering entry shape, all event translations, the shell shim, the client shim, setup() wiring, de-duplication, and session→location routing. Existing tests updated to import the V1 function as a named export.Compatibility
serverfield.Testing
bun run typecheck— cleanbun run compile— cleanbun test— 765 pass / 17 skip / 1 fail. The single failure is pre-existing and unrelated (tests/unit/vscode-focus.test.ts→spyOn(target, prop) does not support accessor properties yet); it fails identically on the unmodified baseline.Verified end-to-end on OpenCode
v2.0.18: the plugin loads, completion notifications fire once (no echo), and permission/question/error paths work.