From 2afd67f93f83c7fc60457a74b31aa096de592902 Mon Sep 17 00:00:00 2001 From: Keshav's Bot Date: Sun, 10 May 2026 17:24:18 +0530 Subject: [PATCH] fix(diagnostics): queue blocked tool events --- .../src/app-server/event-projector.test.ts | 79 +++++++++++++++++++ src/infra/diagnostic-events.ts | 1 + 2 files changed, 80 insertions(+) diff --git a/extensions/codex/src/app-server/event-projector.test.ts b/extensions/codex/src/app-server/event-projector.test.ts index ffed322e9d7..b6f0d0b1352 100644 --- a/extensions/codex/src/app-server/event-projector.test.ts +++ b/extensions/codex/src/app-server/event-projector.test.ts @@ -928,6 +928,85 @@ describe("CodexAppServerEventProjector", () => { expect(toolResultContentItem.content).toBe("ok"); }); + it("orders declined native tool diagnostics after their start event", async () => { + const projector = await createProjector(); + const diagnosticEvents: DiagnosticEventPayload[] = []; + const unsubscribe = onInternalDiagnosticEvent((event) => diagnosticEvents.push(event)); + + try { + await projector.handleNotification( + forCurrentTurn("item/started", { + item: { + type: "commandExecution", + id: "cmd-declined", + command: "pnpm test extensions/codex", + cwd: "/workspace", + processId: null, + source: "agent", + status: "inProgress", + commandActions: [], + aggregatedOutput: null, + exitCode: null, + durationMs: null, + }, + }), + ); + await projector.handleNotification( + forCurrentTurn("item/completed", { + item: { + type: "commandExecution", + id: "cmd-declined", + command: "pnpm test extensions/codex", + cwd: "/workspace", + processId: null, + source: "agent", + status: "declined", + commandActions: [], + aggregatedOutput: null, + exitCode: null, + durationMs: 1, + }, + }), + ); + await flushDiagnosticEvents(); + } finally { + unsubscribe(); + } + + const toolDiagnosticEvents = diagnosticEvents.filter( + ( + event, + ): event is Extract< + DiagnosticEventPayload, + { + type: + | "tool.execution.started" + | "tool.execution.completed" + | "tool.execution.error" + | "tool.execution.blocked"; + } + > => event.type.startsWith("tool.execution."), + ); + expect( + toolDiagnosticEvents.map((event) => ({ + type: event.type, + toolName: event.toolName, + toolCallId: event.toolCallId, + })), + ).toEqual([ + { + type: "tool.execution.started", + toolName: "bash", + toolCallId: "cmd-declined", + }, + { + type: "tool.execution.blocked", + toolName: "bash", + toolCallId: "cmd-declined", + }, + ]); + }); + it("records dynamic OpenClaw tool calls in mirrored transcript snapshots", async () => { const projector = await createProjector(); diff --git a/src/infra/diagnostic-events.ts b/src/infra/diagnostic-events.ts index 56dc33e2c1a..7dffb5001ac 100644 --- a/src/infra/diagnostic-events.ts +++ b/src/infra/diagnostic-events.ts @@ -652,6 +652,7 @@ const ASYNC_DIAGNOSTIC_EVENT_TYPES = new Set([ "tool.execution.started", "tool.execution.completed", "tool.execution.error", + "tool.execution.blocked", "exec.process.completed", "message.delivery.started", "message.delivery.completed",