fix: persist expired code agent trace summaries (#851)
Co-authored-by: Codex Agent <codex@hwlab.local>
This commit is contained in:
@@ -473,6 +473,8 @@ export async function loadPersistedAgentRunResult(traceId, options = {}) {
|
||||
capabilityLevel: CODEX_STDIO_CAPABILITY_LEVEL,
|
||||
sessionMode: CODEX_STDIO_SESSION_MODE,
|
||||
implementationType: CODEX_STDIO_IMPLEMENTATION_TYPE,
|
||||
finalResponse: session.session?.finalResponse ?? null,
|
||||
traceSummary: session.session?.traceSummary ?? null,
|
||||
agentRun: { ...agentRun, adapter: ADAPTER_ID, valuesPrinted: false },
|
||||
valuesPrinted: false
|
||||
};
|
||||
|
||||
@@ -1463,6 +1463,94 @@ test("cloud api /v1/agent/chat/inspect returns not_found for empty conversation
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud api trace returns persisted summary when live trace store has expired", async () => {
|
||||
const ownerSessions = new Map();
|
||||
ownerSessions.set("ses_issue842_expired", testAgentSessionRecord({
|
||||
sessionId: "ses_issue842_expired",
|
||||
projectId: "prj_v02_code_agent",
|
||||
conversationId: "cnv_issue842_expired",
|
||||
threadId: "thread-issue-842-expired",
|
||||
traceId: "trc_issue842_expired",
|
||||
status: "active",
|
||||
session: {
|
||||
finalResponse: {
|
||||
text: "历史 trace 已过期,但 final response 仍可审计。",
|
||||
textChars: 31,
|
||||
role: "assistant",
|
||||
status: "completed",
|
||||
traceId: "trc_issue842_expired",
|
||||
source: "code-agent-result",
|
||||
valuesPrinted: false
|
||||
},
|
||||
traceSummary: {
|
||||
traceId: "trc_issue842_expired",
|
||||
source: "agent-session-snapshot",
|
||||
sourceEventCount: 26,
|
||||
terminalStatus: "completed",
|
||||
noiseEventCount: 4,
|
||||
omittedNoiseCount: 4,
|
||||
valuesPrinted: false
|
||||
},
|
||||
agentRun: {
|
||||
adapter: "agentrun-v01",
|
||||
runId: "run_issue842_expired",
|
||||
commandId: "cmd_issue842_expired",
|
||||
runnerId: "runner_issue842_expired",
|
||||
jobName: "agentrun-v01-runner-issue842-expired",
|
||||
namespace: "agentrun-v01",
|
||||
terminalStatus: "completed",
|
||||
valuesPrinted: false
|
||||
},
|
||||
valuesRedacted: true
|
||||
}
|
||||
}));
|
||||
const traceStore = createCodeAgentTraceStore();
|
||||
const server = createCloudApiServer({
|
||||
traceStore,
|
||||
env: {
|
||||
HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
|
||||
AGENTRUN_MGR_URL: "http://127.0.0.1:9",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
|
||||
HWLAB_ENVIRONMENT: "v02",
|
||||
HWLAB_GITOPS_PROFILE: "v02"
|
||||
},
|
||||
accessController: {
|
||||
required: false,
|
||||
async authenticate() {
|
||||
return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
|
||||
},
|
||||
async getAgentSessionByTraceId(traceId) {
|
||||
return [...ownerSessions.values()].find((session) => session.lastTraceId === traceId) ?? null;
|
||||
}
|
||||
}
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
|
||||
try {
|
||||
const { port } = server.address();
|
||||
const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat/trace/trc_issue842_expired`, {
|
||||
headers: { cookie: "hwlab_session=test-stub-session" }
|
||||
});
|
||||
assert.equal(response.status, 200);
|
||||
const body = await response.json();
|
||||
assert.equal(body.ok, true);
|
||||
assert.equal(body.status, "expired");
|
||||
assert.equal(body.traceStatus, "expired");
|
||||
assert.equal(body.eventCount, 0);
|
||||
assert.equal(body.fallback.available, true);
|
||||
assert.equal(body.finalResponse.text, "历史 trace 已过期,但 final response 仍可审计。");
|
||||
assert.equal(body.traceSummary.sourceEventCount, 26);
|
||||
assert.equal(body.agentRun.runId, "run_issue842_expired");
|
||||
assert.equal(body.agentRun.commandId, "cmd_issue842_expired");
|
||||
assert.equal(body.retention.liveTraceStore, "expired-or-evicted");
|
||||
assert.equal(JSON.stringify(body).includes("password"), false);
|
||||
} finally {
|
||||
await new Promise((resolve, reject) => {
|
||||
server.close((error) => (error ? reject(error) : resolve()));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud api result polling compacts large runnerTrace while preserving providerTrace", async () => {
|
||||
const workspace = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-result-compact-"));
|
||||
const codexHome = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-result-compact-codex-home-"));
|
||||
|
||||
@@ -1526,6 +1526,9 @@ function textValue(value) {
|
||||
}
|
||||
|
||||
function codeAgentSessionOwnerEvidence(payload = {}, params = {}) {
|
||||
const traceId = payload.traceId ?? params.traceId ?? null;
|
||||
const finalResponse = codeAgentFinalResponseEvidence(payload, traceId);
|
||||
const traceSummary = codeAgentTraceSummaryEvidence(payload, traceId, finalResponse);
|
||||
return {
|
||||
provider: payload.provider ?? null,
|
||||
model: payload.model ?? null,
|
||||
@@ -1537,14 +1540,66 @@ function codeAgentSessionOwnerEvidence(payload = {}, params = {}) {
|
||||
conversationId: payload.conversationId ?? params.conversationId ?? null,
|
||||
sessionId: payload.sessionId ?? payload.session?.sessionId ?? payload.sessionReuse?.sessionId ?? params.sessionId ?? null,
|
||||
threadId: payload.session?.threadId ?? payload.sessionReuse?.threadId ?? payload.threadId ?? params.threadId ?? null,
|
||||
traceId: payload.traceId ?? params.traceId ?? null,
|
||||
traceId,
|
||||
projectId: payload.projectId ?? params.projectId ?? null,
|
||||
finalResponse,
|
||||
traceSummary,
|
||||
...agentRunSessionEvidence(payload),
|
||||
secretMaterialStored: false,
|
||||
valuesRedacted: true
|
||||
};
|
||||
}
|
||||
|
||||
function codeAgentFinalResponseEvidence(payload = {}, traceId = null) {
|
||||
const text = textValue(payload.reply?.content ?? payload.message?.content ?? payload.assistantText);
|
||||
if (!text) return null;
|
||||
return {
|
||||
text,
|
||||
textChars: text.length,
|
||||
messageId: payload.reply?.messageId ?? payload.messageId ?? null,
|
||||
role: payload.reply?.role ?? payload.message?.role ?? "assistant",
|
||||
status: payload.status ?? null,
|
||||
traceId,
|
||||
createdAt: payload.reply?.createdAt ?? payload.createdAt ?? null,
|
||||
updatedAt: payload.updatedAt ?? null,
|
||||
source: "code-agent-result",
|
||||
valuesPrinted: false
|
||||
};
|
||||
}
|
||||
|
||||
function codeAgentTraceSummaryEvidence(payload = {}, traceId = null, finalResponse = null) {
|
||||
const runnerTrace = payload.runnerTrace && typeof payload.runnerTrace === "object" ? payload.runnerTrace : null;
|
||||
const events = Array.isArray(runnerTrace?.events) ? runnerTrace.events : [];
|
||||
const terminalEvent = [...events].reverse().find((event) => event?.terminal === true) ?? runnerTrace?.lastEvent ?? null;
|
||||
return {
|
||||
traceId,
|
||||
source: "agent-session-snapshot",
|
||||
sourceEventCount: Number.isFinite(Number(runnerTrace?.eventCount)) ? Number(runnerTrace.eventCount) : events.length,
|
||||
terminalStatus: payload.agentRun?.terminalStatus ?? payload.status ?? terminalEvent?.status ?? null,
|
||||
lastEventLabel: terminalEvent?.label ?? null,
|
||||
finalAssistantRow: finalResponse ? {
|
||||
role: finalResponse.role,
|
||||
status: finalResponse.status,
|
||||
textChars: finalResponse.textChars,
|
||||
textPreview: finalResponse.text.slice(0, 240),
|
||||
messageId: finalResponse.messageId,
|
||||
valuesPrinted: false
|
||||
} : null,
|
||||
agentRun: payload.agentRun ? {
|
||||
runId: payload.agentRun.runId ?? null,
|
||||
commandId: payload.agentRun.commandId ?? null,
|
||||
attemptId: payload.agentRun.attemptId ?? null,
|
||||
runnerId: payload.agentRun.runnerId ?? null,
|
||||
jobName: payload.agentRun.jobName ?? null,
|
||||
namespace: payload.agentRun.namespace ?? null,
|
||||
lastSeq: payload.agentRun.lastSeq ?? null,
|
||||
valuesPrinted: false
|
||||
} : null,
|
||||
updatedAt: payload.updatedAt ?? null,
|
||||
valuesPrinted: false
|
||||
};
|
||||
}
|
||||
|
||||
function annotateOwner(payload, params = {}) {
|
||||
if (!params.ownerUserId) return payload;
|
||||
return {
|
||||
@@ -1648,8 +1703,22 @@ export async function handleCodeAgentTraceHttp(request, response, url, options)
|
||||
}
|
||||
|
||||
const agentRunResult = result?.agentRun ? result : await loadPersistedAgentRunResult(traceId, options);
|
||||
let refreshError = null;
|
||||
if (agentRunResult && !canAccessOwnedResult(agentRunResult, options.actor)) {
|
||||
sendJson(response, 403, {
|
||||
error: {
|
||||
code: "agent_session_owner_required",
|
||||
message: "Only the session owner or admin can read this Code Agent trace"
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (agentRunResult?.agentRun) {
|
||||
await refreshAgentRunTrace({ traceId, result: agentRunResult, options, traceStore });
|
||||
try {
|
||||
await refreshAgentRunTrace({ traceId, result: agentRunResult, options, traceStore });
|
||||
} catch (error) {
|
||||
refreshError = error;
|
||||
}
|
||||
}
|
||||
|
||||
if (parts[5] === "stream") {
|
||||
@@ -1657,7 +1726,124 @@ export async function handleCodeAgentTraceHttp(request, response, url, options)
|
||||
return;
|
||||
}
|
||||
|
||||
sendJson(response, 200, traceStore.snapshot(traceId));
|
||||
const snapshot = traceStore.snapshot(traceId);
|
||||
sendJson(response, 200, traceSnapshotWithPersistentFallback(snapshot, agentRunResult, traceId, refreshError));
|
||||
}
|
||||
|
||||
function traceSnapshotWithPersistentFallback(snapshot, persistedResult, traceId, refreshError = null) {
|
||||
if (snapshot?.status !== "missing") return snapshot;
|
||||
const fallback = persistentTraceFallback(persistedResult, traceId);
|
||||
if (!fallback) return {
|
||||
...snapshot,
|
||||
ok: false,
|
||||
traceStatus: "missing",
|
||||
retention: traceRetentionSummary("missing"),
|
||||
fallback: { available: false, source: null }
|
||||
};
|
||||
return {
|
||||
...snapshot,
|
||||
ok: true,
|
||||
status: "expired",
|
||||
traceStatus: "expired",
|
||||
persisted: true,
|
||||
retention: traceRetentionSummary("expired"),
|
||||
conversationId: fallback.conversationId,
|
||||
sessionId: fallback.sessionId,
|
||||
threadId: fallback.threadId,
|
||||
agentRun: fallback.agentRun,
|
||||
finalResponse: fallback.finalResponse,
|
||||
traceSummary: fallback.traceSummary,
|
||||
fallback: {
|
||||
available: true,
|
||||
source: fallback.source,
|
||||
refresh: refreshError ? {
|
||||
attempted: true,
|
||||
ok: false,
|
||||
code: refreshError?.code ?? "agentrun_trace_refresh_failed",
|
||||
message: refreshError?.message ?? "AgentRun trace refresh failed; using persisted session summary.",
|
||||
valuesPrinted: false
|
||||
} : { attempted: false, ok: null },
|
||||
conversationId: fallback.conversationId,
|
||||
sessionId: fallback.sessionId,
|
||||
threadId: fallback.threadId,
|
||||
agentRun: fallback.agentRun,
|
||||
traceSummary: fallback.traceSummary,
|
||||
finalResponse: fallback.finalResponse,
|
||||
valuesPrinted: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function persistentTraceFallback(result, traceId) {
|
||||
if (!result || typeof result !== "object") return null;
|
||||
const storedSummary = result.traceSummary && typeof result.traceSummary === "object" ? result.traceSummary : null;
|
||||
const finalResponse = persistentFinalResponse(result);
|
||||
const agentRun = result.agentRun && typeof result.agentRun === "object" ? {
|
||||
adapter: result.agentRun.adapter ?? null,
|
||||
runId: result.agentRun.runId ?? null,
|
||||
commandId: result.agentRun.commandId ?? null,
|
||||
attemptId: result.agentRun.attemptId ?? null,
|
||||
runnerId: result.agentRun.runnerId ?? null,
|
||||
jobName: result.agentRun.jobName ?? null,
|
||||
namespace: result.agentRun.namespace ?? null,
|
||||
terminalStatus: result.agentRun.terminalStatus ?? null,
|
||||
lastSeq: result.agentRun.lastSeq ?? null,
|
||||
valuesPrinted: false
|
||||
} : null;
|
||||
if (!storedSummary && !finalResponse && !agentRun) return null;
|
||||
const traceSummary = {
|
||||
traceId,
|
||||
source: storedSummary?.source ?? (finalResponse ? "agent-session-final-response" : "agent-session-agentrun"),
|
||||
sourceEventCount: numberOrNull(storedSummary?.sourceEventCount ?? storedSummary?.eventCount ?? result.runnerTrace?.eventCount),
|
||||
renderedRowSummary: storedSummary?.renderedRowSummary ?? null,
|
||||
noiseEventCount: numberOrNull(storedSummary?.noiseEventCount),
|
||||
omittedNoiseCount: numberOrNull(storedSummary?.omittedNoiseCount),
|
||||
terminalStatus: storedSummary?.terminalStatus ?? result.agentRun?.terminalStatus ?? result.status ?? null,
|
||||
updatedAt: storedSummary?.updatedAt ?? result.updatedAt ?? null,
|
||||
valuesPrinted: false
|
||||
};
|
||||
return {
|
||||
source: storedSummary?.source ?? (finalResponse ? "agent-session-final-response" : "agent-session-agentrun"),
|
||||
conversationId: safeConversationId(result.conversationId) || null,
|
||||
sessionId: safeSessionId(result.sessionId) || null,
|
||||
threadId: safeOpaqueId(result.threadId) || null,
|
||||
agentRun,
|
||||
finalResponse,
|
||||
traceSummary
|
||||
};
|
||||
}
|
||||
|
||||
function persistentFinalResponse(result) {
|
||||
const stored = result.finalResponse && typeof result.finalResponse === "object" ? result.finalResponse : null;
|
||||
const text = textValue(stored?.text ?? result.reply?.content ?? result.message?.content ?? result.assistantText);
|
||||
if (!text) return null;
|
||||
return {
|
||||
text,
|
||||
textChars: text.length,
|
||||
messageId: stored?.messageId ?? result.reply?.messageId ?? result.messageId ?? null,
|
||||
role: stored?.role ?? result.reply?.role ?? "assistant",
|
||||
status: stored?.status ?? result.status ?? null,
|
||||
traceId: safeTraceId(stored?.traceId ?? result.traceId) || null,
|
||||
createdAt: stored?.createdAt ?? result.reply?.createdAt ?? result.createdAt ?? null,
|
||||
updatedAt: stored?.updatedAt ?? result.updatedAt ?? null,
|
||||
source: stored?.source ?? "code-agent-result",
|
||||
valuesPrinted: false
|
||||
};
|
||||
}
|
||||
|
||||
function traceRetentionSummary(status) {
|
||||
return {
|
||||
traceStatus: status,
|
||||
liveTraceStore: status === "missing" ? "missing" : "expired-or-evicted",
|
||||
policy: "live trace events are best-effort short-term storage; completed turns persist final response and summary in the agent session snapshot",
|
||||
replacementEvidence: status === "missing" ? "submit a fresh equivalent trace or inspect conversation/session if available" : "use fallback.finalResponse, fallback.traceSummary, conversationId, sessionId, threadId, and agentRun ids",
|
||||
valuesPrinted: false
|
||||
};
|
||||
}
|
||||
|
||||
function numberOrNull(value) {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
function sendTraceSse(response, traceStore, traceId, options = {}) {
|
||||
|
||||
@@ -1523,6 +1523,53 @@ test("hwlab-cli client agent trace exposes missing Web render state without a bo
|
||||
assert.deepEqual(result.payload.data, result.payload.rendered);
|
||||
});
|
||||
|
||||
test("hwlab-cli client agent trace renders persisted summary for expired traces", async () => {
|
||||
const finalText = "历史 trace 已过期,但 final response 仍可审计。";
|
||||
const result = await runHwlabCli(["client", "agent", "trace", "trc_expired", "--base-url", "http://web.test", "--cookie", "hwlab_session=session-a", "--render", "web"], {
|
||||
fetchImpl: async () => new Response(JSON.stringify({
|
||||
ok: true,
|
||||
status: "expired",
|
||||
traceStatus: "expired",
|
||||
traceId: "trc_expired",
|
||||
eventCount: 0,
|
||||
events: [],
|
||||
conversationId: "cnv_expired",
|
||||
sessionId: "ses_expired",
|
||||
threadId: "thread-expired",
|
||||
retention: { traceStatus: "expired", liveTraceStore: "expired-or-evicted" },
|
||||
agentRun: { runId: "run_expired", commandId: "cmd_expired", valuesPrinted: false },
|
||||
finalResponse: { text: finalText, textChars: finalText.length, role: "assistant", status: "completed", source: "code-agent-result", valuesPrinted: false },
|
||||
traceSummary: { source: "agent-session-snapshot", sourceEventCount: 26, terminalStatus: "completed", valuesPrinted: false },
|
||||
fallback: {
|
||||
available: true,
|
||||
source: "agent-session-snapshot",
|
||||
conversationId: "cnv_expired",
|
||||
sessionId: "ses_expired",
|
||||
threadId: "thread-expired",
|
||||
agentRun: { runId: "run_expired", commandId: "cmd_expired", valuesPrinted: false },
|
||||
finalResponse: { text: finalText, textChars: finalText.length, role: "assistant", status: "completed", valuesPrinted: false },
|
||||
traceSummary: { source: "agent-session-snapshot", sourceEventCount: 26, terminalStatus: "completed", valuesPrinted: false },
|
||||
valuesPrinted: false
|
||||
}
|
||||
}), { status: 200 })
|
||||
});
|
||||
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.equal(result.payload.status, "succeeded");
|
||||
assert.equal(result.payload.traceStatus, "expired");
|
||||
assert.equal(result.payload.body.traceStatus, "expired");
|
||||
assert.equal(result.payload.body.assistantText, finalText);
|
||||
assert.equal(result.payload.rendered.traceStatus, "expired");
|
||||
assert.equal(result.payload.rendered.sourceEventCount, 0);
|
||||
assert.equal(result.payload.rendered.renderedRowCount, 1);
|
||||
assert.match(result.payload.rendered.rows[0].header, /历史 trace 已过期/u);
|
||||
assert.match(result.payload.rendered.rows[0].body, /final response 仍可审计/u);
|
||||
assert.match(result.payload.rendered.rows[0].body, /run_expired/u);
|
||||
assert.equal(result.payload.rendered.fallback.available, true);
|
||||
assert.equal(result.payload.rendered.traceSummary.sourceEventCount, 26);
|
||||
assert.deepEqual(result.payload.data, result.payload.rendered);
|
||||
});
|
||||
|
||||
test("hwlab-cli Web trace render does not treat AgentRun result-ready as final assistant text", async () => {
|
||||
const result = await runHwlabCli(["client", "agent", "trace", "trc_result_ready", "--base-url", "http://web.test", "--cookie", "hwlab_session=session-a", "--render", "web"], {
|
||||
fetchImpl: async () => new Response(JSON.stringify({
|
||||
|
||||
@@ -2674,16 +2674,19 @@ function traceBodyForCli(body: any, parsed: ParsedArgs) {
|
||||
function webTraceRenderBody(traceObject: any, parsed: ParsedArgs) {
|
||||
const events = Array.isArray(traceObject?.events) ? traceObject.events : [];
|
||||
const rows = traceDisplayRows(traceObject ?? {}, events);
|
||||
const fallbackRows = rows.length > 0 ? [] : persistentTraceFallbackRows(traceObject);
|
||||
const allRows = rows.length > 0 ? rows : fallbackRows;
|
||||
const noiseEventCount = traceNoiseEventCount(events);
|
||||
const rowLimit = Math.max(1, Math.min(numberOption(parsed.limit) ?? 80, 500));
|
||||
const rowTail = parsed.full === true ? rows : rows.slice(-rowLimit);
|
||||
const rowTail = parsed.full === true ? allRows : allRows.slice(-rowLimit);
|
||||
return pruneUndefined({
|
||||
traceId: traceObject?.traceId ?? null,
|
||||
status: traceObject?.status ?? null,
|
||||
status: traceObject?.traceStatus ?? traceObject?.status ?? null,
|
||||
traceStatus: traceObject?.traceStatus ?? traceObject?.status ?? null,
|
||||
render: "web",
|
||||
renderer: "tools/src/hwlab-cli/trace-renderer:traceDisplayRows",
|
||||
sourceEventCount: traceObject?.eventCount ?? events.length,
|
||||
renderedRowCount: rows.length,
|
||||
renderedRowCount: allRows.length,
|
||||
returnedRowCount: rowTail.length,
|
||||
noiseEventCount,
|
||||
omittedNoiseCount: noiseEventCount,
|
||||
@@ -2694,10 +2697,42 @@ function webTraceRenderBody(traceObject: any, parsed: ParsedArgs) {
|
||||
} : undefined,
|
||||
assistantText: assistantText(traceObject),
|
||||
rows: rowTail.map(compactTraceRenderRow),
|
||||
retention: traceObject?.retention,
|
||||
fallback: traceObject?.fallback,
|
||||
finalResponse: traceObject?.finalResponse,
|
||||
traceSummary: traceObject?.traceSummary,
|
||||
fullBodyAvailable: true
|
||||
});
|
||||
}
|
||||
|
||||
function persistentTraceFallbackRows(traceObject: any) {
|
||||
const fallback = traceObject?.fallback && typeof traceObject.fallback === "object" ? traceObject.fallback : null;
|
||||
const finalResponse = traceObject?.finalResponse ?? fallback?.finalResponse;
|
||||
const traceSummary = traceObject?.traceSummary ?? fallback?.traceSummary;
|
||||
const textValue = text(finalResponse?.text ?? finalResponse?.textPreview ?? traceSummary?.finalAssistantRow?.textPreview);
|
||||
if (!fallback?.available && !textValue && !traceSummary) return [];
|
||||
const body = [
|
||||
textValue ? `final assistant: ${textValue}` : "final assistant: unavailable in persisted snapshot",
|
||||
`source: ${text(traceSummary?.source ?? fallback?.source ?? "agent-session-snapshot")}`,
|
||||
`terminalStatus: ${text(traceSummary?.terminalStatus ?? finalResponse?.status ?? traceObject?.status ?? "unknown")}`,
|
||||
`sourceEventCount: ${traceSummary?.sourceEventCount ?? traceObject?.eventCount ?? 0}`,
|
||||
fallback?.conversationId ? `conversationId: ${fallback.conversationId}` : null,
|
||||
fallback?.sessionId ? `sessionId: ${fallback.sessionId}` : null,
|
||||
fallback?.threadId ? `threadId: ${fallback.threadId}` : null,
|
||||
fallback?.agentRun?.runId ? `runId: ${fallback.agentRun.runId}` : null,
|
||||
fallback?.agentRun?.commandId ? `commandId: ${fallback.agentRun.commandId}` : null
|
||||
].filter(Boolean).join("\n");
|
||||
return [{
|
||||
rowId: `${traceObject?.traceId ?? "trace"}:persisted-summary`,
|
||||
seq: null,
|
||||
tone: "info",
|
||||
header: "历史 trace 已过期,显示持久化摘要",
|
||||
bodyFormat: "text",
|
||||
terminal: true,
|
||||
body
|
||||
}];
|
||||
}
|
||||
|
||||
function traceResponseAliases(traceBody: any, parsed: ParsedArgs) {
|
||||
if (text(parsed.render) !== "web" || !traceBody || typeof traceBody !== "object") return {};
|
||||
const rendered = pruneUndefined({
|
||||
@@ -2713,7 +2748,11 @@ function traceResponseAliases(traceBody: any, parsed: ParsedArgs) {
|
||||
rowLimit: traceBody.rowLimit,
|
||||
rows: traceBody.rows,
|
||||
eventCountMismatch: traceBody.eventCountMismatch,
|
||||
assistantText: traceBody.assistantText
|
||||
assistantText: traceBody.assistantText,
|
||||
retention: traceBody.retention,
|
||||
fallback: traceBody.fallback,
|
||||
finalResponse: traceBody.finalResponse,
|
||||
traceSummary: traceBody.traceSummary
|
||||
});
|
||||
return {
|
||||
traceStatus: traceBody.status ?? null,
|
||||
@@ -2808,7 +2847,7 @@ function compactAgentRun(value: any) {
|
||||
}
|
||||
|
||||
function assistantText(body: any) {
|
||||
const direct = text(body?.reply?.content ?? body?.message?.content ?? body?.assistantText);
|
||||
const direct = text(body?.reply?.content ?? body?.message?.content ?? body?.assistantText ?? body?.finalResponse?.text ?? body?.fallback?.finalResponse?.text);
|
||||
if (direct) return direct;
|
||||
if (Array.isArray(body?.assistantStreams)) {
|
||||
for (const item of [...body.assistantStreams].reverse()) {
|
||||
@@ -2958,6 +2997,7 @@ function compactBody(body: any) {
|
||||
selectedDevicePodId: body.selectedDevicePodId,
|
||||
devicePodCount: Array.isArray(body.devicePods) ? body.devicePods.length : undefined,
|
||||
traceId: body.traceId,
|
||||
traceStatus: body.traceStatus,
|
||||
conversationId: body.conversationId,
|
||||
sessionId: body.sessionId,
|
||||
threadId: body.threadId,
|
||||
@@ -2970,6 +3010,10 @@ function compactBody(body: any) {
|
||||
error: body.error,
|
||||
blocker: body.blocker,
|
||||
summary: body.summary,
|
||||
retention: body.retention,
|
||||
fallback: body.fallback,
|
||||
finalResponse: body.finalResponse,
|
||||
traceSummary: body.traceSummary,
|
||||
freshness: body.freshness,
|
||||
profileHash: body.profileHash,
|
||||
targetId: body.targetId,
|
||||
|
||||
Reference in New Issue
Block a user