Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions packages/opencode/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ function getLegacyPlugins(mod: Record<string, unknown>) {
if (seen.has(entry)) continue
seen.add(entry)
const plugin = getServerPlugin(entry)
if (!plugin) throw new TypeError("Plugin export is not a function")
if (!plugin) continue
result.push(plugin)
}

Expand Down Expand Up @@ -374,13 +374,11 @@ export const layer = Layer.effect(
return message
},
}).pipe(
Effect.catch(() => {
// TODO: make proper events for this
// bus.publish(Session.Event.Error, {
// error: new NamedError.Unknown({
// message: `Failed to load plugin ${load.spec}: ${message}`,
// }).toObject(),
// })
Effect.catch((err) => {
log.error("unhandled error in plugin loading pipeline", {
path: load.spec,
error: errorMessage(err),
})
return Effect.void
}),
)
Expand Down
32 changes: 32 additions & 0 deletions packages/opencode/test/plugin/loader-shared.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,38 @@ describe("plugin.loader.shared", () => {
expect(await fs.readFile(tmp.extra.mark, "utf8")).toBe("called")
})

test("loads a file:// plugin with non-function exports", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
const file = path.join(dir, "plugin.ts")
const mark = path.join(dir, "called.txt")
await Bun.write(
file,
[
"export const config = { foo: 'bar' }",
"export type Config = { foo: string }",
"export const VERSION = '1.0.0'",
"export default async () => {",
` await Bun.write(${JSON.stringify(mark)}, "called")`,
" return {}",
"}",
"",
].join("\n"),
)

await Bun.write(
path.join(dir, "mimocode.json"),
JSON.stringify({ plugin: [pathToFileURL(file).href] }, null, 2),
)

return { mark }
},
})

await load(tmp.path)
expect(await fs.readFile(tmp.extra.mark, "utf8")).toBe("called")
})

test("deduplicates same function exported as default and named", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
Expand Down