refactor(agents): remove retired Codex CLI parser (#116017)

This commit is contained in:
Peter Steinberger
2026-07-29 14:14:41 -04:00
committed by GitHub
parent 777cfed85a
commit 97d374b357
12 changed files with 25 additions and 297 deletions
-134
View File
@@ -156,11 +156,6 @@ function isGeminiCliProvider(providerId: string): boolean {
return normalizeLowercaseStringOrEmpty(providerId) === "google-gemini-cli";
}
function isCodexExecJsonlProvider(providerId: string): boolean {
const normalized = normalizeLowercaseStringOrEmpty(providerId);
return normalized === "codex" || normalized === "codex-cli";
}
function isGeminiStreamJsonDialect(params: {
backend: CliBackendConfig;
providerId: string;
@@ -1174,128 +1169,6 @@ function dispatchGeminiCliStreamingToolEvent(params: {
}
}
type CodexToolEvent = {
toolCallId: string;
name: string;
kind: CliToolUseStartDelta["kind"];
args: Record<string, unknown>;
result?: unknown;
isError: boolean;
};
function readCodexToolEvent(item: Record<string, unknown>): CodexToolEvent | null {
const toolCallId = typeof item.id === "string" ? item.id.trim() : "";
if (!toolCallId) {
return null;
}
const type = normalizeLowercaseStringOrEmpty(item.type);
if (type === "command_execution") {
return {
toolCallId,
name: "bash",
kind: "tool_use",
args: typeof item.command === "string" ? { command: item.command } : {},
result: item.aggregated_output,
isError: item.status === "failed" || item.status === "declined",
};
}
if (type === "file_change") {
return {
toolCallId,
name: "apply_patch",
kind: "tool_use",
args: Array.isArray(item.changes) ? { changes: item.changes } : {},
result: item.changes,
isError: item.status === "failed",
};
}
if (type === "web_search") {
return {
toolCallId,
name: "web_search",
kind: "server_tool_use",
args: typeof item.query === "string" ? { query: item.query } : {},
result: item.query,
isError: false,
};
}
if (type !== "mcp_tool_call") {
if (type !== "collab_tool_call") {
return null;
}
const tool = typeof item.tool === "string" ? item.tool.trim() : "";
if (!tool) {
return null;
}
return {
toolCallId,
name: `collab.${tool}`,
kind: "server_tool_use",
args: {
...(typeof item.sender_thread_id === "string"
? { sender_thread_id: item.sender_thread_id }
: {}),
...(Array.isArray(item.receiver_thread_ids)
? { receiver_thread_ids: item.receiver_thread_ids }
: {}),
...(typeof item.prompt === "string" ? { prompt: item.prompt } : {}),
},
result: item.agents_states,
isError: item.status === "failed",
};
}
const server = typeof item.server === "string" ? item.server.trim() : "";
const tool = typeof item.tool === "string" ? item.tool.trim() : "";
if (!tool) {
return null;
}
return {
toolCallId,
name: server ? `${server}.${tool}` : tool,
kind: "mcp_tool_use",
args: isRecord(item.arguments) ? item.arguments : {},
result: item.status === "failed" ? item.error : item.result,
isError: item.status === "failed",
};
}
function dispatchCodexCliStreamingToolEvent(params: {
providerId: string;
parsed: Record<string, unknown>;
tracker: ToolUseTracker;
onToolUseStart?: (delta: CliToolUseStartDelta) => void;
onToolResult?: (delta: CliToolResultDelta) => void;
}): void {
if (
!isCodexExecJsonlProvider(params.providerId) ||
(params.parsed.type !== "item.started" && params.parsed.type !== "item.completed") ||
!isRecord(params.parsed.item)
) {
return;
}
const event = readCodexToolEvent(params.parsed.item);
if (!event) {
return;
}
emitToolStartOnce(
params.tracker,
event.toolCallId,
event.name,
event.kind,
event.args,
params.onToolUseStart,
);
if (params.parsed.type === "item.completed") {
emitToolResultOnce(
params.tracker,
event.toolCallId,
event.isError,
event.result,
params.onToolResult,
);
}
}
const GEMINI_CLI_ERROR_EVENT_FALLBACK = "Gemini CLI emitted an error event.";
const GEMINI_CLI_RESULT_ERROR_FALLBACK = "Gemini CLI result status was error.";
@@ -1527,13 +1400,6 @@ export function createCliJsonlStreamingParser(params: {
}
if (params.onToolUseStart || params.onToolResult) {
dispatchCodexCliStreamingToolEvent({
providerId: params.providerId,
parsed,
tracker: toolTracker,
onToolUseStart: params.onToolUseStart,
onToolResult: params.onToolResult,
});
dispatchGeminiCliStreamingToolEvent({
backend: params.backend,
providerId: params.providerId,
@@ -1,108 +0,0 @@
/** Tests Codex exec JSONL tool-summary projection through the CLI process boundary. */
import { readFileSync } from "node:fs";
import { beforeEach, describe, expect, it } from "vitest";
import {
buildPreparedCliRunContext,
type PreparedCliRunContextOverrides,
} from "./cli-runner.test-helpers.js";
import { createManagedRun, supervisorSpawnMock } from "./cli-runner.test-support.js";
import { executePreparedCliRun } from "./cli-runner/execute.js";
const CODEX_BACKEND: PreparedCliRunContextOverrides["backend"] = {
output: "jsonl",
sessionIdFields: ["thread_id"],
systemPromptFileConfigArg: undefined,
};
function queueCodexFixture(name: string) {
supervisorSpawnMock.mockResolvedValueOnce(
createManagedRun({
reason: "exit",
exitCode: 0,
exitSignal: null,
durationMs: 10,
stdout: readFileSync(`test/fixtures/cli/${name}.jsonl`, "utf8"),
stderr: "",
timedOut: false,
noOutputTimedOut: false,
}),
);
}
async function runCodexFixture(name: string) {
queueCodexFixture(name);
return await executePreparedCliRun(
buildPreparedCliRunContext({
provider: "codex-cli",
model: "gpt-5.5",
backend: CODEX_BACKEND,
}),
);
}
beforeEach(() => {
supervisorSpawnMock.mockReset();
});
describe("Codex CLI tool summaries", () => {
it("emits an explicit empty summary for a successful zero-tool turn", async () => {
const output = await runCodexFixture("codex-tool-summary-zero");
expect(output.toolSummary).toEqual({ calls: 0, tools: [], failures: 0 });
});
it("counts paired MCP lifecycle events once", async () => {
const output = await runCodexFixture("codex-tool-summary-paired-mcp");
expect(output.toolSummary).toEqual({ calls: 1, tools: ["github.search"], failures: 0 });
});
it("projects terminal-only MCP and native items in first-observed order", async () => {
const output = await runCodexFixture("codex-tool-summary-terminal-only");
expect(output.toolSummary).toEqual({
calls: 4,
tools: ["lookup", "bash", "apply_patch", "web_search"],
failures: 0,
});
});
it("counts a typed failed terminal MCP item", async () => {
const output = await runCodexFixture("codex-tool-summary-failed-mcp");
expect(output.toolSummary).toEqual({ calls: 1, tools: ["docs.read"], failures: 1 });
});
it("counts a declined command terminal as a failure", async () => {
const output = await runCodexFixture("codex-tool-summary-declined-command");
expect(output.toolSummary).toEqual({ calls: 1, tools: ["bash"], failures: 1 });
});
it.each([
{
fixture: "codex-tool-summary-collab-paired",
tool: "collab.spawn_agent",
failures: 0,
},
{
fixture: "codex-tool-summary-collab-terminal-only",
tool: "collab.wait",
failures: 0,
},
{
fixture: "codex-tool-summary-collab-failed",
tool: "collab.send_input",
failures: 1,
},
{
fixture: "codex-tool-summary-collab-close-agent",
tool: "collab.close_agent",
failures: 0,
},
])("projects $fixture lifecycle metadata", async ({ fixture, tool, failures }) => {
const output = await runCodexFixture(fixture);
expect(output.toolSummary).toEqual({ calls: 1, tools: [tool], failures });
});
});
@@ -690,6 +690,7 @@ describe("executePreparedCliRun supervisor output capture", () => {
expect(spawnInput.captureOutput).toBe(false);
expect(result.text).toBe("Hello world");
expect(result.toolSummary).toEqual({ calls: 0, tools: [], failures: 0 });
expect(agentEvents).toEqual([
{ text: "Hello", delta: "Hello" },
{ text: "Hello world", delta: " world" },
@@ -753,7 +754,12 @@ describe("executePreparedCliRun supervisor output capture", () => {
context.params.agentId = "coder";
try {
await executePreparedCliRun(context);
const result = await executePreparedCliRun(context);
expect(result.toolSummary).toEqual({
calls: 1,
tools: ["mcp__team__lookup"],
failures: 0,
});
} finally {
stop();
}
@@ -859,7 +865,12 @@ describe("executePreparedCliRun supervisor output capture", () => {
context.mcpDeliveryCapture = true;
try {
await executePreparedCliRun(context);
const result = await executePreparedCliRun(context);
expect(result.toolSummary).toEqual({
calls: 1,
tools: ["mcp__openclaw__message"],
failures: 1,
});
} finally {
stop();
}
@@ -938,7 +949,12 @@ describe("executePreparedCliRun supervisor output capture", () => {
context.mcpDeliveryCapture = true;
try {
await executePreparedCliRun(context);
const result = await executePreparedCliRun(context);
expect(result.toolSummary).toEqual({
calls: 1,
tools: ["mcp__openclaw__message"],
failures: 1,
});
} finally {
stop();
}
@@ -1021,7 +1037,12 @@ describe("executePreparedCliRun supervisor output capture", () => {
context.mcpDeliveryCapture = true;
try {
await executePreparedCliRun(context);
const result = await executePreparedCliRun(context);
expect(result.toolSummary).toEqual({
calls: 2,
tools: ["mcp__openclaw__message"],
failures: 1,
});
} finally {
stop();
}
@@ -1,6 +0,0 @@
{"type":"thread.started","thread_id":"thread-collab-close"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"collab-close","type":"collab_tool_call","tool":"close_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"running","message":null}},"status":"in_progress"}}
{"type":"item.completed","item":{"id":"collab-close","type":"collab_tool_call","tool":"close_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"shutdown","message":null}},"status":"completed"}}
{"type":"item.completed","item":{"id":"message-collab-close","type":"agent_message","text":"collab closed"}}
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
@@ -1,5 +0,0 @@
{"type":"thread.started","thread_id":"thread-collab-failed"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"collab-failed","type":"collab_tool_call","tool":"send_input","sender_thread_id":"thread-parent","receiver_thread_ids":["missing-thread"],"prompt":"continue","agents_states":{"missing-thread":{"status":"not_found","message":"agent not found"}},"status":"failed"}}
{"type":"item.completed","item":{"id":"message-collab-failed","type":"agent_message","text":"collab failed"}}
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
@@ -1,6 +0,0 @@
{"type":"thread.started","thread_id":"thread-collab-paired"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"collab-paired","type":"collab_tool_call","tool":"spawn_agent","sender_thread_id":"thread-parent","receiver_thread_ids":[],"prompt":"draft a plan","agents_states":{},"status":"in_progress"}}
{"type":"item.completed","item":{"id":"collab-paired","type":"collab_tool_call","tool":"spawn_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":"draft a plan","agents_states":{"thread-child":{"status":"running","message":null}},"status":"completed"}}
{"type":"item.completed","item":{"id":"message-collab-paired","type":"agent_message","text":"collab paired"}}
{"type":"turn.completed","usage":{"input_tokens":5,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
@@ -1,5 +0,0 @@
{"type":"thread.started","thread_id":"thread-collab-terminal"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"collab-terminal","type":"collab_tool_call","tool":"wait","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"completed","message":"done"}},"status":"completed"}}
{"type":"item.completed","item":{"id":"message-collab-terminal","type":"agent_message","text":"collab terminal"}}
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
@@ -1,6 +0,0 @@
{"type":"thread.started","thread_id":"thread-declined"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"command-declined","type":"command_execution","command":"rm protected.txt","aggregated_output":"","status":"in_progress"}}
{"type":"item.completed","item":{"id":"command-declined","type":"command_execution","command":"rm protected.txt","aggregated_output":"","status":"declined"}}
{"type":"item.completed","item":{"id":"message-declined","type":"agent_message","text":"command declined"}}
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
-5
View File
@@ -1,5 +0,0 @@
{"type":"thread.started","thread_id":"thread-failed"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"mcp-failed","type":"mcp_tool_call","server":"docs","tool":"read","arguments":{"path":"missing"},"error":{"message":"not found"},"status":"failed"}}
{"type":"item.completed","item":{"id":"message-failed","type":"agent_message","text":"handled failure"}}
{"type":"turn.completed","usage":{"input_tokens":6,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
-6
View File
@@ -1,6 +0,0 @@
{"type":"thread.started","thread_id":"thread-paired"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"mcp-paired","type":"mcp_tool_call","server":"github","tool":"search","arguments":{"query":"openclaw"},"status":"in_progress"}}
{"type":"item.completed","item":{"id":"mcp-paired","type":"mcp_tool_call","server":"github","tool":"search","arguments":{"query":"openclaw"},"result":{"content":[],"structured_content":{}},"status":"completed"}}
{"type":"item.completed","item":{"id":"message-paired","type":"agent_message","text":"paired mcp"}}
{"type":"turn.completed","usage":{"input_tokens":5,"cached_input_tokens":1,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
@@ -1,8 +0,0 @@
{"type":"thread.started","thread_id":"thread-terminal-only"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"mcp-terminal","type":"mcp_tool_call","server":"","tool":"lookup","arguments":{"id":"42"},"result":{"content":[],"structured_content":{}},"status":"completed"}}
{"type":"item.completed","item":{"id":"command-terminal","type":"command_execution","command":"pwd","aggregated_output":"/workspace\n","exit_code":0,"status":"completed"}}
{"type":"item.completed","item":{"id":"patch-terminal","type":"file_change","changes":[{"path":"README.md","kind":"update"}],"status":"completed"}}
{"type":"item.completed","item":{"id":"search-terminal","type":"web_search","query":"OpenClaw"}}
{"type":"item.completed","item":{"id":"message-terminal","type":"agent_message","text":"terminal only"}}
{"type":"turn.completed","usage":{"input_tokens":8,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":4,"reasoning_output_tokens":1}}
-4
View File
@@ -1,4 +0,0 @@
{"type":"thread.started","thread_id":"thread-zero"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"message-zero","type":"agent_message","text":"zero tools"}}
{"type":"turn.completed","usage":{"input_tokens":3,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}