in codex-cli/src/components/history-overlay.tsx [101:168]
function formatHistoryForDisplay(items: Array<ResponseItem>): {
commands: Array<string>;
files: Array<string>;
} {
const commands: Array<string> = [];
const filesSet = new Set<string>();
for (const item of items) {
const userPrompt = processUserMessage(item);
if (userPrompt) {
commands.push(userPrompt);
continue;
}
// ------------------------------------------------------------------
// We are interested in tool calls which – for the OpenAI client – are
// represented as `function_call` response items. Skip everything else.
if (item.type !== "function_call") {
continue;
}
const { name: toolName, arguments: argsString } = item as unknown as {
name: unknown;
arguments: unknown;
};
if (typeof argsString !== "string") {
// Malformed – still record the tool name to give users maximal context.
if (typeof toolName === "string" && toolName.length > 0) {
commands.push(toolName);
}
continue;
}
// Best‑effort attempt to parse the JSON arguments. We never throw on parse
// failure – the history view must be resilient to bad data.
let argsJson: unknown = undefined;
try {
argsJson = JSON.parse(argsString);
} catch {
argsJson = undefined;
}
// 1) Shell / exec‑like tool calls expose a `cmd` or `command` property
// that is an array of strings. These are rendered as the joined command
// line for familiarity with traditional shells.
const argsObj = argsJson as Record<string, unknown> | undefined;
const cmdArray: Array<string> | undefined = Array.isArray(argsObj?.["cmd"])
? (argsObj!["cmd"] as Array<string>)
: Array.isArray(argsObj?.["command"])
? (argsObj!["command"] as Array<string>)
: undefined;
if (cmdArray && cmdArray.length > 0) {
commands.push(processCommandArray(cmdArray, filesSet));
continue; // We processed this as a command; no need to treat as generic tool call.
}
// 2) Non‑exec tool calls – we fall back to recording the tool name plus a
// short argument representation to give users an idea of what
// happened.
if (typeof toolName === "string" && toolName.length > 0) {
commands.push(processNonExecTool(toolName, argsJson, filesSet));
}
}
return { commands, files: Array.from(filesSet) };
}