Files
OmniRoute/open-sse/executors/codex/toolCallRepair.ts
Jan Leon 32f8340719 Fix custom tool output pairing during context compression (#8933)
* Fix custom tool output pairing during compression (#8932)

* Bypass proxy compaction for native Codex context

* fix(sse): extract Codex tool-call output repair to leaf module for file-size gate

repairMissingCodexToolCallOutputs (added by #8932 for custom_tool_call
pairing) pushed codex.ts past the frozen file-size baseline. Extract it
to open-sse/executors/codex/toolCallRepair.ts, leaving only the wiring
call in codex.ts. Rebaseline the test file's genuine +41 line growth
from #8932's new custom_tool_call_output coverage.

Co-authored-by: JxnLexn <JxnLexn@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: JxnLexn <JxnLexn@users.noreply.github.com>
2026-08-11 04:25:55 -03:00

58 lines
2.2 KiB
TypeScript

// Repairs Codex Responses-API `input` arrays that are missing an output item for a
// function/custom tool call, which upstream rejects. Extracted from codex.ts to keep
// the executor chokepoint file under the file-size gate (leaf module, no `this` usage).
type ResponsesInputItem = Record<string, unknown>;
const TOOL_CALL_OUTPUT_TYPES = new Set(["function_call_output", "custom_tool_call_output"]);
function outputTypeForCall(callType: "function_call" | "custom_tool_call"): string {
return callType === "custom_tool_call" ? "custom_tool_call_output" : "function_call_output";
}
/**
* Mutates `body.input` in place, inserting an empty output item immediately after
* any `function_call`/`custom_tool_call` item that has no matching output item.
*/
export function repairMissingCodexToolCallOutputs(body: Record<string, unknown>): void {
if (!Array.isArray(body.input)) return;
const existingOutputKeys = new Set<string>();
for (const item of body.input) {
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
const record = item as ResponsesInputItem;
if (typeof record.type !== "string" || !TOOL_CALL_OUTPUT_TYPES.has(record.type)) continue;
if (typeof record.call_id === "string" && record.call_id.trim()) {
existingOutputKeys.add(`${record.type}:${record.call_id.trim()}`);
}
}
const repaired: unknown[] = [];
let insertedCount = 0;
for (const item of body.input) {
repaired.push(item);
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
const record = item as ResponsesInputItem;
if (record.type !== "function_call" && record.type !== "custom_tool_call") continue;
const callId = typeof record.call_id === "string" ? record.call_id.trim() : "";
const outputType = outputTypeForCall(record.type);
const outputKey = `${outputType}:${callId}`;
if (!callId || existingOutputKeys.has(outputKey)) continue;
repaired.push({
type: outputType,
call_id: callId,
output: "",
});
existingOutputKeys.add(outputKey);
insertedCount++;
}
if (insertedCount > 0) {
body.input = repaired;
console.debug(
`[Codex] repairMissingCodexToolCallOutputs: inserted ${insertedCount} empty tool output item(s)`
);
}
}