Job-Scorer / lib /agent-debug-trace.ts
zimejin's picture
Add agent observability (Redis run logs, lab debugger) and copy session export
888d34f
Raw
History Blame Contribute Delete
2.73 kB
import type { AgentRunLog } from "@/lib/agent-run-log-types";
/** Markdown export for pasting into an LLM β€” safe for client bundles (no Redis). */
export function buildDebugTrace(run: AgentRunLog): string {
const lines: string[] = [];
const ts = new Date(run.startedAt).toISOString();
lines.push("# Job Scorer Agent Debug Trace");
lines.push(`Run ID: \`${run.runId}\``);
lines.push(`User: \`${run.userId}\``);
if (run.sessionId) lines.push(`Session: \`${run.sessionId}\``);
lines.push(`Started: ${ts}`);
lines.push(`Duration: ${(run.durationMs / 1000).toFixed(1)}s`);
lines.push(`Stopped because: **${run.stoppedBecause}**`);
lines.push(`Credit cost: ${run.creditCost}`);
lines.push(`Result: ${run.finalResultSummary ?? "none"}`);
if (run.errorMessage) lines.push(`Run error: ${run.errorMessage}`);
lines.push("");
lines.push("## Completion Steps (LLM decisions)");
for (const step of run.completionSteps) {
lines.push(`### Step ${step.stepIndex + 1} β€” ${step.model || "?"} (${step.provider})`);
lines.push(`Duration: ${step.durationMs}ms`);
if (step.assistantReasoningText) {
lines.push("**Model reasoning before tool call:**");
lines.push(`> ${step.assistantReasoningText.replace(/\n/g, "\n> ")}`);
}
if (step.toolCalls?.length) {
lines.push("**Tool calls chosen:**");
for (const tc of step.toolCalls) {
lines.push(`- \`${tc.name}\`: \`${JSON.stringify(tc.input).slice(0, 200)}\``);
}
} else if (!step.errorMessage) {
lines.push("*No tool call β€” final response turn*");
}
if (step.errorMessage) {
lines.push(`**Error:** ${step.errorMessage}`);
}
if (step.messages?.length) {
lines.push(`<details><summary>Full message array (${step.messages.length} messages)</summary>`);
lines.push("");
lines.push("```json");
lines.push(JSON.stringify(step.messages, null, 2).slice(0, 8000));
lines.push("```");
lines.push("</details>");
}
lines.push("");
}
lines.push("## Tool Timeline");
for (const t of run.tools) {
const status = t.status === "ok" ? "βœ“" : t.status === "error" ? "βœ—" : "⚠";
lines.push(`${status} **${t.tool}** β€” ${t.durationMs}ms β€” ${t.provider ?? "unknown provider"}`);
if (t.resultSummary) lines.push(` Result: ${t.resultSummary}`);
if (t.creditCost !== undefined && t.creditCost > 0) lines.push(` Credits: ${t.creditCost}`);
if (t.input && Object.keys(t.input).length > 0) {
lines.push(` Input: \`${JSON.stringify(t.input).slice(0, 300)}\``);
}
}
lines.push("");
lines.push("---");
lines.push("*Job Scorer debug trace β€” paste into Claude for diagnosis*");
return lines.join("\n");
}