File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -315,10 +315,25 @@ const layer = Layer.effect(
315315 }
316316 yield * publish ( event )
317317 if ( event . type !== "tool-call" || event . providerExecuted ) return
318- if ( ! toolMaterialization || ! advertisedTools . has ( event . name ) ) {
318+ if ( ! toolMaterialization ) {
319319 yield * serialized (
320320 publisher . failUnsettledTools ( {
321321 type : "tool.execution" ,
322+ message : "Tools are disabled after the maximum agent steps" ,
323+ } ) ,
324+ )
325+ return
326+ }
327+ // A request hook hid this registered tool from the current request. Fail only
328+ // this call durably and continue so the model can react, instead of executing
329+ // a tool that was not advertised. Unregistered tools flow through settle, which
330+ // durably fails them as unknown.
331+ if ( ! advertisedTools . has ( event . name ) && availableTools . has ( event . name ) ) {
332+ needsContinuation = true
333+ yield * publish (
334+ LLMEvent . toolError ( {
335+ id : event . id ,
336+ name : event . name ,
322337 message : `Tool is not available for this request: ${ event . name } ` ,
323338 } ) ,
324339 )
Original file line number Diff line number Diff line change @@ -6,6 +6,7 @@ import { Tool } from "@opencode-ai/core/tool/tool"
66import { Tools } from "@opencode-ai/core/tool/tools"
77import type { Context as PluginContext } from "@opencode-ai/plugin/v2/effect/plugin"
88import { Effect , type Scope } from "effect"
9+ import { host } from "../plugin/host"
910
1011export const toolIdentity = {
1112 agent : AgentV2 . ID . make ( "build" ) ,
@@ -48,7 +49,7 @@ export const registerToolPlugin = <R>(plugin: {
4849} ) : Effect . Effect < void , never , R | Tools . Service | Scope . Scope > =>
4950 Effect . gen ( function * ( ) {
5051 const tools = yield * Tools . Service
51- const context : Pick < PluginContext , "tool" > = {
52+ const context = host ( {
5253 tool : {
5354 transform : ( callback ) =>
5455 Effect . gen ( function * ( ) {
@@ -71,8 +72,8 @@ export const registerToolPlugin = <R>(plugin: {
7172 } ) ,
7273 hook : ( ) => Effect . die ( "registerToolPlugin does not support tool hooks" ) ,
7374 } ,
74- }
75- yield * plugin . effect ( context as PluginContext )
75+ } )
76+ yield * plugin . effect ( context )
7677 } )
7778
7879export const settleTool = ( registry : ToolRegistry . Interface , input : ToolRegistry . ExecuteInput , model = testModel ) =>
Original file line number Diff line number Diff line change @@ -290,6 +290,7 @@ describe("LocationServiceMap", () => {
290290 "edit" ,
291291 "glob" ,
292292 "grep" ,
293+ "patch" ,
293294 "question" ,
294295 "read" ,
295296 "shell" ,
@@ -307,6 +308,7 @@ describe("LocationServiceMap", () => {
307308 "edit" ,
308309 "glob" ,
309310 "grep" ,
311+ "patch" ,
310312 "question" ,
311313 "read" ,
312314 "shell" ,
Original file line number Diff line number Diff line change @@ -83,7 +83,9 @@ export function host(overrides: Overrides = {}): PluginContext {
8383 prompt : ( ) => Effect . die ( "unused session.prompt" ) ,
8484 command : ( ) => Effect . die ( "unused session.command" ) ,
8585 interrupt : ( ) => Effect . die ( "unused session.interrupt" ) ,
86- hook : ( ) => Effect . die ( "unused session.hook" ) ,
86+ // Plugins register session hooks during setup, so a bare host accepts the
87+ // registration; the callback only runs when a test triggers the request pipeline.
88+ hook : ( ) => Effect . succeed ( { dispose : Effect . void } ) ,
8789 } ,
8890 }
8991}
Original file line number Diff line number Diff line change @@ -107,6 +107,11 @@ const withSubagent = (location: Location.Ref) =>
107107 const locations = yield * LocationServiceMap . Service
108108 yield * AgentV2 . Service . use ( ( agents ) =>
109109 agents . transform ( ( draft ) => {
110+ // The caller identity used by executeTool; subagent permission asserts against it.
111+ draft . update ( toolIdentity . agent , ( agent ) => {
112+ agent . mode = "primary"
113+ agent . permissions . push ( { action : "*" , resource : "*" , effect : "allow" } )
114+ } )
110115 draft . update ( AgentV2 . ID . make ( "reviewer" ) , ( agent ) => {
111116 agent . mode = "subagent"
112117 agent . model = childModel
You can’t perform that action at this time.
0 commit comments