refactor(core): make Code Mode a service
This commit is contained in:
parent
81f6e06681
commit
70b493af15
17 changed files with 268 additions and 87 deletions
|
|
@ -191,7 +191,7 @@ describe("PluginV2", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("groups tool names and defers registrations from direct exposure", () =>
|
||||
it.effect("registers direct and Code Mode tools through separate plugin domains", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* PluginV2.Service
|
||||
const registry = yield* ToolRegistry.Service
|
||||
|
|
@ -205,13 +205,17 @@ describe("PluginV2", () => {
|
|||
const plugin = define({
|
||||
id: "grouped-tools",
|
||||
effect: (ctx) =>
|
||||
ctx.tool
|
||||
.transform((draft) => {
|
||||
draft.add("plain", tool("Plain"))
|
||||
draft.add("look/up", tool("Lookup"), { group: "context 7" })
|
||||
draft.add("search", tool("Search"), { group: "context 7", deferred: true })
|
||||
})
|
||||
.pipe(Effect.orDie),
|
||||
Effect.gen(function* () {
|
||||
yield* ctx.tool
|
||||
.transform((draft) => {
|
||||
draft.add("plain", tool("Plain"))
|
||||
draft.add("look/up", tool("Lookup"), { group: "context 7" })
|
||||
})
|
||||
.pipe(Effect.orDie)
|
||||
yield* ctx.codemode
|
||||
.register((draft) => draft.add(["context_7", "search"], tool("Search")))
|
||||
.pipe(Effect.orDie)
|
||||
}),
|
||||
})
|
||||
|
||||
yield* plugins.activate([{ plugin }])
|
||||
|
|
@ -221,6 +225,9 @@ describe("PluginV2", () => {
|
|||
"context_7_look_up",
|
||||
"execute",
|
||||
])
|
||||
|
||||
yield* plugins.activate([])
|
||||
expect((yield* registry.materialize({ model: testModel })).definitions).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { AgentV2 } from "@opencode-ai/core/agent"
|
||||
import { AISDK } from "@opencode-ai/core/aisdk"
|
||||
import { Catalog } from "@opencode-ai/core/catalog"
|
||||
import { CodeModeV2 } from "@opencode-ai/core/code-mode"
|
||||
import { CommandV2 } from "@opencode-ai/core/command"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
|
|
@ -43,6 +44,7 @@ export const PluginTestLayer = AppNodeBuilder.build(
|
|||
AgentV2.node,
|
||||
AISDK.node,
|
||||
Catalog.node,
|
||||
CodeModeV2.node,
|
||||
CommandV2.node,
|
||||
Integration.node,
|
||||
PluginRuntime.node,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ export function host(overrides: Overrides = {}): PluginContext {
|
|||
transform: () => Effect.die("unused command.transform"),
|
||||
reload: () => Effect.die("unused command.reload"),
|
||||
},
|
||||
codemode: overrides.codemode ?? {
|
||||
register: () => Effect.die("unused codemode.register"),
|
||||
},
|
||||
event: overrides.event ?? {
|
||||
subscribe: () => Stream.empty,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { Tool } from "@opencode-ai/core/tool/tool"
|
||||
import { AgentV2 } from "@opencode-ai/core/agent"
|
||||
import { CodeModeV2 } from "@opencode-ai/core/code-mode"
|
||||
import type { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { SessionV2 } from "@opencode-ai/core/session"
|
||||
import { SessionMessage } from "@opencode-ai/core/session/message"
|
||||
import { ToolOutputStore } from "@opencode-ai/core/tool-output-store"
|
||||
|
|
@ -28,7 +30,9 @@ const outputStore = Layer.mock(ToolOutputStore.Service, {
|
|||
)
|
||||
},
|
||||
})
|
||||
const registryLayer = AppNodeBuilder.build(ToolRegistry.node, [[ToolOutputStore.node, outputStore]])
|
||||
const registryLayer = AppNodeBuilder.build(LayerNode.group([ToolRegistry.node, CodeModeV2.node]), [
|
||||
[ToolOutputStore.node, outputStore],
|
||||
])
|
||||
const it = testEffect(registryLayer)
|
||||
const identity = {
|
||||
agent: AgentV2.ID.make("build"),
|
||||
|
|
@ -53,6 +57,30 @@ const make = (permission?: string) => {
|
|||
}
|
||||
|
||||
describe("ToolRegistry", () => {
|
||||
it.effect("materializes nested Code Mode sources as execute", () =>
|
||||
Effect.gen(function* () {
|
||||
const codeMode = yield* CodeModeV2.Service
|
||||
const service = yield* ToolRegistry.Service
|
||||
yield* codeMode.register((draft) => draft.add(["opencode", "v2", "echo"], make()))
|
||||
|
||||
const definitions = yield* toolDefinitions(service)
|
||||
expect(definitions.map((tool) => tool.name)).toEqual(["execute"])
|
||||
expect(definitions[0]?.description).toContain("tools.opencode.v2.echo")
|
||||
expect(
|
||||
yield* executeTool(service, {
|
||||
sessionID,
|
||||
...identity,
|
||||
call: {
|
||||
type: "tool-call",
|
||||
id: "call-code-mode",
|
||||
name: "execute",
|
||||
input: { code: 'return await tools.opencode.v2.echo({ text: "hello" })' },
|
||||
},
|
||||
}),
|
||||
).toEqual({ type: "text", value: '{\n "text": "hello"\n}' })
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("filters disabled tools with edit aliases and ordered wildcard precedence", () =>
|
||||
Effect.gen(function* () {
|
||||
const service = yield* ToolRegistry.Service
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue