Repository navigation
feat: support opencode v2 (dual V1+V2) - #99
Merged
Merged
Conversation
opencode V2 core publishes session.execution.succeeded|failed|interrupted at the end of a turn (packages/core/src/session/execution.ts). session.idle and session.status are only defined in @opencode/schema and are never published at runtime, so triggering on them made the v2 completion check dead code. - Run the check on session.execution.succeeded, .failed and .interrupted, skipping interrupted with reason "shutdown". - Detect the usage limit from session.execution.failed's structured error instead of re-reading the session context. - Drop the redundant user-facing commands.completion-check-command from the dev opencode.json: config commands are registered after external plugins and would override the plugin's own command, losing the command capture. - Document the v2 command override limitation in the README. Tests updated to cover the new trigger and the shutdown/usage-limit cases.
Contributor
Author
|
Review verdict: request changes — verified against the installed opencode Read: Blocker — config keys (commit
|
opencode v2.0.29 reads config.plugins (plural) and config.commands (plural); the singular keys are the V1-legacy forms and silently drop the object/tuple entries. Revert the singular dev config and README V2 snippet accordingly, and name commands in the V2 override limitation. Handle plugin events without awaiting the handler so a running completion check no longer serializes the whole event stream for all sessions; errors are still caught and logged and the per-session processing guard remains effective.
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.
Fixes https://github.com/bacluc-agent/agent-todo/issues/390
Management summary
Adds opencode V2 support while keeping V1 working, and fixes two correctness bugs on the V2 headless path.
Bugs fixed in this revision:
opencode run(blocker). v2.0.29 never deliverssession.createdto plugin subscribers onopencode run(first real session event issession.inbox.enqueued), so the store stayed empty atsession.execution.succeededand the check never ran.src/v2.tsnow resolves the default command lazily, once per session, on the first event carrying adata.sessionID(directory precedence: event location → event data location →ctx.location.directory), never clobbering an explicitly registered command, and guarded once-only before the firstawait. Decisive evidence: the new regression tests fail on the pre-fix source —npm test, step 6.shutdown, sosupersededandinactivityinterruptions ran the check and re-prompted mid-conversation; the check now runs on interrupt only forreason === 'user'.Carried-over fixes from earlier revisions are in the fold below.
No dependency changes;
package.json/ lockfile untouched.Verification evidence
Both cited runs are manually dispatched
workflow_dispatchruns, not the automatic push/pull_requestruns.src/v2.ts(plus the other sources).tests/v2.test.ts(new lazy-resolution, no-re-registration,superseded/inactivitytests) andsrc/v2.tsruntime:116 passed (116).README.mdandsrc/v2.ts.npm test, step 6 of run 38655245991: the new tests fail on the pre-fix source, so they measure the fixed behaviour.Verifying run 38655090646 (job
116162843147) iscompleted/successon962d0a6.Action runs
dea4b5d,962d0a6workflow_dispatchci.yamlon962d0a6: typecheck, 116 tests, format checkworkflow_dispatchci.yamlon pre-fix source + new tests (throwaway branch, deleted)workflow_dispatchci.yamlondea4b5d: typecheck, 112 tests, format checkworkflow_dispatchcd2a127agent-run/390-38639226682Fixes carried over from earlier revisions and design decisions
Fixes from earlier revisions on this branch:
dea4b5d):opencode.jsonand the README V2 snippet use the V2-native pluralpluginskey with{ package, options }objects; the V1 snippet keeps the legacy singularplugintuple. The binary readsconfig.plugins/config.commands, so the plural keys are the only ones that keep the object/commandsshape.dea4b5d): the sentence names the V2-nativecommandskey, not the legacy singularcommand.dea4b5d):src/v2.tshandles events withvoid handleCompletionCheckEvent(...).catch(...)so a runningexecuteCommandno longer serializes the plugin event stream. Errors are still caught and logged, and the per-sessionprocessingguard is meaningful (synchronousadd/hasbefore the firstawait).Design decisions:
src/server.ts: spreadsPlugin.define({ id, setup })(V2) withserver: CompletionCheckCommandPlugin(V1), so one entrypoint serves both majors;@opencode/plugin@2.0.29added,@opencode-ai/plugin@1.18.33kept for V1.session.execution.succeeded/.failed/.interrupted— the session-terminal events v2.0.29 actually publishes (session.idle/session.statusare defined but never published).opencode.jsonomits acommand.completion-check-commandblock because a same-named config command replaces the plugin registration and loses the capture step.BacLuc/opencode-completion-check-commandis owned byBacLuc, so the outsider fork/PR policy does not apply. The branch lives in thebacluc-agentfork (only the fork has push) and the PR targets upstreammain, matching the repo's own convention.pluginkey with object form →plugins; README V2 snippet →plugins, V1 snippet unchanged; README override sentence now namescommands; the event handler is fire-and-forget soprocessingis a real guard; the verification section cites self-triggeredworkflow_dispatchruns.Out of scope
Upstream doc bug, not this PR:
services/www/src/docs/content/build/plugins/migrate-v1.mdxshows a V2 example usingsession.idle, which v2.0.29 never publishes.