fix(core): settle unadvertised tool calls and repair session hook test contexts
This commit is contained in:
parent
3379e44abb
commit
eb661e6e6d
5 changed files with 30 additions and 5 deletions
|
|
@ -315,10 +315,25 @@ const layer = Layer.effect(
|
|||
}
|
||||
yield* publish(event)
|
||||
if (event.type !== "tool-call" || event.providerExecuted) return
|
||||
if (!toolMaterialization || !advertisedTools.has(event.name)) {
|
||||
if (!toolMaterialization) {
|
||||
yield* serialized(
|
||||
publisher.failUnsettledTools({
|
||||
type: "tool.execution",
|
||||
message: "Tools are disabled after the maximum agent steps",
|
||||
}),
|
||||
)
|
||||
return
|
||||
}
|
||||
// A request hook hid this registered tool from the current request. Fail only
|
||||
// this call durably and continue so the model can react, instead of executing
|
||||
// a tool that was not advertised. Unregistered tools flow through settle, which
|
||||
// durably fails them as unknown.
|
||||
if (!advertisedTools.has(event.name) && availableTools.has(event.name)) {
|
||||
needsContinuation = true
|
||||
yield* publish(
|
||||
LLMEvent.toolError({
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
message: `Tool is not available for this request: ${event.name}`,
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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) =>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 }),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue