Compare commits

...
Author SHA1 Message Date
Dax Raad 4388f386ed fix(core): resolve host packages in bun plugins 2026-08-24 21:07:50 -04:00
5 changed files with 109 additions and 0 deletions
+4
View File
@@ -29,6 +29,10 @@
"./*": "./src/*.ts"
},
"imports": {
"#plugin-imports": {
"bun": "./src/plugin/imports.bun.ts",
"default": "./src/plugin/imports.noop.ts"
},
"#sqlite": {
"workerd": "./src/database/sqlite.workerd.ts",
"bun": "./src/database/sqlite.bun.ts",
+59
View File
@@ -0,0 +1,59 @@
import { plugin } from "bun"
const modules = await Promise.all([
load("effect", import("effect")),
load("@opencode-ai/plugin", import("@opencode-ai/plugin")),
load("@opencode-ai/plugin/app", import("@opencode-ai/plugin/app")),
load("@opencode-ai/plugin/options", import("@opencode-ai/plugin/options")),
load("@opencode-ai/plugin/storage", import("@opencode-ai/plugin/storage")),
load("@opencode-ai/plugin/promise/adapter", import("@opencode-ai/plugin/promise/adapter")),
load("@opencode-ai/plugin/promise/agent", import("@opencode-ai/plugin/promise/agent")),
load("@opencode-ai/plugin/promise/aisdk", import("@opencode-ai/plugin/promise/aisdk")),
load("@opencode-ai/plugin/promise/catalog", import("@opencode-ai/plugin/promise/catalog")),
load("@opencode-ai/plugin/promise/command", import("@opencode-ai/plugin/promise/command")),
load("@opencode-ai/plugin/promise/event", import("@opencode-ai/plugin/promise/event")),
load("@opencode-ai/plugin/promise/index", import("@opencode-ai/plugin/promise/index")),
load("@opencode-ai/plugin/promise/integration", import("@opencode-ai/plugin/promise/integration")),
load("@opencode-ai/plugin/promise/mcp", import("@opencode-ai/plugin/promise/mcp")),
load("@opencode-ai/plugin/promise/plugin", import("@opencode-ai/plugin/promise/plugin")),
load("@opencode-ai/plugin/promise/reference", import("@opencode-ai/plugin/promise/reference")),
load("@opencode-ai/plugin/promise/registration", import("@opencode-ai/plugin/promise/registration")),
load("@opencode-ai/plugin/promise/session", import("@opencode-ai/plugin/promise/session")),
load("@opencode-ai/plugin/promise/shell", import("@opencode-ai/plugin/promise/shell")),
load("@opencode-ai/plugin/promise/skill", import("@opencode-ai/plugin/promise/skill")),
load("@opencode-ai/plugin/promise/storage", import("@opencode-ai/plugin/promise/storage")),
load("@opencode-ai/plugin/promise/tool", import("@opencode-ai/plugin/promise/tool")),
load("@opencode-ai/plugin/promise/types", import("@opencode-ai/plugin/promise/types")),
load("@opencode-ai/plugin/promise/websearch", import("@opencode-ai/plugin/promise/websearch")),
load("@opencode-ai/plugin/effect", import("@opencode-ai/plugin/effect")),
load("@opencode-ai/plugin/effect/agent", import("@opencode-ai/plugin/effect/agent")),
load("@opencode-ai/plugin/effect/aisdk", import("@opencode-ai/plugin/effect/aisdk")),
load("@opencode-ai/plugin/effect/catalog", import("@opencode-ai/plugin/effect/catalog")),
load("@opencode-ai/plugin/effect/command", import("@opencode-ai/plugin/effect/command")),
load("@opencode-ai/plugin/effect/event", import("@opencode-ai/plugin/effect/event")),
load("@opencode-ai/plugin/effect/index", import("@opencode-ai/plugin/effect/index")),
load("@opencode-ai/plugin/effect/integration", import("@opencode-ai/plugin/effect/integration")),
load("@opencode-ai/plugin/effect/mcp", import("@opencode-ai/plugin/effect/mcp")),
load("@opencode-ai/plugin/effect/plugin", import("@opencode-ai/plugin/effect/plugin")),
load("@opencode-ai/plugin/effect/reference", import("@opencode-ai/plugin/effect/reference")),
load("@opencode-ai/plugin/effect/registration", import("@opencode-ai/plugin/effect/registration")),
load("@opencode-ai/plugin/effect/session", import("@opencode-ai/plugin/effect/session")),
load("@opencode-ai/plugin/effect/shell", import("@opencode-ai/plugin/effect/shell")),
load("@opencode-ai/plugin/effect/skill", import("@opencode-ai/plugin/effect/skill")),
load("@opencode-ai/plugin/effect/storage", import("@opencode-ai/plugin/effect/storage")),
load("@opencode-ai/plugin/effect/tool", import("@opencode-ai/plugin/effect/tool")),
load("@opencode-ai/plugin/effect/websearch", import("@opencode-ai/plugin/effect/websearch")),
])
plugin({
name: "opencode-host-modules",
setup(build) {
modules.forEach(([specifier, exports]) => {
build.module(specifier, () => ({ exports, loader: "object" }))
})
},
})
function load(specifier: string, module: Promise<object>) {
return module.then((exports) => [specifier, Object.fromEntries(Object.entries(exports))] as const)
}
+1
View File
@@ -0,0 +1 @@
export {}
+1
View File
@@ -16,6 +16,7 @@ import { PluginInternal } from "./internal.js"
import { SdkPlugins } from "./sdk.js"
import { importModule } from "@opencode-ai/util/runtime-import"
import { Service } from "./supervisor-service.js"
import "#plugin-imports"
const PluginModule = Schema.Struct({
default: Schema.Union([
+44
View File
@@ -95,6 +95,50 @@ describe("PluginSupervisor config", () => {
),
)
it.live("loads plugins without local runtime packages", () =>
withLocation(
{ plugins: ["-*", "./promise.ts", "./effect.ts"] },
Effect.gen(function* () {
yield* ready()
const plugins = yield* Plugin.Service
expect((yield* plugins.list()).map((plugin) => String(plugin.id))).toEqual([
"host-plugin-package",
"host-effect-packages",
])
}),
false,
(directory) =>
Promise.all([
fs.writeFile(
path.join(directory, "promise.ts"),
`import { Plugin } from "@opencode-ai/plugin"
import { fromPromise } from "@opencode-ai/plugin/promise/adapter"
export default Plugin.define({
id: "host-plugin-package",
setup() {
if (typeof fromPromise !== "function") throw new Error("missing Promise adapter")
},
})
`,
),
fs.writeFile(
path.join(directory, "effect.ts"),
`import { Plugin } from "@opencode-ai/plugin/effect/index"
import { Effect } from "effect"
export default Plugin.define({
id: "host-effect-packages",
effect() {
return Effect.void
},
})
`,
),
]).then(() => undefined),
),
)
it.live("disables configured plugins by exported ID", () => {
const plugin = path.join(import.meta.dir, "../plugin/fixtures/config-promise-plugin.ts")
return withLocation(