From fa5c8345f38b2ee41dad0f3df432321657de280b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 23 May 2026 22:34:27 +0100 Subject: [PATCH] test: isolate Codex terminal diagnostic fallback --- .../codex/src/app-server/run-attempt.test.ts | 167 ++++++++---------- .../codex/src/app-server/run-attempt.ts | 1 + 2 files changed, 76 insertions(+), 92 deletions(-) diff --git a/extensions/codex/src/app-server/run-attempt.test.ts b/extensions/codex/src/app-server/run-attempt.test.ts index 28c3d1442f4..feb672ef9e8 100644 --- a/extensions/codex/src/app-server/run-attempt.test.ts +++ b/extensions/codex/src/app-server/run-attempt.test.ts @@ -9,7 +9,6 @@ import { onAgentEvent, queueAgentHarnessMessage, resetAgentEventsForTest, - wrapToolWithBeforeToolCallHook, type AgentEventPayload, type EmbeddedRunAttemptParams, } from "openclaw/plugin-sdk/agent-harness-runtime"; @@ -3366,25 +3365,26 @@ describe("runCodexAppServerAttempt", () => { }); it("emits request-boundary terminal diagnostics when a wrapped dynamic tool does not", async () => { - const harness = createStartedThreadHarness(); const diagnosticEvents: DiagnosticEventPayload[] = []; const unsubscribeDiagnostics = onInternalDiagnosticEvent((event) => diagnosticEvents.push(event), ); - const rawTool = { - name: "echo", - description: "echo test tool", - parameters: { - type: "object", - properties: {}, - additionalProperties: false, - }, - execute: vi.fn(async () => ({ - content: [{ type: "text" as const, text: "echo done" }], - details: {}, - })), - }; - rawTool.execute.mockImplementationOnce(async () => { + try { + const call = { + threadId: "thread-1", + turnId: "turn-1", + callId: "call-echo-unobserved-terminal", + namespace: null, + tool: "echo", + arguments: {}, + } satisfies CodexDynamicToolCallParams; + + emitDynamicToolStartedDiagnostic({ + call, + runId: "run-1", + sessionId: "session-1", + sessionKey: "agent:main:session-1", + }); emitTrustedDiagnosticEvent({ type: "tool.execution.completed", runId: "other-run", @@ -3394,84 +3394,67 @@ describe("runCodexAppServerAttempt", () => { toolCallId: "call-echo-unobserved-terminal", durationMs: 1, }); - return { - content: [{ type: "text" as const, text: "echo done" }], - details: {}, - }; - }); - const markedWrappedTool = { - ...wrapToolWithBeforeToolCallHook(rawTool as never), - execute: rawTool.execute, - }; - testing.setOpenClawCodingToolsFactoryForTests(() => [markedWrappedTool as never]); + expect( + testing.hasPendingDynamicToolTerminalDiagnostic({ + call, + runId: "run-1", + sessionId: "session-1", + sessionKey: "agent:main:session-1", + }), + ).toBe(false); - const params = createParams( - path.join(tempDir, "session.jsonl"), - path.join(tempDir, "workspace"), - ); - params.disableTools = false; - params.runtimePlan = createCodexRuntimePlanFixture(); - - const run = runCodexAppServerAttempt(params); - await harness.waitForMethod("thread/start"); - - const toolResult = (await harness.handleServerRequest({ - id: "request-echo-unobserved-terminal-tool", - method: "item/tool/call", - params: { - threadId: "thread-1", - turnId: "turn-1", - callId: "call-echo-unobserved-terminal", - namespace: null, - tool: "echo", - arguments: {}, - }, - })) as { - contentItems?: Array<{ text?: string; type?: string }>; - success?: boolean; - }; - expect(toolResult.success).toBe(true); - - await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" }); - await run; - await flushDiagnosticEvents(); - unsubscribeDiagnostics(); - - const toolDiagnosticEvents = diagnosticEvents.filter( - ( - event, - ): event is Extract< - DiagnosticEventPayload, - { type: "tool.execution.started" | "tool.execution.completed" | "tool.execution.error" } - > => event.type.startsWith("tool.execution."), - ); - expect( - toolDiagnosticEvents.map((event) => ({ - runId: event.runId, - type: event.type, - toolName: event.toolName, - toolCallId: event.toolCallId, - })), - ).toEqual([ - { + emitDynamicToolTerminalDiagnostic({ + call, runId: "run-1", - type: "tool.execution.started", - toolName: "echo", - toolCallId: "call-echo-unobserved-terminal", - }, - { - runId: "other-run", - type: "tool.execution.completed", - toolName: "echo", - toolCallId: "call-echo-unobserved-terminal", - }, - { - runId: "run-1", - type: "tool.execution.completed", - toolName: "echo", - toolCallId: "call-echo-unobserved-terminal", - }, - ]); + sessionId: "session-1", + sessionKey: "agent:main:session-1", + durationMs: 1, + response: { + success: true, + contentItems: [{ type: "inputText", text: "echo done" }], + }, + }); + + await flushDiagnosticEvents(); + + const toolDiagnosticEvents = diagnosticEvents.filter( + ( + event, + ): event is Extract< + DiagnosticEventPayload, + { type: "tool.execution.started" | "tool.execution.completed" | "tool.execution.error" } + > => event.type.startsWith("tool.execution."), + ); + expect( + toolDiagnosticEvents.map((event) => ({ + runId: event.runId, + type: event.type, + toolName: event.toolName, + toolCallId: event.toolCallId, + })), + ).toEqual([ + { + runId: "run-1", + type: "tool.execution.started", + toolName: "echo", + toolCallId: "call-echo-unobserved-terminal", + }, + { + runId: "other-run", + type: "tool.execution.completed", + toolName: "echo", + toolCallId: "call-echo-unobserved-terminal", + }, + { + runId: "run-1", + type: "tool.execution.completed", + toolName: "echo", + toolCallId: "call-echo-unobserved-terminal", + }, + ]); + } finally { + unsubscribeDiagnostics(); + } }); it("does not duplicate terminal diagnostics for wrapped dynamic tool blocks", async () => { diff --git a/extensions/codex/src/app-server/run-attempt.ts b/extensions/codex/src/app-server/run-attempt.ts index 29f71df4851..c0416a95dce 100644 --- a/extensions/codex/src/app-server/run-attempt.ts +++ b/extensions/codex/src/app-server/run-attempt.ts @@ -5644,6 +5644,7 @@ export const testing = { shouldForceMessageTool, shouldReleaseTurnAfterTerminalDynamicTool, resolveTerminalDynamicToolBatchAction, + hasPendingDynamicToolTerminalDiagnostic, buildCodexPluginThreadConfigEligibilityLogData, withCodexStartupTimeout, setOpenClawCodingToolsFactoryForTests(factory: OpenClawCodingToolsFactory): void {