fix(core): settle unadvertised tool calls and repair session hook test contexts

This commit is contained in:
Kit Langton 2026-07-07 21:51:23 -04:00
commit eb661e6e6d
5 changed files with 30 additions and 5 deletions

View file

@ -6,6 +6,7 @@ import { Tool } from "@opencode-ai/core/tool/tool"
import { Tools } from "@opencode-ai/core/tool/tools"
import type { Context as PluginContext } from "@opencode-ai/plugin/v2/effect/plugin"
import { Effect, type Scope } from "effect"
import { host } from "../plugin/host"
export const toolIdentity = {
agent: AgentV2.ID.make("build"),
@ -48,7 +49,7 @@ export const registerToolPlugin = <R>(plugin: {
}): Effect.Effect<void, never, R | Tools.Service | Scope.Scope> =>
Effect.gen(function* () {
const tools = yield* Tools.Service
const context: Pick<PluginContext, "tool"> = {
const context = host({
tool: {
transform: (callback) =>
Effect.gen(function* () {
@ -71,8 +72,8 @@ export const registerToolPlugin = <R>(plugin: {
}),
hook: () => Effect.die("registerToolPlugin does not support tool hooks"),
},
}
yield* plugin.effect(context as PluginContext)
})
yield* plugin.effect(context)
})
export const settleTool = (registry: ToolRegistry.Interface, input: ToolRegistry.ExecuteInput, model = testModel) =>

View file

@ -290,6 +290,7 @@ describe("LocationServiceMap", () => {
"edit",
"glob",
"grep",
"patch",
"question",
"read",
"shell",
@ -307,6 +308,7 @@ describe("LocationServiceMap", () => {
"edit",
"glob",
"grep",
"patch",
"question",
"read",
"shell",

View file

@ -83,7 +83,9 @@ export function host(overrides: Overrides = {}): PluginContext {
prompt: () => Effect.die("unused session.prompt"),
command: () => Effect.die("unused session.command"),
interrupt: () => Effect.die("unused session.interrupt"),
hook: () => Effect.die("unused session.hook"),
// Plugins register session hooks during setup, so a bare host accepts the
// registration; the callback only runs when a test triggers the request pipeline.
hook: () => Effect.succeed({ dispose: Effect.void }),
},
}
}

View file

@ -107,6 +107,11 @@ const withSubagent = (location: Location.Ref) =>
const locations = yield* LocationServiceMap.Service
yield* AgentV2.Service.use((agents) =>
agents.transform((draft) => {
// The caller identity used by executeTool; subagent permission asserts against it.
draft.update(toolIdentity.agent, (agent) => {
agent.mode = "primary"
agent.permissions.push({ action: "*", resource: "*", effect: "allow" })
})
draft.update(AgentV2.ID.make("reviewer"), (agent) => {
agent.mode = "subagent"
agent.model = childModel