Skip to content

fix(opencode): use PluginModule export for opencode 1.18.x compatibility#603

Closed
LeoNardo-LB wants to merge 1 commit into
EvoMap:mainfrom
LeoNardo-LB:fix/opencode-plugin-export
Closed

fix(opencode): use PluginModule export for opencode 1.18.x compatibility#603
LeoNardo-LB wants to merge 1 commit into
EvoMap:mainfrom
LeoNardo-LB:fix/opencode-plugin-export

Conversation

@LeoNardo-LB

@LeoNardo-LB LeoNardo-LB commented Jul 21, 2026

Copy link
Copy Markdown

Problem

evolver setup-hooks --platform=opencode generates a plugin file whose export shape is rejected by opencode 1.18.x at load time:

level=ERROR message="failed to load plugin"
path=file:///.../.opencode/plugins/evolver.js
error="Plugin export is not a function"

The generated file currently ends with:

module.exports = { Evolver };
module.exports.default = Evolver;

Under Bun (opencode's runtime), the whole module.exports object is treated as the default export, so opencode receives { Evolver } rather than a function and bails out. The plugin is silently skipped — evolver setup-hooks --platform=opencode --verify still passes because it uses Node's require() which sees Evolver as a named export. This means the two disagree, and users only find out when they check opencode debug config.

Reproduction

npm install -g @evomap/evolver
evolver setup-hooks --platform=opencode
opencode --print-logs --log-level INFO debug config 2>&1 | grep evolver

Tested on:

  • opencode 1.18.4 (scoop install)
  • @evomap/evolver 1.92.1 (npm)
  • Node v26.1.0, Windows Server 2022

Fix

opencode 1.18.x accepts either a bare function as the default export or a PluginModule object of shape { id, server }. This PR switches to the PluginModule form, which is what the official opencode plugin docs use (opencode.ai/docs/plugins).

- module.exports = { Evolver };
- module.exports.default = Evolver;
+ module.exports = { id: "evolver", server: Evolver };

The second change updates verify() to recognise the new shape. Without it, the existing mod.Evolver || mod.default lookup would return undefined on the patched export and --verify would falsely report [FAIL] plugin_loadable:

- const fn = mod && (mod.Evolver || mod.default);
+ const fn = mod && (mod.server || mod.Evolver || mod.default);

Verification

Applied the patch locally and ran the full flow end-to-end:

  • opencode --print-logs --log-level INFO debug config0 ERROR / WARN entries (previously failed to load plugin)
  • evolver setup-hooks --platform=opencode --verify → all 5 checks [OK]
  • Other plugins (superpowers, context-mode, opencode-vision, opencode-goal-plugin) unaffected

Related


Note

Low Risk
Small export-shape change in the opencode adapter only; no auth, data, or core runtime logic changes.

Overview
Fixes opencode 1.18.x rejecting the generated evolver plugin with "Plugin export is not a function" under Bun, while evolver setup-hooks --platform=opencode --verify could still pass under Node.

The generated evolver.js now uses the documented PluginModule export ({ id: "evolver", server: Evolver }) instead of { Evolver } plus a default assignment. verify() resolves the plugin factory via mod.server first (then Evolver / default) so --verify matches what opencode loads.

Reviewed by Cursor Bugbot for commit 7b9b773. Bugbot is set up for automated code reviews on this repo. Configure here.

opencode 1.18.x rejects `{ Evolver, default: Evolver }` with
"Plugin export is not a function". Switch to PluginModule format
`{ id, server }` which is the official opencode plugin shape.

Also update verify() to recognize the new format alongside the legacy ones.
@LeoNardo-LB

Copy link
Copy Markdown
Author

Superseded by #604 which provides a more comprehensive fix (5 layers of incompatibility). Closing in favor of #604.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant