{"version":3,"file":"src-adtyx8HT.cjs","names":["SpanStatusCode","SpanKind","getServiceName","standardComponentDefinitions","tool","z","Box","Text","InkRenderer"],"sources":["../src/streaming-processor.ts","../src/span-stream.ts","../src/lib/trace-model.ts","../src/lib/format.ts","../src/lib/service-colors.ts","../src/lib/log-model.ts","../src/log-stream.ts","../src/lib/stats-model.ts","../src/lib/filters.ts","../src/lib/error-model.ts","../src/lib/topology-model.ts","../src/lib/topology-render.ts","../src/lib/export-model.ts","../src/ai/provider.ts","../src/ai/system-prompt.ts","../src/ai/tools.ts","../src/ai/stream.ts","../src/index.tsx"],"sourcesContent":["/**\n * Streaming Span Processor\n *\n * A span processor that emits ReadableSpan objects to subscribers.\n * This allows real-time streaming of spans to terminal dashboards and other consumers.\n *\n * @example Basic usage\n * ```typescript\n * import { StreamingSpanProcessor } from 'autotel-terminal'\n * import { BatchSpanProcessor } from 'autotel/processors'\n * import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\n *\n * const exporter = new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces' })\n * const baseProcessor = new BatchSpanProcessor(exporter)\n * const streamingProcessor = new StreamingSpanProcessor(baseProcessor)\n *\n * // Subscribe to spans\n * const unsubscribe = streamingProcessor.subscribe((span) => {\n *   console.log('Span ended:', span.name)\n * })\n *\n * // Later, unsubscribe\n * unsubscribe()\n * ```\n */\n\nimport type {\n  SpanProcessor,\n  ReadableSpan,\n} from '@opentelemetry/sdk-trace-base';\nimport type { Context } from '@opentelemetry/api';\nimport type { Span } from '@opentelemetry/sdk-trace-base';\n\n/**\n * Span processor that wraps another processor and emits spans to subscribers\n *\n * This processor forwards all span operations to a wrapped processor while\n * also emitting completed spans to registered subscribers. This enables\n * real-time streaming of spans to terminal dashboards, loggers, or other\n * consumers without interfering with normal span processing.\n */\nexport class StreamingSpanProcessor implements SpanProcessor {\n  private wrappedProcessor: SpanProcessor | null;\n  private subscribers = new Set<(span: ReadableSpan) => void>();\n\n  /**\n   * Create a new streaming span processor\n   *\n   * @param wrappedProcessor - The processor to wrap and forward spans to.\n   *                          If null, spans are only emitted to subscribers (no forwarding).\n   */\n  constructor(wrappedProcessor: SpanProcessor | null = null) {\n    this.wrappedProcessor = wrappedProcessor;\n  }\n\n  onStart(span: Span, parentContext: Context): void {\n    if (this.wrappedProcessor) {\n      this.wrappedProcessor.onStart(span, parentContext);\n    }\n  }\n\n  onEnd(span: ReadableSpan): void {\n    // Emit to all subscribers first\n    for (const subscriber of this.subscribers) {\n      try {\n        subscriber(span);\n      } catch (error) {\n        // Don't let subscriber errors break span processing\n        console.error('[autotel-terminal] Subscriber error:', error);\n      }\n    }\n\n    // Forward to wrapped processor\n    if (this.wrappedProcessor) {\n      this.wrappedProcessor.onEnd(span);\n    }\n  }\n\n  /**\n   * Subscribe to span end events\n   *\n   * @param callback - Function called when a span ends\n   * @returns Unsubscribe function\n   *\n   * @example\n   * ```typescript\n   * const unsubscribe = processor.subscribe((span) => {\n   *   console.log('Span ended:', span.name)\n   * })\n   *\n   * // Later, unsubscribe\n   * unsubscribe()\n   * ```\n   */\n  subscribe(callback: (span: ReadableSpan) => void): () => void {\n    this.subscribers.add(callback);\n    return () => this.subscribers.delete(callback);\n  }\n\n  async forceFlush(): Promise<void> {\n    if (this.wrappedProcessor) {\n      return this.wrappedProcessor.forceFlush();\n    }\n  }\n\n  async shutdown(): Promise<void> {\n    // Clear subscribers\n    this.subscribers.clear();\n    if (this.wrappedProcessor) {\n      return this.wrappedProcessor.shutdown();\n    }\n  }\n}\n","/**\n * Terminal Span Stream\n *\n * Converts OpenTelemetry ReadableSpan objects to TerminalSpanEvent format\n * for consumption by the terminal dashboard.\n */\n\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { SpanStatusCode, SpanKind } from 'autotel';\nimport type { StreamingSpanProcessor } from './streaming-processor';\n\n/** Span event (e.g. exception, log annotation) */\nexport interface SpanEvent {\n  /** Event name */\n  name: string;\n  /** Time in milliseconds since epoch */\n  timeMs: number;\n  /** Event attributes */\n  attributes?: Record<string, unknown>;\n}\n\n/** Span link (cross-trace reference) */\nexport interface SpanLink {\n  /** Linked trace ID */\n  traceId: string;\n  /** Linked span ID */\n  spanId: string;\n  /** Link attributes */\n  attributes?: Record<string, unknown>;\n}\n\n/**\n * Span event format for terminal dashboard consumption\n */\nexport interface TerminalSpanEvent {\n  /** Span name */\n  name: string;\n  /** Span ID (hex string) */\n  spanId: string;\n  /** Trace ID (hex string) */\n  traceId: string;\n  /** Parent span ID (hex string, optional) */\n  parentSpanId?: string;\n  /** Start time in milliseconds since epoch */\n  startTime: number;\n  /** End time in milliseconds since epoch */\n  endTime: number;\n  /** Duration in milliseconds */\n  durationMs: number;\n  /** Span status */\n  status: 'OK' | 'ERROR' | 'UNSET';\n  /** Span kind (INTERNAL, SERVER, CLIENT, etc.) */\n  kind?: string;\n  /** Span attributes */\n  attributes?: Record<string, unknown>;\n  /** Span events (exceptions, annotations) */\n  events?: SpanEvent[];\n  /** Span links (cross-trace references) */\n  links?: SpanLink[];\n}\n\n/**\n * Stream interface for terminal dashboard\n */\nexport interface TerminalSpanStream {\n  /**\n   * Subscribe to span end events\n   *\n   * @param callback - Called when a span ends\n   * @returns Unsubscribe function\n   */\n  onSpanEnd(callback: (event: TerminalSpanEvent) => void): () => void;\n}\n\n/**\n * Convert OpenTelemetry time tuple to milliseconds\n */\nfunction timeToMs([seconds, nanoseconds]: [number, number]): number {\n  return seconds * 1000 + nanoseconds / 1_000_000;\n}\n\n/**\n * Map SpanStatusCode to string\n */\nfunction mapStatus(code: SpanStatusCode): 'OK' | 'ERROR' | 'UNSET' {\n  if (code === SpanStatusCode.OK) {\n    return 'OK';\n  }\n  if (code === SpanStatusCode.ERROR) {\n    return 'ERROR';\n  }\n  return 'UNSET';\n}\n\n/**\n * Map SpanKind number to string\n */\nfunction mapKind(kind: SpanKind): string {\n  const kindMap: Record<number, string> = {\n    [SpanKind.INTERNAL]: 'INTERNAL',\n    [SpanKind.SERVER]: 'SERVER',\n    [SpanKind.CLIENT]: 'CLIENT',\n    [SpanKind.PRODUCER]: 'PRODUCER',\n    [SpanKind.CONSUMER]: 'CONSUMER',\n  };\n  return kindMap[kind] ?? 'UNKNOWN';\n}\n\n/**\n * Create a terminal span stream from a streaming processor\n *\n * @param processor - The streaming span processor to subscribe to\n * @returns Terminal span stream interface\n *\n * @example\n * ```typescript\n * import { StreamingSpanProcessor } from 'autotel-terminal'\n * import { createTerminalSpanStream } from 'autotel-terminal'\n *\n * const processor = new StreamingSpanProcessor(baseProcessor)\n * const stream = createTerminalSpanStream(processor)\n *\n * stream.onSpanEnd((event) => {\n *   console.log('Span:', event.name, event.durationMs + 'ms')\n * })\n * ```\n */\nexport function createTerminalSpanStream(\n  processor: StreamingSpanProcessor,\n): TerminalSpanStream {\n  return {\n    onSpanEnd(callback) {\n      return processor.subscribe((span: ReadableSpan) => {\n        const spanContext = span.spanContext();\n        // parentSpanId is not part of the standard ReadableSpan interface\n        // but some implementations (like Node.js SDK) include it\n        const parentSpanId =\n          'parentSpanId' in span && typeof span.parentSpanId === 'string'\n            ? span.parentSpanId\n            : undefined;\n\n        // Convert time tuples to milliseconds\n        const startTime = timeToMs(span.startTime);\n        const endTime = timeToMs(span.endTime);\n        const durationMs = endTime - startTime;\n\n        // Merge resource attributes (e.g. service.name) with span attributes\n        const resourceAttrs = (span.resource?.attributes ?? {}) as Record<\n          string,\n          unknown\n        >;\n        const spanAttrs = span.attributes as Record<string, unknown>;\n        const mergedAttrs: Record<string, unknown> = {};\n        for (const [k, v] of Object.entries(resourceAttrs)) {\n          mergedAttrs[k] = v;\n        }\n        for (const [k, v] of Object.entries(spanAttrs)) {\n          mergedAttrs[k] = v;\n        }\n\n        const spanEvents: SpanEvent[] | undefined = span.events?.length\n          ? span.events.map((e) => ({\n              name: e.name,\n              timeMs: timeToMs(e.time),\n              attributes: e.attributes as Record<string, unknown> | undefined,\n            }))\n          : undefined;\n\n        const spanLinks: SpanLink[] | undefined = span.links?.length\n          ? span.links.map((l) => ({\n              traceId: l.context.traceId,\n              spanId: l.context.spanId,\n              attributes: l.attributes as Record<string, unknown> | undefined,\n            }))\n          : undefined;\n\n        // Create terminal event\n        const event: TerminalSpanEvent = {\n          name: span.name,\n          spanId: spanContext.spanId,\n          traceId: spanContext.traceId,\n          parentSpanId,\n          startTime,\n          endTime,\n          durationMs,\n          status: mapStatus(span.status.code),\n          kind: mapKind(span.kind),\n          attributes: mergedAttrs,\n          ...(spanEvents ? { events: spanEvents } : {}),\n          ...(spanLinks ? { links: spanLinks } : {}),\n        };\n\n        callback(event);\n      });\n    },\n  };\n}\n","/**\n * Trace model utilities - pure logic for trace grouping, tree building, and filtering.\n * Kept in lib/ for testability; no React or Ink.\n */\n\nimport type { TerminalSpanEvent } from '../span-stream';\n\n/** Extract service name from span attributes */\nexport function spanServiceName(span: TerminalSpanEvent): string {\n  const svc = span.attributes?.['service.name'];\n  return typeof svc === 'string' ? svc : 'unknown';\n}\n\n/** Trace summary for the \"Recent traces\" list */\nexport interface TraceSummary {\n  traceId: string;\n  rootName: string;\n  durationMs: number;\n  hasError: boolean;\n  spanCount: number;\n  lastEndTime: number;\n  spans: TerminalSpanEvent[];\n  services: string[];\n}\n\n/** Tree node for indented span tree (parent/child) */\nexport interface SpanTreeNode {\n  span: TerminalSpanEvent;\n  depth: number;\n  children: SpanTreeNode[];\n}\n\n/** Span with depth for waterfall (sorted by startTime, then depth) */\nexport interface SpanWithDepth {\n  span: TerminalSpanEvent;\n  depth: number;\n}\n\n/** Aggregate stats over spans */\nexport interface SpanStats {\n  total: number;\n  errors: number;\n  avg: number;\n  p95: number;\n}\n\n/** Per-span-name stats for \"3x slower than average\" */\nexport interface PerSpanNameStats {\n  byName: Map<string, { count: number; totalMs: number; avgMs: number }>;\n}\n\n/**\n * Build a map traceId -> spans[] from a flat list of spans.\n * Traces are ordered by most recent span end time (latest first).\n */\nexport function buildTraceMap(\n  spans: TerminalSpanEvent[],\n  maxTraces = 50,\n): Map<string, TerminalSpanEvent[]> {\n  const byTrace = new Map<string, TerminalSpanEvent[]>();\n  for (const s of spans) {\n    const list = byTrace.get(s.traceId) ?? [];\n    list.push(s);\n    byTrace.set(s.traceId, list);\n  }\n  // Sort traces by latest span end time (desc)\n  const entries = [...byTrace.entries()].toSorted((a, b) => {\n    const maxA = Math.max(...a[1].map((x) => x.endTime));\n    const maxB = Math.max(...b[1].map((x) => x.endTime));\n    return maxB - maxA;\n  });\n  const limited = entries.slice(0, maxTraces);\n  return new Map(limited);\n}\n\n/**\n * Build a trace summary for the \"Recent traces\" list.\n * Root = span with no parentSpanId or parent not in this trace; duration = root duration or max end - min start.\n */\nexport function buildTraceSummaries(\n  traceMap: Map<string, TerminalSpanEvent[]>,\n): TraceSummary[] {\n  const summaries: TraceSummary[] = [];\n  for (const [traceId, traceSpans] of traceMap) {\n    const spanIds = new Set(traceSpans.map((s) => s.spanId));\n    const root =\n      traceSpans.find((s) => !s.parentSpanId || !spanIds.has(s.parentSpanId)) ??\n      traceSpans[0];\n    const durationMs = root ? root.durationMs : 0;\n    const hasError = traceSpans.some((s) => s.status === 'ERROR');\n    const lastEndTime = Math.max(...traceSpans.map((s) => s.endTime));\n    const services = [...new Set(traceSpans.map((s) => spanServiceName(s)))];\n    summaries.push({\n      traceId,\n      rootName: root?.name ?? 'unknown',\n      durationMs,\n      hasError,\n      spanCount: traceSpans.length,\n      lastEndTime,\n      spans: traceSpans,\n      services,\n    });\n  }\n  return summaries;\n}\n\n/**\n * Build a parent-child tree from spans of one trace.\n * Root = span with no parentSpanId (or parent not in list); children by parentSpanId.\n */\nexport function buildTraceTree(spans: TerminalSpanEvent[]): SpanTreeNode[] {\n  const byId = new Map<string, TerminalSpanEvent>();\n  for (const s of spans) {\n    byId.set(s.spanId, s);\n  }\n  const roots: SpanTreeNode[] = [];\n\n  function addNode(span: TerminalSpanEvent, depth: number): SpanTreeNode {\n    const children = spans\n      .filter((s) => s.parentSpanId === span.spanId)\n      .map((s) => addNode(s, depth + 1));\n    return { span, depth, children };\n  }\n\n  const rootSpans = spans.filter(\n    (s) => !s.parentSpanId || !byId.has(s.parentSpanId),\n  );\n  for (const s of rootSpans) {\n    roots.push(addNode(s, 0));\n  }\n  return roots;\n}\n\n/**\n * Flatten tree to list for display (pre-order: root, then children).\n */\nexport function flattenTraceTree(nodes: SpanTreeNode[]): SpanTreeNode[] {\n  const out: SpanTreeNode[] = [];\n  function walk(n: SpanTreeNode) {\n    out.push(n);\n    for (const c of n.children) walk(c);\n  }\n  for (const n of nodes) walk(n);\n  return out;\n}\n\n/**\n * Sort spans for waterfall: by startTime, then by depth (parent before children at same time).\n */\nexport function sortSpansForWaterfall(\n  spans: TerminalSpanEvent[],\n): SpanWithDepth[] {\n  const byId = new Map<string, TerminalSpanEvent>();\n  for (const s of spans) byId.set(s.spanId, s);\n\n  function depth(s: TerminalSpanEvent): number {\n    if (!s.parentSpanId || !byId.has(s.parentSpanId)) return 0;\n    const parent = byId.get(s.parentSpanId)!;\n    return 1 + depth(parent);\n  }\n\n  const withDepth = spans.map((s) => ({ span: s, depth: depth(s) }));\n  withDepth.sort((a, b) => {\n    if (a.span.startTime !== b.span.startTime)\n      return a.span.startTime - b.span.startTime;\n    return a.depth - b.depth;\n  });\n  return withDepth;\n}\n\n/**\n * Filter spans by search query (substring match on name) and optional errors-only.\n */\nexport function filterBySearch(\n  spans: TerminalSpanEvent[],\n  searchQuery: string,\n  errorsOnly: boolean,\n): TerminalSpanEvent[] {\n  let list = spans;\n  if (errorsOnly) list = list.filter((s) => s.status === 'ERROR');\n  if (searchQuery.trim() === '') return list;\n  const q = searchQuery.toLowerCase();\n  return list.filter((s) => s.name.toLowerCase().includes(q));\n}\n\n/**\n * Filter trace summaries: include trace if any span name matches search (or search empty) and optionally has error.\n */\nexport function filterTraceSummaries(\n  summaries: TraceSummary[],\n  searchQuery: string,\n  errorsOnly: boolean,\n): TraceSummary[] {\n  let list = summaries;\n  if (errorsOnly) list = list.filter((s) => s.hasError);\n  if (searchQuery.trim() === '') return list;\n  const q = searchQuery.toLowerCase();\n  return list.filter((s) =>\n    s.spans.some((sp) => sp.name.toLowerCase().includes(q)),\n  );\n}\n\n/**\n * Compute aggregate stats over spans.\n */\nexport function computeStats(spans: TerminalSpanEvent[]): SpanStats {\n  const total = spans.length;\n  const errors = spans.filter((s) => s.status === 'ERROR').length;\n  const avg = total ? spans.reduce((a, s) => a + s.durationMs, 0) / total : 0;\n  const p95 = total\n    ? (() => {\n        const sorted = spans.map((s) => s.durationMs).toSorted((a, b) => a - b);\n        return sorted[Math.floor(sorted.length * 0.95)] ?? 0;\n      })()\n    : 0;\n  return { total, errors, avg, p95 };\n}\n\n/**\n * Compute per-span-name stats for \"Nx slower than average\".\n */\nexport function computePerSpanNameStats(\n  spans: TerminalSpanEvent[],\n): PerSpanNameStats {\n  const byName = new Map<string, { count: number; totalMs: number }>();\n  for (const s of spans) {\n    const cur = byName.get(s.name) ?? { count: 0, totalMs: 0 };\n    cur.count += 1;\n    cur.totalMs += s.durationMs;\n    byName.set(s.name, cur);\n  }\n  const result = new Map<\n    string,\n    { count: number; totalMs: number; avgMs: number }\n  >();\n  for (const [name, { count, totalMs }] of byName) {\n    result.set(name, { count, totalMs, avgMs: totalMs / count });\n  }\n  return { byName: result };\n}\n","/**\n * Format utilities - duration, relative time, truncation.\n * Pure functions for testability.\n */\n\n/**\n * Format duration: ms or seconds with 2 decimals.\n */\nexport function formatDurationMs(n: number): string {\n  if (n < 1000) return `${n.toFixed(0)}ms`;\n  return `${(n / 1000).toFixed(2)}s`;\n}\n\n/**\n * Format relative time: \"just now\" | \"Ns ago\" | \"Nm ago\" | \"Nh ago\".\n */\nexport function formatRelative(epochMs: number): string {\n  const now = Date.now();\n  const diffMs = now - epochMs;\n  if (diffMs < 0) return 'just now';\n  if (diffMs < 1000) return 'just now';\n  if (diffMs < 60_000) return `${Math.floor(diffMs / 1000)}s ago`;\n  if (diffMs < 3_600_000) return `${Math.floor(diffMs / 60_000)}m ago`;\n  return `${Math.floor(diffMs / 3_600_000)}h ago`;\n}\n\n/**\n * Truncate string with ellipsis.\n */\nexport function truncate(s: string, width: number): string {\n  if (s.length <= width) return s;\n  return s.slice(0, Math.max(0, width - 1)) + '…';\n}\n\n/**\n * Build a fixed-width waterfall bar string.\n * The bar is positioned proportionally within the total width\n * based on the span's start offset and duration relative to the trace.\n */\nexport function buildWaterfallBar(\n  spanStart: number,\n  spanDuration: number,\n  traceStart: number,\n  traceDuration: number,\n  width: number,\n): string {\n  if (width <= 0) return '';\n  if (traceDuration <= 0) return ' '.repeat(width);\n  const offsetRatio = (spanStart - traceStart) / traceDuration;\n  const widthRatio = spanDuration / traceDuration;\n  const barStart = Math.max(0, Math.floor(offsetRatio * width));\n  const barLen = Math.max(1, Math.round(widthRatio * width));\n  const clampedStart = Math.min(barStart, width - 1);\n  const clampedLen = Math.min(barLen, width - clampedStart);\n  const trailing = Math.max(0, width - clampedStart - clampedLen);\n  return (\n    ' '.repeat(clampedStart) + '█'.repeat(clampedLen) + ' '.repeat(trailing)\n  );\n}\n\n/**\n * Build a fixed-width time ruler string.\n * Format: \"0ms          500ms          1000ms\"\n */\nexport function buildTimeRuler(totalMs: number, width: number): string {\n  if (width <= 0) return '';\n  if (width < 10) return ' '.repeat(width);\n  const left = '0ms';\n  const right = formatDurationMs(totalMs);\n  const mid = formatDurationMs(totalMs / 2);\n  const midPos = Math.floor(width / 2) - Math.floor(mid.length / 2);\n  const rightPos = width - right.length;\n\n  const chars = Array.from<string>({ length: width }).fill(' ');\n  // place left\n  for (let i = 0; i < left.length && i < width; i++) chars[i] = left[i];\n  // place mid (if room)\n  if (midPos > left.length + 1 && midPos + mid.length < rightPos - 1) {\n    for (let i = 0; i < mid.length; i++) chars[midPos + i] = mid[i];\n  }\n  // place right\n  for (let i = 0; i < right.length; i++) chars[rightPos + i] = right[i];\n  return chars.join('');\n}\n\n/**\n * Compute marker column positions for event times on a waterfall bar.\n */\nexport function computeMarkerPositions(\n  markerTimesMs: number[],\n  spanStart: number,\n  spanEnd: number,\n  traceStart: number,\n  traceDuration: number,\n  width: number,\n): number[] {\n  if (width <= 0 || traceDuration <= 0 || markerTimesMs.length === 0) return [];\n  return markerTimesMs.map((t) => {\n    const ratio = (t - traceStart) / traceDuration;\n    const col = Math.floor(ratio * width);\n    return Math.max(0, Math.min(col, width - 1));\n  });\n}\n\n/**\n * Build a waterfall bar string with event markers overlaid as ◆.\n */\nexport function buildWaterfallBarWithMarkers(\n  markerTimesMs: number[],\n  spanStart: number,\n  spanDuration: number,\n  traceStart: number,\n  traceDuration: number,\n  width: number,\n): string {\n  const bar = buildWaterfallBar(\n    spanStart,\n    spanDuration,\n    traceStart,\n    traceDuration,\n    width,\n  );\n  if (markerTimesMs.length === 0 || width <= 0) return bar;\n  const positions = computeMarkerPositions(\n    markerTimesMs,\n    spanStart,\n    spanStart + spanDuration,\n    traceStart,\n    traceDuration,\n    width,\n  );\n  const chars = [...bar];\n  for (const pos of positions) {\n    chars[pos] = '◆';\n  }\n  return chars.join('');\n}\n\n/**\n * Adjust a panel split percentage by a delta, clamped to [20, 80].\n */\nexport function adjustPanelSplit(\n  current: number,\n  delta: number,\n  min = 20,\n  max = 80,\n): number {\n  return Math.max(min, Math.min(max, current + delta));\n}\n","/**\n * Deterministic service-name → terminal color mapping.\n * Hash the name, pick from a palette. Same service always gets same color.\n */\n\nexport const SERVICE_COLORS = [\n  'cyan',\n  'magenta',\n  'blue',\n  'yellow',\n  'green',\n  'redBright',\n  'cyanBright',\n  'magentaBright',\n  'blueBright',\n  'yellowBright',\n  'greenBright',\n] as const;\n\nexport type ServiceColor = (typeof SERVICE_COLORS)[number];\n\nfunction hashString(s: string): number {\n  let hash = 0;\n  for (let i = 0; i < s.length; i++) {\n    hash = Math.trunc((hash << 5) - hash + s.codePointAt(i)!);\n  }\n  return Math.abs(hash);\n}\n\nexport function getServiceColor(serviceName: string): ServiceColor {\n  return SERVICE_COLORS[hashString(serviceName) % SERVICE_COLORS.length];\n}\n","/**\n * Log model utilities - pure logic for log grouping, filtering, and timelines.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/**\n * Log event format for terminal dashboard consumption.\n * Designed to align with Autotel canonical log lines / request-logger output.\n */\nexport interface TerminalLogEvent {\n  /** Log timestamp in milliseconds since epoch */\n  time: number;\n  /** Log level */\n  level: LogLevel;\n  /** Short message */\n  message: string;\n  /** Optional trace correlation */\n  traceId?: string;\n  /** Optional span correlation */\n  spanId?: string;\n  /** Structured attributes / fields */\n  attributes?: Record<string, unknown>;\n}\n\n/** Aggregate stats over logs */\nexport interface LogStats {\n  total: number;\n  errors: number;\n}\n\n/** Combined span/log timeline item for a single trace */\nexport type TimelineItemType = 'span' | 'log';\n\nexport interface TimelineItem<TSpan> {\n  type: TimelineItemType;\n  time: number;\n  span?: TSpan;\n  log?: TerminalLogEvent;\n}\n\n/**\n * Filter logs by search query and optional level threshold.\n * Search matches message and flattened stringified attributes.\n */\nexport function filterLogsBySearch(\n  logs: TerminalLogEvent[],\n  searchQuery: string,\n  minLevel: LogLevel | null,\n): TerminalLogEvent[] {\n  let list = logs;\n\n  if (minLevel) {\n    const order: LogLevel[] = ['debug', 'info', 'warn', 'error'];\n    const minIdx = order.indexOf(minLevel);\n    list =\n      minIdx === -1\n        ? list\n        : list.filter((log) => order.indexOf(log.level) >= minIdx);\n  }\n\n  if (searchQuery.trim() === '') return list;\n  const q = searchQuery.toLowerCase();\n\n  return list.filter((log) => {\n    if (log.message.toLowerCase().includes(q)) return true;\n    if (log.attributes) {\n      for (const [k, v] of Object.entries(log.attributes)) {\n        const s = `${k}:${String(v)}`.toLowerCase();\n        if (s.includes(q)) return true;\n      }\n    }\n    return false;\n  });\n}\n\n/**\n * Compute simple aggregate stats over logs.\n */\nexport function computeLogStats(logs: TerminalLogEvent[]): LogStats {\n  const total = logs.length;\n  const errors = logs.filter((l) => l.level === 'error').length;\n  return { total, errors };\n}\n\n/**\n * Build a combined span/log timeline for a single trace.\n * Spans must include { startTime, endTime }; logs are positioned by time.\n */\nexport function buildTraceTimeline<\n  TSpan extends { startTime: number; endTime: number },\n>(spans: TSpan[], logs: TerminalLogEvent[]): TimelineItem<TSpan>[] {\n  const items: TimelineItem<TSpan>[] = [];\n\n  for (const span of spans) {\n    items.push({\n      type: 'span',\n      time: span.startTime,\n      span,\n    });\n  }\n\n  for (const log of logs) {\n    items.push({\n      type: 'log',\n      time: log.time,\n      log,\n    });\n  }\n\n  items.sort((a, b) => a.time - b.time);\n  return items;\n}\n","import type { TerminalLogEvent } from './lib/log-model';\n\n/**\n * Stream interface for terminal log events.\n */\nexport interface TerminalLogStream {\n  /**\n   * Subscribe to log events.\n   *\n   * @param callback - Called when a log event is emitted\n   * @returns Unsubscribe function\n   */\n  onLog(callback: (event: TerminalLogEvent) => void): () => void;\n}\n\n/**\n * Internal in-memory implementation used for the global log stream.\n */\nclass InMemoryTerminalLogStream implements TerminalLogStream {\n  private subscribers = new Set<(event: TerminalLogEvent) => void>();\n\n  onLog(callback: (event: TerminalLogEvent) => void): () => void {\n    this.subscribers.add(callback);\n    return () => this.subscribers.delete(callback);\n  }\n\n  emit(event: TerminalLogEvent): void {\n    for (const subscriber of this.subscribers) {\n      try {\n        subscriber(event);\n      } catch (error) {\n        console.error('[autotel-terminal] Log subscriber error:', error);\n      }\n    }\n  }\n}\n\nlet globalLogStream: InMemoryTerminalLogStream | null = null;\n\n/**\n * Get or create the global terminal log stream.\n *\n * This is intended to be used from Autotel canonical log line drains\n * or request logger hooks:\n *\n * ```ts\n * import { getTerminalLogStream } from 'autotel-terminal';\n *\n * const logStream = getTerminalLogStream();\n * logStream.emit({\n *   time: Date.now(),\n *   level: 'info',\n *   message: 'request completed',\n *   traceId,\n *   spanId,\n *   attributes: { route: '/users/:id', status: 200 },\n * });\n * ```\n */\nexport function getTerminalLogStream(): InMemoryTerminalLogStream {\n  if (!globalLogStream) {\n    globalLogStream = new InMemoryTerminalLogStream();\n  }\n  return globalLogStream;\n}\n","import type { TerminalSpanEvent } from '../span-stream';\n\nexport interface ServiceStats {\n  serviceName: string;\n  total: number;\n  errors: number;\n  avgMs: number;\n  p95Ms: number;\n}\n\nexport interface HotSpan {\n  name: string;\n  avgMs: number;\n  p95Ms: number;\n  count: number;\n}\n\nexport interface RouteStats {\n  route: string;\n  total: number;\n  errors: number;\n  avgMs: number;\n  p95Ms: number;\n}\n\nexport function computeServiceStats(\n  spans: TerminalSpanEvent[],\n): ServiceStats[] {\n  const byService = new Map<\n    string,\n    { durations: number[]; total: number; errors: number }\n  >();\n\n  for (const span of spans) {\n    const attrs = span.attributes ?? {};\n    const serviceName =\n      (attrs['service.name'] as string | undefined) ?? 'unknown';\n    const entry = byService.get(serviceName) ?? {\n      durations: [],\n      total: 0,\n      errors: 0,\n    };\n    entry.total += 1;\n    entry.durations.push(span.durationMs);\n    if (span.status === 'ERROR') entry.errors += 1;\n    byService.set(serviceName, entry);\n  }\n\n  const stats: ServiceStats[] = [];\n  for (const [serviceName, { durations, total, errors }] of byService) {\n    if (total === 0) continue;\n    const avgMs = durations.reduce((a, d) => a + d, 0) / durations.length;\n    const sorted = durations.toSorted((a, b) => a - b);\n    const p95Index = Math.floor(sorted.length * 0.95);\n    const p95Ms = sorted[p95Index] ?? sorted.at(-1) ?? 0;\n    stats.push({ serviceName, total, errors, avgMs, p95Ms });\n  }\n\n  stats.sort((a, b) => b.total - a.total);\n  return stats;\n}\n\nexport function computeRouteStats(spans: TerminalSpanEvent[]): RouteStats[] {\n  const byRoute = new Map<\n    string,\n    { durations: number[]; total: number; errors: number }\n  >();\n\n  for (const span of spans) {\n    const attrs = span.attributes ?? {};\n    const route = (attrs['http.route'] as string | undefined) ?? null;\n    if (!route) continue;\n\n    const entry = byRoute.get(route) ?? {\n      durations: [],\n      total: 0,\n      errors: 0,\n    };\n    entry.total += 1;\n    entry.durations.push(span.durationMs);\n    if (span.status === 'ERROR') entry.errors += 1;\n    byRoute.set(route, entry);\n  }\n\n  const stats: RouteStats[] = [];\n  for (const [route, { durations, total, errors }] of byRoute) {\n    if (total === 0) continue;\n    const avgMs = durations.reduce((a, d) => a + d, 0) / durations.length;\n    const sorted = durations.toSorted((a, b) => a - b);\n    const p95Index = Math.floor(sorted.length * 0.95);\n    const p95Ms = sorted[p95Index] ?? sorted.at(-1) ?? 0;\n    stats.push({ route, total, errors, avgMs, p95Ms });\n  }\n\n  stats.sort((a, b) => b.total - a.total);\n  return stats;\n}\n\nexport function findHotSpanNames(\n  spans: TerminalSpanEvent[],\n  topN: number,\n): HotSpan[] {\n  const byName = new Map<string, number[]>();\n  for (const span of spans) {\n    const list = byName.get(span.name) ?? [];\n    list.push(span.durationMs);\n    byName.set(span.name, list);\n  }\n\n  const hot: HotSpan[] = [];\n  for (const [name, durations] of byName) {\n    if (durations.length === 0) continue;\n    const avgMs = durations.reduce((a, d) => a + d, 0) / durations.length;\n    const sorted = durations.toSorted((a, b) => a - b);\n    const p95Index = Math.floor(sorted.length * 0.95);\n    const p95Ms = sorted[p95Index] ?? sorted.at(-1) ?? 0;\n    hot.push({ name, avgMs, p95Ms, count: durations.length });\n  }\n\n  hot.sort((a, b) => b.p95Ms - a.p95Ms);\n  return hot.slice(0, topN);\n}\n","import type { TerminalSpanEvent } from '../span-stream';\n\nexport interface AvailableFilters {\n  serviceNames: string[];\n  routes: string[];\n  statusCodes: number[];\n}\n\nexport interface SpanFilterState {\n  serviceName?: string;\n  route?: string;\n  statusGroup?: 'all' | '2xx' | '4xx' | '5xx';\n  errorsOnly?: boolean;\n  searchQuery?: string;\n  traceId?: string;\n}\n\nfunction getServiceName(span: TerminalSpanEvent): string | undefined {\n  const attrs = span.attributes ?? {};\n  return (attrs['service.name'] as string | undefined) ?? undefined;\n}\n\nfunction getRoute(span: TerminalSpanEvent): string | undefined {\n  const attrs = span.attributes ?? {};\n  return (attrs['http.route'] as string | undefined) ?? undefined;\n}\n\nfunction getStatusCode(span: TerminalSpanEvent): number | undefined {\n  const attrs = span.attributes ?? {};\n  const code = attrs['http.status_code'];\n  if (typeof code === 'number') return code;\n  if (typeof code === 'string') {\n    const n = Number(code);\n    return Number.isFinite(n) ? n : undefined;\n  }\n  return undefined;\n}\n\nexport function deriveAvailableFilters(\n  spans: TerminalSpanEvent[],\n): AvailableFilters {\n  const serviceSet = new Set<string>();\n  const routeSet = new Set<string>();\n  const statusSet = new Set<number>();\n\n  for (const span of spans) {\n    const svc = getServiceName(span);\n    if (svc) serviceSet.add(svc);\n    const route = getRoute(span);\n    if (route) routeSet.add(route);\n    const status = getStatusCode(span);\n    if (typeof status === 'number') statusSet.add(status);\n  }\n\n  return {\n    serviceNames: [...serviceSet].toSorted(),\n    routes: [...routeSet].toSorted(),\n    statusCodes: [...statusSet].toSorted((a, b) => a - b),\n  };\n}\n\nexport function applySpanFilters(\n  spans: TerminalSpanEvent[],\n  state: SpanFilterState,\n): TerminalSpanEvent[] {\n  const { serviceName, route, statusGroup, errorsOnly, searchQuery, traceId } =\n    state;\n  const q = searchQuery?.trim().toLowerCase() ?? '';\n\n  return spans.filter((span) => {\n    const attrs = span.attributes ?? {};\n\n    if (traceId && span.traceId !== traceId) return false;\n\n    if (errorsOnly && span.status !== 'ERROR') return false;\n\n    if (serviceName) {\n      const svc = getServiceName(span);\n      if (svc !== serviceName) return false;\n    }\n\n    if (route) {\n      const r = getRoute(span);\n      if (r !== route) return false;\n    }\n\n    if (statusGroup && statusGroup !== 'all') {\n      const code = getStatusCode(span);\n      if (!code) return false;\n      if (statusGroup === '2xx' && (code < 200 || code >= 300)) return false;\n      if (statusGroup === '4xx' && (code < 400 || code >= 500)) return false;\n      if (statusGroup === '5xx' && (code < 500 || code >= 600)) return false;\n    }\n\n    if (q) {\n      const nameMatch = span.name.toLowerCase().includes(q);\n      const attrMatch = Object.entries(attrs).some(([k, v]) =>\n        `${k}:${String(v)}`.toLowerCase().includes(q),\n      );\n      if (!nameMatch && !attrMatch) return false;\n    }\n\n    return true;\n  });\n}\n","import type { TerminalSpanEvent } from '../span-stream';\nimport type { TraceSummary } from './trace-model';\n\nexport interface ErrorSummary {\n  traceId: string;\n  rootName: string;\n  serviceName: string;\n  route?: string;\n  statusCode?: number;\n  errorCount: number;\n  lastEndTime: number;\n}\n\nfunction getServiceNameFromSpans(spans: TerminalSpanEvent[]): string {\n  for (const span of spans) {\n    const svc = span.attributes?.['service.name'];\n    if (typeof svc === 'string' && svc.trim()) return svc;\n  }\n  return 'unknown';\n}\n\nfunction getRouteFromSpans(spans: TerminalSpanEvent[]): string | undefined {\n  for (const span of spans) {\n    const route = span.attributes?.['http.route'];\n    if (typeof route === 'string' && route.trim()) return route;\n  }\n  return undefined;\n}\n\nfunction getStatusCodeFromSpans(\n  spans: TerminalSpanEvent[],\n): number | undefined {\n  for (const span of spans) {\n    const code = span.attributes?.['http.status_code'];\n    if (typeof code === 'number') return code;\n    if (typeof code === 'string') {\n      const n = Number(code);\n      if (Number.isFinite(n)) return n;\n    }\n  }\n  return undefined;\n}\n\nexport function buildErrorSummaries(\n  traceSummaries: TraceSummary[],\n): ErrorSummary[] {\n  const out: ErrorSummary[] = [];\n\n  for (const t of traceSummaries) {\n    const errorSpans = t.spans.filter((s) => s.status === 'ERROR');\n    if (errorSpans.length === 0) continue;\n\n    out.push({\n      traceId: t.traceId,\n      rootName: t.rootName,\n      serviceName: getServiceNameFromSpans(t.spans),\n      route: getRouteFromSpans(t.spans),\n      statusCode: getStatusCodeFromSpans(t.spans),\n      errorCount: errorSpans.length,\n      lastEndTime: t.lastEndTime,\n    });\n  }\n\n  out.sort((a, b) => b.lastEndTime - a.lastEndTime);\n  return out;\n}\n","import type { TerminalSpanEvent } from '../span-stream';\n\nexport interface ServiceNode {\n  serviceName: string;\n  spanCount: number;\n  errorCount: number;\n  avgDurationMs: number;\n  p95DurationMs: number;\n}\n\nexport interface ServiceEdge {\n  fromService: string;\n  toService: string;\n  spanCount: number;\n  errorCount: number;\n}\n\nexport interface ServiceGraph {\n  services: ServiceNode[];\n  edges: ServiceEdge[];\n}\n\nfunction getServiceName(span: TerminalSpanEvent): string {\n  const attrs = span.attributes ?? {};\n  const serviceName =\n    (attrs['service.name'] as string | undefined) ??\n    (attrs['resource.service.name'] as string | undefined);\n  return serviceName || 'unknown';\n}\n\nfunction getPeerService(span: TerminalSpanEvent): string | null {\n  const attrs = span.attributes ?? {};\n  const peerService =\n    (attrs['peer.service'] as string | undefined) ??\n    (attrs['db.system'] as string | undefined) ??\n    (attrs['messaging.system'] as string | undefined) ??\n    (attrs['http.host'] as string | undefined);\n  return peerService ?? null;\n}\n\nexport function buildServiceGraph(spans: TerminalSpanEvent[]): ServiceGraph {\n  const byService = new Map<\n    string,\n    { durations: number[]; spanCount: number; errorCount: number }\n  >();\n\n  for (const span of spans) {\n    const svc = getServiceName(span);\n    const entry = byService.get(svc) ?? {\n      durations: [],\n      spanCount: 0,\n      errorCount: 0,\n    };\n    entry.spanCount += 1;\n    entry.durations.push(span.durationMs);\n    if (span.status === 'ERROR') entry.errorCount += 1;\n    byService.set(svc, entry);\n  }\n\n  const services: ServiceNode[] = [];\n  for (const [serviceName, { durations, spanCount, errorCount }] of byService) {\n    if (spanCount === 0) continue;\n    const avgDurationMs =\n      durations.reduce((acc, d) => acc + d, 0) / durations.length;\n    const sorted = durations.toSorted((a, b) => a - b);\n    const p95Index = Math.floor(sorted.length * 0.95);\n    const p95DurationMs = sorted[p95Index] ?? sorted.at(-1) ?? 0;\n    services.push({\n      serviceName,\n      spanCount,\n      errorCount,\n      avgDurationMs,\n      p95DurationMs,\n    });\n  }\n\n  const byEdge = new Map<string, { spanCount: number; errorCount: number }>();\n\n  for (const span of spans) {\n    const to = getPeerService(span);\n    if (!to) continue;\n    const from = getServiceName(span);\n    const key = `${from}→${to}`;\n    const entry = byEdge.get(key) ?? { spanCount: 0, errorCount: 0 };\n    entry.spanCount += 1;\n    if (span.status === 'ERROR') entry.errorCount += 1;\n    byEdge.set(key, entry);\n  }\n\n  const edges: ServiceEdge[] = [];\n  for (const [key, { spanCount, errorCount }] of byEdge) {\n    const [fromService, toService] = key.split('→');\n    edges.push({ fromService, toService, spanCount, errorCount });\n  }\n\n  services.sort((a, b) => b.spanCount - a.spanCount);\n  edges.sort((a, b) => b.spanCount - a.spanCount);\n\n  return { services, edges };\n}\n","import type { ServiceGraph, ServiceEdge } from './topology-model';\nimport { formatDurationMs } from './format';\n\n/**\n * Render a service graph as ASCII lines for terminal display.\n *\n * Layout: root services at top, downstream services below with edges.\n * Recursively traverses the full dependency tree.\n * Each service shows: name, span count, error rate, p95 latency.\n * Each edge shows: call count and error count.\n */\nexport function renderTopologyAscii(graph: ServiceGraph): string[] {\n  if (graph.services.length === 0) {\n    return ['  No services detected yet.'];\n  }\n\n  // Find root services (not a target of any edge)\n  const targetServices = new Set(graph.edges.map((e) => e.toService));\n  const roots = graph.services.filter(\n    (s) => !targetServices.has(s.serviceName),\n  );\n  // If no clear roots (cycle), use all services sorted by span count\n  const rootList = roots.length > 0 ? roots : [...graph.services];\n\n  const lines: string[] = [];\n\n  for (const root of rootList) {\n    renderNode(graph, root.serviceName, '', true, lines, new Set());\n  }\n\n  return lines;\n}\n\nfunction renderNode(\n  graph: ServiceGraph,\n  serviceName: string,\n  prefix: string,\n  isRoot: boolean,\n  lines: string[],\n  ancestors: Set<string>,\n): void {\n  const svc = graph.services.find((s) => s.serviceName === serviceName);\n  const label = svc ? formatServiceLine(svc) : `[${serviceName}]`;\n\n  if (isRoot) {\n    lines.push(label);\n  }\n\n  // Don't recurse into ancestors on the current path (cycle protection)\n  if (ancestors.has(serviceName)) return;\n  const pathAncestors = new Set(ancestors);\n  pathAncestors.add(serviceName);\n\n  const outgoing = graph.edges.filter((e) => e.fromService === serviceName);\n\n  for (let i = 0; i < outgoing.length; i++) {\n    const edge = outgoing[i];\n    const isLast = i === outgoing.length - 1;\n    const connector = isLast ? '└' : '├';\n    const childPrefix = isLast ? '    ' : '│   ';\n    const downstream = graph.services.find(\n      (s) => s.serviceName === edge.toService,\n    );\n    const edgeLabel = formatEdgeLabel(edge);\n    const downstreamLabel = downstream\n      ? formatServiceLine(downstream)\n      : `[${edge.toService}]`;\n\n    lines.push(`${prefix}    ${connector}──${edgeLabel}──→ ${downstreamLabel}`);\n\n    // Recurse into downstream service\n    renderNode(\n      graph,\n      edge.toService,\n      prefix + '    ' + childPrefix,\n      false,\n      lines,\n      pathAncestors,\n    );\n  }\n}\n\nfunction formatServiceLine(svc: {\n  serviceName: string;\n  spanCount: number;\n  errorCount: number;\n  p95DurationMs: number;\n}): string {\n  const errPart = svc.errorCount > 0 ? ` · ${svc.errorCount} err` : '';\n  return `[${svc.serviceName}] ${svc.spanCount} spans${errPart} · p95 ${formatDurationMs(svc.p95DurationMs)}`;\n}\n\nfunction formatEdgeLabel(edge: ServiceEdge): string {\n  const errPart = edge.errorCount > 0 ? `, ${edge.errorCount} err` : '';\n  return `(${edge.spanCount}${errPart})`;\n}\n","import type { TraceSummary } from './trace-model';\nimport type { TerminalLogEvent } from './log-model';\n\nexport interface ExportedTrace {\n  traceId: string;\n  rootName: string;\n  durationMs: number;\n  lastEndTime: number;\n  spans: Array<{\n    name: string;\n    spanId: string;\n    parentSpanId?: string;\n    startTime: number;\n    endTime: number;\n    durationMs: number;\n    status: string;\n    kind?: string;\n    attributes?: Record<string, unknown>;\n  }>;\n  logs: Array<{\n    time: number;\n    level: string;\n    message: string;\n    traceId?: string;\n    spanId?: string;\n    attributes?: Record<string, unknown>;\n  }>;\n}\n\nexport function exportTraceToJson(\n  trace: TraceSummary,\n  logs: TerminalLogEvent[],\n): string {\n  const exported: ExportedTrace = {\n    traceId: trace.traceId,\n    rootName: trace.rootName,\n    durationMs: trace.durationMs,\n    lastEndTime: trace.lastEndTime,\n    spans: trace.spans.map((s) => ({\n      name: s.name,\n      spanId: s.spanId,\n      parentSpanId: s.parentSpanId,\n      startTime: s.startTime,\n      endTime: s.endTime,\n      durationMs: s.durationMs,\n      status: s.status,\n      kind: s.kind,\n      attributes: s.attributes,\n    })),\n    logs: logs.map((l) => ({\n      time: l.time,\n      level: l.level,\n      message: l.message,\n      traceId: l.traceId,\n      spanId: l.spanId,\n      attributes: l.attributes,\n    })),\n  };\n\n  return JSON.stringify(exported, null, 2);\n}\n","import type { LanguageModel } from 'ai';\nimport type { AIConfig, AIProviderType } from './types';\n\nexport async function detectOllama(\n  baseUrl = 'http://127.0.0.1:11434',\n): Promise<boolean> {\n  try {\n    const res = await fetch(`${baseUrl}/api/tags`, {\n      signal: AbortSignal.timeout(1000),\n    });\n    return res.ok;\n  } catch {\n    return false;\n  }\n}\n\nexport function resolveConfig(\n  options: Partial<AIConfig> = {},\n): AIConfig | null {\n  const provider: AIProviderType | undefined =\n    options.provider ??\n    (process.env.AI_PROVIDER as AIProviderType | undefined) ??\n    undefined;\n\n  const model = options.model ?? process.env.AI_MODEL;\n  const apiKey =\n    options.apiKey ??\n    process.env.AI_API_KEY ??\n    (provider === 'openai' ? process.env.OPENAI_API_KEY : undefined);\n  const baseUrl = options.baseUrl ?? process.env.AI_BASE_URL;\n\n  if (provider) {\n    return {\n      provider,\n      model: model ?? (provider === 'ollama' ? 'granite4' : 'gpt-4o'),\n      apiKey,\n      baseUrl,\n    };\n  }\n\n  // Will be resolved async in resolveConfigWithAutoDetect\n  return null;\n}\n\nconst defaultAutoDetectDeps = { detectOllama };\n\nexport async function resolveConfigWithAutoDetect(\n  options: Partial<AIConfig> = {},\n  deps: { detectOllama: typeof detectOllama } = defaultAutoDetectDeps,\n): Promise<AIConfig | null> {\n  const config = resolveConfig(options);\n  if (config) return config;\n\n  // Auto-detect: check Ollama first\n  const ollamaUrl =\n    options.baseUrl ?? process.env.AI_BASE_URL ?? 'http://127.0.0.1:11434';\n  if (await deps.detectOllama(ollamaUrl)) {\n    return {\n      provider: 'ollama',\n      model: options.model ?? process.env.AI_MODEL ?? 'granite4',\n      baseUrl: ollamaUrl,\n    };\n  }\n\n  // Check for OpenAI key\n  const openaiKey =\n    options.apiKey ?? process.env.AI_API_KEY ?? process.env.OPENAI_API_KEY;\n  if (openaiKey) {\n    return {\n      provider: 'openai',\n      model: options.model ?? process.env.AI_MODEL ?? 'gpt-4o',\n      apiKey: openaiKey,\n    };\n  }\n\n  return null;\n}\n\nexport type AIModelResult = {\n  model: LanguageModel;\n  providerType: AIProviderType;\n  config: AIConfig;\n};\n\nexport async function createAIModel(config: AIConfig): Promise<AIModelResult> {\n  switch (config.provider) {\n    case 'ollama': {\n      const { createOllama } = await import('ai-sdk-ollama');\n      const ollama = createOllama({\n        baseURL: config.baseUrl ?? 'http://127.0.0.1:11434',\n      });\n      return { model: ollama(config.model), providerType: 'ollama', config };\n    }\n    case 'openai': {\n      const { createOpenAI } = await import('@ai-sdk/openai');\n      const openai = createOpenAI({\n        apiKey: config.apiKey,\n        ...(config.baseUrl ? { baseURL: config.baseUrl } : {}),\n      });\n      return { model: openai(config.model), providerType: 'openai', config };\n    }\n    case 'openai-compatible': {\n      const { createOpenAICompatible } =\n        await import('@ai-sdk/openai-compatible');\n      const provider = createOpenAICompatible({\n        baseURL: config.baseUrl ?? 'http://127.0.0.1:11434/v1',\n        name: 'custom',\n        ...(config.apiKey\n          ? { headers: { Authorization: `Bearer ${config.apiKey}` } }\n          : {}),\n      });\n      return {\n        model: provider(config.model),\n        providerType: 'openai-compatible',\n        config,\n      };\n    }\n    default: {\n      throw new Error(\n        `Unsupported provider: \"${config.provider}\". Expected \"ollama\", \"openai\", or \"openai-compatible\".`,\n      );\n    }\n  }\n}\n","export function buildSystemPrompt(\n  viewMode: string,\n  contextJson: string,\n): string {\n  return `You are an OpenTelemetry expert assistant analyzing live telemetry data from a running application.\nThe user is viewing their ${viewMode} dashboard in a terminal TUI.\n\nYou have tools to query the telemetry data precisely. Use them to answer questions:\n- getOverviewStats: high-level stats (spans, errors, latency)\n- listServices: all services with error rates and p95\n- findSlowestSpans: find slow spans, optionally by service\n- findErrorTraces: find traces with errors\n- getTraceDetail: deep dive into a specific trace\n- searchSpans: search spans by name\n- searchLogs: search logs by message content\n- renderUI: display rich terminal UI (tables, charts, badges)\n\n## Workflow\n1. Use data tools first to gather data\n2. Use renderUI to display structured results as tables, charts, or cards\n3. Add a brief text explanation after the rendered UI\n\n## When to use renderUI\nUse renderUI for tables, comparisons, and metrics. Do NOT use it for short text answers.\n\nrenderUI spec format: { root: \"id\", elements: { \"id\": { type: \"ComponentName\", props: {...}, children: [] } } }\n\nComponents: Table (columns, rows), KeyValue (label, value), Badge (label, variant: success/error/warning/info), BarChart (data: [{label,value}]), Card (title, children), Heading (text), Divider, Text (text, color, bold), Box (flexDirection, children).\n\nTable example: { type: \"Table\", props: { columns: [{ header: \"Name\", key: \"name\" }], rows: [{ name: \"api\" }] }, children: [] }\n\nKeep text responses under 300 words.\nUse specific span names, durations, and attribute values from the data.\n\nCurrent dashboard summary:\n${contextJson}`;\n}\n","import { tool } from 'ai';\nimport { z } from 'zod';\nimport type { TerminalSpanEvent } from '../span-stream';\nimport type { TerminalLogEvent } from '../lib/log-model';\nimport type { TraceSummary, SpanStats } from '../lib/trace-model';\nimport type { ServiceStats } from '../lib/stats-model';\nimport type { ErrorSummary } from '../lib/error-model';\nimport type { InkSpec } from './types';\nimport { validateSpec } from '@json-render/core';\nimport { standardComponentDefinitions } from '@json-render/ink/catalog';\n\n/** Valid component names from the Ink catalog */\nconst COMPONENT_NAMES = Object.keys(standardComponentDefinitions) as [\n  string,\n  ...string[],\n];\n\n// Helper: zod v4 schemas need to be cast for ai SDK v6's tool() which expects zod v3 types\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst t: (...args: any[]) => any = tool;\n\n/**\n * Snapshot of dashboard state passed to tools at query time.\n * Tools read from this — they don't mutate dashboard state.\n */\nexport type ToolContext = {\n  spans: TerminalSpanEvent[];\n  logs: TerminalLogEvent[];\n  traces: TraceSummary[];\n  stats: SpanStats;\n  serviceStats: ServiceStats[];\n  errorSummaries: ErrorSummary[];\n};\n\nexport function createTelemetryTools(\n  ctx: ToolContext,\n  onRenderUI?: (spec: InkSpec) => void,\n) {\n  return {\n    getOverviewStats: t({\n      description:\n        'Get high-level stats: total spans, error count, average duration, p95 duration, and service count.',\n      parameters: z.object({}),\n      execute: async () => ({\n        totalSpans: ctx.stats.total,\n        errors: ctx.stats.errors,\n        avgMs: Math.round(ctx.stats.avg),\n        p95Ms: Math.round(ctx.stats.p95),\n        serviceCount: ctx.serviceStats.length,\n        traceCount: ctx.traces.length,\n      }),\n    }),\n\n    listServices: t({\n      description:\n        'List all services with their span counts, error counts, and p95 latencies.',\n      parameters: z.object({}),\n      execute: async () =>\n        ctx.serviceStats.map((s) => ({\n          serviceName: s.serviceName,\n          total: s.total,\n          errors: s.errors,\n          avgMs: Math.round(s.avgMs),\n          p95Ms: Math.round(s.p95Ms),\n        })),\n    }),\n\n    findSlowestSpans: t({\n      description:\n        'Find the slowest spans, optionally filtered by service name. Returns span name, duration, status, and key attributes.',\n      parameters: z.object({\n        service: z.string().optional().describe('Filter by service name'),\n        limit: z.number().optional().describe('Max results (default 10)'),\n      }),\n      execute: async ({\n        service,\n        limit,\n      }: {\n        service?: string;\n        limit?: number;\n      }) => {\n        const max = limit ?? 10;\n        let filtered = ctx.spans;\n        if (service) {\n          filtered = filtered.filter(\n            (s) => (s.attributes?.['service.name'] as string) === service,\n          );\n        }\n        return filtered\n          .toSorted((a, b) => b.durationMs - a.durationMs)\n          .slice(0, max)\n          .map((s) => ({\n            name: s.name,\n            durationMs: Math.round(s.durationMs),\n            status: s.status,\n            service: (s.attributes?.['service.name'] as string) ?? 'unknown',\n            route: s.attributes?.['http.route'] as string | undefined,\n            traceId: s.traceId.slice(0, 8),\n          }));\n      },\n    }),\n\n    findErrorTraces: t({\n      description:\n        'Find traces that contain errors, with root span name, service, route, and error count.',\n      parameters: z.object({\n        service: z.string().optional().describe('Filter by service name'),\n        limit: z.number().optional().describe('Max results (default 10)'),\n      }),\n      execute: async ({\n        service,\n        limit,\n      }: {\n        service?: string;\n        limit?: number;\n      }) => {\n        const max = limit ?? 10;\n        let errors = ctx.errorSummaries;\n        if (service) {\n          errors = errors.filter((e) => e.serviceName === service);\n        }\n        return errors.slice(0, max).map((e) => ({\n          traceId: e.traceId.slice(0, 8),\n          rootName: e.rootName,\n          serviceName: e.serviceName,\n          route: e.route,\n          errorCount: e.errorCount,\n        }));\n      },\n    }),\n\n    getTraceDetail: t({\n      description:\n        'Get full detail of a specific trace by trace ID prefix. Returns all spans with their parent relationships, durations, and attributes.',\n      parameters: z.object({\n        traceIdPrefix: z\n          .string()\n          .describe('First 8+ characters of the trace ID'),\n      }),\n      execute: async ({ traceIdPrefix }: { traceIdPrefix: string }) => {\n        const trace = ctx.traces.find((t) =>\n          t.traceId.startsWith(traceIdPrefix),\n        );\n        if (!trace) {\n          return { error: `No trace found matching ${traceIdPrefix}` };\n        }\n        const traceLogs = ctx.logs.filter((l) => l.traceId === trace.traceId);\n        return {\n          traceId: trace.traceId.slice(0, 16),\n          rootName: trace.rootName,\n          durationMs: Math.round(trace.durationMs),\n          hasError: trace.hasError,\n          spanCount: trace.spanCount,\n          spans: trace.spans.map((s) => ({\n            name: s.name,\n            durationMs: Math.round(s.durationMs),\n            status: s.status,\n            kind: s.kind,\n            parentSpanId: s.parentSpanId?.slice(0, 8),\n            attrs: Object.fromEntries(\n              Object.entries(s.attributes ?? {}).filter(([k]) =>\n                [\n                  'http.method',\n                  'http.route',\n                  'http.status_code',\n                  'db.operation',\n                  'db.system',\n                  'service.name',\n                  'error.message',\n                  'error.type',\n                ].includes(k),\n              ),\n            ),\n          })),\n          logs: traceLogs.slice(0, 10).map((l) => ({\n            level: l.level,\n            message: l.message.slice(0, 100),\n          })),\n        };\n      },\n    }),\n\n    searchSpans: t({\n      description:\n        'Search spans by name pattern (case-insensitive substring match). Returns matching spans with details.',\n      parameters: z.object({\n        query: z.string().describe('Search string to match against span names'),\n        limit: z.number().optional().describe('Max results (default 20)'),\n      }),\n      execute: async ({ query, limit }: { query: string; limit?: number }) => {\n        const max = limit ?? 20;\n        const q = query.toLowerCase();\n        return ctx.spans\n          .filter((s) => s.name.toLowerCase().includes(q))\n          .slice(0, max)\n          .map((s) => ({\n            name: s.name,\n            durationMs: Math.round(s.durationMs),\n            status: s.status,\n            traceId: s.traceId.slice(0, 8),\n            service: (s.attributes?.['service.name'] as string) ?? 'unknown',\n          }));\n      },\n    }),\n\n    searchLogs: t({\n      description:\n        'Search logs by message content (case-insensitive). Returns matching log entries.',\n      parameters: z.object({\n        query: z\n          .string()\n          .describe('Search string to match against log messages'),\n        level: z\n          .enum(['debug', 'info', 'warn', 'error'])\n          .optional()\n          .describe('Filter by log level'),\n        limit: z.number().optional().describe('Max results (default 20)'),\n      }),\n      execute: async ({\n        query,\n        level,\n        limit,\n      }: {\n        query: string;\n        level?: string;\n        limit?: number;\n      }) => {\n        const max = limit ?? 20;\n        const q = query.toLowerCase();\n        let filtered = ctx.logs.filter((l) =>\n          l.message.toLowerCase().includes(q),\n        );\n        if (level) {\n          filtered = filtered.filter((l) => l.level === level);\n        }\n        return filtered.slice(0, max).map((l) => ({\n          level: l.level,\n          message: l.message.slice(0, 200),\n          traceId: l.traceId?.slice(0, 8),\n          attrs: l.attributes,\n        }));\n      },\n    }),\n\n    renderUI: t({\n      description:\n        'Render rich terminal UI (tables, charts, badges) to display structured data. Use this when showing tabular data, comparisons, or metrics — not for short text answers. Available components: Table (columns + rows), KeyValue (key-value pairs), Badge (status labels: default/info/success/warning/error), BarChart (horizontal bars with labels), Card (grouped content with title), Heading (section title), Divider (separator), Text (styled text), Box (layout container).',\n      parameters: z.object({\n        spec: z\n          .object({\n            root: z.string().describe('ID of the root element'),\n            elements: z\n              .record(\n                z.string(),\n                z.object({\n                  type: z.enum(COMPONENT_NAMES).describe('Component name'),\n                  props: z.record(z.string(), z.unknown()).optional(),\n                  children: z.array(z.string()).describe('Child element keys'),\n                }),\n              )\n              .describe('Map of element ID to component definition'),\n          })\n          .describe('json-render spec defining the UI to display'),\n      }),\n      execute: async ({ spec }: { spec: InkSpec }) => {\n        const validation = validateSpec(spec);\n        if (!validation.valid) {\n          return {\n            rendered: false,\n            error: validation.issues.map((i) => i.message).join('; '),\n          };\n        }\n        onRenderUI?.(spec);\n        return { rendered: true };\n      },\n    }),\n  };\n}\n","/**\n * Provider-aware streamText wrapper.\n *\n * When the provider is Ollama, uses ai-sdk-ollama's streamText which has\n * enhanced response synthesis for tool calling (Ollama models often return\n * empty text after tool execution — the enhanced version detects this and\n * synthesizes a response from tool results).\n *\n * For all other providers, uses the standard ai SDK streamText.\n */\nimport type { LanguageModel } from 'ai';\nimport type { AIProviderType } from './types';\n\ntype StreamTextParams = {\n  model: LanguageModel;\n  system?: string;\n  messages: Array<{ role: 'user' | 'assistant'; content: string }>;\n  tools?: Record<string, unknown>;\n  maxSteps?: number;\n  abortSignal?: AbortSignal;\n};\n\ntype StreamResult = {\n  textStream: AsyncIterable<string>;\n};\n\nexport async function providerStreamText(\n  providerType: AIProviderType,\n  params: StreamTextParams,\n): Promise<StreamResult> {\n  if (providerType === 'ollama') {\n    const mod = await import('ai-sdk-ollama');\n    // ai-sdk-ollama's streamText has enhanced synthesis for tool calling\n    const result = await mod.streamText(\n      params as Parameters<typeof mod.streamText>[0],\n    );\n    return result as unknown as StreamResult;\n  }\n\n  const mod = await import('ai');\n  return mod.streamText(\n    params as Parameters<typeof mod.streamText>[0],\n  ) as unknown as StreamResult;\n}\n","/**\n * Terminal Dashboard for Autotel\n *\n * Beautiful react-ink powered dashboard for viewing traces in real-time.\n *\n * @example Basic usage (auto-wire)\n * ```typescript\n * import { init } from 'autotel'\n * import { renderTerminal } from 'autotel-terminal'\n *\n * init({ service: 'my-app' })\n * renderTerminal() // Automatically creates stream from current tracer provider\n * ```\n *\n * @example With options\n * ```typescript\n * renderTerminal({\n *   title: 'My App Traces',\n *   showStats: true,\n *   maxSpans: 200,\n * })\n * ```\n *\n * @example Manual stream (advanced)\n * ```typescript\n * import { StreamingSpanProcessor } from 'autotel-terminal'\n * import { createTerminalSpanStream } from 'autotel-terminal'\n * import { BatchSpanProcessor } from 'autotel/processors'\n *\n * const processor = new StreamingSpanProcessor(new BatchSpanProcessor(exporter))\n * const stream = createTerminalSpanStream(processor)\n * renderTerminal({}, stream)\n * ```\n *\n * @module autotel-terminal\n */\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { render, Box, Text, useInput, useStdin } from 'ink';\nimport type { TerminalSpanEvent, TerminalSpanStream } from './span-stream';\nimport { StreamingSpanProcessor } from './streaming-processor';\nimport { createTerminalSpanStream } from './span-stream';\nimport { getAutotelTracerProvider } from 'autotel/tracer-provider';\nimport type { TracerProvider } from '@opentelemetry/api';\nimport {\n  buildTraceMap,\n  buildTraceSummaries,\n  buildTraceTree,\n  flattenTraceTree,\n  filterBySearch,\n  filterTraceSummaries,\n  computeStats,\n  computePerSpanNameStats,\n  sortSpansForWaterfall,\n  spanServiceName,\n} from './lib/trace-model';\nimport { formatDurationMs, formatRelative, truncate, buildWaterfallBar, buildTimeRuler } from './lib/format';\nimport { getServiceColor } from './lib/service-colors';\nimport type { SpanTreeNode } from './lib/trace-model';\nimport type { TerminalLogEvent, LogStats } from './lib/log-model';\nimport {\n  filterLogsBySearch,\n  computeLogStats,\n  buildTraceTimeline,\n} from './lib/log-model';\nimport { getTerminalLogStream, type TerminalLogStream } from './log-stream';\nimport {\n  computeServiceStats,\n  computeRouteStats,\n  findHotSpanNames,\n} from './lib/stats-model';\nimport { applySpanFilters, type SpanFilterState } from './lib/filters';\nimport type { ViewMode } from './lib/dashboard-keymap';\nimport { buildErrorSummaries } from './lib/error-model';\nimport { buildServiceGraph } from './lib/topology-model';\nimport { renderTopologyAscii } from './lib/topology-render';\nimport { exportTraceToJson } from './lib/export-model';\nimport type { AIConfig, ChatMessage, AIState } from './ai/types';\nimport {\n  resolveConfigWithAutoDetect,\n  createAIModel,\n  type AIModelResult,\n} from './ai/provider';\nimport { buildSystemPrompt } from './ai/system-prompt';\nimport { createTelemetryTools, type ToolContext } from './ai/tools';\nimport { providerStreamText } from './ai/stream';\nimport { Renderer as InkRenderer } from '@json-render/ink';\nimport type { InkSpec } from './ai/types';\n\n/** Key attribute keys to show first (autotel / OTel conventions) */\nconst KEY_ATTR_KEYS = new Set([\n  'http.route',\n  'http.method',\n  'db.operation',\n  'db.statement',\n  'db.system',\n  'code.function',\n  'code.filepath',\n  'code.lineno',\n  'user.id',\n  'order.id',\n]);\n\n/**\n * Terminal dashboard options\n */\nexport interface TerminalOptions {\n  /**\n   * Dashboard title\n   * @default 'Autotel Trace Inspector'\n   */\n  title?: string;\n\n  /**\n   * Show statistics bar (span count, error rate, avg duration)\n   * @default true\n   */\n  showStats?: boolean;\n\n  /**\n   * Maximum number of spans to display\n   * @default 100\n   */\n  maxSpans?: number;\n\n  /**\n   * Enable colors (auto-detect by default)\n   * @default true if TTY\n   */\n  colors?: boolean;\n\n  /**\n   * AI assistant configuration. Auto-detects Ollama/OpenAI if not provided.\n   */\n  ai?: Partial<AIConfig>;\n}\n\nconst THROTTLE_MS = 50;\nconst MAX_TRACES = 50;\nconst NEW_ERROR_DISPLAY_MS = 2000;\nconst RECORD_LIMIT_DEFAULT = 200;\nconst LIST_HEIGHT = 20;\n\ninterface DashboardProps {\n  title: string;\n  showStats: boolean;\n  maxSpans: number;\n  colors: boolean;\n  stream: TerminalSpanStream;\n  logStream?: TerminalLogStream | null;\n  aiConfig?: Partial<AIConfig>;\n}\n\nfunction Dashboard({\n  title,\n  showStats,\n  maxSpans,\n  colors,\n  stream,\n  logStream,\n  aiConfig,\n}: DashboardProps): React.ReactElement {\n  const [paused, setPaused] = useState(false);\n  const [recording, setRecording] = useState(false);\n  const [spans, setSpans] = useState<TerminalSpanEvent[]>([]);\n  const [selected, setSelected] = useState(0);\n  const [filterErrorsOnly, setFilterErrorsOnly] = useState(false);\n  const [searchQuery, setSearchQuery] = useState('');\n  const [showHelp, setShowHelp] = useState(false);\n  const [viewMode, setViewMode] = useState<ViewMode>('trace');\n  const [spanFilters, setSpanFilters] = useState<SpanFilterState>({\n    statusGroup: 'all',\n  });\n  const [drilldownTraceId, setDrilldownTraceId] = useState<string | null>(null);\n  const [drilldownSelectedIndex, setDrilldownSelectedIndex] = useState(0);\n  const [drilldownScrollOffset, setDrilldownScrollOffset] = useState(0);\n  const [drilldownTab, setDrilldownTab] = useState<\n    'timeline' | 'spans' | 'logs'\n  >('timeline');\n  const [newErrorCount, setNewErrorCount] = useState(0);\n  const [searchMode, setSearchMode] = useState(false);\n  const [traceIdMode, setTraceIdMode] = useState(false);\n  const [traceIdInput, setTraceIdInput] = useState('');\n  const throttleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const pendingSpansRef = useRef<TerminalSpanEvent[]>([]);\n  const [logs, setLogs] = useState<TerminalLogEvent[]>([]);\n\n  // AI state\n  const [aiMessages, setAiMessages] = useState<ChatMessage[]>([]);\n  const [aiInput, setAiInput] = useState('');\n  const [aiState, setAiState] = useState<AIState>({ status: 'unconfigured' });\n  const [aiInputMode, setAiInputMode] = useState(false);\n  const [aiSpec, setAiSpec] = useState<InkSpec | null>(null);\n  const aiModelRef = useRef<AIModelResult | null>(null);\n  const aiAbortRef = useRef<AbortController | null>(null);\n\n  // Initialize AI model on mount\n  useEffect(() => {\n    let cancelled = false;\n    resolveConfigWithAutoDetect(aiConfig).then(async (config) => {\n      if (cancelled || !config) return;\n      try {\n        const result = await createAIModel(config);\n        aiModelRef.current = result;\n        setAiState({ status: 'idle' });\n      } catch {\n        setAiState({\n          status: 'error',\n          message: 'Failed to initialize AI model',\n        });\n      }\n    });\n    return () => {\n      cancelled = true;\n    };\n  }, [aiConfig]);\n\n  // Subscribe to log stream if provided\n  useEffect(() => {\n    if (!logStream) return;\n    const unsubscribe = logStream.onLog((event) => {\n      if (paused) return;\n      if (recording) {\n        setLogs((prev) => {\n          const next = [event, ...prev];\n          if (next.length >= RECORD_LIMIT_DEFAULT) {\n            setRecording(false);\n            setPaused(true);\n          }\n          return next.slice(0, RECORD_LIMIT_DEFAULT);\n        });\n        return;\n      }\n      setLogs((prev) => [event, ...prev].slice(0, maxSpans));\n    });\n    return () => {\n      unsubscribe();\n    };\n  }, [logStream, paused, maxSpans, recording]);\n\n  useEffect(() => {\n    const flush = () => {\n      const batch = pendingSpansRef.current;\n      pendingSpansRef.current = [];\n      if (batch.length === 0) return;\n      setSpans((prev) => {\n        const next = [...batch, ...prev];\n        return next.slice(0, maxSpans);\n      });\n      setSelected(0);\n      setDrilldownTraceId(null);\n    };\n    const unsubscribe = stream.onSpanEnd((span) => {\n      if (paused) return;\n      if (span.status === 'ERROR') {\n        setNewErrorCount((n) => n + 1);\n        setTimeout(\n          () => setNewErrorCount((n) => Math.max(0, n - 1)),\n          NEW_ERROR_DISPLAY_MS,\n        );\n      }\n      if (recording) {\n        setSpans((prev) => {\n          const next = [span, ...prev];\n          if (next.length >= RECORD_LIMIT_DEFAULT) {\n            setRecording(false);\n            setPaused(true);\n          }\n          return next.slice(0, RECORD_LIMIT_DEFAULT);\n        });\n        setSelected(0);\n        setDrilldownTraceId(null);\n        return;\n      }\n      pendingSpansRef.current = [span, ...pendingSpansRef.current];\n      if (throttleRef.current) return;\n      throttleRef.current = setTimeout(() => {\n        throttleRef.current = null;\n        flush();\n      }, THROTTLE_MS);\n    });\n    return () => {\n      if (throttleRef.current) clearTimeout(throttleRef.current);\n      unsubscribe();\n    };\n  }, [stream, paused, maxSpans, recording]);\n\n  const filteredSpanBuffer = useMemo(\n    () =>\n      applySpanFilters(spans, {\n        ...spanFilters,\n        errorsOnly: filterErrorsOnly,\n        searchQuery,\n      }),\n    [spans, spanFilters, filterErrorsOnly, searchQuery],\n  );\n\n  const traceMap = useMemo(\n    () => buildTraceMap(filteredSpanBuffer, MAX_TRACES),\n    [filteredSpanBuffer],\n  );\n  const traceSummaries = useMemo(\n    () => buildTraceSummaries(traceMap),\n    [traceMap],\n  );\n  const filteredSummaries = useMemo(() => {\n    const base = filterTraceSummaries(traceSummaries, '', false);\n    return spanFilters.traceId\n      ? base.filter((t) => t.traceId === spanFilters.traceId)\n      : base;\n  }, [traceSummaries, spanFilters.traceId]);\n  const filteredSpans = useMemo(\n    () => filterBySearch(filteredSpanBuffer, '', false),\n    [filteredSpanBuffer],\n  );\n\n  const stats = useMemo(() => computeStats(spans), [spans]);\n  const perSpanNameStats = useMemo(\n    () => computePerSpanNameStats(spans),\n    [spans],\n  );\n  const logStats: LogStats = useMemo(() => computeLogStats(logs), [logs]);\n  const filteredLogs = useMemo(() => {\n    const traceFilteredLogs = spanFilters.traceId\n      ? logs.filter((l) => l.traceId === spanFilters.traceId)\n      : logs;\n    return filterLogsBySearch(traceFilteredLogs, searchQuery, null);\n  }, [logs, searchQuery, spanFilters.traceId]);\n\n  const serviceStats = useMemo(() => computeServiceStats(spans), [spans]);\n  const selectedServiceName = serviceStats[selected]?.serviceName ?? null;\n  const spansForSelectedService = useMemo(() => {\n    if (!selectedServiceName) return spans;\n    return spans.filter(\n      (s) =>\n        (s.attributes?.['service.name'] as string | undefined) ===\n        selectedServiceName,\n    );\n  }, [spans, selectedServiceName]);\n  const selectedServiceRouteStats = useMemo(\n    () => computeRouteStats(spansForSelectedService).slice(0, 8),\n    [spansForSelectedService],\n  );\n  const selectedServiceHotSpans = useMemo(\n    () => findHotSpanNames(spansForSelectedService, 8),\n    [spansForSelectedService],\n  );\n\n  const selectedTraceSummary =\n    drilldownTraceId == null\n      ? (filteredSummaries[selected] ?? null)\n      : (filteredSummaries.find((t) => t.traceId === drilldownTraceId) ?? null);\n  const serviceGraph = useMemo(() => buildServiceGraph(spans), [spans]);\n  const topologyLines = useMemo(() => renderTopologyAscii(serviceGraph), [serviceGraph]);\n  const errorSummaries = useMemo(\n    () => buildErrorSummaries(traceSummaries),\n    [traceSummaries],\n  );\n  const filteredErrorSummaries = spanFilters.traceId\n    ? errorSummaries.filter((e) => e.traceId === spanFilters.traceId)\n    : errorSummaries;\n  const traceTree =\n    selectedTraceSummary == null\n      ? []\n      : flattenTraceTree(buildTraceTree(selectedTraceSummary.spans));\n  const waterfallSpans =\n    selectedTraceSummary == null\n      ? []\n      : sortSpansForWaterfall(selectedTraceSummary.spans);\n\n  const currentSpanInTrace = traceTree[drilldownSelectedIndex] ?? null;\n  const currentSpanInFlat = filteredSpans[selected] ?? null;\n  const selectedTraceSummaryForDetails =\n    viewMode === 'trace' &&\n    drilldownTraceId == null &&\n    filteredSummaries[selected]\n      ? filteredSummaries[selected]!\n      : null;\n  const rootSpanOfSelectedTrace =\n    selectedTraceSummaryForDetails != null &&\n    selectedTraceSummaryForDetails.spans.length > 0\n      ? (selectedTraceSummaryForDetails.spans.find(\n          (s) =>\n            !selectedTraceSummaryForDetails.spans.some(\n              (p) => p.spanId === s.parentSpanId,\n            ),\n        ) ?? selectedTraceSummaryForDetails.spans[0])\n      : null;\n  const currentSpan =\n    viewMode === 'trace'\n      ? drilldownTraceId == null\n        ? (rootSpanOfSelectedTrace ?? null)\n        : (currentSpanInTrace?.span ?? null)\n      : viewMode === 'span'\n        ? currentSpanInFlat\n        : null;\n\n  const selectedTraceLogs =\n    selectedTraceSummary?.traceId && logs.length > 0\n      ? logs.filter((l) => l.traceId === selectedTraceSummary.traceId)\n      : [];\n\n  const timelineItems =\n    selectedTraceSummary &&\n    (selectedTraceSummary.spans.length > 0 || selectedTraceLogs.length > 0)\n      ? buildTraceTimeline(selectedTraceSummary.spans, selectedTraceLogs)\n      : [];\n\n  /** Spans belonging to the drilled-down trace */\n  const drilldownSpans = useMemo(\n    () =>\n      drilldownTraceId\n        ? spans.filter((s) => s.traceId === drilldownTraceId)\n        : [],\n    [spans, drilldownTraceId],\n  );\n\n  /** Span tree for drill-down */\n  const drilldownTree = useMemo(\n    () =>\n      drilldownSpans.length > 0\n        ? flattenTraceTree(buildTraceTree(drilldownSpans))\n        : [],\n    [drilldownSpans],\n  );\n\n  /** Logs for the drilled-down trace */\n  const drilldownLogs = useMemo(\n    () =>\n      drilldownTraceId\n        ? logs.filter((l) => l.traceId === drilldownTraceId)\n        : [],\n    [logs, drilldownTraceId],\n  );\n\n  /** Combined timeline for drill-down (spans + logs interleaved by time) */\n  const drilldownTimeline = useMemo(\n    () =>\n      drilldownSpans.length > 0 || drilldownLogs.length > 0\n        ? buildTraceTimeline(drilldownSpans, drilldownLogs)\n        : [],\n    [drilldownSpans, drilldownLogs],\n  );\n\n  /** Summary for the drilled-down trace (for header display) */\n  const drilldownSummary = useMemo(\n    () =>\n      drilldownTraceId\n        ? (traceSummaries.find((t) => t.traceId === drilldownTraceId) ?? null)\n        : null,\n    [traceSummaries, drilldownTraceId],\n  );\n\n  /** Currently selected item in the drill-down view */\n  const drilldownSelectedItem = useMemo(() => {\n    if (!drilldownTraceId) return null;\n    if (drilldownTab === 'timeline') {\n      const item = drilldownTimeline[drilldownSelectedIndex];\n      if (!item) return null;\n      return item;\n    }\n    if (drilldownTab === 'spans') {\n      return drilldownTree[drilldownSelectedIndex]\n        ? {\n            type: 'span' as const,\n            span: drilldownTree[drilldownSelectedIndex]!.span,\n          }\n        : null;\n    }\n    if (drilldownTab === 'logs') {\n      return drilldownLogs[drilldownSelectedIndex]\n        ? { type: 'log' as const, log: drilldownLogs[drilldownSelectedIndex] }\n        : null;\n    }\n    return null;\n  }, [\n    drilldownTraceId,\n    drilldownTab,\n    drilldownSelectedIndex,\n    drilldownTimeline,\n    drilldownTree,\n    drilldownLogs,\n  ]);\n\n  // AI query sender — uses tools for precise telemetry queries\n  const sendAIQuery = async (question: string) => {\n    const aiResult = aiModelRef.current;\n    if (!aiResult || aiState.status === 'streaming') return;\n\n    const userMsg: ChatMessage = { role: 'user', content: question };\n    setAiMessages((prev) => [...prev, userMsg]);\n    setAiInput('');\n\n    const abort = new AbortController();\n    aiAbortRef.current = abort;\n    setAiSpec(null);\n    setAiState({ status: 'streaming', abortController: abort });\n\n    // Build tool context from current dashboard state\n    const toolCtx: ToolContext = {\n      spans,\n      logs,\n      traces: traceSummaries,\n      stats,\n      serviceStats,\n      errorSummaries,\n    };\n    const tools = createTelemetryTools(toolCtx, (spec) => setAiSpec(spec));\n\n    // Compact stats for system prompt (tools provide the detailed data)\n    const statsContext = JSON.stringify({\n      viewMode,\n      stats: {\n        totalSpans: stats.total,\n        errors: stats.errors,\n        avgMs: Math.round(stats.avg),\n        p95Ms: Math.round(stats.p95),\n      },\n      services: serviceStats.length,\n      traces: traceSummaries.length,\n    });\n    const drilldownContext = drilldownTraceId\n      ? `\\n\\nCurrently viewing trace ${drilldownTraceId}. This trace has ${drilldownSpans.length} spans and ${drilldownLogs.length} logs. The root span is \"${drilldownSummary?.rootName ?? 'unknown'}\" with duration ${drilldownSummary ? formatDurationMs(drilldownSummary.durationMs) : 'unknown'}.`\n      : '';\n    const systemPrompt =\n      buildSystemPrompt(viewMode, statsContext) + drilldownContext;\n\n    try {\n      // Add empty assistant message for streaming\n      setAiMessages((prev) => [...prev, { role: 'assistant', content: '' }]);\n\n      const result = await providerStreamText(aiResult.providerType, {\n        model: aiResult.model,\n        system: systemPrompt,\n        messages: [...aiMessages, userMsg].map((m) => ({\n          role: m.role,\n          content: m.content,\n        })),\n        tools,\n        maxSteps: 10,\n        abortSignal: abort.signal,\n      });\n\n      let fullText = '';\n\n      for await (const chunk of result.textStream) {\n        if (abort.signal.aborted) break;\n        fullText += chunk;\n        const captured = fullText;\n        setAiMessages((prev) => {\n          const updated = [...prev];\n          const lastMsg = updated.at(-1);\n          if (lastMsg?.role === 'assistant') {\n            updated[updated.length - 1] = {\n              role: 'assistant',\n              content: captured,\n            };\n          }\n          return updated;\n        });\n      }\n\n      // If model returned no text (common with small models after tool calls),\n      // show a fallback message\n      if (!fullText.trim()) {\n        setAiMessages((prev) => {\n          const updated = [...prev];\n          const lastMsg = updated.at(-1);\n          if (lastMsg?.role === 'assistant' && !lastMsg.content.trim()) {\n            updated[updated.length - 1] = {\n              role: 'assistant',\n              content: '(No response from model — try a simpler question or a larger model)',\n            };\n          }\n          return updated;\n        });\n      }\n\n      setAiState({ status: 'idle' });\n    } catch (error: unknown) {\n      if (abort.signal.aborted) {\n        setAiState({ status: 'idle' });\n        return;\n      }\n      const errorMsg = error instanceof Error ? error.message : String(error);\n      process.stderr.write(`[autotel-terminal] AI error: ${errorMsg}\\n`);\n      setAiState({\n        status: 'error',\n        message: errorMsg,\n      });\n    } finally {\n      aiAbortRef.current = null;\n    }\n  };\n\n  const { isRawModeSupported } = useStdin();\n\n  useInput(\n    (input, key) => {\n      if (showHelp && input !== '?') {\n        if (input === '?') setShowHelp(false);\n        return;\n      }\n      if (input === '?') {\n        setShowHelp((h) => !h);\n        return;\n      }\n      if (input === '/') {\n        setSearchMode((m) => !m);\n        if (searchMode) setSearchQuery('');\n        return;\n      }\n      if (searchMode) {\n        if (key.escape || key.return) {\n          setSearchMode(false);\n        } else if (key.backspace || key.delete) {\n          setSearchQuery((q) => q.slice(0, -1));\n        } else if (key.tab) {\n          // Autocomplete: find first matching traceId and apply it\n          if (searchQuery.length >= 4) {\n            const match = traceSummaries.find((t) =>\n              t.traceId.toLowerCase().startsWith(searchQuery.toLowerCase()),\n            );\n            if (match) {\n              setSpanFilters((prev) => ({ ...prev, traceId: match.traceId }));\n              setSearchMode(false);\n              setSearchQuery('');\n            }\n          }\n        } else if (input && input.length === 1 && !key.ctrl && !key.meta) {\n          setSearchQuery((q) => q + input);\n        }\n        return;\n      }\n      if (traceIdMode) {\n        if (key.escape) {\n          setTraceIdMode(false);\n          setTraceIdInput('');\n        } else if (key.return) {\n          if (traceIdInput.trim()) {\n            // Find matching traceId (prefix match)\n            const match = traceSummaries.find((t) =>\n              t.traceId.toLowerCase().startsWith(traceIdInput.toLowerCase()),\n            );\n            if (match) {\n              setSpanFilters((prev) => ({ ...prev, traceId: match.traceId }));\n            }\n          } else {\n            // Empty input — clear traceId filter\n            setSpanFilters((prev) => {\n              // eslint-disable-next-line @typescript-eslint/no-unused-vars\n              const { traceId: _, ...rest } = prev;\n              return rest;\n            });\n          }\n          setTraceIdMode(false);\n          setTraceIdInput('');\n        } else if (key.tab) {\n          // Autocomplete: fill in first matching traceId\n          if (traceIdInput.length >= 2) {\n            const match = traceSummaries.find((t) =>\n              t.traceId.toLowerCase().startsWith(traceIdInput.toLowerCase()),\n            );\n            if (match) {\n              setTraceIdInput(match.traceId);\n            }\n          }\n        } else if (key.backspace || key.delete) {\n          setTraceIdInput((q) => q.slice(0, -1));\n        } else if (input && input.length === 1 && !key.ctrl && !key.meta) {\n          setTraceIdInput((q) => q + input);\n        }\n        return;\n      }\n      // AI input mode — intercepts all input when typing a question\n      if (aiInputMode) {\n        if (key.escape) {\n          if (aiState.status === 'streaming') {\n            aiAbortRef.current?.abort();\n          } else {\n            setAiInputMode(false);\n            setViewMode('trace');\n          }\n          return;\n        }\n        if (key.backspace || key.delete) {\n          setAiInput((q) => q.slice(0, -1));\n          return;\n        }\n        if (key.return) {\n          if (aiInput.trim()) {\n            sendAIQuery(aiInput.trim());\n          }\n          return;\n        }\n        if (input && input.length === 1 && !key.ctrl && !key.meta) {\n          setAiInput((q) => q + input);\n        }\n        return;\n      }\n      if (input === 'a') {\n        if (viewMode === 'ai') {\n          setViewMode('trace');\n          setAiInputMode(false);\n        } else {\n          setViewMode('ai');\n          if (aiState.status !== 'unconfigured') {\n            setAiInputMode(true);\n          }\n        }\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n        return;\n      }\n      if (key.escape) {\n        if (drilldownTraceId == null) {\n          setSearchMode(false);\n        } else {\n          setDrilldownTraceId(null);\n          setDrilldownSelectedIndex(0);\n          setDrilldownScrollOffset(0);\n          setDrilldownTab('timeline');\n        }\n        return;\n      }\n      if (key.tab && drilldownTraceId != null) {\n        const tabs: Array<'timeline' | 'spans' | 'logs'> = [\n          'timeline',\n          'spans',\n          'logs',\n        ];\n        const currentIdx = tabs.indexOf(drilldownTab);\n        const nextIdx = key.shift\n          ? (currentIdx - 1 + tabs.length) % tabs.length\n          : (currentIdx + 1) % tabs.length;\n        setDrilldownTab(tabs[nextIdx]!);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n        return;\n      }\n      if (key.return && drilldownTraceId == null) {\n        let targetTraceId: string | undefined;\n        let preSelectIndex = 0;\n        if (viewMode === 'trace' && filteredSummaries[selected]) {\n          targetTraceId = filteredSummaries[selected]!.traceId;\n        } else if (viewMode === 'log' && filteredLogs[selected]?.traceId) {\n          targetTraceId = filteredLogs[selected]!.traceId;\n          const originLog = filteredLogs[selected]!;\n          const traceSpans = spans.filter((s) => s.traceId === targetTraceId);\n          const traceLogs = logs.filter((l) => l.traceId === targetTraceId);\n          const timeline = buildTraceTimeline(traceSpans, traceLogs);\n          preSelectIndex = timeline.findIndex(\n            (item) => item.type === 'log' && item.log === originLog,\n          );\n          if (preSelectIndex < 0) preSelectIndex = 0;\n        } else if (viewMode === 'span' && filteredSpans[selected]?.traceId) {\n          targetTraceId = filteredSpans[selected]!.traceId;\n          const originSpan = filteredSpans[selected]!;\n          const traceSpans = spans.filter((s) => s.traceId === targetTraceId);\n          const traceLogs = logs.filter((l) => l.traceId === targetTraceId);\n          const timeline = buildTraceTimeline(traceSpans, traceLogs);\n          preSelectIndex = timeline.findIndex(\n            (item) =>\n              item.type === 'span' && item.span?.spanId === originSpan.spanId,\n          );\n          if (preSelectIndex < 0) preSelectIndex = 0;\n        }\n        if (targetTraceId) {\n          setDrilldownTraceId(targetTraceId);\n          setDrilldownSelectedIndex(preSelectIndex);\n          setDrilldownScrollOffset(Math.max(0, preSelectIndex - LIST_HEIGHT + 1));\n          setDrilldownTab('timeline');\n          return;\n        }\n      }\n      if (key.upArrow || key.downArrow) {\n        if (drilldownTraceId != null) {\n          // In drill-down mode — navigate within the active tab's list\n          const listLength =\n            drilldownTab === 'timeline'\n              ? drilldownTimeline.length\n              : drilldownTab === 'spans'\n                ? drilldownTree.length\n                : drilldownLogs.length;\n          if (key.upArrow) {\n            setDrilldownSelectedIndex((prev) => {\n              const next = Math.max(0, prev - 1);\n              setDrilldownScrollOffset((off) => Math.min(next, off));\n              return next;\n            });\n          } else {\n            setDrilldownSelectedIndex((prev) => {\n              const next = Math.min(listLength - 1, prev + 1);\n              setDrilldownScrollOffset((off) =>\n                next >= off + LIST_HEIGHT ? next - LIST_HEIGHT + 1 : off,\n              );\n              return next;\n            });\n          }\n          return;\n        }\n        switch (viewMode) {\n          case 'trace': {\n            if (key.upArrow) {\n              setSelected((i) => Math.max(0, i - 1));\n              setDrilldownSelectedIndex(0);\n            } else if (key.downArrow) {\n              setSelected((i) => Math.min(filteredSummaries.length - 1, i + 1));\n              setDrilldownSelectedIndex(0);\n            }\n            break;\n          }\n          case 'span': {\n            if (key.upArrow) {\n              setSelected((i) => Math.max(0, i - 1));\n            } else if (key.downArrow) {\n              setSelected((i) => Math.min(filteredSpans.length - 1, i + 1));\n            }\n            break;\n          }\n          case 'log': {\n            if (key.upArrow) {\n              setSelected((i) => Math.max(0, i - 1));\n            } else if (key.downArrow) {\n              setSelected((i) => Math.min(filteredLogs.length - 1, i + 1));\n            }\n            break;\n          }\n          case 'service-summary': {\n            if (key.upArrow) {\n              setSelected((i) => Math.max(0, i - 1));\n            } else if (key.downArrow) {\n              setSelected((i) => Math.min(serviceStats.length - 1, i + 1));\n            }\n            break;\n          }\n          case 'errors': {\n            if (key.upArrow) {\n              setSelected((i) => Math.max(0, i - 1));\n            } else if (key.downArrow) {\n              setSelected((i) =>\n                Math.min(filteredErrorSummaries.length - 1, i + 1),\n              );\n            }\n            break;\n          }\n        }\n      }\n      if (input === 'p') setPaused((p) => !p);\n      if (input === 'e') setFilterErrorsOnly((v) => !v);\n      if (input === 't') {\n        setViewMode((m) => (m === 'trace' ? 'span' : 'trace'));\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'l') {\n        setViewMode((m) => (m === 'log' ? 'trace' : 'log'));\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'v') {\n        setViewMode((m) =>\n          m === 'service-summary' ? 'trace' : 'service-summary',\n        );\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'E') {\n        setViewMode((m) => (m === 'errors' ? 'trace' : 'errors'));\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'G') {\n        setViewMode((m) => (m === 'topology' ? 'trace' : 'topology'));\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'c') {\n        setSpans([]);\n        setLogs([]);\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n        setNewErrorCount(0);\n        setSpanFilters({ statusGroup: 'all' });\n        setRecording(false);\n        setPaused(false);\n      }\n      if (input === 'r') {\n        setSpans([]);\n        setLogs([]);\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n        setNewErrorCount(0);\n        setSpanFilters({ statusGroup: 'all' });\n        setPaused(false);\n        setRecording(true);\n      }\n      if (input === 'x') {\n        setSpanFilters({ statusGroup: 'all' });\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'f') {\n        setTraceIdMode(true);\n        setTraceIdInput(spanFilters.traceId ?? '');\n        return;\n      }\n      if (input === 'H') {\n        setSpanFilters((prev) => {\n          const next =\n            prev.statusGroup === 'all'\n              ? '2xx'\n              : prev.statusGroup === '2xx'\n                ? '4xx'\n                : prev.statusGroup === '4xx'\n                  ? '5xx'\n                  : 'all';\n          return { ...prev, statusGroup: next };\n        });\n        setSelected(0);\n        setDrilldownTraceId(null);\n        setDrilldownSelectedIndex(0);\n        setDrilldownScrollOffset(0);\n      }\n      if (input === 'S') {\n        const svc = currentSpan?.attributes?.['service.name'];\n        if (typeof svc === 'string' && svc.trim()) {\n          setSpanFilters((prev) => ({ ...prev, serviceName: svc }));\n          setSelected(0);\n          setDrilldownTraceId(null);\n          setDrilldownSelectedIndex(0);\n          setDrilldownScrollOffset(0);\n        }\n      }\n      if (input === 'R') {\n        const route = currentSpan?.attributes?.['http.route'];\n        if (typeof route === 'string' && route.trim()) {\n          setSpanFilters((prev) => ({ ...prev, route }));\n          setSelected(0);\n          setDrilldownTraceId(null);\n          setDrilldownSelectedIndex(0);\n          setDrilldownScrollOffset(0);\n        }\n      }\n      if (input === 'T') {\n        // Jump to trace view with traceId filter from current item\n        let traceId: string | undefined;\n        if (drilldownTraceId) {\n          traceId = drilldownTraceId;\n        } else {\n          switch (viewMode) {\n            case 'log': {\n              traceId = filteredLogs[selected]?.traceId;\n              break;\n            }\n            case 'span': {\n              traceId = filteredSpans[selected]?.traceId;\n              break;\n            }\n            case 'errors': {\n              traceId = filteredErrorSummaries[selected]?.traceId;\n              break;\n            }\n          }\n        }\n        if (traceId && viewMode !== 'trace') {\n          setSpanFilters((prev) => ({ ...prev, traceId }));\n          setViewMode('trace');\n          setSelected(0);\n          setDrilldownTraceId(null);\n          setDrilldownSelectedIndex(0);\n          setDrilldownScrollOffset(0);\n          setDrilldownTab('timeline');\n        }\n        return;\n      }\n      if (input === 'L') {\n        // Jump to log view with traceId filter from current item\n        let traceId: string | undefined;\n        if (drilldownTraceId) {\n          traceId = drilldownTraceId;\n        } else {\n          switch (viewMode) {\n            case 'trace': {\n              traceId = filteredSummaries[selected]?.traceId;\n              break;\n            }\n            case 'span': {\n              traceId = filteredSpans[selected]?.traceId;\n              break;\n            }\n            case 'errors': {\n              traceId = filteredErrorSummaries[selected]?.traceId;\n              break;\n            }\n          }\n        }\n        if (traceId && viewMode !== 'log') {\n          setSpanFilters((prev) => ({ ...prev, traceId }));\n          setViewMode('log');\n          setSelected(0);\n          setDrilldownTraceId(null);\n          setDrilldownSelectedIndex(0);\n          setDrilldownScrollOffset(0);\n          setDrilldownTab('timeline');\n        }\n        return;\n      }\n      if (input === 'J') {\n        const t = selectedTraceSummary;\n        if (!t) return;\n        const json = exportTraceToJson(t, selectedTraceLogs);\n        process.stdout.write(`\\n[autotel-terminal] trace export\\n${json}\\n`);\n      }\n    },\n    { isActive: isRawModeSupported },\n  );\n\n  const headerRight = recording\n    ? '[Recording]'\n    : paused\n      ? '[Paused]'\n      : '[Live]';\n  const headerModeLabel =\n    viewMode === 'trace'\n      ? 'traces'\n      : viewMode === 'span'\n        ? 'spans'\n        : viewMode === 'log'\n          ? 'logs'\n          : viewMode === 'service-summary'\n            ? 'services'\n            : viewMode === 'topology'\n              ? 'topology'\n            : viewMode === 'ai'\n              ? 'AI'\n              : 'errors';\n  const showNewError = newErrorCount > 0;\n\n  function renderTreeRow(\n    node: SpanTreeNode,\n    index: number,\n  ): React.ReactElement {\n    const isSel = drilldownTraceId != null && index === drilldownSelectedIndex;\n    const prefix =\n      node.depth === 0\n        ? ''\n        : '  '.repeat(node.depth) +\n          (node.children.length > 0 ? '├── ' : '└── ');\n    const svcName = spanServiceName(node.span);\n    const svcColor = getServiceColor(svcName);\n    const statusColor =\n      node.span.status === 'ERROR'\n        ? 'red'\n        : node.span.durationMs > 500\n          ? 'yellow'\n          : 'green';\n    return (\n      <Box\n        key={`${node.span.spanId}-${node.span.startTime}`}\n        flexDirection=\"row\"\n      >\n        <Text backgroundColor={isSel ? 'blue' : undefined} color={isSel ? 'white' : undefined}>{isSel ? '▸ ' : '  '}</Text>\n        <Text color={node.span.status === 'ERROR' ? 'red' : undefined}>{node.span.status === 'ERROR' ? '✗' : ' '}</Text>\n        <Text dimColor>{prefix}</Text>\n        <Text color={colors ? statusColor : undefined}>\n          {truncate(node.span.name, 23)}\n        </Text>\n        <Text color={svcColor}> {truncate(svcName, 10)}</Text>\n        <Text dimColor> {node.span.kind ?? ''}</Text>\n        <Text dimColor> {formatDurationMs(node.span.durationMs)}</Text>\n      </Box>\n    );\n  }\n\n  function keyAttrsAndRest(attrs: Record<string, unknown> | undefined) {\n    if (!attrs || Object.keys(attrs).length === 0)\n      return {\n        key: [] as [string, unknown][],\n        rest: [] as [string, unknown][],\n      };\n    const entries = Object.entries(attrs);\n    const key = entries.filter(([k]) => KEY_ATTR_KEYS.has(k));\n    const rest = entries.filter(([k]) => !KEY_ATTR_KEYS.has(k));\n    return { key, rest };\n  }\n\n  const waterfallMaxMs =\n    waterfallSpans.length > 0\n      ? Math.max(...waterfallSpans.map((w) => w.span.durationMs))\n      : 1;\n  const barWidth = 30;\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      paddingX={1}\n    >\n      <Box justifyContent=\"space-between\" marginBottom={1}>\n        <Text key=\"title\" bold>\n          🔭 {title} — {headerModeLabel}\n        </Text>\n        <Box flexDirection=\"row\" gap={1}>\n          {showNewError && (\n            <Text key=\"newError\" color=\"red\">\n              1 new error\n            </Text>\n          )}\n          <Text key=\"status\" color={paused ? 'yellow' : 'green'}>\n            {headerRight}\n          </Text>\n        </Box>\n      </Box>\n\n      {/* Controls bar — always exactly 2 lines */}\n      <Box marginBottom={0} flexDirection=\"column\">\n        {searchMode ? (\n          <Text color=\"cyan\">\n            Search: {searchQuery || '(type to filter)'}\n            <Text dimColor> (Tab: match traceId, Esc: cancel)</Text>\n          </Text>\n        ) : traceIdMode ? (\n          <Text color=\"yellow\">\n            TraceId: {traceIdInput || '(type prefix, Tab to complete)'}\n            {traceIdInput.length >= 2 && (\n              <Text dimColor>\n                {' → '}\n                {traceSummaries\n                  .find((t) =>\n                    t.traceId.toLowerCase().startsWith(traceIdInput.toLowerCase()),\n                  )\n                  ?.traceId.slice(0, 16) ?? 'no match'}…\n              </Text>\n            )}\n          </Text>\n        ) : (\n          <Box flexDirection=\"row\" justifyContent=\"space-between\">\n            <Text dimColor>\n              {drilldownTraceId == null\n                ? '↑/↓ select • Enter open • Tab cycle tabs • Esc back • t trace • l logs • a AI • ? help'\n                : '↑/↓ select • Tab cycle tabs • Esc back • t trace • l logs • a AI • ? help'}\n            </Text>\n            <Text dimColor>\n              {viewMode === 'trace'\n                ? `traces ${filteredSummaries.length}/${traceSummaries.length}`\n                : viewMode === 'span'\n                  ? `spans ${filteredSpans.length}/${spans.length}`\n                  : viewMode === 'service-summary'\n                    ? `services ${serviceStats.length}`\n                    : viewMode === 'errors'\n                      ? `errors ${filteredErrorSummaries.length}/${errorSummaries.length}`\n                      : viewMode === 'topology'\n                        ? `services ${serviceGraph.services.length} · edges ${serviceGraph.edges.length}`\n                      : viewMode === 'ai'\n                        ? `messages ${aiMessages.length}`\n                        : `logs ${filteredLogs.length}/${logs.length}`}\n            </Text>\n          </Box>\n        )}\n        {showHelp && (\n          <Text dimColor>\n            Views: t/l/v/E/G/a • Search: / • Filters: e/S/R/H/f/x • Capture: p/r/J • Clear: c\n          </Text>\n        )}\n      </Box>\n\n      <Box marginBottom={0}>\n        <Text dimColor>\n          {spanFilters.serviceName || spanFilters.route || spanFilters.statusGroup !== 'all' || spanFilters.traceId\n            ? `filters:${spanFilters.serviceName ? ` service=${spanFilters.serviceName}` : ''}${spanFilters.route ? ` route=${spanFilters.route}` : ''}${spanFilters.statusGroup && spanFilters.statusGroup !== 'all' ? ` status=${spanFilters.statusGroup}` : ''}${spanFilters.traceId ? ` trace=${spanFilters.traceId.slice(0, 8)}…` : ''}`\n            : 'filters: none'}\n        </Text>\n      </Box>\n\n      {viewMode === 'topology' && (\n        <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n          <Text bold>Service Topology</Text>\n          <Text dimColor>Press G to toggle · Shows service dependencies from span data</Text>\n          <Box flexDirection=\"column\" marginTop={1}>\n            {topologyLines.map((line, i) => {\n              const hasErr = line.includes(' err');\n              return (\n                <Text key={`topo-${i}`} color={hasErr ? 'red' : undefined}>\n                  {line}\n                </Text>\n              );\n            })}\n          </Box>\n        </Box>\n      )}\n\n      {viewMode === 'ai' && (\n        <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1} paddingY={0}>\n          <Box marginBottom={1} justifyContent=\"space-between\">\n            <Text bold>AI Assistant</Text>\n            <Text dimColor>\n              {aiState.status === 'streaming'\n                ? '(streaming...)'\n                : aiState.status === 'unconfigured'\n                  ? '(no provider)'\n                  : aiState.status === 'error'\n                    ? '(error)'\n                    : ''}\n            </Text>\n          </Box>\n\n          {aiState.status === 'unconfigured' ? (\n            <Box flexDirection=\"column\">\n              <Text dimColor>No AI provider configured.</Text>\n              <Text dimColor>Set AI_PROVIDER and AI_MODEL env vars, or start Ollama locally.</Text>\n              <Text dimColor>Press a to close this view.</Text>\n            </Box>\n          ) : (\n            <>\n              {aiMessages.length === 0 && aiState.status !== 'error' && (\n                <Text dimColor>Ask a question about your telemetry data. Press Enter to send.</Text>\n              )}\n              {aiMessages.slice(-10).map((msg, i) => (\n                <Box key={`ai-msg-${i}`} flexDirection=\"column\" marginBottom={msg.role === 'assistant' ? 1 : 0}>\n                  <Text color={msg.role === 'user' ? 'cyan' : undefined}>\n                    {msg.role === 'user' ? '> ' : ''}\n                    {msg.content.slice(0, 1000)}\n                    {msg.content.length > 1000 ? '...' : ''}\n                  </Text>\n                </Box>\n              ))}\n              {aiSpec && (\n                <Box flexDirection=\"column\" marginBottom={1} borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n                  <InkRenderer spec={aiSpec} />\n                </Box>\n              )}\n              {aiState.status === 'error' && (\n                <Text color=\"red\">Error: {aiState.message}</Text>\n              )}\n              <Box marginTop={1} borderStyle=\"single\" borderColor=\"cyan\" paddingX={1}>\n                <Text color=\"cyan\">&gt; </Text>\n                <Text>\n                  {aiInput || (aiInputMode ? '(type your question)' : '(press a to focus)')}\n                </Text>\n              </Box>\n            </>\n          )}\n        </Box>\n      )}\n\n      {/* eslint-disable unicorn/no-negated-condition */}\n      {viewMode !== 'topology' && viewMode !== 'ai' && (drilldownTraceId != null ? (\n        <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1} paddingY={0}>\n          {/* Trace header */}\n          <Box marginBottom={0} flexDirection=\"column\">\n            <Text bold>Trace {drilldownTraceId.slice(0, 16)}…</Text>\n            <Box flexDirection=\"row\" gap={1}>\n              {drilldownSummary?.services?.map((svc) => (\n                <Text key={svc} color={getServiceColor(svc)}>{svc}</Text>\n              ))}\n              <Text dimColor>·</Text>\n              <Text>{drilldownSummary?.rootName ?? 'unknown'}</Text>\n              <Text dimColor>·</Text>\n              <Text dimColor>{drilldownSpans.length} spans</Text>\n              <Text dimColor>·</Text>\n              <Text dimColor>{drilldownSummary?.services?.length ?? 0} services</Text>\n              {drilldownSummary?.hasError && <Text color=\"red\">{' '}ERROR</Text>}\n            </Box>\n            <Box flexDirection=\"row\" gap={2}>\n              <Text dimColor>Duration: </Text>\n              <Text color=\"green\">{formatDurationMs(drilldownSummary?.durationMs ?? 0)}</Text>\n            </Box>\n          </Box>\n          {/* Tabs — blue active */}\n          <Box marginBottom={0} flexDirection=\"row\" gap={2}>\n            <Text\n              color={drilldownTab === 'timeline' ? 'blue' : undefined}\n              dimColor={drilldownTab !== 'timeline'}\n              bold={drilldownTab === 'timeline'}\n            >\n              Timeline\n            </Text>\n            <Text\n              color={drilldownTab === 'spans' ? 'blue' : undefined}\n              dimColor={drilldownTab !== 'spans'}\n              bold={drilldownTab === 'spans'}\n            >\n              Spans ({drilldownSpans.length})\n            </Text>\n            <Text\n              color={drilldownTab === 'logs' ? 'blue' : undefined}\n              dimColor={drilldownTab !== 'logs'}\n              bold={drilldownTab === 'logs'}\n            >\n              Logs ({drilldownLogs.length})\n            </Text>\n          </Box>\n\n          {drilldownTab === 'timeline' &&\n            (() => {\n              const NAME_COL = 28;\n              const SERVICE_COL = 12;\n              const KIND_COL = 10;\n              let traceStartMs = Infinity;\n              for (const s of drilldownSummary?.spans ?? []) {\n                if (s.startTime < traceStartMs) traceStartMs = s.startTime;\n              }\n              if (traceStartMs === Infinity) traceStartMs = 0;\n              const traceDurMs = drilldownSummary?.durationMs ?? 1;\n              const WATERFALL_WIDTH = 44;\n              const items = drilldownTimeline.slice(drilldownScrollOffset, drilldownScrollOffset + LIST_HEIGHT);\n\n              return (\n                <>\n                  {/* Time ruler */}\n                  <Box flexDirection=\"row\">\n                    <Text dimColor>{''.padEnd(NAME_COL + SERVICE_COL + KIND_COL + 2)}</Text>\n                    <Text dimColor>{buildTimeRuler(traceDurMs, WATERFALL_WIDTH)}</Text>\n                  </Box>\n                  {items.map((item, i) => {\n                    const isSel = i + drilldownScrollOffset === drilldownSelectedIndex;\n                    if (item.type === 'span' && item.span) {\n                      const s = item.span;\n                      const node = drilldownTree.find(\n                        (n) => n.span.spanId === s.spanId,\n                      );\n                      const depth = node?.depth ?? 0;\n                      const indent = '  '.repeat(Math.min(depth, 4));\n                      const nameWidth = NAME_COL - Math.min(depth, 4) * 2 - 1;\n                      const svcName = spanServiceName(s);\n                      const svcColor = getServiceColor(svcName);\n                      const kindStr = (s.kind ?? '').padEnd(KIND_COL);\n                      const svcStr = truncate(svcName, SERVICE_COL - 2).padEnd(SERVICE_COL);\n                      const errorMark = s.status === 'ERROR' ? '✗' : ' ';\n                      const namePart = `${indent}${truncate(s.name, nameWidth - 1)}`.padEnd(NAME_COL - 1);\n                      const bar = buildWaterfallBar(\n                        s.startTime, s.durationMs,\n                        traceStartMs, traceDurMs,\n                        WATERFALL_WIDTH,\n                      );\n                      return (\n                        <Box key={`${s.spanId}-${i}`} flexDirection=\"row\">\n                          <Text backgroundColor={isSel ? 'blue' : undefined} color={isSel ? 'white' : undefined}>\n                            {isSel ? '▸' : ' '}<Text color={s.status === 'ERROR' ? 'red' : undefined}>{errorMark}</Text>{namePart}\n                          </Text>\n                          <Text color={svcColor}> {svcStr}</Text>\n                          <Text dimColor>{kindStr}</Text>\n                          <Text color={s.status === 'ERROR' ? 'red' : svcColor}>{bar}</Text>\n                          <Text color={s.status === 'ERROR' ? 'red' : svcColor}>\n                            {' '}{formatDurationMs(s.durationMs)}\n                          </Text>\n                        </Box>\n                      );\n                    } else if (item.type === 'log' && item.log) {\n                      const l = item.log;\n                      const levelColor =\n                        l.level === 'error' ? 'red' : l.level === 'warn' ? 'yellow' : 'blue';\n                      const relTime = drilldownSummary\n                        ? `+${formatDurationMs(l.time - traceStartMs)}`\n                        : '';\n                      const logName = `  ${l.level.toUpperCase()} ${truncate(l.message, NAME_COL - 8)}`.padEnd(NAME_COL);\n                      const logOffset = drilldownSummary\n                        ? Math.floor(((l.time - traceStartMs) / traceDurMs) * WATERFALL_WIDTH)\n                        : 0;\n                      const clampedOffset = Math.max(0, Math.min(logOffset, WATERFALL_WIDTH - 1));\n                      const logBar = ' '.repeat(clampedOffset) + '·' + ' '.repeat(WATERFALL_WIDTH - clampedOffset - 1);\n                      return (\n                        <Box key={`log-${i}`} flexDirection=\"row\">\n                          <Text backgroundColor={isSel ? 'blue' : undefined} color={isSel ? 'white' : undefined}>\n                            {isSel ? '▸' : ' '}<Text color={levelColor}>{logName}</Text>\n                          </Text>\n                          <Text dimColor>{' '.padEnd(SERVICE_COL + KIND_COL + 1)}</Text>\n                          <Text dimColor>{logBar}</Text>\n                          <Text dimColor> {relTime}</Text>\n                        </Box>\n                      );\n                    }\n                    return null;\n                  })}\n                  {Array.from({ length: Math.max(0, LIST_HEIGHT - items.length) }).map((_, i) => (\n                    <Box key={`pad-${i}`}><Text> </Text></Box>\n                  ))}\n                </>\n              );\n            })()}\n\n          {drilldownTab === 'spans' &&\n            drilldownTree.slice(drilldownScrollOffset, drilldownScrollOffset + LIST_HEIGHT).map((node, i) => renderTreeRow(node, i + drilldownScrollOffset))}\n          {drilldownTab === 'spans' &&\n            Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(drilldownTree.length, LIST_HEIGHT)) }).map((_, i) => (\n              <Box key={`pad-${i}`}><Text> </Text></Box>\n            ))}\n\n          {drilldownTab === 'logs' &&\n            drilldownLogs.slice(drilldownScrollOffset, drilldownScrollOffset + LIST_HEIGHT).map((log, i) => {\n              const isSel = i + drilldownScrollOffset === drilldownSelectedIndex;\n              const levelColor =\n                log.level === 'error'\n                  ? 'red'\n                  : log.level === 'warn'\n                    ? 'yellow'\n                    : log.level === 'info'\n                      ? 'green'\n                      : undefined;\n              return (\n                <Box key={`log-${i}`}>\n                  <Text\n                    backgroundColor={isSel ? 'blue' : undefined}\n                    color={isSel ? 'white' : undefined}\n                  >\n                    {isSel ? '▸' : ' '}\n                    <Text color={levelColor}>\n                      {' '}\n                      {log.level.toUpperCase()}\n                    </Text>{' '}\n                    <Text dimColor>[{truncate(log.message, 50)}]</Text>\n                  </Text>\n                </Box>\n              );\n            })}\n          {drilldownTab === 'logs' &&\n            Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(drilldownLogs.length, LIST_HEIGHT)) }).map((_, i) => (\n              <Box key={`pad-${i}`}><Text> </Text></Box>\n            ))}\n\n          {/* Inline detail for selected span */}\n          {drilldownSelectedItem?.type === 'span' && drilldownSelectedItem.span && (\n            (() => {\n              const span = drilldownSelectedItem.span;\n              const { key: keyAttrs, rest: restAttrs } = keyAttrsAndRest(span.attributes);\n              return (\n                <Box marginTop={1} flexDirection=\"column\" borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n                  <Box flexDirection=\"row\" gap={2}>\n                    <Text bold>{span.name}</Text>\n                    <Text color={getServiceColor(spanServiceName(span))}>{spanServiceName(span)}</Text>\n                    <Text dimColor>{span.kind ?? ''}</Text>\n                    <Text color={span.status === 'ERROR' ? 'red' : 'green'}>{span.status}</Text>\n                    <Text>{formatDurationMs(span.durationMs)}</Text>\n                  </Box>\n                  <Box flexDirection=\"row\" gap={2}>\n                    <Text dimColor>Trace: {span.traceId}</Text>\n                    <Text dimColor>Span: {span.spanId}</Text>\n                    {span.parentSpanId && <Text dimColor>Parent: {span.parentSpanId}</Text>}\n                  </Box>\n                  {keyAttrs.length > 0 && (\n                    <Box marginTop={1} flexDirection=\"column\">\n                      <Text bold>Key attributes</Text>\n                      {keyAttrs.slice(0, 6).map(([k, v]) => (\n                        <Text key={k} dimColor>\n                          {truncate(k, 18)}: {truncate(String(v), 28)}\n                        </Text>\n                      ))}\n                    </Box>\n                  )}\n                  {restAttrs.length > 0 && (\n                    <Box marginTop={1} flexDirection=\"column\">\n                      <Text bold>Attributes</Text>\n                      {restAttrs.slice(0, 8).map(([k, v]) => (\n                        <Text key={k} dimColor>\n                          {truncate(k, 18)}: {truncate(String(v), 28)}\n                        </Text>\n                      ))}\n                    </Box>\n                  )}\n                  {/* Span Events */}\n                  {span.events && span.events.length > 0 && (\n                    <Box flexDirection=\"column\" marginTop={0}>\n                      <Text bold dimColor>Events ({span.events.length})</Text>\n                      {span.events.slice(0, 5).map((ev, i) => (\n                        <Box key={`ev-${i}`} flexDirection=\"row\">\n                          <Text color={ev.name === 'exception' ? 'red' : 'yellow'}>\n                            {'  '}{'\\u25C6'} {truncate(ev.name, 20)}\n                          </Text>\n                          <Text dimColor>\n                            {' '}+{formatDurationMs(ev.timeMs - span.startTime)}\n                          </Text>\n                          {ev.attributes && Object.keys(ev.attributes).length > 0 && (\n                            <Text dimColor>\n                              {' '}{Object.entries(ev.attributes).slice(0, 2).map(([k, v]) => `${k}=${String(v)}`).join(' ')}\n                            </Text>\n                          )}\n                        </Box>\n                      ))}\n                    </Box>\n                  )}\n                  {/* Span Links */}\n                  {span.links && span.links.length > 0 && (\n                    <Box flexDirection=\"column\" marginTop={0}>\n                      <Text bold dimColor>Links ({span.links.length})</Text>\n                      {span.links.slice(0, 5).map((lnk, i) => (\n                        <Box key={`lnk-${i}`} flexDirection=\"row\">\n                          <Text color=\"cyan\">\n                            {'  '}{'\\u2192'} trace:{lnk.traceId.slice(0, 8)}{'\\u2026'} span:{lnk.spanId.slice(0, 8)}{'\\u2026'}\n                          </Text>\n                          {lnk.attributes && Object.keys(lnk.attributes).length > 0 && (\n                            <Text dimColor>\n                              {' '}{Object.entries(lnk.attributes).slice(0, 2).map(([k, v]) => `${k}=${String(v)}`).join(' ')}\n                            </Text>\n                          )}\n                        </Box>\n                      ))}\n                    </Box>\n                  )}\n                </Box>\n              );\n            })()\n          )}\n          {/* Inline detail for selected log */}\n          {drilldownSelectedItem?.type === 'log' && drilldownSelectedItem.log && (\n            (() => {\n              const log = drilldownSelectedItem.log;\n              return (\n                <Box marginTop={1} flexDirection=\"column\" borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n                  <Box flexDirection=\"row\" gap={2}>\n                    <Text bold>{log.level.toUpperCase()}</Text>\n                    <Text>{log.message}</Text>\n                  </Box>\n                  <Text>\n                    <Text dimColor>Time: </Text>\n                    <Text>{new Date(log.time).toISOString()}</Text>\n                  </Text>\n                  {log.traceId && <Text dimColor>Trace: {log.traceId}</Text>}\n                  {log.spanId && <Text dimColor>Span: {log.spanId}</Text>}\n                  {log.attributes && Object.keys(log.attributes).length > 0 && (\n                    <Box marginTop={1} flexDirection=\"column\">\n                      <Text bold>Attributes</Text>\n                      {Object.entries(log.attributes).slice(0, 10).map(([k, v]) => (\n                        <Text key={k} dimColor>\n                          {truncate(k, 18)}: {truncate(String(v), 40)}\n                        </Text>\n                      ))}\n                    </Box>\n                  )}\n                </Box>\n              );\n            })()\n          )}\n        </Box>\n      ) : (\n      <Box flexDirection=\"row\" gap={2}>\n        <Box\n          flexDirection=\"column\"\n          width=\"55%\"\n          borderStyle=\"round\"\n          borderColor=\"gray\"\n          paddingX={1}\n          paddingY={0}\n        >\n          <Box marginTop={0} marginBottom={1}>\n            <Text key=\"list-title\" bold>\n              {viewMode === 'trace'\n                ? 'Recent traces'\n                : viewMode === 'span'\n                  ? 'Recent spans'\n                  : viewMode === 'service-summary'\n                    ? 'Service summary'\n                    : viewMode === 'errors'\n                      ? 'Recent errors'\n                      : 'Recent logs'}\n            </Text>\n            {filterErrorsOnly && (\n              <Text key=\"errors-only-label\" color=\"red\">\n                {' '}\n                (errors only)\n              </Text>\n            )}\n            {searchQuery && (\n              <Text key=\"search-label\" dimColor>\n                {' '}\n                /{searchQuery}\n              </Text>\n            )}\n          </Box>\n\n            <>\n              {viewMode === 'trace' ? (\n                filteredSummaries.length === 0 ? (\n                  <>\n                    <Box flexDirection=\"column\">\n                      <Text dimColor>\n                        No traces yet. Call a traced function or hit an endpoint\n                        to see them here.\n                      </Text>\n                      <Text dimColor>\n                        Tip: trace() your handlers with autotel to get spans.\n                      </Text>\n                    </Box>\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - 2) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                ) : (\n                  <>\n                    {filteredSummaries.slice(0, 20).map((t, i) => {\n                      const isSel = i === selected;\n                      return (\n                        <Box key={t.traceId} flexDirection=\"row\">\n                          <Text color={isSel ? 'cyan' : undefined}>\n                            {isSel ? '▸ ' : '  '}\n                          </Text>\n                          <Text color={t.hasError ? 'red' : 'yellow'} bold={isSel}>\n                            {truncate(t.rootName, 28)}\n                          </Text>\n                          <Text dimColor>\n                            {'  '}{t.spans.length} spans\n                          </Text>\n                          <Text color=\"green\">\n                            {'  '}{formatDurationMs(t.durationMs)}\n                          </Text>\n                          <Text dimColor>\n                            {'  '}{formatRelative(t.lastEndTime)}\n                          </Text>\n                          <Text dimColor>{'  '}{t.traceId.slice(0, 12)}…</Text>\n                          {t.hasError && <Text color=\"red\"> ●</Text>}\n                        </Box>\n                      );\n                    })}\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(filteredSummaries.length, 20)) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                )\n              ) : viewMode === 'span' ? (\n                filteredSpans.length === 0 ? (\n                  <>\n                    <Box flexDirection=\"column\">\n                      <Text dimColor>\n                        No spans yet. Call a traced function or hit an endpoint to\n                        see them here.\n                      </Text>\n                      <Text dimColor>\n                        Tip: trace() your handlers with autotel to get spans.\n                      </Text>\n                    </Box>\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - 2) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                ) : (\n                  <>\n                    {filteredSpans.slice(0, 20).map((s, i) => {\n                      const isSel = i === selected;\n                      const svcName = spanServiceName(s);\n                      const svcColor = getServiceColor(svcName);\n                      const statusColor =\n                        s.status === 'ERROR'\n                          ? 'red'\n                          : s.durationMs > 500\n                            ? 'yellow'\n                            : 'green';\n                      return (\n                        <Box\n                          key={`${s.spanId}-${s.startTime}`}\n                          flexDirection=\"row\"\n                        >\n                          <Text color={isSel ? 'cyan' : undefined}>\n                            {isSel ? '› ' : '  '}\n                          </Text>\n                          <Text color={colors ? statusColor : undefined}>\n                            {truncate(s.name, 26)}\n                          </Text>\n                          <Text color={svcColor}> {truncate(svcName, 10)}</Text>\n                          <Text dimColor> {formatDurationMs(s.durationMs)}</Text>\n                          <Text dimColor> {formatRelative(s.endTime)}</Text>\n                        </Box>\n                      );\n                    })}\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(filteredSpans.length, 20)) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                )\n              ) : viewMode === 'service-summary' ? (\n                serviceStats.length === 0 ? (\n                  <>\n                    <Box flexDirection=\"column\">\n                      <Text dimColor>\n                        No service stats yet. Add `service.name` attributes to\n                        spans.\n                      </Text>\n                    </Box>\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - 1) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                ) : (\n                  <>\n                    {serviceStats.slice(0, 20).map((svc, i) => {\n                      const isSel = i === selected;\n                      const errorRate = svc.total\n                        ? (svc.errors / svc.total) * 100\n                        : 0;\n                      return (\n                        <Box key={svc.serviceName} flexDirection=\"row\">\n                          <Text color={isSel ? 'cyan' : undefined}>\n                            {isSel ? '› ' : '  '}\n                          </Text>\n                          <Text>{truncate(svc.serviceName, 16)}</Text>\n                          <Text dimColor>\n                            {' '}\n                            {svc.errors}/{svc.total}\n                          </Text>\n                          <Text dimColor> {errorRate.toFixed(0)}%</Text>\n                          <Text dimColor> p95 {formatDurationMs(svc.p95Ms)}</Text>\n                        </Box>\n                      );\n                    })}\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(serviceStats.length, 20)) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                )\n              ) : viewMode === 'errors' ? (\n                filteredErrorSummaries.length === 0 ? (\n                  <>\n                    <Box flexDirection=\"column\">\n                      <Text dimColor>No errors yet.</Text>\n                    </Box>\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - 1) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                ) : (\n                  <>\n                    {filteredErrorSummaries.slice(0, 20).map((e, i) => {\n                      const isSel = i === selected;\n                      return (\n                        <Box key={e.traceId} flexDirection=\"row\">\n                          <Text color={isSel ? 'cyan' : undefined}>\n                            {isSel ? '› ' : '  '}\n                          </Text>\n                          <Text color=\"red\">{truncate(e.rootName, 16)}</Text>\n                          <Text dimColor> {truncate(e.serviceName, 10)}</Text>\n                          {e.route && (\n                            <Text dimColor> {truncate(e.route, 14)}</Text>\n                          )}\n                          {typeof e.statusCode === 'number' && (\n                            <Text dimColor> {e.statusCode}</Text>\n                          )}\n                          <Text dimColor> ({e.errorCount})</Text>\n                        </Box>\n                      );\n                    })}\n                    {Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(filteredErrorSummaries.length, 20)) }).map((_, i) => (\n                      <Box key={`pad-${i}`}><Text> </Text></Box>\n                    ))}\n                  </>\n                )\n              ) : filteredLogs.length === 0 ? (\n                <>\n                  <Box flexDirection=\"column\">\n                    <Text dimColor>\n                      No logs yet. Emit request logs or canonical log lines to see\n                      them here.\n                    </Text>\n                    <Text dimColor>\n                      Tip: hook getTerminalLogStream() into your canonical log\n                      line drain.\n                    </Text>\n                  </Box>\n                  {Array.from({ length: Math.max(0, LIST_HEIGHT - 2) }).map((_, i) => (\n                    <Box key={`pad-${i}`}><Text> </Text></Box>\n                  ))}\n                </>\n              ) : (\n                <>\n                  {filteredLogs.slice(0, 20).map((log, i) => {\n                    const isSel = i === selected;\n                    const levelColor =\n                      log.level === 'error'\n                        ? 'red'\n                        : log.level === 'warn'\n                          ? 'yellow'\n                          : log.level === 'debug'\n                            ? 'gray'\n                            : 'green';\n                    return (\n                      <Box key={`${log.time}-${i}`} flexDirection=\"row\">\n                        <Text color={isSel ? 'cyan' : undefined}>\n                          {isSel ? '› ' : '  '}\n                        </Text>\n                        <Text color={colors ? levelColor : undefined}>\n                          {truncate(log.level.toUpperCase(), 5)}\n                        </Text>\n                        <Text> </Text>\n                        <Text>{truncate(log.message, 32)}</Text>\n                      </Box>\n                    );\n                  })}\n                  {Array.from({ length: Math.max(0, LIST_HEIGHT - Math.min(filteredLogs.length, 20)) }).map((_, i) => (\n                    <Box key={`pad-${i}`}><Text> </Text></Box>\n                  ))}\n                </>\n              )}\n            </>\n        </Box>\n\n        <Box\n          flexDirection=\"column\"\n          width=\"45%\"\n          borderStyle=\"round\"\n          borderColor=\"gray\"\n          paddingX={1}\n          paddingY={0}\n        >\n            <>\n              <Box marginBottom={1}>\n                <Text bold>Details</Text>\n              </Box>\n\n              {viewMode === 'errors' ? (\n                  (() => {\n                    const e = filteredErrorSummaries[selected] ?? null;\n                    if (!e)\n                      return (\n                        <Text dimColor>Select an error to view details.</Text>\n                      );\n                    return (\n                      <>\n                        <Text>\n                          <Text dimColor>Trace: </Text>\n                          <Text>{e.traceId}</Text>\n                        </Text>\n                        <Text dimColor>\n                          Service: {e.serviceName}\n                          {e.route ? ` • Route: ${e.route}` : ''}\n                          {typeof e.statusCode === 'number'\n                            ? ` • Status: ${e.statusCode}`\n                            : ''}\n                        </Text>\n                        <Text dimColor>Errors: {e.errorCount}</Text>\n                        <Text dimColor>\n                          Press T to jump to trace view for this trace.\n                        </Text>\n                      </>\n                    );\n                  })()\n                ) : viewMode === 'service-summary' ? (\n                  (() => {\n                    const svc = serviceStats[selected] ?? null;\n                    if (!svc)\n                      return (\n                        <Text dimColor>Select a service to view details.</Text>\n                      );\n                    return (\n                      <>\n                        <Text>\n                          <Text dimColor>Service: </Text>\n                          <Text>{svc.serviceName}</Text>\n                        </Text>\n                        <Text dimColor>\n                          Spans: {svc.total} | Errors: {svc.errors} | Avg:{' '}\n                          {formatDurationMs(svc.avgMs)} | P95:{' '}\n                          {formatDurationMs(svc.p95Ms)}\n                        </Text>\n\n                        <Box marginTop={1} flexDirection=\"column\">\n                          <Text bold>Top routes</Text>\n                          {selectedServiceRouteStats.length === 0 ? (\n                            <Text dimColor>(no http.route)</Text>\n                          ) : (\n                            selectedServiceRouteStats.map((r) => (\n                              <Text key={r.route} dimColor>\n                                {truncate(r.route, 20)} {r.errors}/{r.total} p95{' '}\n                                {formatDurationMs(r.p95Ms)}\n                              </Text>\n                            ))\n                          )}\n                        </Box>\n\n                        <Box marginTop={1} flexDirection=\"column\">\n                          <Text bold>Hot spans</Text>\n                          {selectedServiceHotSpans.length === 0 ? (\n                            <Text dimColor>(no spans)</Text>\n                          ) : (\n                            selectedServiceHotSpans.map((h) => (\n                              <Text key={h.name} dimColor>\n                                {truncate(h.name, 20)} p95{' '}\n                                {formatDurationMs(h.p95Ms)} ({h.count}x)\n                              </Text>\n                            ))\n                          )}\n                        </Box>\n                      </>\n                    );\n                  })()\n                ) : viewMode === 'log' ? (\n                  (() => {\n                    const log = filteredLogs[selected] ?? null;\n                    if (!log) {\n                      return (\n                        <Text dimColor>Select a log to view details.</Text>\n                      );\n                    }\n                    return (\n                      <>\n                        <Text>\n                          <Text dimColor>Level: </Text>\n                          <Text>{log.level.toUpperCase()}</Text>\n                        </Text>\n                        <Text>\n                          <Text dimColor>Time: </Text>\n                          <Text>{new Date(log.time).toISOString()}</Text>\n                        </Text>\n                        <Text>\n                          <Text dimColor>Message: </Text>\n                          <Text>{log.message}</Text>\n                        </Text>\n                        {log.traceId && (\n                          <Text dimColor>Trace: {log.traceId}</Text>\n                        )}\n                        {log.spanId && <Text dimColor>Span: {log.spanId}</Text>}\n                        {log.attributes &&\n                          Object.keys(log.attributes).length > 0 && (\n                            <Box marginTop={1} flexDirection=\"column\">\n                              <Text bold>Attributes</Text>\n                              {Object.entries(log.attributes)\n                                .slice(0, 10)\n                                .map(([k, v]) => (\n                                  <Text key={k} dimColor>\n                                    {truncate(k, 18)}: {truncate(String(v), 40)}\n                                  </Text>\n                                ))}\n                            </Box>\n                          )}\n                        {timelineItems.length > 0 && (\n                          <Box marginTop={1} flexDirection=\"column\">\n                            <Text bold>Timeline (trace)</Text>\n                            {timelineItems.slice(0, 10).map((item, idx) => {\n                              const relMs =\n                                item.time -\n                                (selectedTraceSummary?.spans[0]?.startTime ??\n                                  item.time);\n                              if (item.type === 'span' && item.span) {\n                                return (\n                                  <Text key={`span-${idx}`} dimColor>\n                                    +{relMs}ms span{' '}\n                                    {truncate(item.span.name, 20)}\n                                  </Text>\n                                );\n                              }\n                              if (item.type === 'log' && item.log) {\n                                return (\n                                  <Text key={`log-${idx}`}>\n                                    +{relMs}ms log{' '}\n                                    {truncate(item.log.message, 24)}\n                                  </Text>\n                                );\n                              }\n                              return null;\n                            })}\n                          </Box>\n                        )}\n                      </>\n                    );\n                  })()\n                ) : currentSpan ? (\n                  <>\n                    <Text>\n                      <Text dimColor>Name: </Text>\n                      <Text>{currentSpan.name}</Text>\n                    </Text>\n                    <Text>\n                      <Text dimColor>Status: </Text>\n                      <Text\n                        color={currentSpan.status === 'ERROR' ? 'red' : 'green'}\n                      >\n                        {currentSpan.status}\n                      </Text>\n                    </Text>\n                    <Text>\n                      <Text dimColor>Duration: </Text>\n                      <Text>\n                        {formatDurationMs(currentSpan.durationMs)}\n                        {perSpanNameStats.byName.has(currentSpan.name) &&\n                          (() => {\n                            const p = perSpanNameStats.byName.get(\n                              currentSpan.name,\n                            )!;\n                            const ratio =\n                              p.avgMs > 0\n                                ? currentSpan.durationMs / p.avgMs\n                                : 1;\n                            if (ratio >= 1.5)\n                              return ` (${ratio.toFixed(1)}x avg)`;\n                            return '';\n                          })()}\n                      </Text>\n                    </Text>\n                    <Text dimColor>Trace: {currentSpan.traceId}</Text>\n                    <Text dimColor>Span: {currentSpan.spanId}</Text>\n                    {currentSpan.parentSpanId && (\n                      <Text dimColor>Parent: {currentSpan.parentSpanId}</Text>\n                    )}\n                    {currentSpan.kind && (\n                      <Text dimColor>Kind: {currentSpan.kind}</Text>\n                    )}\n\n                    {(() => {\n                      const { key: keyAttrs, rest: restAttrs } =\n                        keyAttrsAndRest(currentSpan.attributes);\n                      return (\n                        <>\n                          {keyAttrs.length > 0 && (\n                            <Box marginTop={1} flexDirection=\"column\">\n                              <Text bold>Key attributes</Text>\n                              {keyAttrs.slice(0, 6).map(([k, v]) => (\n                                <Text key={k} dimColor>\n                                  {truncate(k, 18)}: {truncate(String(v), 28)}\n                                </Text>\n                              ))}\n                            </Box>\n                          )}\n                          {restAttrs.length > 0 && (\n                            <Box marginTop={1} flexDirection=\"column\">\n                              <Text bold>Attributes</Text>\n                              {restAttrs.slice(0, 8).map(([k, v]) => (\n                                <Text key={k} dimColor>\n                                  {truncate(k, 18)}: {truncate(String(v), 28)}\n                                </Text>\n                              ))}\n                            </Box>\n                          )}\n                          {keyAttrs.length === 0 && restAttrs.length === 0 && (\n                            <Text dimColor>(no attributes)</Text>\n                          )}\n                        </>\n                      );\n                    })()}\n\n                    {waterfallSpans.length > 0 && drilldownTraceId != null && (\n                      <Box marginTop={1} flexDirection=\"column\">\n                        <Text bold>Waterfall</Text>\n                        {waterfallSpans.slice(0, 10).map((w) => {\n                          const barLen =\n                            Math.round(\n                              (w.span.durationMs / waterfallMaxMs) * barWidth,\n                            ) || 1;\n                          const bar = '█'.repeat(barLen);\n                          const indent = '  '.repeat(w.depth);\n                          return (\n                            <Box key={w.span.spanId} flexDirection=\"row\">\n                              <Text dimColor>{indent}</Text>\n                              <Text>{truncate(w.span.name, 12)}</Text>\n                              <Text dimColor> {bar}</Text>\n                              <Text dimColor>\n                                {' '}\n                                {formatDurationMs(w.span.durationMs)}\n                              </Text>\n                            </Box>\n                          );\n                        })}\n                      </Box>\n                    )}\n                  </>\n                ) : (\n                  <Text dimColor>Select a trace or span to view details.</Text>\n                )}\n            </>\n        </Box>\n      </Box>\n      ))}\n\n      {showStats && (\n        <Box marginTop={1} borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n          <Text dimColor>\n            Spans: {stats.total} | Span errors: {stats.errors} | Logs:{' '}\n            {logStats.total} | Log errors: {logStats.errors} | Avg:{' '}\n            {formatDurationMs(stats.avg)} | P95: {formatDurationMs(stats.p95)}\n          </Text>\n        </Box>\n      )}\n    </Box>\n  );\n}\n\n// Global streaming processor for auto-wiring\nlet globalStreamingProcessor: StreamingSpanProcessor | null = null;\n\n/**\n * Check if a TracerProvider has an addSpanProcessor method\n * (Node.js SDK providers have this, but API-level providers don't)\n */\nfunction canAddSpanProcessor(\n  provider: TracerProvider,\n): provider is TracerProvider & {\n  addSpanProcessor: (processor: unknown) => void;\n} {\n  return (\n    typeof provider === 'object' &&\n    provider !== null &&\n    'addSpanProcessor' in provider &&\n    typeof (provider as { addSpanProcessor?: unknown }).addSpanProcessor ===\n      'function'\n  );\n}\n\n/**\n * Render the terminal dashboard\n *\n * Automatically wires up a streaming processor from the current tracer provider\n * if no stream is provided. Otherwise uses the provided stream.\n *\n * @param options - Dashboard configuration options\n * @param stream - Optional manual stream (for advanced use cases)\n *\n * @example Auto-wire (recommended)\n * ```typescript\n * import { init } from 'autotel'\n * import { renderTerminal } from 'autotel-terminal'\n *\n * init({ service: 'my-app' })\n * renderTerminal() // Automatically creates stream from current tracer provider\n * ```\n *\n * @example Manual stream\n * ```typescript\n * import { StreamingSpanProcessor } from 'autotel-terminal'\n * import { createTerminalSpanStream } from 'autotel-terminal'\n *\n * const processor = new StreamingSpanProcessor(baseProcessor)\n * const stream = createTerminalSpanStream(processor)\n * renderTerminal({}, stream)\n * ```\n */\nexport function renderTerminal(\n  options: TerminalOptions = {},\n  stream?: TerminalSpanStream,\n): void {\n  const title = options.title ?? 'Autotel Trace Inspector';\n  const showStats = options.showStats !== false;\n  const maxSpans = options.maxSpans ?? 100;\n  const colors = options.colors ?? Boolean(process.stdout.isTTY);\n  const aiConfig = options.ai;\n\n  // Check if stdin supports raw mode (needed for keyboard input)\n  // If not, we disable stdin to prevent Ink from throwing an error\n  const stdinOption = process.stdin.isTTY ? process.stdin : undefined;\n\n  // If stream provided, use it directly\n  if (stream) {\n    try {\n      render(\n        <Dashboard\n          title={title}\n          showStats={showStats}\n          maxSpans={maxSpans}\n          colors={colors}\n          stream={stream}\n          logStream={getTerminalLogStream()}\n          aiConfig={aiConfig}\n        />,\n        { stdin: stdinOption },\n      );\n    } catch (error) {\n      console.error('[autotel-terminal] Failed to render dashboard:', error);\n    }\n    return;\n  }\n\n  // Otherwise, auto-wire from current tracer provider\n  let provider: TracerProvider;\n  try {\n    provider = getAutotelTracerProvider();\n  } catch (error) {\n    console.error(\n      '[autotel-terminal] Failed to get tracer provider. Call init() first or provide a stream.',\n      error,\n    );\n    return;\n  }\n\n  if (!provider) {\n    console.error(\n      '[autotel-terminal] No tracer provider found. Call init() first or provide a stream.',\n    );\n    return;\n  }\n\n  // Check if provider supports addSpanProcessor (Node.js SDK providers do)\n  if (!canAddSpanProcessor(provider)) {\n    console.error(\n      '[autotel-terminal] TracerProvider does not support addSpanProcessor. Provide a stream manually.',\n    );\n    return;\n  }\n\n  // Create streaming processor that doesn't wrap anything (just streams)\n  // This way it doesn't interfere with existing processors\n  globalStreamingProcessor = new StreamingSpanProcessor(null);\n  const terminalStream = createTerminalSpanStream(globalStreamingProcessor);\n\n  // Add streaming processor to provider\n  provider.addSpanProcessor(globalStreamingProcessor);\n\n  try {\n    render(\n      <Dashboard\n        title={title}\n        showStats={showStats}\n        maxSpans={maxSpans}\n        colors={colors}\n        stream={terminalStream}\n        logStream={getTerminalLogStream()}\n      />,\n      { stdin: stdinOption },\n    );\n  } catch (error) {\n    console.error('[autotel-terminal] Failed to render dashboard:', error);\n  }\n}\n\n// Re-export types and utilities\nexport type { TerminalSpanEvent, TerminalSpanStream, SpanEvent, SpanLink } from './span-stream';\nexport { StreamingSpanProcessor } from './streaming-processor';\nexport { createTerminalSpanStream } from './span-stream';\nexport { getTerminalLogStream } from './log-stream';\nexport type { TerminalLogStream } from './log-stream';\nexport type { TerminalLogEvent } from './lib/log-model';\n\n// Re-export OpenTelemetry types for advanced users\nexport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nexport { SpanStatusCode, SpanKind } from 'autotel';\n\n// Re-export PrettyConsoleExporter for convenience\nexport {\n  PrettyConsoleExporter,\n  type PrettyConsoleExporterOptions,\n} from 'autotel/exporters';\n"],"mappings":"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"}