test(agent): skip InstanceBootstrap in plugin-agent regression test (#25737)

This commit is contained in:
Kit Langton
2026-05-04 17:11:33 +00:00
committed by GitHub
parent fb07c2070c
commit 007b57f078
3 changed files with 36 additions and 55 deletions
@@ -1,65 +1,28 @@
import { expect } from "bun:test" import { expect } from "bun:test"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { Effect, Layer } from "effect" import { Effect, Layer } from "effect"
import path from "path" import path from "path"
import { pathToFileURL } from "url" import { pathToFileURL } from "url"
import { Agent } from "../../src/agent/agent" import { Agent } from "../../src/agent/agent"
import { InstanceRef } from "../../src/effect/instance-ref" import { Plugin } from "../../src/plugin"
import { InstanceLayer } from "../../src/project/instance-layer"
import { InstanceStore } from "../../src/project/instance-store"
import { tmpdirScoped } from "../fixture/fixture"
import { testEffect } from "../lib/effect" import { testEffect } from "../lib/effect"
import { PLUGIN_AGENT } from "../fixture/agent-plugin.constants"
const pluginAgent = { // `it.instance` skips InstanceBootstrap so FileWatcher / LSP / MCP don't spin
name: "plugin_added", // up — those services hang during scope teardown on Windows and aren't needed
description: "Added by a plugin via the config hook", // to verify plugin config hook → Agent.list.
mode: "subagent", const pluginUrl = pathToFileURL(path.join(import.meta.dir, "..", "fixture", "agent-plugin.ts")).href
} as const
const it = testEffect(Layer.mergeAll(Agent.defaultLayer, InstanceLayer.layer, CrossSpawnSpawner.defaultLayer)) const it = testEffect(Layer.mergeAll(Agent.defaultLayer, Plugin.defaultLayer))
it.live("plugin-registered agents appear in Agent.list", () => it.instance(
Effect.gen(function* () { "plugin-registered agents appear in Agent.list",
const dir = yield* tmpdirScoped() () =>
const pluginFile = path.join(dir, "plugin.ts") Effect.gen(function* () {
yield* Plugin.Service.use((p) => p.init())
yield* Effect.promise(async () => { const agents = yield* Agent.Service.use((svc) => svc.list())
await Promise.all([ const added = agents.find((agent) => agent.name === PLUGIN_AGENT.name)
Bun.write( expect(added?.description).toBe(PLUGIN_AGENT.description)
pluginFile, expect(added?.mode).toBe(PLUGIN_AGENT.mode)
[ }),
"export default async () => ({", { config: { plugin: [pluginUrl] } },
" config: async (cfg) => {",
" cfg.agent = cfg.agent ?? {}",
` cfg.agent[${JSON.stringify(pluginAgent.name)}] = {`,
` description: ${JSON.stringify(pluginAgent.description)},`,
` mode: ${JSON.stringify(pluginAgent.mode)},`,
" }",
" },",
"})",
"",
].join("\n"),
),
Bun.write(
path.join(dir, "opencode.json"),
JSON.stringify({
$schema: "https://opencode.ai/config.json",
plugin: [pathToFileURL(pluginFile).href],
}),
),
])
})
const agents = yield* InstanceStore.Service.use((store) =>
Effect.gen(function* () {
const ctx = yield* store.load({ directory: dir })
yield* Effect.addFinalizer(() => store.dispose(ctx).pipe(Effect.ignore))
return yield* Agent.Service.use((svc) => svc.list()).pipe(Effect.provideService(InstanceRef, ctx))
}),
)
const added = agents.find((agent) => agent.name === pluginAgent.name)
expect(added?.description).toBe(pluginAgent.description)
expect(added?.mode).toBe(pluginAgent.mode)
}),
) )
@@ -0,0 +1,6 @@
// Separate file because every export in `agent-plugin.ts` must be a function.
export const PLUGIN_AGENT = {
name: "plugin_added",
description: "Added by a plugin via the config hook",
mode: "subagent",
} as const
@@ -0,0 +1,12 @@
// Every export in this file must be a plugin function — `getLegacyPlugins`
// (src/plugin/index.ts) throws on anything else. Test constants live in
// `agent-plugin.constants.ts`.
export default async () => ({
config: async (cfg: { agent?: Record<string, unknown> }) => {
cfg.agent = cfg.agent ?? {}
cfg.agent["plugin_added"] = {
description: "Added by a plugin via the config hook",
mode: "subagent",
}
},
})