|
1 | 1 | import { expect } from "bun:test" |
2 | | -import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner" |
3 | 2 | import { Effect, Layer } from "effect" |
4 | 3 | import path from "path" |
5 | 4 | import { pathToFileURL } from "url" |
6 | 5 | import { Agent } from "../../src/agent/agent" |
7 | | -import { InstanceRef } from "../../src/effect/instance-ref" |
8 | | -import { InstanceLayer } from "../../src/project/instance-layer" |
9 | | -import { InstanceStore } from "../../src/project/instance-store" |
10 | | -import { tmpdirScoped } from "../fixture/fixture" |
| 6 | +import { Plugin } from "../../src/plugin" |
11 | 7 | import { testEffect } from "../lib/effect" |
| 8 | +import { PLUGIN_AGENT } from "../fixture/agent-plugin.constants" |
12 | 9 |
|
13 | | -const pluginAgent = { |
14 | | - name: "plugin_added", |
15 | | - description: "Added by a plugin via the config hook", |
16 | | - mode: "subagent", |
17 | | -} as const |
| 10 | +// `it.instance` skips InstanceBootstrap so FileWatcher / LSP / MCP don't spin |
| 11 | +// up — those services hang during scope teardown on Windows and aren't needed |
| 12 | +// to verify plugin → config hook → Agent.list. |
| 13 | +const pluginUrl = pathToFileURL(path.join(import.meta.dir, "..", "fixture", "agent-plugin.ts")).href |
18 | 14 |
|
19 | | -const it = testEffect(Layer.mergeAll(Agent.defaultLayer, InstanceLayer.layer, CrossSpawnSpawner.defaultLayer)) |
| 15 | +const it = testEffect(Layer.mergeAll(Agent.defaultLayer, Plugin.defaultLayer)) |
20 | 16 |
|
21 | | -it.live("plugin-registered agents appear in Agent.list", () => |
22 | | - Effect.gen(function* () { |
23 | | - const dir = yield* tmpdirScoped() |
24 | | - const pluginFile = path.join(dir, "plugin.ts") |
25 | | - |
26 | | - yield* Effect.promise(async () => { |
27 | | - await Promise.all([ |
28 | | - Bun.write( |
29 | | - pluginFile, |
30 | | - [ |
31 | | - "export default async () => ({", |
32 | | - " config: async (cfg) => {", |
33 | | - " cfg.agent = cfg.agent ?? {}", |
34 | | - ` cfg.agent[${JSON.stringify(pluginAgent.name)}] = {`, |
35 | | - ` description: ${JSON.stringify(pluginAgent.description)},`, |
36 | | - ` mode: ${JSON.stringify(pluginAgent.mode)},`, |
37 | | - " }", |
38 | | - " },", |
39 | | - "})", |
40 | | - "", |
41 | | - ].join("\n"), |
42 | | - ), |
43 | | - Bun.write( |
44 | | - path.join(dir, "opencode.json"), |
45 | | - JSON.stringify({ |
46 | | - $schema: "https://opencode.ai/config.json", |
47 | | - plugin: [pathToFileURL(pluginFile).href], |
48 | | - }), |
49 | | - ), |
50 | | - ]) |
51 | | - }) |
52 | | - |
53 | | - const agents = yield* InstanceStore.Service.use((store) => |
54 | | - Effect.gen(function* () { |
55 | | - const ctx = yield* store.load({ directory: dir }) |
56 | | - yield* Effect.addFinalizer(() => store.dispose(ctx).pipe(Effect.ignore)) |
57 | | - return yield* Agent.Service.use((svc) => svc.list()).pipe(Effect.provideService(InstanceRef, ctx)) |
58 | | - }), |
59 | | - ) |
60 | | - const added = agents.find((agent) => agent.name === pluginAgent.name) |
61 | | - |
62 | | - expect(added?.description).toBe(pluginAgent.description) |
63 | | - expect(added?.mode).toBe(pluginAgent.mode) |
64 | | - }), |
| 17 | +it.instance( |
| 18 | + "plugin-registered agents appear in Agent.list", |
| 19 | + () => |
| 20 | + Effect.gen(function* () { |
| 21 | + yield* Plugin.Service.use((p) => p.init()) |
| 22 | + const agents = yield* Agent.Service.use((svc) => svc.list()) |
| 23 | + const added = agents.find((agent) => agent.name === PLUGIN_AGENT.name) |
| 24 | + expect(added?.description).toBe(PLUGIN_AGENT.description) |
| 25 | + expect(added?.mode).toBe(PLUGIN_AGENT.mode) |
| 26 | + }), |
| 27 | + { config: { plugin: [pluginUrl] } }, |
65 | 28 | ) |
0 commit comments