11import type { AgentToolResult } from "openclaw/plugin-sdk/agent-core" ;
2+ import {
3+ onInternalDiagnosticEvent ,
4+ waitForDiagnosticEventsDrained ,
5+ type DiagnosticEventPayload ,
6+ } from "openclaw/plugin-sdk/diagnostic-runtime" ;
27import type { AnyAgentTool } from "openclaw/plugin-sdk/agent-harness" ;
38import {
49 HEARTBEAT_RESPONSE_TOOL_NAME ,
@@ -293,18 +298,33 @@ describe("createCodexDynamicToolBridge", () => {
293298
294299 it ( "quarantines dynamic tools with unsupported input schemas" , async ( ) => {
295300 const warn = vi . spyOn ( embeddedAgentLog , "warn" ) . mockImplementation ( ( ) => undefined ) ;
301+ const diagnosticEvents : DiagnosticEventPayload [ ] = [ ] ;
302+ const unsubscribeDiagnostics = onInternalDiagnosticEvent ( ( event ) =>
303+ diagnosticEvents . push ( event ) ,
304+ ) ;
296305 const badExecute = vi . fn ( ) ;
297- const bridge = createCodexDynamicToolBridge ( {
298- tools : [
299- createTool ( { name : "message" } ) ,
300- createTool ( {
301- name : "dofbot_move_angles" ,
302- parameters : { type : "array" , items : { type : "number" } } ,
303- execute : badExecute ,
304- } ) ,
305- ] ,
306- signal : new AbortController ( ) . signal ,
307- } ) ;
306+ let bridge ! : ReturnType < typeof createCodexDynamicToolBridge > ;
307+ try {
308+ bridge = createCodexDynamicToolBridge ( {
309+ tools : [
310+ createTool ( { name : "message" } ) ,
311+ createTool ( {
312+ name : "dofbot_move_angles" ,
313+ parameters : { type : "array" , items : { type : "number" } } ,
314+ execute : badExecute ,
315+ } ) ,
316+ ] ,
317+ signal : new AbortController ( ) . signal ,
318+ hookContext : {
319+ runId : "run-1" ,
320+ sessionId : "session-1" ,
321+ sessionKey : "agent:main:session-1" ,
322+ } ,
323+ } ) ;
324+ await waitForDiagnosticEventsDrained ( ) ;
325+ } finally {
326+ unsubscribeDiagnostics ( ) ;
327+ }
308328
309329 expect ( bridge . availableSpecs . map ( ( tool ) => tool . name ) ) . toEqual ( [ "message" ] ) ;
310330 expect ( bridge . specs . map ( ( tool ) => tool . name ) ) . toEqual ( [ "message" ] ) ;
@@ -325,6 +345,23 @@ describe("createCodexDynamicToolBridge", () => {
325345 ] ,
326346 } ) ,
327347 ) ;
348+ const blockedEvents = diagnosticEvents . filter (
349+ (
350+ event ,
351+ ) : event is Extract < DiagnosticEventPayload , { type : "tool.execution.blocked" } > =>
352+ event . type === "tool.execution.blocked" ,
353+ ) ;
354+ expect ( blockedEvents ) . toContainEqual (
355+ expect . objectContaining ( {
356+ type : "tool.execution.blocked" ,
357+ runId : "run-1" ,
358+ sessionId : "session-1" ,
359+ sessionKey : "agent:main:session-1" ,
360+ toolName : "dofbot_move_angles" ,
361+ deniedReason : "unsupported_tool_schema" ,
362+ reason : 'dofbot_move_angles.inputSchema.type must be "object"' ,
363+ } ) ,
364+ ) ;
328365
329366 const result = await bridge . handleToolCall ( {
330367 threadId : "thread-1" ,
0 commit comments