| --- |
| interface Props { |
| src: string; |
| title?: string; |
| desc?: string; |
| height?: number; |
| wide?: boolean; |
| sourceUrl?: string; |
| } |
|
|
| type TraceCard = { |
| kind: string; |
| label: string; |
| meta?: string; |
| text: string; |
| status?: string; |
| }; |
|
|
| const { |
| src, |
| title, |
| desc, |
| height = 640, |
| wide = true, |
| sourceUrl, |
| } = Astro.props as Props; |
|
|
| const traces = (import.meta as any).glob("../content/assets/traces/**/*.jsonl", { |
| query: "?raw", |
| import: "default", |
| eager: true, |
| }) as Record<string, string>; |
|
|
| function resolveTrace(requested: string): string | null { |
| const needle = requested.replace(/^\/*/, ""); |
| for (const [key, raw] of Object.entries(traces)) { |
| if (key.endsWith("/" + needle) || key.endsWith("/" + needle.replace(/^traces\//, ""))) { |
| return raw; |
| } |
| } |
| return null; |
| } |
|
|
| function escapeHtml(value: unknown): string { |
| return String(value ?? "") |
| .replace(/&/g, "&") |
| .replace(/</g, "<") |
| .replace(/>/g, ">") |
| .replace(/"/g, """) |
| .replace(/'/g, "'"); |
| } |
|
|
| function compact(value: string, max = 180): string { |
| const text = value.replace(/\s+/g, " ").trim(); |
| return text.length > max ? `${text.slice(0, max - 1)}...` : text; |
| } |
|
|
| function contentText(content: any): string { |
| if (typeof content === "string") return content; |
| if (!Array.isArray(content)) return ""; |
| return content |
| .map((part) => { |
| if (!part || typeof part !== "object") return ""; |
| return part.text ?? part.input_text ?? part.output_text ?? ""; |
| }) |
| .filter(Boolean) |
| .join("\n\n"); |
| } |
|
|
| function parseArgs(args: unknown): Record<string, any> { |
| if (!args) return {}; |
| if (typeof args === "object") return args as Record<string, any>; |
| try { |
| return JSON.parse(String(args)); |
| } catch { |
| return { raw: String(args) }; |
| } |
| } |
|
|
| function parseTrace(raw: string) { |
| const cards: TraceCard[] = []; |
| let meta: Record<string, any> = {}; |
| let sawEventUser = false; |
|
|
| for (const line of raw.split(/\r?\n/)) { |
| if (!line.trim()) continue; |
| let item: any; |
| try { |
| item = JSON.parse(line); |
| } catch { |
| continue; |
| } |
|
|
| if (item.type === "session_meta") { |
| meta = item.payload ?? {}; |
| continue; |
| } |
|
|
| const payload = item.payload ?? {}; |
|
|
| if (item.type === "event_msg") { |
| if (payload.type === "user_message" && payload.message) { |
| sawEventUser = true; |
| cards.push({ |
| kind: "user", |
| label: "User", |
| meta: item.timestamp, |
| text: payload.message, |
| }); |
| } |
| continue; |
| } |
|
|
| if (item.type !== "response_item") continue; |
|
|
| if (payload.type === "message") { |
| const role = payload.role ?? "message"; |
| if (role === "user" && sawEventUser) continue; |
| const text = contentText(payload.content); |
| if (!text.trim()) continue; |
| cards.push({ |
| kind: role === "developer" ? "system" : role, |
| label: role === "developer" ? "System" : role[0].toUpperCase() + role.slice(1), |
| meta: item.timestamp, |
| text, |
| }); |
| continue; |
| } |
|
|
| if (payload.type === "reasoning") { |
| const text = contentText(payload.summary); |
| if (!text.trim()) continue; |
| cards.push({ |
| kind: "thinking", |
| label: "Thinking", |
| meta: item.timestamp, |
| text, |
| }); |
| continue; |
| } |
|
|
| if (payload.type === "function_call") { |
| const args = parseArgs(payload.arguments); |
| const body = args.command |
| ? String(args.command) |
| : JSON.stringify(args, null, 2); |
| cards.push({ |
| kind: "tool-call", |
| label: `Tool Call · ${payload.name ?? "tool"}`, |
| meta: payload.call_id, |
| text: body, |
| }); |
| continue; |
| } |
|
|
| if (payload.type === "function_call_output") { |
| cards.push({ |
| kind: payload.status === "success" ? "tool-result success" : "tool-result", |
| label: "Tool Result", |
| meta: payload.call_id, |
| text: payload.output ?? "", |
| status: payload.status, |
| }); |
| } |
| } |
|
|
| return { meta, cards }; |
| } |
|
|
| const rawTrace = resolveTrace(src); |
| const trace = rawTrace ? parseTrace(rawTrace) : { meta: {}, cards: [] }; |
| const filename = src.split("/").pop() ?? src; |
| const externalHref = |
| sourceUrl ?? |
| `https://huggingface.co/datasets/evalstate/all-defects/blob/main/${encodeURIComponent(filename)}`; |
| const openedCutoff = Math.max(0, trace.cards.length - 4); |
|
|
| const cardHtml = rawTrace |
| ? trace.cards |
| .map((card, index) => { |
| const open = index < 2 || index >= openedCutoff ? " open" : ""; |
| const meta = card.meta ? `<span>${escapeHtml(card.meta)}</span>` : ""; |
| const status = card.status ? `<span>${escapeHtml(card.status)}</span>` : ""; |
| return ` |
| <details class="trace-event ${escapeHtml(card.kind)}"${open}> |
| <summary> |
| <span class="trace-pill">${escapeHtml(card.label)}</span> |
| <span class="trace-preview">${escapeHtml(compact(card.text))}</span> |
| <span class="trace-meta">${meta}${status}</span> |
| </summary> |
| <pre>${escapeHtml(card.text)}</pre> |
| </details> |
| `; |
| }) |
| .join("") |
| : `<div class="trace-missing">Trace not found: <code>${escapeHtml(src)}</code></div>`; |
|
|
| const iframeDoc = `<!doctype html> |
| <html> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <style> |
| :root { |
| color-scheme: light; |
| --trace-page: #ffffff; |
| --trace-surface: #f8fafc; |
| --trace-card: #ffffff; |
| --trace-border: #e5e7eb; |
| --trace-text: #1f2937; |
| --trace-muted: #64748b; |
| --trace-code: #334155; |
| --trace-system: #d97706; |
| --trace-user: #2563eb; |
| --trace-assistant: #ea580c; |
| --trace-tool: #475569; |
| --trace-success: #10b981; |
| } |
| :root[data-theme="dark"] { |
| color-scheme: dark; |
| --trace-page: #0f1115; |
| --trace-surface: #111827; |
| --trace-card: #172033; |
| --trace-border: #334155; |
| --trace-text: #e5e7eb; |
| --trace-muted: #9ca3af; |
| --trace-code: #d1d5db; |
| --trace-system: #f59e0b; |
| --trace-user: #60a5fa; |
| --trace-assistant: #fb923c; |
| --trace-tool: #cbd5e1; |
| --trace-success: #34d399; |
| } |
| * { box-sizing: border-box; } |
| body { |
| margin: 0; |
| background: var(--trace-page); |
| color: var(--trace-text); |
| font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; |
| font-size: 14px; |
| line-height: 1.55; |
| } |
| .trace-shell { |
| min-height: 100vh; |
| background: var(--trace-page); |
| } |
| .trace-topbar { |
| position: sticky; |
| top: 0; |
| z-index: 2; |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| gap: 16px; |
| padding: 10px 14px; |
| border-bottom: 1px solid var(--trace-border); |
| background: color-mix(in srgb, var(--trace-surface) 94%, transparent); |
| } |
| .trace-brand { |
| display: flex; |
| min-width: 0; |
| align-items: center; |
| gap: 8px; |
| font-weight: 650; |
| } |
| .trace-brand svg { |
| width: 16px; |
| height: 16px; |
| flex: none; |
| color: var(--trace-muted); |
| } |
| .trace-session { |
| min-width: 0; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| color: var(--trace-muted); |
| font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| font-size: 11px; |
| } |
| .trace-link { |
| flex: none; |
| color: var(--trace-user); |
| font-size: 12px; |
| text-decoration: none; |
| } |
| .trace-link:hover { text-decoration: underline; } |
| .trace-meta-grid { |
| display: grid; |
| grid-template-columns: repeat(3, minmax(0, 1fr)); |
| gap: 8px; |
| padding: 12px 14px; |
| border-bottom: 1px solid var(--trace-border); |
| background: var(--trace-page); |
| } |
| .trace-kv { |
| min-width: 0; |
| border: 1px solid var(--trace-border); |
| border-radius: 8px; |
| background: var(--trace-card); |
| padding: 8px 10px; |
| } |
| .trace-kv span { |
| display: block; |
| color: var(--trace-muted); |
| font-size: 11px; |
| text-transform: uppercase; |
| } |
| .trace-kv strong { |
| display: block; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| font-size: 12px; |
| font-weight: 600; |
| } |
| .trace-events { |
| padding: 14px; |
| } |
| .trace-event { |
| overflow: hidden; |
| border: 1px solid var(--trace-border); |
| border-radius: 8px; |
| background: var(--trace-card); |
| box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04); |
| } |
| .trace-event + .trace-event { |
| margin-top: 10px; |
| } |
| .trace-event summary { |
| display: grid; |
| grid-template-columns: max-content minmax(0, 1fr) max-content; |
| align-items: center; |
| gap: 8px; |
| min-height: 34px; |
| padding: 6px 8px; |
| cursor: pointer; |
| list-style: none; |
| } |
| .trace-event summary::-webkit-details-marker { |
| display: none; |
| } |
| .trace-event summary:hover { |
| background: color-mix(in srgb, var(--trace-surface) 78%, transparent); |
| } |
| .trace-pill { |
| border: 1px solid var(--trace-border); |
| border-radius: 6px; |
| background: var(--trace-surface); |
| padding: 2px 7px; |
| color: var(--trace-muted); |
| font-size: 12px; |
| font-weight: 650; |
| white-space: nowrap; |
| } |
| .system .trace-pill { color: var(--trace-system); } |
| .user .trace-pill { color: var(--trace-user); } |
| .assistant .trace-pill { color: var(--trace-assistant); } |
| .tool-call .trace-pill, |
| .tool-result .trace-pill { color: var(--trace-tool); } |
| .tool-result.success .trace-meta::before { |
| content: ""; |
| display: inline-block; |
| width: 7px; |
| height: 7px; |
| margin-right: 5px; |
| border-radius: 50%; |
| background: var(--trace-success); |
| } |
| .trace-preview { |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| color: var(--trace-muted); |
| font-size: 13px; |
| } |
| .trace-meta { |
| display: flex; |
| align-items: center; |
| gap: 6px; |
| color: var(--trace-muted); |
| font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| font-size: 11px; |
| } |
| .trace-event pre { |
| overflow: auto; |
| max-height: 520px; |
| margin: 0; |
| border-top: 1px solid var(--trace-border); |
| padding: 12px; |
| background: color-mix(in srgb, var(--trace-surface) 84%, var(--trace-card)); |
| color: var(--trace-code); |
| white-space: pre-wrap; |
| word-break: break-word; |
| font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| font-size: 12px; |
| line-height: 1.45; |
| } |
| .trace-missing { |
| padding: 18px; |
| color: #b91c1c; |
| } |
| @media (max-width: 680px) { |
| .trace-topbar { |
| align-items: flex-start; |
| flex-direction: column; |
| gap: 4px; |
| } |
| .trace-meta-grid { |
| grid-template-columns: 1fr; |
| } |
| .trace-event summary { |
| grid-template-columns: 1fr; |
| } |
| .trace-meta { |
| display: none; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="trace-shell"> |
| <div class="trace-topbar"> |
| <div class="trace-brand"> |
| <svg viewBox="0 0 12 12" aria-hidden="true"><path d="M10.28 5.1a2.5 2.5 0 0 0-.21-2.05 2.52 2.52 0 0 0-2.71-1.21 2.53 2.53 0 0 0-4.29.9 2.5 2.5 0 0 0-1.66 1.21 2.52 2.52 0 0 0 .3 2.96 2.5 2.5 0 0 0 .22 2.04 2.52 2.52 0 0 0 2.72 1.21 2.5 2.5 0 0 0 1.87.84 2.52 2.52 0 0 0 2.4-1.75 2.5 2.5 0 0 0 2-2.73 2.52 2.52 0 0 0-.64-1.43Z" fill="currentColor"/></svg> |
| <span>Codex trace</span> |
| <span class="trace-session">${escapeHtml(trace.meta.id ?? filename)}</span> |
| </div> |
| <a class="trace-link" href="${escapeHtml(externalHref)}" target="_blank" rel="noopener noreferrer">Open raw trace</a> |
| </div> |
| <div class="trace-meta-grid"> |
| <div class="trace-kv"><span>Model</span><strong>${escapeHtml(trace.meta.model_spec ?? "unknown")}</strong></div> |
| <div class="trace-kv"><span>Started</span><strong>${escapeHtml(trace.meta.timestamp ?? "unknown")}</strong></div> |
| <div class="trace-kv"><span>Working Directory</span><strong>${escapeHtml(trace.meta.cwd ?? "unknown")}</strong></div> |
| </div> |
| <div class="trace-events">${cardHtml}</div> |
| </div> |
| <script> |
| (() => { |
| const applyTheme = () => { |
| try { |
| const theme = parent.document.documentElement.getAttribute("data-theme"); |
| if (theme) document.documentElement.setAttribute("data-theme", theme); |
| else document.documentElement.removeAttribute("data-theme"); |
| } catch {} |
| }; |
| applyTheme(); |
| try { |
| new MutationObserver(applyTheme).observe(parent.document.documentElement, { |
| attributes: true, |
| attributeFilter: ["data-theme"], |
| }); |
| } catch {} |
| })(); |
| </script> |
| </body> |
| </html>`; |
| --- |
|
|
| <figure class={`html-embed trace-embed${wide ? " html-embed--wide" : ""}`}> |
| {title && <figcaption class="html-embed__title">{title}</figcaption>} |
| <div class="html-embed__card trace-embed__card"> |
| <iframe |
| class="trace-embed__iframe" |
| srcdoc={iframeDoc} |
| title={title ?? "Agent trace"} |
| loading="lazy" |
| style={`height:${height}px`} |
| ></iframe> |
| </div> |
| {desc && <figcaption class="html-embed__desc" set:html={desc} />} |
| </figure> |
|
|
| <style is:global> |
| .trace-embed__card { |
| overflow: hidden; |
| padding: 0; |
| } |
| |
| .trace-embed__iframe { |
| display: block; |
| width: 100%; |
| min-height: 460px; |
| border: 0; |
| background: var(--surface-bg); |
| } |
| |
| @media (max-width: 768px) { |
| .trace-embed__iframe { |
| min-height: 520px; |
| } |
| } |
| </style> |
|
|