From 342ff6bf33a5a639124dc7aed1dc4f8efb6d91ff Mon Sep 17 00:00:00 2001 From: Zach Rouan Date: Sun, 5 Jul 2026 20:03:13 -0400 Subject: [PATCH] fix(plugin): skip non-function exports instead of throwing getLegacyPlugins threw a TypeError on the first non-function export, and that error is swallowed by the plugin apply catch, so a plugin module that exports anything besides its plugin function (a version constant, a helper) silently registered no hooks with no diagnostic. Skip non-plugin exports instead, matching the existing seen-entry skip right above it. Fixes #31575 --- packages/opencode/src/plugin/index.ts | 4 +++- packages/opencode/test/plugin/trigger.test.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index 1558c707c3f7..40b97fe60777 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -100,7 +100,9 @@ function getLegacyPlugins(mod: Record) { if (seen.has(entry)) continue seen.add(entry) const plugin = getServerPlugin(entry) - if (!plugin) throw new TypeError("Plugin export is not a function") + // Skip non-plugin exports (constants, helpers, etc.) instead of throwing — + // a single non-function export must not discard the module's real plugins. + if (!plugin) continue result.push(plugin) } diff --git a/packages/opencode/test/plugin/trigger.test.ts b/packages/opencode/test/plugin/trigger.test.ts index 07fd8e2f21bc..a8ac9b06fdc6 100644 --- a/packages/opencode/test/plugin/trigger.test.ts +++ b/packages/opencode/test/plugin/trigger.test.ts @@ -105,4 +105,21 @@ describe("plugin.trigger", () => { }), ), ) + + it.instance("loads a plugin module that also exports non-function values", () => + withProject( + [ + 'export const VERSION = "1.0.0"', + "export const plugin = async () => ({", + ` ${JSON.stringify(systemHook)}: (_input, output) => {`, + ' output.system.unshift("sync")', + " },", + "})", + "", + ].join("\n"), + Effect.gen(function* () { + expect(yield* triggerSystemTransform()).toEqual(["sync"]) + }), + ), + ) })