Repository navigation
Conversation
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
…upstream anomalyco#38470 Empirical repro: opencode serve (1.18.15/1.18.16) imports the plugin bundle (module scope 'plugin loaded') but never materializes the lazy InstanceState, so plugin.server(input) is never invoked. Identical bundle works fine in TUI / opencode run. Proposal document at PROPOSAL-server-plugin-init.md lays out the reproducer, source evidence, the fix sketch (warm InstanceStore for process.cwd() at serve startup), tests to add, and reviewer notes tied to upstream issue anomalyco#38470. No source code is changed in this commit — the fix is intentionally kept as a proposal so the smallest possible diff can be reviewed against the v2 Effect refactor before merging.
d4f0a16 to
48dc42d
Compare
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
|
Thanks for picking this up — and to be clear up front, I'm not disputing the plugin fix. The But I think #38470 is about MCP server tools, not plugins. I filed it, and the symptom was that a configured stdio MCP server shows I built the reproducer against your branch to check whether the fix happens to cover it anyway. It doesn't. Method: a fixture project with a one-tool stdio MCP server, and a local Anthropic-compatible endpoint standing in for the model so I could capture the exact
Row 1 is the control: same fixture, same server, tools present — so the MCP config and the harness are working, and the misses below it are real. The distinguishing factor is the Worth noting this also means #38470 is unfixed on latest (1.18.18), not just on 1.18.3. Ask: could you change |
|
Hey, can I somehow help to get this fix merged? This issue kind of blocks our use-case right now. |
|
Confirming the plugin-side symptom from @herjarsa/[email protected] (V2 plugin registered in \opencode.json's \plugin\ array). Reproduction:
This is independent of \omo-meta-governor\ itself — we shipped 4 v0.38.x releases assuming the plugin was loading in Desktop and only learned otherwise when users reported missing tools. So we have a concrete user-visible regression class that maps cleanly to \Plugin.service\ never being materialised in serve mode. @brad07 is right that \Closes #38470\ looks wrong (the original bug is MCP-server-tools-in-via-API, different subsystem). The plugin fix stands on its own — just needs to be unlinked from #38470 so it can merge and we can declare \peerDependencies\ floor on OpenCode Desktop with confidence. Happy to ship a regression test in \omo-meta-governor\ that exercises the serve-mode init sequence against a mocked \Plugin.service\ and fails when \plugin.server(input)\ is not called — that would document the contract from downstream's perspective. Filed #42280 as the canonical tracking issue if it's helpful for cross-reference. |
OpenCode Desktop spawns 'opencode serve' in HTTP/sidecar mode. In some
versions, the plugin service is never materialised during serve startup,
so plugin.server(input) is never called and the plugin's omo_* tools
never appear in the session — even though the module loads (you can see
'MetaGovernor plugin loaded' in meta-governor.log).
Two changes:
1. New regression test in src/plugin.test.ts: 'serve-mode plugin init
contract (v0.38.5)'. Documents the @opencode-ai/plugin contract from
the plugin author's POV:
- createMetaGovernorPlugin() must return a callable Plugin function
- plugin(input, options) must return a Promise<Hooks> with the 4 standard
hook keys (tool.execute.before, tool.execute.after,
experimental.chat.system.transform, experimental.chat.messages.transform)
- The bundled entry (dist/index.js) must export a callable default
These tests pass today because we exercise the factory directly.
When upstream PR #41728 lands, the test should be extended to cover
the new 'opencode serve' integration test shipped with that PR.
2. README.md 'Known limitation: OpenCode Desktop plugin init (v0.38.5)'
section. Links to the upstream tracking:
- anomalyco/opencode#42280 (V2 plugin init race)
- anomalyco/opencode#41728 (PR with the fix, currently OPEN)
- anomalyco/opencode#44367 (Desktop-specific npm plugin issue)
Documents the workaround: use opencode CLI (plugin loads normally) or
enable the MCP server mode (omo_* tools via sidecar process).
Also posted a comment on PR #41728 (comment ID 5461960479) confirming our
case from the plugin author's side and requesting the author separate
'Closes #38470' (which is wrong — it's an MCP-tools issue, not a plugin
issue) so the PR can merge.
Test count: 1094 pass / 0 fail / 0 error (1102 total, 92 files).
No production code changed.
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes #38470
Type of change
What does this PR do?
HTTP serve mode (\opencode serve, used by OpenChamber, desktop and web clients) never materialises the Plugin service. The serve command declared \instance: false\ ("no need for an ambient project InstanceContext at startup"), so the lazy \InstanceState\ used by \plugin/index.ts\ is only built when \Plugin.init/trigger/list\ is called. In HTTP mode that never happens for the conversation pipeline, so \plugin.server(input)\ is never invoked. Result: plugins listed in \plugins:\ (e.g. omo-meta-governor) silently do nothing under serve — no hooks, no custom tools, no system/messages transforms — while the same plugins work fine in the TUI and \opencode run.
Fix: switch the serve command to \instance: true\ with \directory: () => process.cwd(). The \effectCmd\ wrapper (\src/cli/effect-cmd.ts) already loads the InstanceStore and runs InstanceBootstrap (which calls \Plugin.init()) at startup when \instance\ is \ rue. Per-request \x-opencode-directory\ handlers still load their own InstanceStore entries (different ScopedCache key), so the ambient cwd is only a warm-up, not a replacement of per-request semantics. The handler is \Effect.never, so the wrapper's \inally { store.dispose(ctx) }\ never runs while the serve is alive and the loaded plugin state persists for the process lifetime.
How did you verify your code works?
Checklist