@tracebird/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/dist/cli.js +1484 -0
- package/dist/cli.js.map +1 -0
- package/dist/ui/assets/index-BEvedEM9.css +1 -0
- package/dist/ui/assets/index-BU67d56w.js +44 -0
- package/dist/ui/index.html +13 -0
- package/package.json +51 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/live.ts","../src/server.ts","../src/otlp/protobuf.ts","../src/storage/session-store.ts","../src/trace-buffer.ts","../src/render/tree.ts","../src/render/format.ts","../src/api.ts","../src/export.ts","../src/static-files.ts","../src/app.ts","../src/ui-dir.ts","../src/open-browser.ts","../src/sse.ts","../src/commands/open.ts","../src/commands/demo.ts","../../../libs/fixtures/src/otlp/builders.ts","../../../libs/fixtures/src/otlp/weather-happy-path.ts","../../../libs/fixtures/src/otlp/tool-error.ts","../../../libs/fixtures/src/otlp/diff-pair.ts","../../../libs/fixtures/src/otlp/openinference.ts","../../../libs/fixtures/src/otlp/vercel-ai-sdk.ts","../../../libs/fixtures/src/otlp/claude-code.ts","../../../libs/fixtures/src/index.ts"],"sourcesContent":["import { parseArgs } from 'node:util';\nimport { resolve } from 'node:path';\nimport { runLive } from './commands/live.js';\nimport { runOpen } from './commands/open.js';\nimport { runDemo } from './commands/demo.js';\n\nconst HELP = `tracebird — a local-first, time-travel debugger for AI agent runs.\n\nUsage:\n tracebird [live] Start the OTLP receiver + UI (default).\n tracebird demo Serve the UI with bundled sample runs (no agent needed).\n tracebird open <file.jsonl> Load a saved session and serve the UI.\n tracebird --help Show this help.\n\nOptions:\n --port <n> Port for the OTLP receiver / UI server (default 4318).\n --host <addr> Address to bind (default 127.0.0.1).\n --out <dir> Directory for captured sessions (default ./.tracebird).\n --no-open Do not open the browser on start.\n\nPoint your agent's OpenTelemetry exporter at the receiver:\n export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\n`;\n\nasync function main(argv: string[]): Promise<void> {\n // Node's parseArgs has no built-in negation; handle --no-open ourselves.\n const noOpen = argv.includes('--no-open');\n const cleaned = argv.filter((a) => a !== '--no-open');\n\n const { values, positionals } = parseArgs({\n args: cleaned,\n allowPositionals: true,\n options: {\n port: { type: 'string' },\n host: { type: 'string' },\n out: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n },\n });\n\n if (values.help) {\n process.stdout.write(HELP);\n return;\n }\n\n const command = positionals[0] ?? 'live';\n const port = values.port ? Number(values.port) : 4318;\n const host = values.host ?? '127.0.0.1';\n const outDir = resolve(values.out ?? '.tracebird');\n const open = !noOpen;\n\n switch (command) {\n case 'live':\n await runLive({ port, host, outDir, open });\n break;\n case 'demo':\n await runDemo({ port, host, open });\n break;\n case 'open': {\n const file = positionals[1];\n if (!file) {\n process.stderr.write('Usage: tracebird open <file.jsonl>\\n');\n process.exitCode = 1;\n break;\n }\n await runOpen({ file, port, host, open });\n break;\n }\n case 'help':\n process.stdout.write(HELP);\n break;\n default:\n process.stderr.write(`Unknown command: ${command}\\n\\n${HELP}`);\n process.exitCode = 1;\n }\n}\n\nmain(process.argv.slice(2)).catch((err) => {\n process.stderr.write(`tracebird: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n});\n","import { join } from 'node:path';\nimport { buildRun } from '@tracebird/core';\nimport { createServer, listen } from '../server.js';\nimport { SessionStore } from '../storage/session-store.js';\nimport { TraceBuffer } from '../trace-buffer.js';\nimport { renderRunTree } from '../render/tree.js';\nimport { createAppHandler } from '../app.js';\nimport { resolveUiDir } from '../ui-dir.js';\nimport { openBrowser } from '../open-browser.js';\nimport { SseHub } from '../sse.js';\n\nexport interface LiveOptions {\n port: number;\n host: string;\n outDir: string;\n open: boolean;\n}\n\n/**\n * `tracebird live` — start the OTLP receiver, reconstruct each completed trace,\n * print its tree, persist it, and serve the UI (which polls the JSON API).\n */\nexport async function runLive(options: LiveOptions): Promise<void> {\n const store = new SessionStore(join(options.outDir, `session-${Date.now()}.jsonl`));\n const sse = new SseHub();\n\n const buffer = new TraceBuffer({\n onComplete: (_traceId, spans) => {\n const run = buildRun(spans);\n store.addRun(run);\n process.stdout.write('\\n' + renderRunTree(run) + '\\n');\n sse.broadcast('run', { id: run.id });\n },\n });\n\n const server = createServer({\n onExport: (spans) => {\n buffer.add(spans);\n sse.broadcast('activity', { spans: spans.length });\n },\n extraHandler: createAppHandler({ store, live: true }, resolveUiDir(), sse),\n });\n\n const boundPort = await listen(server, options.port, options.host);\n const endpoint = `http://${options.host}:${boundPort}`;\n\n process.stdout.write(\n [\n '',\n ' tracebird — listening for OpenTelemetry traces',\n '',\n ` UI ${endpoint}`,\n ` OTLP endpoint ${endpoint}/v1/traces`,\n ` Session file ${store.filePath}`,\n '',\n ' Point your agent at this receiver:',\n ` export OTEL_EXPORTER_OTLP_ENDPOINT=${endpoint}`,\n '',\n ' Waiting for your first agent run… (Ctrl-C to stop)',\n '',\n ].join('\\n') + '\\n',\n );\n\n if (options.open) openBrowser(endpoint);\n\n await new Promise<void>((resolveShutdown) => {\n const shutdown = () => {\n process.stdout.write('\\n Stopping…\\n');\n buffer.flushAll();\n sse.close();\n server.close(() => {\n void store.close().then(() => resolveShutdown());\n });\n };\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n });\n}\n","import {\n createServer as createHttpServer,\n type IncomingMessage,\n type Server,\n type ServerResponse,\n} from 'node:http';\nimport { parseOtlp, type ExportTraceServiceRequest, type Span } from '@tracebird/core';\nimport { decodeProtobufTraces } from './otlp/protobuf.js';\n\n/** Called whenever a batch of spans is received and parsed. */\nexport type ExportHandler = (spans: Span[], raw: ExportTraceServiceRequest) => void | Promise<void>;\n\nexport interface ServerOptions {\n /** Invoked with the parsed spans for every accepted OTLP export. */\n onExport?: ExportHandler;\n /**\n * Optional extra request handler tried before the 404 fallback — used by the\n * UI/API layer in later stages. Return `true` if it handled the request.\n */\n extraHandler?: (req: IncomingMessage, res: ServerResponse) => boolean | Promise<boolean>;\n}\n\nconst MAX_BODY_BYTES = 50 * 1024 * 1024; // 50 MB — generous for batched exports.\n\nfunction readBody(req: IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_BYTES) {\n reject(new Error('payload too large'));\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks)));\n req.on('error', reject);\n });\n}\n\nfunction decodeExport(contentType: string, body: Buffer): ExportTraceServiceRequest {\n if (\n contentType.includes('application/x-protobuf') ||\n contentType.includes('application/protobuf')\n ) {\n return decodeProtobufTraces(body);\n }\n // Default to JSON (the OTLP/HTTP JSON content type, or anything unspecified).\n const text = body.toString('utf8').trim();\n return text ? (JSON.parse(text) as ExportTraceServiceRequest) : {};\n}\n\nfunction sendProtobuf(res: ServerResponse, status: number): void {\n // An empty ExportTraceServiceResponse encodes to zero bytes (full success).\n res.writeHead(status, { 'content-type': 'application/x-protobuf' });\n res.end();\n}\n\nfunction sendJson(res: ServerResponse, status: number, payload: unknown): void {\n res.writeHead(status, { 'content-type': 'application/json' });\n res.end(JSON.stringify(payload));\n}\n\nasync function handleTraces(\n req: IncomingMessage,\n res: ServerResponse,\n onExport?: ExportHandler,\n): Promise<void> {\n const contentType = req.headers['content-type'] ?? 'application/json';\n let body: Buffer;\n try {\n body = await readBody(req);\n } catch {\n sendJson(res, 413, { error: 'payload too large' });\n return;\n }\n\n let request: ExportTraceServiceRequest;\n try {\n request = decodeExport(contentType, body);\n } catch (err) {\n sendJson(res, 400, { error: `failed to decode OTLP payload: ${(err as Error).message}` });\n return;\n }\n\n const spans = parseOtlp(request);\n try {\n await onExport?.(spans, request);\n } catch (err) {\n sendJson(res, 500, { error: `export handler failed: ${(err as Error).message}` });\n return;\n }\n\n const isProtobuf =\n contentType.includes('application/x-protobuf') || contentType.includes('application/protobuf');\n if (isProtobuf) sendProtobuf(res, 200);\n else sendJson(res, 200, {});\n}\n\n/** Create the tracebird HTTP server (OTLP receiver + optional extra routes). */\nexport function createServer(options: ServerOptions = {}): Server {\n return createHttpServer((req, res) => {\n void (async () => {\n const url = (req.url ?? '/').split('?')[0];\n\n if (req.method === 'POST' && url === '/v1/traces') {\n await handleTraces(req, res, options.onExport);\n return;\n }\n\n if (req.method === 'GET' && (url === '/health' || url === '/healthz')) {\n sendJson(res, 200, { status: 'ok' });\n return;\n }\n\n if (options.extraHandler) {\n const handled = await options.extraHandler(req, res);\n if (handled) return;\n }\n\n sendJson(res, 404, { error: 'not found' });\n })().catch((err) => {\n if (!res.headersSent) sendJson(res, 500, { error: (err as Error).message });\n });\n });\n}\n\n/** Start a server and resolve once it is listening, with the bound port. */\nexport function listen(server: Server, port: number, host: string): Promise<number> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => {\n const addr = server.address();\n const boundPort = typeof addr === 'object' && addr ? addr.port : port;\n resolve(boundPort);\n });\n });\n}\n","import protobuf from 'protobufjs';\nimport type { ExportTraceServiceRequest } from '@tracebird/core';\n\n/**\n * Decode OTLP/HTTP protobuf trace payloads without a build-time codegen step.\n *\n * Most OpenTelemetry SDKs default to `http/protobuf`, so this is the path that\n * makes tracebird genuinely drop-in. We describe just the subset of the OTLP\n * trace schema we need as a protobufjs JSON descriptor, decode, then convert to\n * the exact same camelCase shape that `parseOtlp` consumes from OTLP/JSON\n * (hex trace/span ids, stringified nanos).\n */\n\nconst common = {\n AnyValue: {\n oneofs: {\n value: {\n oneof: [\n 'stringValue',\n 'boolValue',\n 'intValue',\n 'doubleValue',\n 'arrayValue',\n 'kvlistValue',\n 'bytesValue',\n ],\n },\n },\n fields: {\n stringValue: { type: 'string', id: 1 },\n boolValue: { type: 'bool', id: 2 },\n intValue: { type: 'int64', id: 3 },\n doubleValue: { type: 'double', id: 4 },\n arrayValue: { type: 'ArrayValue', id: 5 },\n kvlistValue: { type: 'KeyValueList', id: 6 },\n bytesValue: { type: 'bytes', id: 7 },\n },\n },\n ArrayValue: { fields: { values: { rule: 'repeated', type: 'AnyValue', id: 1 } } },\n KeyValueList: { fields: { values: { rule: 'repeated', type: 'KeyValue', id: 1 } } },\n KeyValue: {\n fields: { key: { type: 'string', id: 1 }, value: { type: 'AnyValue', id: 2 } },\n },\n InstrumentationScope: {\n fields: {\n name: { type: 'string', id: 1 },\n version: { type: 'string', id: 2 },\n attributes: { rule: 'repeated', type: 'KeyValue', id: 3 },\n },\n },\n};\n\nconst KV = 'opentelemetry.proto.common.v1.KeyValue';\n\nconst descriptor = {\n nested: {\n opentelemetry: {\n nested: {\n proto: {\n nested: {\n common: { nested: { v1: { nested: common } } },\n resource: {\n nested: {\n v1: {\n nested: {\n Resource: {\n fields: { attributes: { rule: 'repeated', type: KV, id: 1 } },\n },\n },\n },\n },\n },\n trace: {\n nested: {\n v1: {\n nested: {\n ResourceSpans: {\n fields: {\n resource: { type: 'opentelemetry.proto.resource.v1.Resource', id: 1 },\n scopeSpans: { rule: 'repeated', type: 'ScopeSpans', id: 2 },\n schemaUrl: { type: 'string', id: 3 },\n },\n },\n ScopeSpans: {\n fields: {\n scope: {\n type: 'opentelemetry.proto.common.v1.InstrumentationScope',\n id: 1,\n },\n spans: { rule: 'repeated', type: 'Span', id: 2 },\n schemaUrl: { type: 'string', id: 3 },\n },\n },\n Span: {\n fields: {\n traceId: { type: 'bytes', id: 1 },\n spanId: { type: 'bytes', id: 2 },\n traceState: { type: 'string', id: 3 },\n parentSpanId: { type: 'bytes', id: 4 },\n name: { type: 'string', id: 5 },\n kind: { type: 'int32', id: 6 },\n startTimeUnixNano: { type: 'fixed64', id: 7 },\n endTimeUnixNano: { type: 'fixed64', id: 8 },\n attributes: { rule: 'repeated', type: KV, id: 9 },\n events: { rule: 'repeated', type: 'Event', id: 11 },\n status: { type: 'Status', id: 15 },\n },\n nested: {\n Event: {\n fields: {\n timeUnixNano: { type: 'fixed64', id: 1 },\n name: { type: 'string', id: 2 },\n attributes: { rule: 'repeated', type: KV, id: 3 },\n },\n },\n },\n },\n Status: {\n fields: {\n message: { type: 'string', id: 2 },\n code: { type: 'int32', id: 3 },\n },\n },\n },\n },\n },\n },\n collector: {\n nested: {\n trace: {\n nested: {\n v1: {\n nested: {\n ExportTraceServiceRequest: {\n fields: {\n resourceSpans: {\n rule: 'repeated',\n type: 'opentelemetry.proto.trace.v1.ResourceSpans',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nconst root = protobuf.Root.fromJSON(descriptor);\nconst RequestType = root.lookupType(\n 'opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest',\n);\n\nfunction hexToBytes(hex: string | undefined): Uint8Array {\n if (!hex) return new Uint8Array(0);\n const clean = hex.length % 2 === 0 ? hex : '0' + hex;\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\nfunction bytesToHex(bytes: unknown): string | undefined {\n if (!bytes) return undefined;\n const arr: number[] = Array.isArray(bytes)\n ? bytes\n : bytes instanceof Uint8Array\n ? Array.from(bytes)\n : [];\n if (arr.length === 0) return undefined;\n return arr.map((b) => (b & 0xff).toString(16).padStart(2, '0')).join('');\n}\n\ninterface RawSpan {\n traceId?: unknown;\n spanId?: unknown;\n parentSpanId?: unknown;\n [key: string]: unknown;\n}\n\n/** Decode an OTLP/protobuf body into the JSON `ExportTraceServiceRequest` shape. */\nexport function decodeProtobufTraces(body: Uint8Array): ExportTraceServiceRequest {\n const message = RequestType.decode(body);\n const obj = RequestType.toObject(message, {\n longs: String,\n enums: Number,\n bytes: Array,\n defaults: false,\n arrays: true,\n objects: true,\n }) as ExportTraceServiceRequest;\n\n // protobuf carries trace/span ids as bytes; OTLP/JSON (and parseOtlp) want hex.\n for (const rs of obj.resourceSpans ?? []) {\n for (const ss of rs.scopeSpans ?? []) {\n for (const span of (ss.spans ?? []) as RawSpan[]) {\n span.traceId = bytesToHex(span.traceId) ?? '';\n span.spanId = bytesToHex(span.spanId) ?? '';\n const parent = bytesToHex(span.parentSpanId);\n if (parent) span.parentSpanId = parent;\n else delete span.parentSpanId;\n }\n }\n }\n return obj;\n}\n\ninterface MutableSpan {\n traceId?: unknown;\n spanId?: unknown;\n parentSpanId?: unknown;\n}\n\n/**\n * Encode a JSON `ExportTraceServiceRequest` (hex ids, string nanos) back into\n * OTLP/protobuf bytes. The inverse of {@link decodeProtobufTraces}; used by\n * tests and the e2e harness to exercise the protobuf ingest path.\n */\nexport function encodeProtobufTraces(request: ExportTraceServiceRequest): Uint8Array {\n const clone = structuredClone(request) as ExportTraceServiceRequest;\n for (const rs of clone.resourceSpans ?? []) {\n for (const ss of rs.scopeSpans ?? []) {\n for (const span of (ss.spans ?? []) as MutableSpan[]) {\n span.traceId = hexToBytes(span.traceId as string | undefined);\n span.spanId = hexToBytes(span.spanId as string | undefined);\n if (span.parentSpanId) span.parentSpanId = hexToBytes(span.parentSpanId as string);\n else delete span.parentSpanId;\n }\n }\n }\n const message = RequestType.fromObject(clone as Record<string, unknown>);\n return RequestType.encode(message).finish();\n}\n","import { createWriteStream, mkdirSync, readFileSync, type WriteStream } from 'node:fs';\nimport { dirname } from 'node:path';\nimport {\n parseSession,\n runMatches,\n serializeRun,\n StatusCode,\n type Run,\n type TraceNode,\n} from '@tracebird/core';\n\nexport interface RunFilter {\n /** Deep text search across summary, prompts, completions, tool I/O. */\n query?: string;\n /** Restrict by status; `'all'` (default) keeps everything. */\n status?: 'all' | 'ok' | 'error' | 'unset';\n}\n\n/** Lightweight run summary for list views (no heavy prompt/completion payloads). */\nexport interface RunSummary {\n id: string;\n traceId: string;\n summary: string;\n startTimeUnixNano: string;\n durationMs: number;\n status: 'ok' | 'error' | 'unset';\n tokens: Run['tokens'];\n costUsd: number | null;\n service?: string;\n nodeCount: number;\n}\n\nfunction statusLabel(code: StatusCode): RunSummary['status'] {\n if (code === StatusCode.Error) return 'error';\n if (code === StatusCode.Ok) return 'ok';\n return 'unset';\n}\n\nfunction countNodes(node: TraceNode): number {\n return 1 + node.children.reduce((sum, child) => sum + countNodes(child), 0);\n}\n\n/**\n * Holds the runs for one session in memory and (optionally) appends them to a\n * `.jsonl` file. Backs both `live` capture (append mode) and `open` (read-only).\n */\nexport class SessionStore {\n private readonly runs: Run[] = [];\n private readonly byId = new Map<string, Run>();\n private stream?: WriteStream;\n readonly filePath?: string;\n\n constructor(filePath?: string) {\n if (filePath) {\n mkdirSync(dirname(filePath), { recursive: true });\n this.filePath = filePath;\n this.stream = createWriteStream(filePath, { flags: 'a' });\n }\n }\n\n /** Load an existing session file read-only (for `tracebird open`). */\n static load(filePath: string): SessionStore {\n const store = new SessionStore();\n const text = readFileSync(filePath, 'utf8');\n for (const run of parseSession(text)) store.addRun(run, { persist: false });\n return store;\n }\n\n addRun(run: Run, options: { persist?: boolean } = {}): void {\n this.runs.push(run);\n this.byId.set(run.id, run);\n if (options.persist !== false) this.stream?.write(serializeRun(run) + '\\n');\n }\n\n get(id: string): Run | undefined {\n return this.byId.get(id);\n }\n\n all(): Run[] {\n return this.runs;\n }\n\n /** Run summaries, newest first, optionally filtered by text and status. */\n list(filter: RunFilter = {}): RunSummary[] {\n const status = filter.status ?? 'all';\n const query = filter.query ?? '';\n return this.runs\n .filter((run) => status === 'all' || statusLabel(run.status.code) === status)\n .filter((run) => runMatches(run, query))\n .map((run) => ({\n id: run.id,\n traceId: run.traceId,\n summary: run.summary,\n startTimeUnixNano: run.startTimeUnixNano,\n durationMs: run.durationMs,\n status: statusLabel(run.status.code),\n tokens: run.tokens,\n costUsd: run.costUsd,\n ...(run.service ? { service: run.service } : {}),\n nodeCount: countNodes(run.root),\n }))\n .sort((a, b) => (a.startTimeUnixNano < b.startTimeUnixNano ? 1 : -1));\n }\n\n get size(): number {\n return this.runs.length;\n }\n\n async close(): Promise<void> {\n const stream = this.stream;\n if (!stream) return;\n await new Promise<void>((resolve, reject) => {\n stream.end((err?: Error | null) => (err ? reject(err) : resolve()));\n });\n }\n}\n","import type { Span } from '@tracebird/core';\n\nexport interface TraceBufferOptions {\n /** Flush a trace after this many ms with no new spans. Default 1500. */\n idleMs?: number;\n /** Called with all buffered spans for a trace once it goes idle. */\n onComplete: (traceId: string, spans: Span[]) => void;\n}\n\n/**\n * Buffers incoming spans per trace id and flushes a trace once it has been idle\n * for `idleMs`. OTLP gives us no explicit \"trace complete\" signal, so idle\n * detection is the pragmatic trigger; `flushAll` forces completion on shutdown.\n */\nexport class TraceBuffer {\n private readonly idleMs: number;\n private readonly onComplete: TraceBufferOptions['onComplete'];\n private readonly traces = new Map<string, { spans: Span[]; timer: NodeJS.Timeout }>();\n\n constructor(options: TraceBufferOptions) {\n this.idleMs = options.idleMs ?? 1500;\n this.onComplete = options.onComplete;\n }\n\n add(spans: Span[]): void {\n const grouped = new Map<string, Span[]>();\n for (const span of spans) {\n const list = grouped.get(span.traceId) ?? [];\n list.push(span);\n grouped.set(span.traceId, list);\n }\n for (const [traceId, group] of grouped) {\n const entry = this.traces.get(traceId);\n if (entry) {\n entry.spans.push(...group);\n clearTimeout(entry.timer);\n entry.timer = this.schedule(traceId);\n } else {\n this.traces.set(traceId, { spans: group, timer: this.schedule(traceId) });\n }\n }\n }\n\n private schedule(traceId: string): NodeJS.Timeout {\n const timer = setTimeout(() => this.flush(traceId), this.idleMs);\n // Don't keep the event loop alive solely for a pending flush.\n timer.unref?.();\n return timer;\n }\n\n /** Flush a single trace now, if buffered. */\n flush(traceId: string): void {\n const entry = this.traces.get(traceId);\n if (!entry) return;\n clearTimeout(entry.timer);\n this.traces.delete(traceId);\n this.onComplete(traceId, entry.spans);\n }\n\n /** Flush every buffered trace (e.g. on shutdown). */\n flushAll(): void {\n for (const traceId of [...this.traces.keys()]) this.flush(traceId);\n }\n\n get pending(): number {\n return this.traces.size;\n }\n}\n","import { StatusCode, type LlmCall, type Run, type ToolCall, type TraceNode } from '@tracebird/core';\nimport { formatCost, formatDuration, formatTokens } from './format.js';\n\n/** Render a reconstructed {@link Run} as an indented tree for the terminal. */\n\nconst ICON: Record<TraceNode['kind'], string> = {\n run: '⏺',\n agent: '◆',\n llm: '✦',\n tool: '⚙',\n step: '▫',\n};\n\nfunction metrics(node: TraceNode): string {\n const parts: string[] = [formatDuration(node.durationMs)];\n if (node.kind === 'llm') {\n const llm = node as LlmCall;\n const tok = formatTokens(llm.usage.total ?? llm.usage.input);\n if (tok) parts.push(tok);\n const cost = formatCost(llm.costUsd);\n if (cost) parts.push(cost);\n if (llm.model) parts.push(llm.model);\n }\n if (node.kind === 'tool' && (node as ToolCall).isError) parts.push('ERROR');\n return parts.join(' ');\n}\n\nfunction label(node: TraceNode): string {\n return `${ICON[node.kind]} ${node.name} ${metrics(node)}`;\n}\n\nfunction renderChildren(nodes: TraceNode[], prefix: string, lines: string[]): void {\n nodes.forEach((node, i) => {\n const last = i === nodes.length - 1;\n lines.push(`${prefix}${last ? '└─ ' : '├─ '}${label(node)}`);\n renderChildren(node.children, prefix + (last ? ' ' : '│ '), lines);\n });\n}\n\nexport function renderRunTree(run: Run): string {\n const header: string[] = [run.summary, formatDuration(run.durationMs)];\n const tok = formatTokens(run.tokens.total);\n if (tok) header.push(tok);\n const cost = formatCost(run.costUsd);\n if (cost) header.push(cost);\n if (run.status.code === StatusCode.Error) header.push('ERROR');\n\n const lines: string[] = [header.join(' · ')];\n renderChildren(run.root.children, '', lines);\n return lines.join('\\n');\n}\n","/** Compact formatters for terminal output. */\n\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const seconds = ms / 1000;\n if (seconds < 60) return `${seconds.toFixed(2).replace(/\\.?0+$/, '')}s`;\n const mins = Math.floor(seconds / 60);\n const rem = Math.round(seconds % 60);\n return `${mins}m ${rem}s`;\n}\n\nexport function formatTokens(tokens: number | undefined): string | undefined {\n return tokens == null ? undefined : `${tokens.toLocaleString('en-US')} tok`;\n}\n\nexport function formatCost(usd: number | null | undefined): string | undefined {\n if (usd == null) return undefined;\n if (usd === 0) return '$0';\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(2)}`;\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { diffRuns, type Run } from '@tracebird/core';\nimport type { SessionStore } from './storage/session-store.js';\nimport { buildHtmlSnapshot, exportJsonl } from './export.js';\n\n/**\n * The JSON API the UI reads. Pure delegation to the {@link SessionStore} (which\n * delegates reconstruction/diff to `@tracebird/core`); no business logic here.\n *\n * GET /api/session → { live, filePath, count }\n * GET /api/runs → RunSummary[]\n * GET /api/runs/:id → Run\n */\n\nexport interface ApiContext {\n store: SessionStore;\n live: boolean;\n /** Directory of the built UI assets (needed for HTML snapshot export). */\n uiDir?: string;\n}\n\nfunction json(res: ServerResponse, status: number, payload: unknown): void {\n res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store' });\n res.end(JSON.stringify(payload));\n}\n\n/** Handle an `/api/*` request. Returns false if the path isn't an API route. */\nexport function handleApi(ctx: ApiContext, req: IncomingMessage, res: ServerResponse): boolean {\n const url = (req.url ?? '/').split('?')[0];\n if (!url.startsWith('/api/')) return false;\n\n if (req.method !== 'GET') {\n json(res, 405, { error: 'method not allowed' });\n return true;\n }\n\n if (url === '/api/session') {\n json(res, 200, {\n live: ctx.live,\n filePath: ctx.store.filePath ?? null,\n count: ctx.store.size,\n });\n return true;\n }\n\n if (url === '/api/runs') {\n const params = new URL(req.url ?? '', 'http://localhost').searchParams;\n const query = params.get('q') ?? undefined;\n const statusParam = params.get('status');\n const status =\n statusParam === 'ok' || statusParam === 'error' || statusParam === 'unset'\n ? statusParam\n : 'all';\n json(res, 200, ctx.store.list({ query, status }));\n return true;\n }\n\n if (url === '/api/diff') {\n const params = new URL(req.url ?? '', 'http://localhost').searchParams;\n const aId = params.get('a');\n const bId = params.get('b');\n if (!aId || !bId) {\n json(res, 400, { error: 'diff requires ?a=<runId>&b=<runId>' });\n return true;\n }\n const a = ctx.store.get(aId);\n const b = ctx.store.get(bId);\n if (!a || !b) {\n json(res, 404, { error: `run not found: ${!a ? aId : bId}` });\n return true;\n }\n json(res, 200, diffRuns(a, b));\n return true;\n }\n\n if (url === '/api/export') {\n const params = new URL(req.url ?? '', 'http://localhost').searchParams;\n const id = params.get('id');\n const format = params.get('format') === 'jsonl' ? 'jsonl' : 'html';\n\n let runs: Run[];\n let name: string;\n if (id) {\n const run = ctx.store.get(id);\n if (!run) {\n json(res, 404, { error: `run not found: ${id}` });\n return true;\n }\n runs = [run];\n name = `tracebird-run-${run.traceId.slice(0, 8) || 'export'}`;\n } else {\n runs = ctx.store.all();\n name = 'tracebird-session';\n }\n\n if (format === 'jsonl') {\n res.writeHead(200, {\n 'content-type': 'application/x-ndjson; charset=utf-8',\n 'content-disposition': `attachment; filename=\"${name}.jsonl\"`,\n });\n res.end(exportJsonl(runs));\n return true;\n }\n\n if (!ctx.uiDir || !existsSync(join(ctx.uiDir, 'index.html'))) {\n json(res, 503, { error: 'UI assets not available for HTML export' });\n return true;\n }\n res.writeHead(200, {\n 'content-type': 'text/html; charset=utf-8',\n 'content-disposition': `attachment; filename=\"${name}.html\"`,\n });\n res.end(buildHtmlSnapshot(ctx.uiDir, runs));\n return true;\n }\n\n const match = /^\\/api\\/runs\\/([^/]+)$/.exec(url);\n if (match) {\n const id = decodeURIComponent(match[1]);\n const run = ctx.store.get(id);\n if (!run) json(res, 404, { error: `run not found: ${id}` });\n else json(res, 200, run);\n return true;\n }\n\n json(res, 404, { error: 'unknown api route' });\n return true;\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { serializeSession, type Run } from '@tracebird/core';\nimport { SessionStore } from './storage/session-store.js';\n\n/**\n * Shareable-run export. Two formats:\n * - `jsonl` — the run(s) as a session file (re-openable with `tracebird open`).\n * - `html` — a single self-contained page that inlines the UI bundle + the run\n * data, so a coworker can open it offline with no install.\n */\n\nexport function exportJsonl(runs: Run[]): string {\n return serializeSession(runs);\n}\n\nfunction inlineAssets(uiDir: string, html: string): string {\n const withJs = html.replace(\n /<script\\b[^>]*\\bsrc=\"(\\.?\\/?assets\\/[^\"]+\\.js)\"[^>]*><\\/script>/g,\n (_match, src: string) => {\n const code = readFileSync(join(uiDir, src.replace(/^\\.?\\//, '')), 'utf8').replace(\n /<\\/(script)/gi,\n '<\\\\/$1',\n );\n return `<script type=\"module\">${code}</script>`;\n },\n );\n return withJs.replace(\n /<link\\b[^>]*\\bhref=\"(\\.?\\/?assets\\/[^\"]+\\.css)\"[^>]*>/g,\n (_match, href: string) => {\n const css = readFileSync(join(uiDir, href.replace(/^\\.?\\//, '')), 'utf8');\n return `<style>${css}</style>`;\n },\n );\n}\n\n/** Produce a self-contained HTML snapshot of the given runs. */\nexport function buildHtmlSnapshot(uiDir: string, runs: Run[]): string {\n const store = new SessionStore();\n for (const run of runs) store.addRun(run, { persist: false });\n\n const snapshot = {\n session: { live: false, filePath: null, count: runs.length },\n runs: store.list(),\n runsById: Object.fromEntries(runs.map((r) => [r.id, r])),\n };\n // Escape `</` so the JSON can't break out of the <script> element.\n const json = JSON.stringify(snapshot).replace(/<\\//g, '<\\\\/');\n const inject = `<script>window.__TRACEBIRD_SNAPSHOT__=${json}</script>`;\n\n const html = inlineAssets(uiDir, readFileSync(join(uiDir, 'index.html'), 'utf8'));\n if (html.includes('<script type=\"module\">')) {\n return html.replace('<script type=\"module\">', `${inject}<script type=\"module\">`);\n }\n return html.replace('</head>', `${inject}</head>`);\n}\n","import { createReadStream, existsSync, statSync } from 'node:fs';\nimport { join, normalize, extname } from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.ico': 'image/x-icon',\n '.woff2': 'font/woff2',\n '.map': 'application/json; charset=utf-8',\n};\n\n/**\n * Serve the pre-built UI static assets from `rootDir`, with SPA fallback to\n * `index.html`. Returns false if `rootDir` doesn't exist (UI not bundled).\n */\nexport function serveStatic(rootDir: string, req: IncomingMessage, res: ServerResponse): boolean {\n if (!existsSync(rootDir)) return false;\n if (req.method !== 'GET' && req.method !== 'HEAD') return false;\n\n const urlPath = decodeURIComponent((req.url ?? '/').split('?')[0]);\n // Resolve within rootDir; reject path traversal.\n const rel = normalize(urlPath).replace(/^(\\.\\.[/\\\\])+/, '');\n let filePath = join(rootDir, rel);\n if (!filePath.startsWith(rootDir)) filePath = join(rootDir, 'index.html');\n\n if (!existsSync(filePath) || statSync(filePath).isDirectory()) {\n filePath = join(rootDir, 'index.html'); // SPA fallback\n }\n if (!existsSync(filePath)) return false;\n\n const type = MIME[extname(filePath)] ?? 'application/octet-stream';\n res.writeHead(200, { 'content-type': type });\n if (req.method === 'HEAD') {\n res.end();\n return true;\n }\n createReadStream(filePath).pipe(res);\n return true;\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { handleApi, type ApiContext } from './api.js';\nimport { serveStatic } from './static-files.js';\nimport type { SseHub } from './sse.js';\n\n/**\n * Build the combined UI/API request handler passed to the server as its\n * `extraHandler`: the SSE stream and API routes first, then the static UI\n * (with SPA fallback).\n */\nexport function createAppHandler(ctx: ApiContext, uiDir: string, sse?: SseHub) {\n const apiCtx: ApiContext = { ...ctx, uiDir };\n return (req: IncomingMessage, res: ServerResponse): boolean => {\n const url = (req.url ?? '/').split('?')[0];\n if (sse && req.method === 'GET' && url === '/api/stream') {\n sse.handle(req, res);\n return true;\n }\n if (handleApi(apiCtx, req, res)) return true;\n if (serveStatic(uiDir, req, res)) return true;\n return false;\n };\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate the pre-built UI assets. In the published package they sit next to the\n * bundled `cli.js` at `dist/ui`; in the dev tree they're at `packages/ui/dist`.\n */\nexport function resolveUiDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, 'ui'), // dist/ui (published / built)\n join(here, '..', '..', 'ui', 'dist'), // packages/cli/dist → packages/ui/dist\n ];\n return candidates.find((dir) => existsSync(join(dir, 'index.html'))) ?? candidates[0];\n}\n","import { spawn } from 'node:child_process';\n\n/** Best-effort: open a URL in the user's default browser. Never throws. */\nexport function openBrowser(url: string): void {\n const platform = process.platform;\n const command = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open';\n const args = platform === 'win32' ? ['/c', 'start', '\"\"', url] : [url];\n try {\n const child = spawn(command, args, { stdio: 'ignore', detached: true });\n child.on('error', () => undefined);\n child.unref();\n } catch {\n // Headless environment, etc. — the URL is printed for the user anyway.\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\n\n/**\n * A tiny Server-Sent-Events hub. The UI subscribes once to `GET /api/stream`\n * and is pushed `activity` (spans arriving) and `run` (a run completed) events,\n * so it updates instantly instead of polling.\n */\nexport class SseHub {\n private readonly clients = new Set<ServerResponse>();\n private heartbeat?: ReturnType<typeof setInterval>;\n\n /** Register a long-lived SSE connection. */\n handle(req: IncomingMessage, res: ServerResponse): void {\n res.writeHead(200, {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache, no-transform',\n connection: 'keep-alive',\n 'x-accel-buffering': 'no',\n });\n res.write('retry: 2000\\n\\n');\n this.clients.add(res);\n req.on('close', () => this.clients.delete(res));\n\n if (!this.heartbeat) {\n this.heartbeat = setInterval(() => this.write(':ping\\n\\n'), 15000);\n this.heartbeat.unref?.();\n }\n }\n\n /** Push a named event with a JSON payload to every connected client. */\n broadcast(event: string, data: unknown = {}): void {\n this.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n }\n\n private write(text: string): void {\n for (const res of this.clients) {\n try {\n res.write(text);\n } catch {\n this.clients.delete(res);\n }\n }\n }\n\n get size(): number {\n return this.clients.size;\n }\n\n close(): void {\n if (this.heartbeat) clearInterval(this.heartbeat);\n for (const res of this.clients) {\n try {\n res.end();\n } catch {\n /* client already gone */\n }\n }\n this.clients.clear();\n }\n}\n","import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { createServer, listen } from '../server.js';\nimport { SessionStore } from '../storage/session-store.js';\nimport { createAppHandler } from '../app.js';\nimport { resolveUiDir } from '../ui-dir.js';\nimport { openBrowser } from '../open-browser.js';\n\nexport interface OpenOptions {\n file: string;\n port: number;\n host: string;\n open: boolean;\n}\n\n/**\n * `tracebird open <file.jsonl>` — load a saved session and serve the UI with no\n * receiver. The \"drag a run to a coworker\" loop.\n */\nexport async function runOpen(options: OpenOptions): Promise<void> {\n const file = resolve(options.file);\n if (!existsSync(file)) {\n process.stderr.write(`tracebird: session file not found: ${file}\\n`);\n process.exitCode = 1;\n return;\n }\n\n let store: SessionStore;\n try {\n store = SessionStore.load(file);\n } catch (err) {\n process.stderr.write(`tracebird: failed to load session: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n return;\n }\n\n const server = createServer({\n extraHandler: createAppHandler({ store, live: false }, resolveUiDir()),\n });\n\n const boundPort = await listen(server, options.port, options.host);\n const endpoint = `http://${options.host}:${boundPort}`;\n\n process.stdout.write(\n [\n '',\n ` tracebird — serving ${store.size} run(s) from`,\n ` ${file}`,\n '',\n ` UI ${endpoint}`,\n '',\n ' (Ctrl-C to stop)',\n '',\n ].join('\\n') + '\\n',\n );\n\n if (options.open) openBrowser(endpoint);\n\n await new Promise<void>((resolveShutdown) => {\n const shutdown = () => {\n process.stdout.write('\\n Stopping…\\n');\n server.close(() => resolveShutdown());\n };\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n });\n}\n","import { buildRuns, parseOtlp } from '@tracebird/core';\nimport { otlpFixtures } from '@tracebird/fixtures';\nimport { createServer, listen } from '../server.js';\nimport { SessionStore } from '../storage/session-store.js';\nimport { createAppHandler } from '../app.js';\nimport { resolveUiDir } from '../ui-dir.js';\nimport { openBrowser } from '../open-browser.js';\n\nexport interface DemoOptions {\n port: number;\n host: string;\n open: boolean;\n}\n\n/**\n * `tracebird demo` — serve the UI pre-loaded with the bundled sample runs\n * (a multi-tool run, a tool error, and a diff pair) so you can explore the\n * inspector, scrubber, and diff without wiring up a real agent.\n */\nexport async function runDemo(options: DemoOptions): Promise<void> {\n const store = new SessionStore();\n for (const payload of Object.values(otlpFixtures)) {\n for (const run of buildRuns(parseOtlp(payload))) store.addRun(run, { persist: false });\n }\n\n const server = createServer({\n extraHandler: createAppHandler({ store, live: false }, resolveUiDir()),\n });\n const boundPort = await listen(server, options.port, options.host);\n const endpoint = `http://${options.host}:${boundPort}`;\n\n process.stdout.write(\n [\n '',\n ` tracebird — demo mode, ${store.size} sample run(s) loaded`,\n '',\n ` UI ${endpoint}`,\n '',\n ' Try the Diff tab (the two support-triage runs differ on one decision),',\n ' and drag the scrubber to time-travel through a run.',\n '',\n ' (Ctrl-C to stop)',\n '',\n ].join('\\n') + '\\n',\n );\n\n if (options.open) openBrowser(endpoint);\n\n await new Promise<void>((resolveShutdown) => {\n const shutdown = () => {\n process.stdout.write('\\n Stopping…\\n');\n server.close(() => resolveShutdown());\n };\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n });\n}\n","/**\n * Tiny builders for assembling OTLP/HTTP JSON trace payloads by hand.\n *\n * Intentionally self-contained — fixtures import nothing internal so the\n * project graph stays acyclic (core's tests depend on fixtures, not vice-versa).\n * The emitted shape matches the OTLP/JSON protobuf mapping that\n * `@tracebird/core`'s `parseOtlp` consumes.\n */\n\nexport interface AnyValue {\n stringValue?: string;\n boolValue?: boolean;\n intValue?: string;\n doubleValue?: number;\n arrayValue?: { values: AnyValue[] };\n}\n\nexport interface KeyValue {\n key: string;\n value: AnyValue;\n}\n\nexport type AttrInput = string | number | boolean;\n\nfunction toAnyValue(v: AttrInput): AnyValue {\n if (typeof v === 'string') return { stringValue: v };\n if (typeof v === 'boolean') return { boolValue: v };\n return Number.isInteger(v) ? { intValue: String(v) } : { doubleValue: v };\n}\n\n/** Convert a flat record into an OTLP `KeyValue[]`. */\nexport function attrs(record: Record<string, AttrInput>): KeyValue[] {\n return Object.entries(record).map(([key, v]) => ({ key, value: toAnyValue(v) }));\n}\n\nexport interface SpanInput {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n kind?: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes?: Record<string, AttrInput>;\n /** OTLP status code: 0 unset, 1 ok, 2 error. */\n statusCode?: number;\n statusMessage?: string;\n}\n\nexport interface OtlpSpanJson {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: KeyValue[];\n status: { code: number; message?: string };\n}\n\nexport function span(input: SpanInput): OtlpSpanJson {\n return {\n traceId: input.traceId,\n spanId: input.spanId,\n ...(input.parentSpanId ? { parentSpanId: input.parentSpanId } : {}),\n name: input.name,\n kind: input.kind ?? 1,\n startTimeUnixNano: input.startTimeUnixNano,\n endTimeUnixNano: input.endTimeUnixNano,\n attributes: attrs(input.attributes ?? {}),\n status: {\n code: input.statusCode ?? 0,\n ...(input.statusMessage ? { message: input.statusMessage } : {}),\n },\n };\n}\n\nexport interface TraceRequestInput {\n serviceName: string;\n scopeName: string;\n scopeVersion?: string;\n spans: OtlpSpanJson[];\n}\n\n/** Wrap spans into a complete `ExportTraceServiceRequest` JSON payload. */\nexport function traceRequest(input: TraceRequestInput) {\n return {\n resourceSpans: [\n {\n resource: {\n attributes: attrs({ 'service.name': input.serviceName }),\n },\n scopeSpans: [\n {\n scope: {\n name: input.scopeName,\n ...(input.scopeVersion ? { version: input.scopeVersion } : {}),\n },\n spans: input.spans,\n },\n ],\n },\n ],\n };\n}\n\n/** Nanosecond timestamp helper: base epoch-nanos + a millisecond offset. */\nexport function at(baseNano: bigint, offsetMs: number): string {\n return (baseNano + BigInt(offsetMs) * 1_000_000n).toString();\n}\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * Happy-path, multi-tool agent run: a weather assistant that makes one planning\n * LLM call, fans out to two tools (get_weather, get_forecast), then makes a\n * final LLM call to compose the answer. Uses the OpenLLMetry-style buffered\n * prompt/completion attributes (`gen_ai.prompt.N.*` / `gen_ai.completion.N.*`).\n */\n\nconst BASE = 1733000000000000000n;\nconst TRACE = '0af7651916cd43dd8448eb211c80319c';\n\nconst ROOT = '1111111111111111';\nconst LLM1 = '2222222222222222';\nconst TOOL1 = '3333333333333333';\nconst TOOL2 = '4444444444444444';\nconst LLM2 = '5555555555555555';\n\nexport const weatherHappyPath = traceRequest({\n serviceName: 'weather-assistant',\n scopeName: 'opentelemetry.instrumentation.openai',\n scopeVersion: '0.30.0',\n spans: [\n span({\n traceId: TRACE,\n spanId: ROOT,\n name: 'invoke_agent weather-assistant',\n startTimeUnixNano: at(BASE, 0),\n endTimeUnixNano: at(BASE, 1300),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'invoke_agent',\n 'gen_ai.agent.name': 'weather-assistant',\n 'gen_ai.system': 'openai',\n },\n }),\n span({\n traceId: TRACE,\n spanId: LLM1,\n parentSpanId: ROOT,\n name: 'chat gpt-4o',\n startTimeUnixNano: at(BASE, 10),\n endTimeUnixNano: at(BASE, 520),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'chat',\n 'gen_ai.system': 'openai',\n 'gen_ai.request.model': 'gpt-4o',\n 'gen_ai.response.model': 'gpt-4o-2024-08-06',\n 'gen_ai.request.temperature': 0.7,\n 'gen_ai.usage.input_tokens': 58,\n 'gen_ai.usage.output_tokens': 34,\n 'gen_ai.prompt.0.role': 'system',\n 'gen_ai.prompt.0.content':\n 'You are a helpful weather assistant. Use tools to look up live data before answering.',\n 'gen_ai.prompt.1.role': 'user',\n 'gen_ai.prompt.1.content': 'What should I wear in Paris today?',\n 'gen_ai.completion.0.role': 'assistant',\n 'gen_ai.completion.0.content': '',\n 'gen_ai.completion.0.tool_calls.0.id': 'call_weather',\n 'gen_ai.completion.0.tool_calls.0.name': 'get_weather',\n 'gen_ai.completion.0.tool_calls.0.arguments': '{\"location\":\"Paris\"}',\n 'gen_ai.completion.0.tool_calls.1.id': 'call_forecast',\n 'gen_ai.completion.0.tool_calls.1.name': 'get_forecast',\n 'gen_ai.completion.0.tool_calls.1.arguments': '{\"location\":\"Paris\",\"hours\":12}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL1,\n parentSpanId: ROOT,\n name: 'execute_tool get_weather',\n startTimeUnixNano: at(BASE, 530),\n endTimeUnixNano: at(BASE, 548),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'execute_tool',\n 'gen_ai.tool.name': 'get_weather',\n 'gen_ai.tool.call.id': 'call_weather',\n 'gen_ai.tool.call.arguments': '{\"location\":\"Paris\"}',\n 'gen_ai.tool.call.result': '{\"tempC\":18,\"condition\":\"sunny\",\"humidity\":0.41}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL2,\n parentSpanId: ROOT,\n name: 'execute_tool get_forecast',\n startTimeUnixNano: at(BASE, 532),\n endTimeUnixNano: at(BASE, 560),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'execute_tool',\n 'gen_ai.tool.name': 'get_forecast',\n 'gen_ai.tool.call.id': 'call_forecast',\n 'gen_ai.tool.call.arguments': '{\"location\":\"Paris\",\"hours\":12}',\n 'gen_ai.tool.call.result': '{\"highC\":21,\"lowC\":12,\"rain\":false}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: LLM2,\n parentSpanId: ROOT,\n name: 'chat gpt-4o',\n startTimeUnixNano: at(BASE, 580),\n endTimeUnixNano: at(BASE, 1290),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'chat',\n 'gen_ai.system': 'openai',\n 'gen_ai.request.model': 'gpt-4o',\n 'gen_ai.response.model': 'gpt-4o-2024-08-06',\n 'gen_ai.request.temperature': 0.7,\n 'gen_ai.usage.input_tokens': 140,\n 'gen_ai.usage.output_tokens': 42,\n 'gen_ai.prompt.0.role': 'system',\n 'gen_ai.prompt.0.content':\n 'You are a helpful weather assistant. Use tools to look up live data before answering.',\n 'gen_ai.prompt.1.role': 'user',\n 'gen_ai.prompt.1.content': 'What should I wear in Paris today?',\n 'gen_ai.prompt.2.role': 'tool',\n 'gen_ai.prompt.2.content': '{\"tempC\":18,\"condition\":\"sunny\",\"humidity\":0.41}',\n 'gen_ai.prompt.3.role': 'tool',\n 'gen_ai.prompt.3.content': '{\"highC\":21,\"lowC\":12,\"rain\":false}',\n 'gen_ai.completion.0.role': 'assistant',\n 'gen_ai.completion.0.content':\n \"It's 18°C and sunny in Paris, with a high of 21°C and no rain expected. \" +\n \"A light jacket or long sleeves will be perfect — you won't need an umbrella.\",\n },\n }),\n ],\n});\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * A run where a tool call fails: the model asks for weather in a place the tool\n * can't resolve, the `execute_tool` span carries an ERROR status, and the agent\n * recovers with an apology. Exercises error propagation in the tree.\n */\n\nconst BASE = 1733000100000000000n;\nconst TRACE = 'b2c3d4e5f60718293a4b5c6d7e8f9012';\n\nconst ROOT = 'aa00000000000001';\nconst LLM1 = 'aa00000000000002';\nconst TOOL1 = 'aa00000000000003';\nconst LLM2 = 'aa00000000000004';\n\nexport const toolError = traceRequest({\n serviceName: 'weather-assistant',\n scopeName: 'opentelemetry.instrumentation.openai',\n scopeVersion: '0.30.0',\n spans: [\n span({\n traceId: TRACE,\n spanId: ROOT,\n name: 'invoke_agent weather-assistant',\n startTimeUnixNano: at(BASE, 0),\n endTimeUnixNano: at(BASE, 900),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'invoke_agent',\n 'gen_ai.agent.name': 'weather-assistant',\n 'gen_ai.system': 'openai',\n },\n }),\n span({\n traceId: TRACE,\n spanId: LLM1,\n parentSpanId: ROOT,\n name: 'chat gpt-4o',\n startTimeUnixNano: at(BASE, 8),\n endTimeUnixNano: at(BASE, 410),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'chat',\n 'gen_ai.system': 'openai',\n 'gen_ai.request.model': 'gpt-4o',\n 'gen_ai.response.model': 'gpt-4o-2024-08-06',\n 'gen_ai.usage.input_tokens': 52,\n 'gen_ai.usage.output_tokens': 16,\n 'gen_ai.prompt.0.role': 'user',\n 'gen_ai.prompt.0.content': \"What's the weather in Atlantis?\",\n 'gen_ai.completion.0.role': 'assistant',\n 'gen_ai.completion.0.content': '',\n 'gen_ai.completion.0.tool_calls.0.id': 'call_weather',\n 'gen_ai.completion.0.tool_calls.0.name': 'get_weather',\n 'gen_ai.completion.0.tool_calls.0.arguments': '{\"location\":\"Atlantis\"}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL1,\n parentSpanId: ROOT,\n name: 'execute_tool get_weather',\n startTimeUnixNano: at(BASE, 420),\n endTimeUnixNano: at(BASE, 438),\n statusCode: 2,\n statusMessage: 'UnknownLocationError: no such location \"Atlantis\"',\n attributes: {\n 'gen_ai.operation.name': 'execute_tool',\n 'gen_ai.tool.name': 'get_weather',\n 'gen_ai.tool.call.id': 'call_weather',\n 'gen_ai.tool.call.arguments': '{\"location\":\"Atlantis\"}',\n 'error.type': 'UnknownLocationError',\n 'gen_ai.tool.call.result': '{\"error\":\"no such location \\\\\"Atlantis\\\\\"\"}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: LLM2,\n parentSpanId: ROOT,\n name: 'chat gpt-4o',\n startTimeUnixNano: at(BASE, 450),\n endTimeUnixNano: at(BASE, 890),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'chat',\n 'gen_ai.system': 'openai',\n 'gen_ai.request.model': 'gpt-4o',\n 'gen_ai.response.model': 'gpt-4o-2024-08-06',\n 'gen_ai.usage.input_tokens': 88,\n 'gen_ai.usage.output_tokens': 28,\n 'gen_ai.prompt.0.role': 'user',\n 'gen_ai.prompt.0.content': \"What's the weather in Atlantis?\",\n 'gen_ai.prompt.1.role': 'tool',\n 'gen_ai.prompt.1.content': '{\"error\":\"no such location \\\\\"Atlantis\\\\\"\"}',\n 'gen_ai.completion.0.role': 'assistant',\n 'gen_ai.completion.0.content':\n 'I couldn\\'t find a place called \"Atlantis\" to look up the weather. Could you double-check the spelling or give me a nearby city?',\n },\n }),\n ],\n});\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * Two near-identical triage runs over the same support ticket that diverge on a\n * single decision: run A (gpt-4o) assigns priority P1; run B (gpt-4o-mini)\n * assigns P2. Same prompt, same shape — ideal for the diff demo.\n */\n\nconst TICKET =\n 'Customer reports the checkout page returns a 500 error intermittently on mobile Safari. ' +\n 'They have tried twice. No charge was made.';\n\nconst SYSTEM =\n 'You are a support triage agent. Read the ticket and assign a priority from P1 (urgent) to P4 (low).';\n\nfunction triageRun(opts: {\n base: bigint;\n trace: string;\n rootId: string;\n llmId: string;\n model: string;\n responseModel: string;\n outputTokens: number;\n endMs: number;\n completion: string;\n}) {\n return traceRequest({\n serviceName: 'support-triage',\n scopeName: 'opentelemetry.instrumentation.openai',\n scopeVersion: '0.30.0',\n spans: [\n span({\n traceId: opts.trace,\n spanId: opts.rootId,\n name: 'invoke_agent support-triage',\n startTimeUnixNano: at(opts.base, 0),\n endTimeUnixNano: at(opts.base, opts.endMs),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'invoke_agent',\n 'gen_ai.agent.name': 'support-triage',\n 'gen_ai.system': 'openai',\n },\n }),\n span({\n traceId: opts.trace,\n spanId: opts.llmId,\n parentSpanId: opts.rootId,\n name: `chat ${opts.model}`,\n startTimeUnixNano: at(opts.base, 6),\n endTimeUnixNano: at(opts.base, opts.endMs - 4),\n statusCode: 1,\n attributes: {\n 'gen_ai.operation.name': 'chat',\n 'gen_ai.system': 'openai',\n 'gen_ai.request.model': opts.model,\n 'gen_ai.response.model': opts.responseModel,\n 'gen_ai.request.temperature': 0.2,\n 'gen_ai.usage.input_tokens': 96,\n 'gen_ai.usage.output_tokens': opts.outputTokens,\n 'gen_ai.prompt.0.role': 'system',\n 'gen_ai.prompt.0.content': SYSTEM,\n 'gen_ai.prompt.1.role': 'user',\n 'gen_ai.prompt.1.content': TICKET,\n 'gen_ai.completion.0.role': 'assistant',\n 'gen_ai.completion.0.content': opts.completion,\n },\n }),\n ],\n });\n}\n\nexport const diffPairA = triageRun({\n base: 1733000200000000000n,\n trace: 'c1000000000000000000000000000a01',\n rootId: 'c100000000000a01',\n llmId: 'c100000000000a02',\n model: 'gpt-4o',\n responseModel: 'gpt-4o-2024-08-06',\n outputTokens: 54,\n endMs: 640,\n completion:\n 'Priority: P1. A 500 error at checkout blocks revenue and affects all mobile Safari ' +\n 'users intermittently. Escalate to the payments team immediately.',\n});\n\nexport const diffPairB = triageRun({\n base: 1733000300000000000n,\n trace: 'c2000000000000000000000000000b01',\n rootId: 'c200000000000b01',\n llmId: 'c200000000000b02',\n model: 'gpt-4o-mini',\n responseModel: 'gpt-4o-mini-2024-07-18',\n outputTokens: 48,\n endMs: 410,\n completion:\n 'Priority: P2. Checkout returns a 500 on mobile Safari intermittently, but no charge ' +\n 'was made and a retry path exists. Route to the web team for investigation.',\n});\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * OpenInference (Arize Phoenix) dialect: `openinference.span.kind` + `llm.*` /\n * `tool.*` / `input.value` attributes. A small agent that calls one tool.\n */\n\nconst BASE = 1733000400000000000n;\nconst TRACE = 'd1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1';\nconst ROOT = 'd1000000000000a1';\nconst LLM = 'd1000000000000a2';\nconst TOOL = 'd1000000000000a3';\n\nexport const openinferenceAgent = traceRequest({\n serviceName: 'docs-assistant',\n scopeName: 'openinference.instrumentation.openai',\n scopeVersion: '0.1.0',\n spans: [\n span({\n traceId: TRACE,\n spanId: ROOT,\n name: 'agent',\n startTimeUnixNano: at(BASE, 0),\n endTimeUnixNano: at(BASE, 900),\n statusCode: 1,\n attributes: { 'openinference.span.kind': 'AGENT' },\n }),\n span({\n traceId: TRACE,\n spanId: LLM,\n parentSpanId: ROOT,\n name: 'ChatCompletion',\n startTimeUnixNano: at(BASE, 10),\n endTimeUnixNano: at(BASE, 460),\n statusCode: 1,\n attributes: {\n 'openinference.span.kind': 'LLM',\n 'llm.model_name': 'gpt-4o',\n 'llm.provider': 'openai',\n 'llm.token_count.prompt': 42,\n 'llm.token_count.completion': 18,\n 'llm.input_messages.0.message.role': 'system',\n 'llm.input_messages.0.message.content': 'You answer questions about the docs.',\n 'llm.input_messages.1.message.role': 'user',\n 'llm.input_messages.1.message.content': 'How do I enable telemetry?',\n 'llm.output_messages.0.message.role': 'assistant',\n 'llm.output_messages.0.message.content': '',\n 'llm.output_messages.0.message.tool_calls.0.tool_call.function.name': 'search_docs',\n 'llm.output_messages.0.message.tool_calls.0.tool_call.function.arguments':\n '{\"query\":\"enable telemetry\"}',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL,\n parentSpanId: ROOT,\n name: 'search_docs',\n startTimeUnixNano: at(BASE, 470),\n endTimeUnixNano: at(BASE, 500),\n statusCode: 1,\n attributes: {\n 'openinference.span.kind': 'TOOL',\n 'tool.name': 'search_docs',\n 'input.value': '{\"query\":\"enable telemetry\"}',\n 'output.value': '{\"hits\":[\"Set OTEL_EXPORTER_OTLP_ENDPOINT=…\"]}',\n },\n }),\n ],\n});\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * Vercel AI SDK dialect: `ai.generateText` wrapper, an inner `.doGenerate`\n * model call, and an `ai.toolCall` span — the shape emitted by\n * `experimental_telemetry`.\n */\n\nconst BASE = 1733000500000000000n;\nconst TRACE = 'e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1';\nconst ROOT = 'e1000000000000b1';\nconst GEN = 'e1000000000000b2';\nconst TOOL = 'e1000000000000b3';\n\nexport const vercelAiSdk = traceRequest({\n serviceName: 'ai-sdk-app',\n scopeName: 'ai',\n scopeVersion: '4.0.0',\n spans: [\n span({\n traceId: TRACE,\n spanId: ROOT,\n name: 'ai.generateText',\n startTimeUnixNano: at(BASE, 0),\n endTimeUnixNano: at(BASE, 1100),\n statusCode: 1,\n attributes: {\n 'ai.model.id': 'gpt-4o',\n 'ai.model.provider': 'openai.chat',\n 'ai.usage.promptTokens': 64,\n 'ai.usage.completionTokens': 30,\n },\n }),\n span({\n traceId: TRACE,\n spanId: GEN,\n parentSpanId: ROOT,\n name: 'ai.generateText.doGenerate',\n startTimeUnixNano: at(BASE, 20),\n endTimeUnixNano: at(BASE, 540),\n statusCode: 1,\n attributes: {\n 'ai.model.id': 'gpt-4o',\n 'ai.model.provider': 'openai.chat',\n 'ai.usage.promptTokens': 64,\n 'ai.usage.completionTokens': 30,\n 'ai.prompt.messages':\n '[{\"role\":\"user\",\"content\":\"What is the weather in San Francisco?\"}]',\n 'ai.response.text': 'Let me check the current conditions in San Francisco.',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL,\n parentSpanId: ROOT,\n name: 'ai.toolCall',\n startTimeUnixNano: at(BASE, 560),\n endTimeUnixNano: at(BASE, 600),\n statusCode: 1,\n attributes: {\n 'ai.toolCall.name': 'getWeather',\n 'ai.toolCall.args': '{\"city\":\"San Francisco\"}',\n 'ai.toolCall.result': '{\"tempC\":17,\"condition\":\"foggy\"}',\n },\n }),\n ],\n});\n","import { at, span, traceRequest } from './builders.js';\n\n/**\n * Claude Code (CLI) enhanced-telemetry dialect: `claude_code.interaction`,\n * `claude_code.llm_request`, `claude_code.tool` spans with bare token counts\n * and `tool_name` / `user_prompt` attributes.\n */\n\nconst BASE = 1733000600000000000n;\nconst TRACE = 'f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1';\nconst ROOT = 'f1000000000000c1';\nconst LLM = 'f1000000000000c2';\nconst TOOL = 'f1000000000000c3';\n\nexport const claudeCodeSession = traceRequest({\n serviceName: 'claude-code',\n scopeName: 'com.anthropic.claude_code',\n scopeVersion: '2.0.0',\n spans: [\n span({\n traceId: TRACE,\n spanId: ROOT,\n name: 'claude_code.interaction',\n startTimeUnixNano: at(BASE, 0),\n endTimeUnixNano: at(BASE, 4200),\n statusCode: 1,\n attributes: {\n 'user_prompt': 'Add a --json flag to the parser CLI',\n 'interaction.sequence': 1,\n },\n }),\n span({\n traceId: TRACE,\n spanId: LLM,\n parentSpanId: ROOT,\n name: 'claude_code.llm_request',\n startTimeUnixNano: at(BASE, 30),\n endTimeUnixNano: at(BASE, 2600),\n statusCode: 1,\n attributes: {\n 'gen_ai.system': 'anthropic',\n 'gen_ai.request.model': 'claude-sonnet-4',\n 'input_tokens': 1840,\n 'output_tokens': 420,\n 'cache_read_tokens': 12000,\n 'gen_ai.response.finish_reasons': 'tool_use',\n 'user_prompt': 'Add a --json flag to the parser CLI',\n },\n }),\n span({\n traceId: TRACE,\n spanId: TOOL,\n parentSpanId: ROOT,\n name: 'claude_code.tool',\n startTimeUnixNano: at(BASE, 2650),\n endTimeUnixNano: at(BASE, 2710),\n statusCode: 1,\n attributes: {\n 'tool_name': 'Edit',\n 'file_path': 'packages/cli/src/parser.ts',\n 'tool_output': 'Applied 1 edit to packages/cli/src/parser.ts',\n },\n }),\n ],\n});\n","/**\n * @tracebird/fixtures — sample OTLP payloads and recorded sessions used by\n * core/cli tests and as demo data for `tracebird open`.\n */\n\nexport * from './otlp/builders.js';\nexport { weatherHappyPath } from './otlp/weather-happy-path.js';\nexport { toolError } from './otlp/tool-error.js';\nexport { diffPairA, diffPairB } from './otlp/diff-pair.js';\nexport { openinferenceAgent } from './otlp/openinference.js';\nexport { vercelAiSdk } from './otlp/vercel-ai-sdk.js';\nexport { claudeCodeSession } from './otlp/claude-code.js';\n\nimport { weatherHappyPath } from './otlp/weather-happy-path.js';\nimport { toolError } from './otlp/tool-error.js';\nimport { diffPairA, diffPairB } from './otlp/diff-pair.js';\nimport { openinferenceAgent } from './otlp/openinference.js';\nimport { vercelAiSdk } from './otlp/vercel-ai-sdk.js';\nimport { claudeCodeSession } from './otlp/claude-code.js';\n\n/** All OTLP request fixtures, keyed by a short name. */\nexport const otlpFixtures = {\n weatherHappyPath,\n toolError,\n diffPairA,\n diffPairB,\n openinferenceAgent,\n vercelAiSdk,\n claudeCodeSession,\n} as const;\n\nexport type OtlpFixtureName = keyof typeof otlpFixtures;\n"],"mappings":"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","names":["resolve","join","span","resolve","resolve","span","StatusCode","StatusCode","join","readFileSync","readFileSync","json","join","existsSync","join","existsSync","dirname","join","join","existsSync","existsSync","parseOtlp","BASE","TRACE","ROOT","LLM1","TOOL1","LLM2","BASE","TRACE","ROOT","BASE","TRACE","ROOT","TOOL","BASE","TRACE","ROOT","LLM","TOOL","parseOtlp","resolve"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--bg: #0f1117;--panel: #171a23;--panel-2: #1d212c;--border: #272b38;--text: #e6e8ee;--muted: #9aa0ad;--accent: #6ea8fe;--error: #ff6b6b;--ok: #5ec5a0;font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--bg);color:var(--text)}.app-shell{display:flex;flex-direction:column;height:100vh}.app-header{display:flex;align-items:center;gap:12px;padding:10px 18px;border-bottom:1px solid var(--border);background:var(--panel)}.logo{font-weight:700;letter-spacing:-.01em}.tagline{color:var(--muted);font-size:12px}.spacer{flex:1}.run-count{color:var(--muted);font-size:12px}.mode-toggle{display:flex;border:1px solid var(--border);border-radius:8px;overflow:hidden;margin-left:8px}.mode-toggle button{background:transparent;border:none;color:var(--muted);padding:5px 14px;cursor:pointer;font-size:13px}.mode-toggle button.active{background:var(--panel-2);color:var(--text)}.scrubber{padding:10px 16px;border-bottom:1px solid var(--border);background:var(--panel)}.scrubber-ticks{display:flex;gap:3px;height:10px;margin-bottom:8px}.scrubber-tick{flex:1;border:none;border-radius:2px;opacity:.35;cursor:pointer;padding:0;min-width:4px}.scrubber-tick.active{opacity:1;outline:2px solid var(--text)}.scrubber-controls input[type=range]{width:100%;accent-color:var(--accent)}.scrubber-readout{display:flex;align-items:center;gap:8px;font-size:13px;margin-top:2px}.scrubber-name{font-weight:500}.layout-diff{flex:1;overflow:auto;padding:16px 20px 40px}.diff-pickers{display:flex;align-items:center;gap:12px;margin-bottom:16px}.run-picker{display:flex;align-items:center;gap:8px}.run-picker-label{width:20px;height:20px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:700}.run-picker-a .run-picker-label{background:#ff6b6b2e;color:var(--error)}.run-picker-b .run-picker-label{background:#5ec5a02e;color:var(--ok)}.run-picker select{background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:8px;padding:6px 10px;max-width:360px}.diff-arrow{color:var(--muted)}.diff-section{margin-bottom:20px}.diff-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:0 0 8px}.field-changes{border-collapse:collapse;font-size:13px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.field-changes td{padding:2px 10px 2px 0;vertical-align:top}.field-name{color:var(--muted)}.field-a{color:var(--error)}.field-b{color:var(--ok)}.field-arrow{color:var(--muted)}.diff-node{border-left:2px solid var(--border);padding:6px 0 6px 12px;margin:6px 0 6px 4px}.diff-node.diff-added{border-left-color:var(--ok)}.diff-node.diff-removed{border-left-color:var(--error)}.diff-node.diff-changed{border-left-color:var(--accent)}.diff-node-head{display:flex;align-items:center;gap:8px}.diff-node-name{font-weight:500}.diff-status-tag{font-size:10px;text-transform:uppercase;letter-spacing:.05em;padding:1px 6px;border-radius:999px;border:1px solid var(--border);color:var(--muted)}.tag-added{color:var(--ok);border-color:var(--ok)}.tag-removed{color:var(--error);border-color:var(--error)}.tag-changed{color:var(--accent);border-color:var(--accent)}.diff-text{margin:6px 0}.diff-text-label{font-size:11px;text-transform:uppercase;color:var(--muted);margin-bottom:2px}.text-diff{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:8px 10px;margin:0;white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5}.seg-add{background:#5ec5a038;color:#b6f0db}.seg-remove{background:#ff6b6b38;color:#ffc9c9;text-decoration:line-through}.layout{flex:1;display:grid;grid-template-columns:280px minmax(0,1fr) 380px;min-height:0}.sidebar,.inspector-pane{background:var(--panel);overflow-y:auto}.sidebar{border-right:1px solid var(--border)}.inspector-pane{border-left:1px solid var(--border)}.main{display:flex;flex-direction:column;min-height:0;overflow:hidden}.pane-title{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:0;padding:14px 16px 8px}.run-filters{padding:0 12px 8px;display:flex;flex-direction:column;gap:8px}.run-search{width:100%;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:8px;padding:7px 10px;font-size:13px}.run-search:focus{outline:none;border-color:var(--accent)}.status-filter{display:flex;border:1px solid var(--border);border-radius:8px;overflow:hidden;width:fit-content}.status-filter button{background:transparent;border:none;color:var(--muted);padding:4px 12px;cursor:pointer;font-size:12px}.status-filter button.active{background:var(--panel-2);color:var(--text)}.run-list{list-style:none;margin:0;padding:0 8px 8px}.sidebar-empty,.inspector-empty{color:var(--muted);padding:8px 16px}.run-item{width:100%;text-align:left;background:transparent;border:1px solid transparent;border-radius:8px;padding:9px 10px;color:inherit;cursor:pointer;display:flex;flex-direction:column;gap:6px}.run-item:hover{background:var(--panel-2)}.run-item.selected{background:var(--panel-2);border-color:var(--border)}.run-item-top{display:flex;align-items:center;gap:8px}.run-summary{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.run-item-meta{display:flex;gap:10px;color:var(--muted);font-size:12px;padding-left:16px}.status-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:var(--muted)}.status-ok{background:var(--ok)}.status-error{background:var(--error)}.run-bar{padding:12px 16px;border-bottom:1px solid var(--border);background:var(--panel);display:flex;align-items:center;gap:12px}.run-bar-main{min-width:0;flex:1}.run-bar-actions{display:flex;gap:6px;flex:0 0 auto}.share-btn{display:inline-flex;align-items:center;border:1px solid var(--accent);color:var(--accent);background:transparent;border-radius:8px;padding:5px 12px;font-size:12px;text-decoration:none;cursor:pointer}.share-btn:hover{background:#6ea8fe1f}.share-btn-ghost{border-color:var(--border);color:var(--muted)}.run-bar-summary{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.run-bar-metrics{display:flex;gap:14px;color:var(--muted);font-size:12px;margin-top:4px}.tree{flex:1;overflow:auto;padding:8px 0}.tree-row{display:flex;align-items:center;gap:6px;padding:4px 12px 4px 0;cursor:pointer;font-variant-numeric:tabular-nums}.tree-row:hover{background:var(--panel-2)}.tree-row.selected{background:#223052}.tree-toggle{width:16px;background:none;border:none;color:var(--muted);cursor:pointer;padding:0;flex:0 0 auto}.tree-icon{flex:0 0 auto}.tree-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tree-metrics{margin-left:auto;display:flex;gap:12px;color:var(--muted);font-size:12px;padding-left:12px;flex:0 0 auto}.badge{font-size:11px;padding:2px 7px;border-radius:999px;border:1px solid var(--border)}.badge-error{color:var(--error);border-color:var(--error)}.badge-live{color:var(--ok);border-color:var(--ok)}.badge-activity{color:var(--accent);border-color:var(--accent);animation:pulse 1s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.45}}.inspector{padding:4px 16px 24px}.inspector-header{display:flex;gap:10px;align-items:center;padding:8px 0 12px}.inspector-title{font-weight:600;word-break:break-word}.inspector-kind{color:var(--muted);font-size:12px}.facts{display:grid;grid-template-columns:auto 1fr;gap:4px 14px;margin:0 0 12px}.fact{display:contents}.fact dt{color:var(--muted);font-size:12px}.fact dd{margin:0;font-size:13px;word-break:break-word}.inspector-section{margin-top:16px}.inspector-section h3{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:0 0 8px;display:flex;align-items:center;gap:8px}.inspector-section h3 .count{background:var(--panel-2);border-radius:999px;padding:0 7px;font-size:11px}.muted{color:var(--muted)}.messages{display:flex;flex-direction:column;gap:8px}.message{background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:8px 10px}.message-role{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);margin-bottom:4px}.message-content{white-space:pre-wrap;word-break:break-word;line-height:1.45}.tool-calls{margin-top:6px}.tool-call-name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ok);font-size:12px}.json-block{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:10px 12px;margin:6px 0 0;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word}.empty-state{margin:auto;max-width:520px;text-align:center;padding:48px 24px}.empty-state h1{font-size:20px;font-weight:600}.empty-state p{color:var(--muted)}.empty-state pre{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:12px 14px;color:var(--accent);overflow-x:auto}
|