Skip to content

fix(plugin): serve bundled SDK to loose plugin files on Bun - #49097

Closed
rekram1-node wants to merge 1 commit into
devfrom
plugin-bun-shim
Closed

rekram1-node wants to merge 1 commit into
devfrom
plugin-bun-shim

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Problem

A loose plugin file (.opencode/plugins/foo.ts, ~/.config/opencode/plugins/foo.ts, or "/abs/path/plugin.ts" in plugins) that does import { Plugin } from "@opencode/plugin" fails in the shipped Bun executable:

failed to load plugin ... ResolveMessage: Cannot find package '@opencode/plugin' imported from .../.opencode/plugins/hello.ts

Bun resolves the bare specifier from the plugin file's own location, there is no node_modules there, and compiled executables do not auto-install. The docs example (Plugin.define from @opencode/plugin in a loose file) therefore did not work.

The Node executable already handles this: its bundle prelude (packages/cli/vite.node.config.ts) registers module.registerHooks that map @opencode/plugin* to the bundled SDK via globalThis[Symbol.for("opencode.plugin.v2.*")] (added in #36309). The TUI does the same for @opencode/plugin/tui through OpenTUI's runtime plugin. Only the Bun server side was missing it, most likely because V1 plugins only ever imported the SDK for types and V2's Plugin.define is the first runtime value import.

Fix

  • packages/plugin/src/runtime.bun.ts: register the host's own @opencode/plugin, /effect, /promise/plugin, /promise/tool, /effect/plugin, /effect/tool as Bun virtual modules (build.module, loader: "object") once, so plugins share one module identity with the host.
  • packages/plugin/src/runtime.node.ts: no-op; the Node prelude already covers it.
  • Host.load ensures the shim is installed before importing the entrypoint, so every loader (core, TUI, plugin add/list) gets it.
  • Wired through a #plugin-runtime conditional import, same pattern as the existing #plugin-source.

Verification

  • New Host.load test loads a loose .ts from a temp dir with no node_modules, importing all three specifier shapes, and asserts identity with the host's modules.
  • service-smoke.ts now writes a plugin that imports @opencode/plugin, so CI exercises the compiled executable path. Ran it locally against a --single Bun build: passes.
  • Drove the compiled binary TUI with a .opencode/plugins/acme/{index.ts,tui.ts} where tui.ts imports both @opencode/plugin/tui and @opencode/plugin; /plugins shows both acme.server and acme.tui active, confirming coexistence with OpenTUI's runtime plugin.
  • bun typecheck in packages/plugin, packages/core, packages/cli, packages/tui.

Docs updated to state that @opencode/plugin resolves at runtime and an install is only needed for editor types.

Notes

  • The shim takes precedence over an installed node_modules/@opencode/plugin next to a plugin, matching the Node prelude's behavior. This is intentional: the SDK must match the running host, and it keeps instanceof/brand checks consistent.
  • The Node prelude's re-export list (Agent, Command, ..., Skill) has drifted from the root index, which now also exports Location, Mcp, PersistentPty, Rpc, Vcs, WebSearch, Worktree. Not addressed here; the Bun shim hands over the full namespace so it cannot drift.

Loose plugin files under .opencode/plugins or configured by path have no
node_modules, so the compiled Bun executable failed to resolve
@opencode/plugin. Register the host's own SDK modules as Bun virtual modules
when a plugin loads, matching the module hooks the Node executable already
registers in its bundle prelude.
@github-actions

Copy link
Copy Markdown
Contributor

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:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant