Improve codex activity log tool-call summaries
This commit is contained in:
@@ -73,6 +73,29 @@ describe("curateAgentActivity", () => {
|
|||||||
expect(result).toContain("[Shell] npm test");
|
expect(result).toContain("[Shell] npm test");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders terminal tool calls as one-line command summaries", () => {
|
||||||
|
const timeline: AgentTimelineItem[] = [
|
||||||
|
toolCallItem({
|
||||||
|
callId: "terminal-1",
|
||||||
|
name: "terminal",
|
||||||
|
detail: {
|
||||||
|
type: "plain_text",
|
||||||
|
label: `skills/paseo-chat/bin/chat.sh post --room storage-revamp --body $'first line
|
||||||
|
|
||||||
|
second line'`,
|
||||||
|
icon: "square_terminal",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = curateAgentActivity(timeline);
|
||||||
|
|
||||||
|
expect(result).toContain(
|
||||||
|
"[Terminal] skills/paseo-chat/bin/chat.sh post --room storage-revamp --body $'first line second line'",
|
||||||
|
);
|
||||||
|
expect(result).not.toContain("[Interacted with terminal]");
|
||||||
|
});
|
||||||
|
|
||||||
it("does not infer summary from raw input when detail is missing", () => {
|
it("does not infer summary from raw input when detail is missing", () => {
|
||||||
const timeline: AgentTimelineItem[] = [
|
const timeline: AgentTimelineItem[] = [
|
||||||
toolCallItem({
|
toolCallItem({
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { buildToolCallDisplayModel } from "../../shared/tool-call-display.js";
|
|||||||
|
|
||||||
const DEFAULT_MAX_ITEMS = 40;
|
const DEFAULT_MAX_ITEMS = 40;
|
||||||
const MAX_TOOL_INPUT_CHARS = 400;
|
const MAX_TOOL_INPUT_CHARS = 400;
|
||||||
|
const MAX_TOOL_SUMMARY_CHARS = 200;
|
||||||
|
|
||||||
function appendText(buffer: string, text: string): string {
|
function appendText(buffer: string, text: string): string {
|
||||||
const normalized = text.trim();
|
const normalized = text.trim();
|
||||||
@@ -45,6 +46,20 @@ function formatToolInputJson(input: unknown): string | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatToolSummary(summary: string | undefined): string | null {
|
||||||
|
if (typeof summary !== "string") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const normalized = summary.replace(/\s+/g, " ").trim();
|
||||||
|
if (!normalized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (normalized.length <= MAX_TOOL_SUMMARY_CHARS) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return `${normalized.slice(0, MAX_TOOL_SUMMARY_CHARS - 3)}...`;
|
||||||
|
}
|
||||||
|
|
||||||
function hasNonEmptyObject(value: unknown): boolean {
|
function hasNonEmptyObject(value: unknown): boolean {
|
||||||
return (
|
return (
|
||||||
typeof value === "object" &&
|
typeof value === "object" &&
|
||||||
@@ -215,7 +230,7 @@ export function curateAgentActivity(
|
|||||||
metadata: item.metadata,
|
metadata: item.metadata,
|
||||||
});
|
});
|
||||||
const displayName = display.displayName;
|
const displayName = display.displayName;
|
||||||
const summary = display.summary;
|
const summary = formatToolSummary(display.summary);
|
||||||
if (isLikelyExternalToolName(item.name) && inputJson) {
|
if (isLikelyExternalToolName(item.name) && inputJson) {
|
||||||
lines.push(`[${displayName}] ${inputJson}`);
|
lines.push(`[${displayName}] ${inputJson}`);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2039,6 +2039,7 @@ class CodexAppServerAgentSession implements AgentSession {
|
|||||||
private pendingCommandOutputDeltas = new Map<string, string[]>();
|
private pendingCommandOutputDeltas = new Map<string, string[]>();
|
||||||
private pendingFileChangeOutputDeltas = new Map<string, string[]>();
|
private pendingFileChangeOutputDeltas = new Map<string, string[]>();
|
||||||
private terminalCommandByProcessId = new Map<string, string>();
|
private terminalCommandByProcessId = new Map<string, string>();
|
||||||
|
private pendingUnlabeledTerminalInteractions = new Set<string>();
|
||||||
private emittedTerminalInteractionKeys = new Set<string>();
|
private emittedTerminalInteractionKeys = new Set<string>();
|
||||||
private emittedExecCommandStartedCallIds = new Set<string>();
|
private emittedExecCommandStartedCallIds = new Set<string>();
|
||||||
private emittedExecCommandCompletedCallIds = new Set<string>();
|
private emittedExecCommandCompletedCallIds = new Set<string>();
|
||||||
@@ -3000,12 +3001,16 @@ class CodexAppServerAgentSession implements AgentSession {
|
|||||||
if (!this.shouldEmitTerminalInteractionKey(interactionKey)) {
|
if (!this.shouldEmitTerminalInteractionKey(interactionKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const command =
|
||||||
|
(parsed.processId ? this.terminalCommandByProcessId.get(parsed.processId) : undefined) ??
|
||||||
|
null;
|
||||||
|
if (!command && parsed.processId) {
|
||||||
|
this.pendingUnlabeledTerminalInteractions.add(parsed.processId);
|
||||||
|
}
|
||||||
const timelineItem = mapCodexTerminalInteractionToToolCall({
|
const timelineItem = mapCodexTerminalInteractionToToolCall({
|
||||||
processId: parsed.processId,
|
processId: parsed.processId,
|
||||||
fallbackCallId: parsed.callId,
|
fallbackCallId: parsed.callId,
|
||||||
command:
|
command,
|
||||||
(parsed.processId ? this.terminalCommandByProcessId.get(parsed.processId) : undefined) ??
|
|
||||||
null,
|
|
||||||
});
|
});
|
||||||
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
||||||
return;
|
return;
|
||||||
@@ -3217,6 +3222,18 @@ class CodexAppServerAgentSession implements AgentSession {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.terminalCommandByProcessId.set(processId, displayCommand);
|
this.terminalCommandByProcessId.set(processId, displayCommand);
|
||||||
|
if (!this.pendingUnlabeledTerminalInteractions.has(processId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.pendingUnlabeledTerminalInteractions.delete(processId);
|
||||||
|
this.emitEvent({
|
||||||
|
type: "timeline",
|
||||||
|
provider: CODEX_PROVIDER,
|
||||||
|
item: mapCodexTerminalInteractionToToolCall({
|
||||||
|
processId,
|
||||||
|
command: displayCommand,
|
||||||
|
}),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private shouldEmitTerminalInteractionKey(key: string): boolean {
|
private shouldEmitTerminalInteractionKey(key: string): boolean {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ describe("shared tool-call display mapping", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(display).toEqual({
|
expect(display).toEqual({
|
||||||
displayName: "Interacted with terminal",
|
displayName: "Terminal",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ describe("shared tool-call display mapping", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(display).toEqual({
|
expect(display).toEqual({
|
||||||
displayName: "Interacted with terminal",
|
displayName: "Terminal",
|
||||||
summary: "npm run test",
|
summary: "npm run test",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ function buildUnknownDetailOverride(input: ToolCallDisplayInput): DetailDisplay
|
|||||||
}
|
}
|
||||||
if (lowerName === "terminal") {
|
if (lowerName === "terminal") {
|
||||||
return {
|
return {
|
||||||
displayName: "Interacted with terminal",
|
displayName: "Terminal",
|
||||||
summary: input.detail.type === "plain_text" ? readString(input.detail.label) : undefined,
|
summary: input.detail.type === "plain_text" ? readString(input.detail.label) : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user