fix: expose mcp tool calls in trace events

This commit is contained in:
lyon
2026-06-15 23:49:00 +08:00
parent 990165c097
commit b94b9b2027
4 changed files with 81 additions and 7 deletions
+46 -4
View File
@@ -849,7 +849,7 @@ function isSuppressedCodexStatusNotification(method: string): boolean {
}
function isVisibleCodexToolItemType(itemType: string): boolean {
return itemType === "commandExecution" || itemType === "webSearch";
return itemType === "commandExecution" || itemType === "webSearch" || itemType === "mcpToolCall" || itemType === "dynamicToolCall";
}
function assistantMessageEventForCompleted(message: CompletedAssistantMessage, messageIndex: number): BackendEvent {
@@ -944,9 +944,10 @@ function toolCallPayload(method: string, item: JsonRecord): JsonRecord {
const redacted = redactJson(item);
const itemId = typeof redacted.id === "string" ? redacted.id : null;
const itemType = typeof redacted.type === "string" ? redacted.type : "unknown";
const command = typeof redacted.command === "string" ? redacted.command : null;
const toolName = toolCallName(redacted, itemType);
const command = toolCallCommandSummary(redacted, itemType, toolName);
const cwd = typeof redacted.cwd === "string" ? redacted.cwd : null;
const status = typeof redacted.status === "string" ? redacted.status : null;
const status = toolCallStatus(method, redacted);
const processId = typeof redacted.processId === "string" || typeof redacted.processId === "number" ? String(redacted.processId) : null;
const exitCode = typeof redacted.exitCode === "number" ? redacted.exitCode : null;
const durationMs = typeof redacted.durationMs === "number" ? redacted.durationMs : null;
@@ -955,7 +956,7 @@ function toolCallPayload(method: string, item: JsonRecord): JsonRecord {
method,
itemId,
type: itemType,
toolName: itemType,
toolName,
...(command ? { command } : {}),
...(cwd ? { cwd } : {}),
...(status ? { status } : {}),
@@ -967,6 +968,47 @@ function toolCallPayload(method: string, item: JsonRecord): JsonRecord {
};
}
function toolCallStatus(method: string, item: JsonRecord): string | null {
if (typeof item.status === "string" && item.status.trim().length > 0) return item.status;
if (method === "item/started") return "started";
if (method === "item/completed") return "completed";
return null;
}
function toolCallName(item: JsonRecord, itemType: string): string {
const direct = firstToolCallString(item, ["toolName", "name", "tool", "functionName"]);
const server = firstToolCallString(item, ["serverName", "server", "mcpServer"]);
if (server && direct && !direct.includes(server)) return `${server}.${direct}`;
return direct ?? itemType;
}
function toolCallCommandSummary(item: JsonRecord, itemType: string, toolName: string): string | null {
const direct = typeof item.command === "string" && item.command.trim().length > 0 ? item.command : null;
if (direct) return direct;
if (itemType !== "mcpToolCall" && itemType !== "dynamicToolCall") return null;
const input = toolCallInputSummary(item);
return input ? `${toolName} ${input}` : toolName;
}
function toolCallInputSummary(item: JsonRecord): string | null {
for (const key of ["arguments", "args", "input", "params", "parameters"] as const) {
if (!Object.prototype.hasOwnProperty.call(item, key)) continue;
const value = item[key];
if (value === null || value === undefined) continue;
const text = typeof value === "string" ? value : JSON.stringify(value);
if (typeof text === "string" && text.trim().length > 0 && text.trim() !== "{}") return String(boundedTextSummary(text, { limitChars: 600 }).text);
}
return null;
}
function firstToolCallString(item: JsonRecord, keys: readonly string[]): string | null {
for (const key of keys) {
const value = item[key];
if (typeof value === "string" && value.trim().length > 0) return value;
}
return null;
}
function toolCallOutputSummary(item: JsonRecord): string | null {
const direct = item.outputSummary ?? item.stdoutSummary ?? item.message;
if (typeof direct === "string" && direct.trim().length > 0) return String(boundedTextSummary(direct).text);