@tangle-network/agent-eval 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +4 -5
  3. package/dist/{baseline-4R5deP0N.d.ts → baseline-BwdCXUS8.d.ts} +1 -1
  4. package/dist/builder-eval/index.d.ts +3 -3
  5. package/dist/builder-eval/index.js +1 -1
  6. package/dist/{chunk-WWYCWKUM.js → chunk-3CKU6VGU.js} +2 -2
  7. package/dist/{chunk-2A5XJB43.js → chunk-5AKPEK5L.js} +3 -3
  8. package/dist/chunk-5AKPEK5L.js.map +1 -0
  9. package/dist/{chunk-RAF443UI.js → chunk-DBIGN5MJ.js} +2 -2
  10. package/dist/{chunk-JLZQWFV3.js → chunk-K33INZHH.js} +2 -2
  11. package/dist/chunk-K33INZHH.js.map +1 -0
  12. package/dist/{chunk-NU65VQ7M.js → chunk-MAZ26DC7.js} +1 -1
  13. package/dist/chunk-MAZ26DC7.js.map +1 -0
  14. package/dist/{chunk-LSH4MMOZ.js → chunk-NCRFYPS3.js} +1 -1
  15. package/dist/chunk-NCRFYPS3.js.map +1 -0
  16. package/dist/{chunk-ZN274SWR.js → chunk-PALJO75S.js} +2 -2
  17. package/dist/{chunk-OWLAAMME.js → chunk-QHF6EQKK.js} +3 -2
  18. package/dist/chunk-QHF6EQKK.js.map +1 -0
  19. package/dist/chunk-R5UQJNKC.js +722 -0
  20. package/dist/chunk-R5UQJNKC.js.map +1 -0
  21. package/dist/{chunk-SESZDQPX.js → chunk-RUI6SIHY.js} +3 -3
  22. package/dist/chunk-RUI6SIHY.js.map +1 -0
  23. package/dist/{chunk-WHZMVFUV.js → chunk-SZSBQUIJ.js} +2 -2
  24. package/dist/chunk-SZSBQUIJ.js.map +1 -0
  25. package/dist/chunk-UW4NOOZI.js +1561 -0
  26. package/dist/chunk-UW4NOOZI.js.map +1 -0
  27. package/dist/{chunk-4F5DQN55.js → chunk-VSMTAMNK.js} +1 -1
  28. package/dist/chunk-VSMTAMNK.js.map +1 -0
  29. package/dist/{chunk-5LBB5B3Z.js → chunk-XFZCM5Z3.js} +1 -1
  30. package/dist/chunk-XFZCM5Z3.js.map +1 -0
  31. package/dist/cli.js +1 -1
  32. package/dist/{control-CBShYYA6.d.ts → control-rJhEDdpy.d.ts} +4 -4
  33. package/dist/{control-runtime-BuJHoLg0.d.ts → control-runtime-BRdQ0wrx.d.ts} +3 -2
  34. package/dist/control.d.ts +5 -5
  35. package/dist/control.js +2 -2
  36. package/dist/{emitter-DP_cSSiw.d.ts → emitter-BqjeOvJh.d.ts} +1 -1
  37. package/dist/{failure-cluster-C2EGSDiT.d.ts → failure-cluster-D1NZKqYu.d.ts} +2 -3
  38. package/dist/{feedback-trajectory-DfFdrraJ.d.ts → feedback-trajectory-j0nJFgC6.d.ts} +1 -1
  39. package/dist/governance/index.d.ts +2 -2
  40. package/dist/{index-D3iBCjdF.d.ts → index-Cgt3DKXr.d.ts} +2 -2
  41. package/dist/index.d.ts +1279 -468
  42. package/dist/index.js +1992 -1259
  43. package/dist/index.js.map +1 -1
  44. package/dist/{integrity-DK2EBVZC.d.ts → integrity-BAxLGJ9I.d.ts} +2 -2
  45. package/dist/knowledge/index.d.ts +3 -3
  46. package/dist/knowledge/index.js +2 -2
  47. package/dist/meta-eval/index.d.ts +1 -1
  48. package/dist/{multi-layer-verifier-LkP3LVKj.d.ts → multi-layer-verifier-BNi4-8lR.d.ts} +2 -2
  49. package/dist/openapi.json +1 -1
  50. package/dist/optimization.d.ts +8 -8
  51. package/dist/optimization.js +5 -5
  52. package/dist/pipelines/index.d.ts +6 -6
  53. package/dist/pipelines/index.js +2 -2
  54. package/dist/prm/index.d.ts +4 -4
  55. package/dist/{query-DODUYdPg.d.ts → query-BFDT0kX_.d.ts} +1 -1
  56. package/dist/{release-report-wfUySN5F.d.ts → release-report-PWhGlpfO.d.ts} +1 -1
  57. package/dist/replay-BX5Fm8en.d.ts +529 -0
  58. package/dist/reporting.d.ts +5 -5
  59. package/dist/reporting.js +5 -5
  60. package/dist/{researcher-bGkI7vCl.d.ts → researcher-ClDX3KZx.d.ts} +13 -14
  61. package/dist/rl.d.ts +29 -47
  62. package/dist/rl.js +5 -5
  63. package/dist/rl.js.map +1 -1
  64. package/dist/{rubric-D5tjHNJQ.d.ts → rubric-DgSqjqqj.d.ts} +2 -2
  65. package/dist/{sequential-Dgz1n51-.d.ts → sequential-5iSVfzl2.d.ts} +2 -2
  66. package/dist/{store-Db2Bv8Cf.d.ts → store-BP5be6s7.d.ts} +1 -1
  67. package/dist/{summary-report-DZVXOCK_.d.ts → summary-report-jrSGb2xZ.d.ts} +5 -5
  68. package/dist/{test-graded-scenario-B2kWEdh9.d.ts → test-graded-scenario-BJ54PDan.d.ts} +2 -2
  69. package/dist/traces.d.ts +9 -311
  70. package/dist/traces.js +16 -987
  71. package/dist/traces.js.map +1 -1
  72. package/dist/{trajectory-CnoBo-JY.d.ts → trajectory-BFmveYZt.d.ts} +1 -1
  73. package/dist/wire/index.d.ts +4 -4
  74. package/dist/wire/index.js +1 -1
  75. package/docs/research-report-methodology.md +4 -4
  76. package/docs/three-package-architecture.md +12 -24
  77. package/package.json +1 -1
  78. package/dist/chunk-2A5XJB43.js.map +0 -1
  79. package/dist/chunk-4F5DQN55.js.map +0 -1
  80. package/dist/chunk-5LBB5B3Z.js.map +0 -1
  81. package/dist/chunk-I4MBDTY5.js +0 -272
  82. package/dist/chunk-I4MBDTY5.js.map +0 -1
  83. package/dist/chunk-JLZQWFV3.js.map +0 -1
  84. package/dist/chunk-K2TPS5LB.js +0 -569
  85. package/dist/chunk-K2TPS5LB.js.map +0 -1
  86. package/dist/chunk-LSH4MMOZ.js.map +0 -1
  87. package/dist/chunk-NU65VQ7M.js.map +0 -1
  88. package/dist/chunk-OWLAAMME.js.map +0 -1
  89. package/dist/chunk-SESZDQPX.js.map +0 -1
  90. package/dist/chunk-WHZMVFUV.js.map +0 -1
  91. package/dist/replay-BL96gCEP.d.ts +0 -226
  92. /package/dist/{chunk-WWYCWKUM.js.map → chunk-3CKU6VGU.js.map} +0 -0
  93. /package/dist/{chunk-RAF443UI.js.map → chunk-DBIGN5MJ.js.map} +0 -0
  94. /package/dist/{chunk-ZN274SWR.js.map → chunk-PALJO75S.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/trace-analyst/prompts.ts","../src/trace-analyst/types.ts","../src/trace-analyst/store-otlp.ts","../src/trace-analyst/store.ts","../src/trace-analyst/tools.ts","../src/trace-analyst/analyst.ts","../src/trace/store.ts","../src/trace/otel.ts","../src/trace/redact.ts","../src/replay.ts"],"sourcesContent":["/** Ax RLM prompt for bounded trace discovery and evidence-backed analysis. */\n\nexport const TRACE_ANALYST_ACTOR_DESCRIPTION = `You answer questions about an OTLP-shaped JSONL trace dataset using the trace tools provided in the \\`traces\\` namespace.\n\nDISCOVERY → NARROW → DEEP-READ protocol — follow exactly:\n\n1. ALWAYS call \\`traces.getDatasetOverview({})\\` FIRST without a regex_pattern. The result tells you total_traces, raw_jsonl_bytes, services, agents, models, and sample_trace_ids (real ids — never fabricate one).\n\n2. Use raw_jsonl_bytes to gauge how expensive raw scans will be. \\`filters.regex_pattern\\` is the one scan-heavy filter on getDatasetOverview / queryTraces / countTraces — narrow with indexed fields (has_errors, model_names, service_names, agent_names, time bounds) BEFORE adding a regex on a large dataset.\n\n3. To list more traces than the sample, call \\`traces.queryTraces({ filters?, limit, offset? })\\`. Each summary carries raw_jsonl_bytes — use it to choose between viewTrace and searchTrace BEFORE calling either.\n\n4. Per-trace inspection:\n - SMALL trace (raw_jsonl_bytes well under 150_000): call \\`traces.viewTrace({ trace_id })\\`. Returns all spans. Per-attribute payloads are head-capped at ~4KB; large \\`input.value\\` / \\`output.value\\` / \\`llm.input_messages\\` will show a \\`[trace-analyst truncated: N bytes]\\` marker.\n - LARGE trace (raw_jsonl_bytes near or above 150_000, or you saw an \\`oversized\\` response): use \\`traces.searchTrace({ trace_id, regex_pattern })\\` to get bounded SpanMatchRecords (span metadata + matched text + surrounding context). Then call \\`traces.viewSpans({ trace_id, span_ids: [...] })\\` for surgical reads (~16KB cap, 4× higher than discovery), or \\`traces.searchSpan({ trace_id, span_id, regex_pattern })\\` for one large span. Stays bounded regardless of trace size.\n - Useful regex patterns: \\`STATUS_CODE_ERROR\\` (failures), tool names like \\`grep\\` or \\`view_trace\\`, error strings like \\`MaxTurnsExceeded\\`, model names, attribute keys.\n\n5. ONLY call viewTrace / viewSpans / searchTrace / searchSpan with trace/span ids you have already seen in sample_trace_ids, a queryTraces page, or a previous search result. Never invent ids.\n\n5a. **Result-shape contract** — searchTrace and searchSpan return \\`{ trace_id, hits, total_matches, has_more }\\`. Iterate \\`result.hits\\` (NOT result.matches). Each hit has \\`{ span_id, span_name, span_kind, attribute_path, matched_text, context_before, context_after, match_offset }\\`. viewTrace returns \\`{ trace_id, spans }\\` (or \\`oversized\\`). viewSpans returns \\`{ trace_id, spans, missing_span_ids, truncated_attribute_count }\\`. Never assume a field name — log the result shape first if unsure.\n\n6. If viewTrace returns an \\`oversized\\` summary instead of \\`spans\\`, DO NOT retry the same call. Read the summary's top_span_names, span_count, span_response_bytes_max, error_span_count to plan a follow-up: switch to searchTrace (or searchSpan for one large span), then viewSpans on a smaller, surgical span_ids set.\n\n7. If searchTrace or searchSpan returns has_more=true, REFINE the regex to be more specific rather than blindly raising max_matches.\n\n8. If a tool errors (invalid regex, range error), STOP and reconsider — don't retry with a guessed id or argument. Use the discovery tools above to recover.\n\n9. If a ~4KB-truncated payload from viewTrace / searchTrace matters for your answer, first try viewSpans on that span id (~16KB cap). If a 16KB-truncated payload from viewSpans still matters, narrow further with searchSpan against a more specific regex rather than asking for the full payload again.\n\n10. If maxDepth > 0 and the question splits into independent semantic branches, delegate well-defined subtasks to subagents using \\`await llmQuery(...)\\`. Pass narrow context and a focused query. Examples:\n\n const reviews = await llmQuery([\n { query: 'Drill into trace abc123 — what tool calls preceded the failure?', context: { trace_id: 'abc123' } },\n { query: 'Drill into trace def456 — same failure mode?', context: { trace_id: 'def456' } },\n ]);\n\nOBSERVABILITY rules:\n- Each non-final actor turn must emit at least one \\`console.log(...)\\` for evidence. Up to 3 logs per turn is fine when correlating multiple data sources (e.g. one log for findings list, one for source-file content, one for derived analysis).\n- Do NOT combine \\`console.log\\` with \\`final(...)\\` or \\`askClarification(...)\\` in the same turn — finish gathering data first, then call final on its own turn.\n- Reuse runtime variables across turns; don't recompute.\n- When done, call \\`await final(answer)\\` with the fully-formed report. The responder rewrites the answer into output fields; if you only pass a vague summary string the responder has nothing concrete to format.\n\nCRITICAL — \\`final()\\` payload contract for evidence-grounded analysis tasks:\n- Pass a STRUCTURED object as the second arg with the actual data the responder needs to format the answer. Do NOT pass abstract instructions; pass evidence.\n- Example for per-item verdict tasks:\n \\`\\`\\`js\n await final(\"Format the per-item verdict report from the evidence below.\", {\n findings: [\n { id: 'sub-1-finding-1', claim: '...', verdict: 'TRUE-POSITIVE', evidence: 'lines 42-45 of contracts/X.sol show ...' },\n ...all items\n ],\n systemic_summary: '3 sentences I wrote based on the evidence above'\n });\n \\`\\`\\`\n- Calling \\`final(\"answer\", {})\\` with no evidence is a failure mode — the responder will hallucinate or echo back the field names. Always include the gathered data.\n- Premature final after a single viewSpans call is INSUFFICIENT for per-finding analysis tasks. Read the requested attributes (e.g. \\`spans[i].attributes['redteam.finding.title']\\`), and for each one perform the requested cross-reference (e.g. read the source SPAN's \\`attributes['source.content']\\`).\n\nOUTPUT contract — your final answer must include:\n- A clear prose conclusion answering the user's question.\n- Trace ids and span ids cited as evidence for each claim.\n- Failure modes named in the user's domain language, with frequency and concrete examples.\n\nDo NOT invent trace ids, span ids, error messages, or model names. Every fact must be traceable to a tool result.`\n\nexport const TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION = 'trace-analyst-actor-v5-2026-05-06'\n\n/** Subagent prompt for focused trace-inspection subtasks. */\nexport const TRACE_ANALYST_SUBAGENT_DESCRIPTION = `You are a trace-analyst subagent. Your parent has delegated a focused trace-inspection question. Use the same DISCOVERY → NARROW → DEEP-READ protocol but stay tightly scoped: do exactly what was asked, return a concise compact answer, do NOT spawn further subagents unless the parent's question is genuinely multi-branch.\n\nCite trace ids and span ids for every claim. Do NOT invent ids.`\n","/**\n * Shared types for the trace-analyst module.\n *\n * Wire format. The store interface speaks `OtlpSpanLike` rows — one JSONL\n * line per span, OTLP-shaped. We do NOT depend on a specific tracing\n * vendor at the type level. Adapter\n * layers map upstream shapes onto this interface.\n *\n * Design constraint. Every read operation that can return arbitrary\n * payload must carry a byte budget so the agent's tool result stays\n * bounded regardless of input trace size. Oversized responses\n * substitute a deterministic summary instead of bytes — see\n * `ViewTraceOversized`.\n */\n\n/** OTLP span kind (subset we actually use). */\nexport type TraceAnalystSpanKind =\n | 'AGENT'\n | 'LLM'\n | 'TOOL'\n | 'CHAIN'\n | 'GUARDRAIL'\n | 'SPAN'\n | 'UNKNOWN'\n\nexport type TraceAnalystSpanStatus = 'OK' | 'ERROR' | 'UNSET'\n\n/** Subset of OTLP span fields the analyst exposes to the agent. The\n * store's job is to project upstream's full span shape down to this\n * view — the analyst never sees vendor extensions directly. */\nexport interface TraceAnalystSpan {\n trace_id: string\n span_id: string\n parent_span_id: string | null\n name: string\n kind: TraceAnalystSpanKind\n start_time: string\n end_time: string\n duration_ms: number\n status: TraceAnalystSpanStatus\n status_message?: string\n service_name: string | null\n agent_name: string | null\n model_name: string | null\n tool_name: string | null\n /** Raw JSON-serialisable attribute map. May contain large strings;\n * callers must respect the per-attribute byte cap. */\n attributes: Record<string, unknown>\n}\n\nexport interface TraceAnalystTraceSummary {\n trace_id: string\n service_name: string | null\n agent_name: string | null\n span_count: number\n has_errors: boolean\n start_time: string\n end_time: string\n duration_ms: number\n raw_jsonl_bytes: number\n models: string[]\n tools: string[]\n}\n\nexport interface TraceAnalystFilters {\n /** Restrict to traces that contain at least one error span. */\n has_errors?: boolean\n /** Match if any span's `service.name` is in this list. */\n service_names?: string[]\n /** Match if any span's `agent.name` is in this list. */\n agent_names?: string[]\n /** Match if any LLM span's `llm.model_name` is in this list. */\n model_names?: string[]\n /** Match if any tool span's `tool.name` is in this list. */\n tool_names?: string[]\n /** ISO-8601 lower bound on the trace's earliest start time. */\n start_time_after?: string\n /** ISO-8601 upper bound on the trace's earliest start time. */\n start_time_before?: string\n /** Single regex applied to raw JSONL bytes for the trace. Opt-in;\n * expensive on large datasets. Use the indexed filters above first. */\n regex_pattern?: string\n}\n\nexport interface DatasetOverview {\n total_traces: number\n raw_jsonl_bytes: number\n services: string[]\n agents: string[]\n models: string[]\n tool_names: string[]\n /** Up to 20 real trace ids the agent may pass to view/search tools. */\n sample_trace_ids: string[]\n errors: { trace_count: number; span_count: number }\n time_range: { earliest: string; latest: string } | null\n}\n\nexport interface QueryTracesPage {\n traces: TraceAnalystTraceSummary[]\n total: number\n has_more: boolean\n}\n\n/** Full-trace view. When the response would exceed the per-call byte\n * budget, `oversized` is populated INSTEAD of `spans` so the agent\n * knows to switch to `searchTrace` / `viewSpans`. */\nexport interface ViewTraceResult {\n trace_id: string\n spans?: TraceAnalystSpan[]\n oversized?: ViewTraceOversized\n}\n\nexport interface ViewTraceOversized {\n span_count: number\n /** Names with their counts, sorted desc. Capped at 20 entries. */\n top_span_names: Array<[string, number]>\n /** Largest single span body (bytes after attribute-cap projection). */\n span_response_bytes_max: number\n error_span_count: number\n}\n\nexport interface ViewSpansResult {\n trace_id: string\n spans: TraceAnalystSpan[]\n /** Number of requested span ids that were not found in the trace. */\n missing_span_ids: string[]\n /** Number of attribute fields truncated to fit the per-attribute cap. */\n truncated_attribute_count: number\n}\n\nexport interface SpanMatchRecord {\n trace_id: string\n span_id: string\n span_name: string\n span_kind: TraceAnalystSpanKind\n /** JSON pointer-style path to the matched value, e.g.\n * `attributes.\"llm.input_messages\"[2].content`. */\n attribute_path: string\n matched_text: string\n context_before: string\n context_after: string\n match_offset: number\n}\n\nexport interface SearchTraceResult {\n trace_id: string\n hits: SpanMatchRecord[]\n total_matches: number\n has_more: boolean\n}\n\nexport interface SearchSpanResult {\n trace_id: string\n span_id: string\n hits: SpanMatchRecord[]\n total_matches: number\n has_more: boolean\n}\n\n/** Tunable byte budgets for bounded RLM tool output. */\nexport interface TraceAnalystByteBudgets {\n /** Max bytes any single tool response may emit. Hard ceiling enforced\n * by the store; oversized → summary. Default 150_000. */\n perCallByteCeiling: number\n /** Per-attribute string truncation cap on `viewTrace` (discovery scan).\n * Default 4096. */\n perAttributeViewBudget: number\n /** Per-attribute string truncation cap on `viewSpans` (surgical reads).\n * Default 16384. */\n perAttributeSpanBudget: number\n /** Per-attribute cap on a single match record's `matched_text` and\n * context window. Default 1024. */\n perMatchTextBudget: number\n}\n\nexport const DEFAULT_TRACE_ANALYST_BUDGETS: TraceAnalystByteBudgets = {\n perCallByteCeiling: 150_000,\n perAttributeViewBudget: 4_096,\n perAttributeSpanBudget: 16_384,\n perMatchTextBudget: 1_024,\n}\n\n/** Marker substituted in place of truncated string payloads. Callers\n * parsing tool output can detect it deterministically. */\nexport const TRACE_ANALYST_TRUNCATION_MARKER_PREFIX = '[trace-analyst truncated:'\n","/**\n * `OtlpFileTraceStore` — read-only OTLP-JSONL trace store for the\n * trace-analyst.\n *\n * Wire shape. Each line of the input file is one OTLP-shaped span. The\n * store understands flattened OTLP JSONL plus the OpenInference vocab.\n * We project upstream's full\n * span shape down to `TraceAnalystSpan` lazily — full materialisation\n * only happens for the spans the agent actually requests.\n *\n * Indexing. On first read the store builds an in-memory index keyed\n * by `trace_id` carrying:\n * - byte offsets + lengths for each span line (for surgical reads\n * without re-parsing the whole file)\n * - a `TraceAnalystTraceSummary` rollup\n * - sets of services / agents / models / tools / has_errors\n * - byte size of the trace's JSONL slab\n *\n * Memory bound. The index keeps span metadata only — names, kinds,\n * offsets, status. Attribute payloads stay on disk until requested.\n * For a 50MB JSONL with 50k spans, the index is ~5MB.\n *\n * Concurrency. The store builds the index once on first read and\n * caches it. Subsequent reads reuse the index. The file is opened on\n * each read; we never hold a long-lived FD.\n */\n\nimport { readFile, stat } from 'node:fs/promises'\nimport { NotFoundError } from '../errors'\nimport { compileSearchRegex, type TraceAnalysisStore, truncateForBudget } from './store'\nimport {\n type DatasetOverview,\n DEFAULT_TRACE_ANALYST_BUDGETS,\n type QueryTracesPage,\n type SearchSpanResult,\n type SearchTraceResult,\n type SpanMatchRecord,\n type TraceAnalystFilters,\n type TraceAnalystSpan,\n type TraceAnalystSpanKind,\n type TraceAnalystSpanStatus,\n type TraceAnalystTraceSummary,\n type ViewSpansResult,\n type ViewTraceOversized,\n type ViewTraceResult,\n} from './types'\n\ninterface SpanIndexEntry {\n span_id: string\n parent_span_id: string | null\n name: string\n kind: TraceAnalystSpanKind\n start_time: string\n end_time: string\n duration_ms: number\n status: TraceAnalystSpanStatus\n status_message: string | undefined\n service_name: string | null\n agent_name: string | null\n model_name: string | null\n tool_name: string | null\n /** Byte offset in the raw JSONL file to the start of this span's line. */\n line_byte_offset: number\n /** Length of this line in bytes (excluding the trailing newline). */\n line_byte_length: number\n}\n\ninterface TraceIndexEntry {\n trace_id: string\n service_name: string | null\n agent_name: string | null\n span_count: number\n has_errors: boolean\n start_time: string\n end_time: string\n duration_ms: number\n raw_jsonl_bytes: number\n models: Set<string>\n tools: Set<string>\n spans: SpanIndexEntry[]\n /** Sorted by line offset for stable iteration. */\n}\n\ninterface DatasetIndex {\n byTrace: Map<string, TraceIndexEntry>\n totalRawBytes: number\n // Pre-computed sorted trace_ids for sample/query stability.\n sortedTraceIds: string[]\n}\n\nexport interface OtlpFileTraceStoreOptions {\n /** Path to the OTLP-JSONL file. */\n path: string\n /** Override the discovery (`viewTrace`) per-attribute byte cap. */\n perAttributeViewBudget?: number\n /** Override the surgical (`viewSpans`) per-attribute byte cap. */\n perAttributeSpanBudget?: number\n /** Override the per-call ceiling that triggers oversized summaries. */\n perCallByteCeiling?: number\n /** Override the per-match text budget. */\n perMatchTextBudget?: number\n}\n\nexport class OtlpFileTraceStore implements TraceAnalysisStore {\n private readonly path: string\n private readonly perAttributeViewBudget: number\n private readonly perAttributeSpanBudget: number\n private readonly perCallByteCeiling: number\n private readonly perMatchTextBudget: number\n private indexPromise?: Promise<DatasetIndex>\n /** Cached UTF-8 buffer of the file. We pin it once because every\n * read needs slice access and re-reading on each call balloons the\n * syscall count. */\n private bufferPromise?: Promise<Buffer>\n\n constructor(opts: OtlpFileTraceStoreOptions) {\n this.path = opts.path\n this.perAttributeViewBudget =\n opts.perAttributeViewBudget ?? DEFAULT_TRACE_ANALYST_BUDGETS.perAttributeViewBudget\n this.perAttributeSpanBudget =\n opts.perAttributeSpanBudget ?? DEFAULT_TRACE_ANALYST_BUDGETS.perAttributeSpanBudget\n this.perCallByteCeiling =\n opts.perCallByteCeiling ?? DEFAULT_TRACE_ANALYST_BUDGETS.perCallByteCeiling\n this.perMatchTextBudget =\n opts.perMatchTextBudget ?? DEFAULT_TRACE_ANALYST_BUDGETS.perMatchTextBudget\n }\n\n // ─── Public API ────────────────────────────────────────────────────\n\n async getOverview(filters?: TraceAnalystFilters): Promise<DatasetOverview> {\n const idx = await this.index()\n const matched = await this.matchedTraces(idx, filters)\n\n const services = new Set<string>()\n const agents = new Set<string>()\n const models = new Set<string>()\n const tools = new Set<string>()\n let rawBytes = 0\n let earliest: string | null = null\n let latest: string | null = null\n let errorTraceCount = 0\n let errorSpanCount = 0\n\n for (const t of matched) {\n if (t.service_name) services.add(t.service_name)\n if (t.agent_name) agents.add(t.agent_name)\n for (const m of t.models) models.add(m)\n for (const tn of t.tools) tools.add(tn)\n rawBytes += t.raw_jsonl_bytes\n if (!earliest || t.start_time < earliest) earliest = t.start_time\n if (!latest || t.end_time > latest) latest = t.end_time\n if (t.has_errors) {\n errorTraceCount += 1\n for (const s of t.spans) if (s.status === 'ERROR') errorSpanCount += 1\n }\n }\n\n const sample_trace_ids = matched.slice(0, 20).map((t) => t.trace_id)\n return {\n total_traces: matched.length,\n raw_jsonl_bytes: rawBytes,\n services: [...services].sort(),\n agents: [...agents].sort(),\n models: [...models].sort(),\n tool_names: [...tools].sort(),\n sample_trace_ids,\n errors: { trace_count: errorTraceCount, span_count: errorSpanCount },\n time_range: earliest && latest ? { earliest, latest } : null,\n }\n }\n\n async queryTraces(opts: {\n filters?: TraceAnalystFilters\n limit: number\n offset?: number\n }): Promise<QueryTracesPage> {\n if (!Number.isInteger(opts.limit) || opts.limit < 1 || opts.limit > 200) {\n throw new RangeError(`queryTraces.limit must be 1..200, got ${opts.limit}`)\n }\n const offset = opts.offset ?? 0\n if (!Number.isInteger(offset) || offset < 0) {\n throw new RangeError(`queryTraces.offset must be >=0, got ${offset}`)\n }\n\n const idx = await this.index()\n const matched = await this.matchedTraces(idx, opts.filters)\n const slice = matched.slice(offset, offset + opts.limit)\n return {\n traces: slice.map((t) => this.toSummary(t)),\n total: matched.length,\n has_more: offset + slice.length < matched.length,\n }\n }\n\n async countTraces(filters?: TraceAnalystFilters): Promise<number> {\n const idx = await this.index()\n const matched = await this.matchedTraces(idx, filters)\n return matched.length\n }\n\n async viewTrace(opts: {\n trace_id: string\n per_attribute_byte_cap?: number\n }): Promise<ViewTraceResult> {\n const idx = await this.index()\n const trace = idx.byTrace.get(opts.trace_id)\n if (!trace) {\n throw new TraceNotFoundError(opts.trace_id)\n }\n const cap = opts.per_attribute_byte_cap ?? this.perAttributeViewBudget\n\n // Probe size first — if the materialised payload would exceed\n // the per-call ceiling we return an oversized summary rather than\n // blowing the agent's context.\n const buf = await this.buffer()\n const spans: TraceAnalystSpan[] = []\n let runningBytes = 0\n let span_response_bytes_max = 0\n for (const s of trace.spans) {\n const projected = await this.projectSpan(buf, trace.trace_id, s, cap)\n const bytes = Buffer.byteLength(JSON.stringify(projected), 'utf8')\n span_response_bytes_max = Math.max(span_response_bytes_max, bytes)\n runningBytes += bytes\n if (runningBytes > this.perCallByteCeiling) {\n return {\n trace_id: trace.trace_id,\n oversized: this.buildOversizedSummary(trace, span_response_bytes_max),\n }\n }\n spans.push(projected)\n }\n return { trace_id: trace.trace_id, spans }\n }\n\n async viewSpans(opts: {\n trace_id: string\n span_ids: readonly string[]\n per_attribute_byte_cap?: number\n }): Promise<ViewSpansResult> {\n const idx = await this.index()\n const trace = idx.byTrace.get(opts.trace_id)\n if (!trace) throw new TraceNotFoundError(opts.trace_id)\n if (opts.span_ids.length === 0) {\n return {\n trace_id: trace.trace_id,\n spans: [],\n missing_span_ids: [],\n truncated_attribute_count: 0,\n }\n }\n if (opts.span_ids.length > 100) {\n throw new RangeError(`viewSpans.span_ids cap is 100, got ${opts.span_ids.length}`)\n }\n const cap = opts.per_attribute_byte_cap ?? this.perAttributeSpanBudget\n\n const wantSet = new Set(opts.span_ids)\n const found = trace.spans.filter((s) => wantSet.has(s.span_id))\n const missing = opts.span_ids.filter((id) => !found.some((f) => f.span_id === id))\n\n const buf = await this.buffer()\n const spans: TraceAnalystSpan[] = []\n let truncated = 0\n let runningBytes = 0\n for (const s of found) {\n const before = truncationCounter(this)\n const projected = await this.projectSpan(buf, trace.trace_id, s, cap)\n truncated += before.delta()\n const bytes = Buffer.byteLength(JSON.stringify(projected), 'utf8')\n runningBytes += bytes\n if (runningBytes > this.perCallByteCeiling) {\n // Stop adding further spans rather than truncate mid-list.\n // Callers can refetch the rest with a smaller `span_ids`.\n break\n }\n spans.push(projected)\n }\n return {\n trace_id: trace.trace_id,\n spans,\n missing_span_ids: missing,\n truncated_attribute_count: truncated,\n }\n }\n\n async searchTrace(opts: {\n trace_id: string\n regex_pattern: string\n max_matches?: number\n }): Promise<SearchTraceResult> {\n const max_matches = opts.max_matches ?? 50\n if (!Number.isInteger(max_matches) || max_matches < 1 || max_matches > 500) {\n throw new RangeError(`searchTrace.max_matches must be 1..500, got ${max_matches}`)\n }\n const idx = await this.index()\n const trace = idx.byTrace.get(opts.trace_id)\n if (!trace) throw new TraceNotFoundError(opts.trace_id)\n const re = compileSearchRegex(opts.regex_pattern)\n\n const buf = await this.buffer()\n const hits: SpanMatchRecord[] = []\n let total = 0\n let capped = false\n for (const s of trace.spans) {\n const remaining = max_matches - hits.length\n const localHits = await this.scanSpanForMatches(\n buf,\n trace.trace_id,\n s,\n re,\n this.perMatchTextBudget,\n remaining,\n )\n total += localHits.total\n for (const h of localHits.records) {\n if (hits.length >= max_matches) break\n hits.push(h)\n }\n if (hits.length >= max_matches) {\n capped = true\n total = Math.max(total, hits.length + 1)\n break\n }\n }\n return {\n trace_id: trace.trace_id,\n hits,\n total_matches: total,\n has_more: capped || total > hits.length,\n }\n }\n\n async searchSpan(opts: {\n trace_id: string\n span_id: string\n regex_pattern: string\n max_matches?: number\n }): Promise<SearchSpanResult> {\n const max_matches = opts.max_matches ?? 50\n if (!Number.isInteger(max_matches) || max_matches < 1 || max_matches > 500) {\n throw new RangeError(`searchSpan.max_matches must be 1..500, got ${max_matches}`)\n }\n const idx = await this.index()\n const trace = idx.byTrace.get(opts.trace_id)\n if (!trace) throw new TraceNotFoundError(opts.trace_id)\n const span = trace.spans.find((s) => s.span_id === opts.span_id)\n if (!span) {\n throw new SpanNotFoundError(opts.trace_id, opts.span_id)\n }\n const re = compileSearchRegex(opts.regex_pattern)\n const buf = await this.buffer()\n const localHits = await this.scanSpanForMatches(\n buf,\n trace.trace_id,\n span,\n re,\n this.perMatchTextBudget,\n max_matches,\n )\n return {\n trace_id: trace.trace_id,\n span_id: span.span_id,\n hits: localHits.records,\n total_matches: localHits.total,\n has_more: localHits.total > localHits.records.length,\n }\n }\n\n // ─── Index building ────────────────────────────────────────────────\n\n /** Force the index to materialise. Useful to amortise startup cost\n * before the first agent call. */\n async ensureIndexed(): Promise<void> {\n await this.index()\n }\n\n private async buffer(): Promise<Buffer> {\n if (!this.bufferPromise) {\n this.bufferPromise = readFile(this.path)\n }\n return this.bufferPromise\n }\n\n private async index(): Promise<DatasetIndex> {\n if (!this.indexPromise) {\n this.indexPromise = this.buildIndex()\n }\n return this.indexPromise\n }\n\n private async buildIndex(): Promise<DatasetIndex> {\n let buf: Buffer\n try {\n buf = await this.buffer()\n } catch (err) {\n const stats = await stat(this.path).catch(() => null)\n if (!stats) {\n throw new TraceFileMissingError(this.path)\n }\n throw err\n }\n\n const byTrace = new Map<string, TraceIndexEntry>()\n let cursor = 0\n while (cursor < buf.length) {\n const newlineIndex = buf.indexOf(0x0a, cursor) // \\n\n const lineEnd = newlineIndex === -1 ? buf.length : newlineIndex\n const lineLength = lineEnd - cursor\n if (lineLength === 0) {\n cursor = lineEnd + 1\n continue\n }\n const lineSlice = buf.subarray(cursor, lineEnd).toString('utf8')\n const lineOffset = cursor\n cursor = lineEnd + 1\n\n let parsed: unknown\n try {\n parsed = JSON.parse(lineSlice)\n } catch {\n // Skip malformed lines silently. The agent shouldn't see them\n // but we don't want one bad line to nuke an entire dataset.\n continue\n }\n if (!parsed || typeof parsed !== 'object') continue\n const span = readOtlpSpan(parsed as Record<string, unknown>)\n if (!span) continue\n\n let entry = byTrace.get(span.trace_id)\n if (!entry) {\n entry = {\n trace_id: span.trace_id,\n service_name: span.service_name,\n agent_name: span.agent_name,\n span_count: 0,\n has_errors: false,\n start_time: span.start_time,\n end_time: span.end_time,\n duration_ms: 0,\n raw_jsonl_bytes: 0,\n models: new Set(),\n tools: new Set(),\n spans: [],\n }\n byTrace.set(span.trace_id, entry)\n } else {\n // Pin the trace's service/agent to the first AGENT span we\n // Prefer the first agent/service fields that appear in the trace.\n if (!entry.service_name && span.service_name) entry.service_name = span.service_name\n if (!entry.agent_name && span.agent_name) entry.agent_name = span.agent_name\n }\n\n const indexEntry: SpanIndexEntry = {\n span_id: span.span_id,\n parent_span_id: span.parent_span_id,\n name: span.name,\n kind: span.kind,\n start_time: span.start_time,\n end_time: span.end_time,\n duration_ms: span.duration_ms,\n status: span.status,\n status_message: span.status_message,\n service_name: span.service_name,\n agent_name: span.agent_name,\n model_name: span.model_name,\n tool_name: span.tool_name,\n line_byte_offset: lineOffset,\n line_byte_length: lineLength,\n }\n entry.spans.push(indexEntry)\n entry.span_count += 1\n entry.raw_jsonl_bytes += lineLength + 1 // +1 newline byte\n if (span.status === 'ERROR') entry.has_errors = true\n if (span.start_time < entry.start_time) entry.start_time = span.start_time\n if (span.end_time > entry.end_time) entry.end_time = span.end_time\n if (span.model_name) entry.models.add(span.model_name)\n if (span.tool_name) entry.tools.add(span.tool_name)\n }\n\n // Compute trace duration once, sort spans by start time for\n // stable iteration.\n let totalRawBytes = 0\n for (const t of byTrace.values()) {\n totalRawBytes += t.raw_jsonl_bytes\n t.spans.sort(\n (a, b) =>\n a.start_time.localeCompare(b.start_time) || a.line_byte_offset - b.line_byte_offset,\n )\n t.duration_ms = Math.max(0, new Date(t.end_time).getTime() - new Date(t.start_time).getTime())\n }\n const sortedTraceIds = [...byTrace.keys()].sort()\n\n return { byTrace, totalRawBytes, sortedTraceIds }\n }\n\n // ─── Filter pipeline ───────────────────────────────────────────────\n\n private async matchedTraces(\n idx: DatasetIndex,\n filters: TraceAnalystFilters | undefined,\n ): Promise<TraceIndexEntry[]> {\n const traces = idx.sortedTraceIds.map((id) => idx.byTrace.get(id)).filter(isPresent)\n if (!filters) return traces\n\n const indexedFiltered = traces.filter((t) => {\n if (filters.has_errors !== undefined && t.has_errors !== filters.has_errors) return false\n if (filters.service_names && filters.service_names.length > 0) {\n if (!t.service_name || !filters.service_names.includes(t.service_name)) return false\n }\n if (filters.agent_names && filters.agent_names.length > 0) {\n if (!t.agent_name || !filters.agent_names.includes(t.agent_name)) return false\n }\n if (filters.model_names && filters.model_names.length > 0) {\n if (![...t.models].some((m) => filters.model_names!.includes(m))) return false\n }\n if (filters.tool_names && filters.tool_names.length > 0) {\n if (![...t.tools].some((tn) => filters.tool_names!.includes(tn))) return false\n }\n if (filters.start_time_after && t.start_time < filters.start_time_after) return false\n if (filters.start_time_before && t.start_time > filters.start_time_before) return false\n return true\n })\n\n if (!filters.regex_pattern) return indexedFiltered\n\n // Opt-in raw-bytes scan — only over the already-narrowed set.\n const re = compileSearchRegex(filters.regex_pattern)\n const buf = await this.buffer()\n const out: TraceIndexEntry[] = []\n for (const t of indexedFiltered) {\n let matched = false\n for (const s of t.spans) {\n const slice = buf.subarray(s.line_byte_offset, s.line_byte_offset + s.line_byte_length)\n // Buffer.toString allocates; tolerate it because regex_pattern\n // is opt-in. Future optimisation: byte-level fast-path for\n // ASCII-only patterns.\n if (re.test(slice.toString('utf8'))) {\n matched = true\n break\n }\n }\n if (matched) out.push(t)\n }\n return out\n }\n\n private toSummary(t: TraceIndexEntry): TraceAnalystTraceSummary {\n return {\n trace_id: t.trace_id,\n service_name: t.service_name,\n agent_name: t.agent_name,\n span_count: t.span_count,\n has_errors: t.has_errors,\n start_time: t.start_time,\n end_time: t.end_time,\n duration_ms: t.duration_ms,\n raw_jsonl_bytes: t.raw_jsonl_bytes,\n models: [...t.models].sort(),\n tools: [...t.tools].sort(),\n }\n }\n\n // ─── Span projection (lazy attribute reads) ────────────────────────\n\n private async projectSpan(\n buf: Buffer,\n trace_id: string,\n s: SpanIndexEntry,\n perAttrCap: number,\n ): Promise<TraceAnalystSpan> {\n const slice = buf\n .subarray(s.line_byte_offset, s.line_byte_offset + s.line_byte_length)\n .toString('utf8')\n let raw: Record<string, unknown> = {}\n try {\n const parsed = JSON.parse(slice)\n if (parsed && typeof parsed === 'object') raw = parsed as Record<string, unknown>\n } catch {\n // Should not happen — index pre-validated.\n }\n const attrs = extractAttributes(raw)\n const projected: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(attrs)) {\n if (typeof v === 'string') {\n const trunc = truncateForBudget(v, perAttrCap)\n if (trunc !== v) trackTruncation(this)\n projected[k] = trunc\n } else if (Array.isArray(v) || (v && typeof v === 'object')) {\n const json = JSON.stringify(v)\n const trunc = truncateForBudget(json, perAttrCap)\n if (trunc !== json) {\n trackTruncation(this)\n projected[k] = trunc\n } else {\n projected[k] = v\n }\n } else {\n projected[k] = v\n }\n }\n return {\n trace_id,\n span_id: s.span_id,\n parent_span_id: s.parent_span_id,\n name: s.name,\n kind: s.kind,\n start_time: s.start_time,\n end_time: s.end_time,\n duration_ms: s.duration_ms,\n status: s.status,\n status_message: s.status_message,\n service_name: s.service_name,\n agent_name: s.agent_name,\n model_name: s.model_name,\n tool_name: s.tool_name,\n attributes: projected,\n }\n }\n\n private buildOversizedSummary(\n t: TraceIndexEntry,\n span_response_bytes_max: number,\n ): ViewTraceOversized {\n const counts = new Map<string, number>()\n let errorCount = 0\n for (const s of t.spans) {\n counts.set(s.name, (counts.get(s.name) ?? 0) + 1)\n if (s.status === 'ERROR') errorCount += 1\n }\n const top = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20)\n return {\n span_count: t.span_count,\n top_span_names: top,\n span_response_bytes_max,\n error_span_count: errorCount,\n }\n }\n\n private async scanSpanForMatches(\n buf: Buffer,\n trace_id: string,\n s: SpanIndexEntry,\n re: RegExp,\n textBudget: number,\n recordCap: number,\n ): Promise<{ records: SpanMatchRecord[]; total: number; hasMore: boolean }> {\n // We scan against the original raw JSONL slice for each span and\n // record byte positions; the matched_text + context window is\n // truncated to `textBudget` bytes per record so total tool output\n // stays bounded even if hits cluster.\n const slice = buf\n .subarray(s.line_byte_offset, s.line_byte_offset + s.line_byte_length)\n .toString('utf8')\n const records: SpanMatchRecord[] = []\n const globalRe = new RegExp(re.source, re.flags.includes('g') ? re.flags : `${re.flags}g`)\n let total = 0\n let hasMore = false\n let m: RegExpExecArray | null\n while ((m = globalRe.exec(slice)) !== null) {\n total += 1\n if (m.index === globalRe.lastIndex) globalRe.lastIndex += 1 // zero-width guard\n if (records.length >= recordCap) {\n hasMore = true\n break\n }\n const before = slice.slice(Math.max(0, m.index - textBudget / 2), m.index)\n const after = slice.slice(\n m.index + m[0].length,\n m.index + m[0].length + Math.floor(textBudget / 2),\n )\n records.push({\n trace_id,\n span_id: s.span_id,\n span_name: s.name,\n span_kind: s.kind,\n attribute_path: bestAttributePathForOffset(slice, m.index) ?? 'span.raw',\n matched_text: truncateForBudget(m[0], textBudget),\n context_before: truncateForBudget(before, textBudget),\n context_after: truncateForBudget(after, textBudget),\n match_offset: m.index,\n })\n }\n return { records, total, hasMore }\n }\n}\n\n// ─── Errors ──────────────────────────────────────────────────────────\n\nexport class TraceFileMissingError extends NotFoundError {\n constructor(path: string) {\n super(`trace file not found: ${path}`)\n }\n}\nexport class TraceNotFoundError extends NotFoundError {\n readonly trace_id: string\n constructor(trace_id: string) {\n super(`trace not found: ${trace_id}`)\n this.trace_id = trace_id\n }\n}\nexport class SpanNotFoundError extends NotFoundError {\n readonly trace_id: string\n readonly span_id: string\n constructor(trace_id: string, span_id: string) {\n super(`span ${span_id} not found in trace ${trace_id}`)\n this.trace_id = trace_id\n this.span_id = span_id\n }\n}\n\n// ─── OTLP shape readers ──────────────────────────────────────────────\n\ninterface ProjectedSpanShape {\n trace_id: string\n span_id: string\n parent_span_id: string | null\n name: string\n kind: TraceAnalystSpanKind\n start_time: string\n end_time: string\n duration_ms: number\n status: TraceAnalystSpanStatus\n status_message: string | undefined\n service_name: string | null\n agent_name: string | null\n model_name: string | null\n tool_name: string | null\n}\n\nfunction readOtlpSpan(raw: Record<string, unknown>): ProjectedSpanShape | null {\n const trace_id = stringField(raw, 'trace_id') ?? stringField(raw, 'traceId')\n const span_id = stringField(raw, 'span_id') ?? stringField(raw, 'spanId')\n if (!trace_id || !span_id) return null\n\n const parent_id = stringField(raw, 'parent_span_id') ?? stringField(raw, 'parentSpanId') ?? null\n const name = stringField(raw, 'name') ?? 'unknown'\n const start_time = stringField(raw, 'start_time') ?? stringField(raw, 'startTime') ?? ''\n const end_time = stringField(raw, 'end_time') ?? stringField(raw, 'endTime') ?? start_time\n\n const status = readStatus(raw)\n const attrs = extractAttributes(raw)\n\n // Service name lives under resource.attributes; we projected it into\n // attributes already via extractAttributes. Same for the inference.*\n // and openinference.* keys.\n const service_name =\n asString(attrs['service.name']) ?? asString(attrs['resource.attributes.service.name']) ?? null\n const agent_name =\n asString(attrs['agent.name']) ?? asString(attrs['inference.agent.name']) ?? null\n const model_name =\n asString(attrs['llm.model_name']) ?? asString(attrs['inference.llm.model_name']) ?? null\n const tool_name = asString(attrs['tool.name']) ?? asString(attrs['inference.tool.name']) ?? null\n\n const kind = inferKind(attrs)\n\n let duration_ms = 0\n if (start_time && end_time) {\n const a = Date.parse(start_time)\n const b = Date.parse(end_time)\n if (!Number.isNaN(a) && !Number.isNaN(b)) duration_ms = Math.max(0, b - a)\n }\n\n return {\n trace_id,\n span_id,\n parent_span_id: parent_id && parent_id.length > 0 ? parent_id : null,\n name,\n kind,\n start_time,\n end_time,\n duration_ms,\n status: status.code,\n status_message: status.message,\n service_name,\n agent_name,\n model_name,\n tool_name,\n }\n}\n\nfunction readStatus(raw: Record<string, unknown>): {\n code: TraceAnalystSpanStatus\n message: string | undefined\n} {\n const status = raw.status\n if (status && typeof status === 'object' && !Array.isArray(status)) {\n const codeRaw = (status as Record<string, unknown>).code\n const code: TraceAnalystSpanStatus =\n codeRaw === 'STATUS_CODE_OK' || codeRaw === 'OK'\n ? 'OK'\n : codeRaw === 'STATUS_CODE_ERROR' || codeRaw === 'ERROR'\n ? 'ERROR'\n : 'UNSET'\n const messageRaw = (status as Record<string, unknown>).message\n const message = typeof messageRaw === 'string' && messageRaw.length > 0 ? messageRaw : undefined\n return { code, message }\n }\n return { code: 'UNSET', message: undefined }\n}\n\nfunction inferKind(attrs: Record<string, unknown>): TraceAnalystSpanKind {\n const opik =\n asString(attrs['openinference.span.kind']) ?? asString(attrs['inference.observation_kind'])\n if (opik) {\n const upper = opik.toUpperCase()\n if (\n upper === 'AGENT' ||\n upper === 'LLM' ||\n upper === 'TOOL' ||\n upper === 'CHAIN' ||\n upper === 'GUARDRAIL' ||\n upper === 'SPAN'\n ) {\n return upper as TraceAnalystSpanKind\n }\n }\n return 'UNKNOWN'\n}\n\n/**\n * Flatten OTLP `attributes` + `resource.attributes` into a single\n * dotted-key map. Preserves nested objects/arrays as-is — projection\n * to byte-budgeted form happens later.\n */\nfunction extractAttributes(raw: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n // Resource attributes nest under raw.resource.attributes\n const resource = raw.resource\n if (resource && typeof resource === 'object' && !Array.isArray(resource)) {\n const ra = (resource as Record<string, unknown>).attributes\n if (ra && typeof ra === 'object' && !Array.isArray(ra)) {\n for (const [k, v] of Object.entries(ra as Record<string, unknown>)) {\n out[k] = v\n }\n }\n }\n // Span attributes override resource attributes when keys overlap.\n const spanAttrs = raw.attributes\n if (spanAttrs && typeof spanAttrs === 'object' && !Array.isArray(spanAttrs)) {\n for (const [k, v] of Object.entries(spanAttrs as Record<string, unknown>)) {\n out[k] = v\n }\n }\n return out\n}\n\nfunction stringField(raw: Record<string, unknown>, key: string): string | undefined {\n const v = raw[key]\n return typeof v === 'string' ? v : undefined\n}\n\nfunction asString(v: unknown): string | null {\n return typeof v === 'string' && v.length > 0 ? v : null\n}\n\nfunction isPresent<T>(v: T | undefined): v is T {\n return v !== undefined\n}\n\n// Truncation counter — module-private, lets viewSpans report the\n// number of attribute fields it had to truncate without threading\n// a counter through every call.\nconst truncationCounters = new WeakMap<OtlpFileTraceStore, { value: number }>()\n\nfunction trackTruncation(store: OtlpFileTraceStore): void {\n let c = truncationCounters.get(store)\n if (!c) {\n c = { value: 0 }\n truncationCounters.set(store, c)\n }\n c.value += 1\n}\n\nfunction truncationCounter(store: OtlpFileTraceStore): { delta(): number } {\n const before = truncationCounters.get(store)?.value ?? 0\n return {\n delta() {\n const after = truncationCounters.get(store)?.value ?? 0\n return after - before\n },\n }\n}\n\n/**\n * Best-effort: locate the JSON path for the substring at `offset` in\n * a single span's JSONL slice. We walk the parsed JSON structurally\n * and return the dotted path when we find a string field whose\n * serialised form contains `offset`. Returns `null` if the offset\n * doesn't fall inside a recognisable string field.\n */\nfunction bestAttributePathForOffset(slice: string, offset: number): string | null {\n // The slice contains '\"key\":\"value...\"' — find the nearest '\"'\n // wrapping `offset` and walk back to a key. This is heuristic but\n // bounded by the span line length, not the whole file.\n let i = offset\n while (i > 0 && slice[i] !== '\"') i -= 1\n if (i <= 0) return null\n // Scan backwards for the preceding '\"': pattern is \"key\":\"value\"\n let j = i - 1\n while (j > 0 && slice[j] !== ':') j -= 1\n if (j <= 0) return null\n // Find the key: walk back from `:` to the matching closing '\"' then to opening '\"'.\n let k = j - 1\n while (k > 0 && slice[k] !== '\"') k -= 1\n let l = k - 1\n while (l > 0 && slice[l] !== '\"') l -= 1\n if (l <= 0) return null\n return slice.slice(l + 1, k)\n}\n","/**\n * `TraceAnalysisStore` — read-side interface the trace-analyst calls\n * through. Six operations, all bounded:\n *\n * - `getOverview(filters?)` — dataset rollup + sample trace ids.\n * - `queryTraces(filters?, limit, offset)` — paginated summaries.\n * - `countTraces(filters?)` — cheap count without materialisation.\n * - `viewTrace(trace_id, perAttrCap)` — full span list, oversized → summary.\n * - `viewSpans(trace_id, span_ids, perAttrCap)` — surgical span fetch.\n * - `searchTrace(trace_id, regex, max_matches)` — bounded regex hits.\n * - `searchSpan(trace_id, span_id, regex, max_matches)` — single-span search.\n *\n * Multiple implementations ship in the core (`OtlpFileTraceStore`).\n * Downstream callers can supply their own — e.g. a DuckDB-backed\n * adapter or an in-memory adapter for tests — by implementing this\n * interface.\n *\n * Filters compose with AND semantics. Empty/undefined fields impose\n * no constraint. `regex_pattern` is the only opt-in raw-bytes scan —\n * implementations may skip it via `count`/`overview` when not set.\n */\n\nimport type {\n DatasetOverview,\n QueryTracesPage,\n SearchSpanResult,\n SearchTraceResult,\n TraceAnalystFilters,\n ViewSpansResult,\n ViewTraceResult,\n} from './types'\n\nexport interface TraceAnalysisStore {\n getOverview(filters?: TraceAnalystFilters): Promise<DatasetOverview>\n\n queryTraces(opts: {\n filters?: TraceAnalystFilters\n limit: number\n offset?: number\n }): Promise<QueryTracesPage>\n\n countTraces(filters?: TraceAnalystFilters): Promise<number>\n\n viewTrace(opts: {\n trace_id: string\n /** Override per-attribute byte cap. Defaults to discovery budget. */\n per_attribute_byte_cap?: number\n }): Promise<ViewTraceResult>\n\n viewSpans(opts: {\n trace_id: string\n span_ids: readonly string[]\n /** Override per-attribute byte cap. Defaults to surgical budget. */\n per_attribute_byte_cap?: number\n }): Promise<ViewSpansResult>\n\n searchTrace(opts: {\n trace_id: string\n regex_pattern: string\n /** Hard cap on matches returned. Default 50. */\n max_matches?: number\n }): Promise<SearchTraceResult>\n\n searchSpan(opts: {\n trace_id: string\n span_id: string\n regex_pattern: string\n max_matches?: number\n }): Promise<SearchSpanResult>\n}\n\n/** Compile a regex with the same anchoring + flags semantics across\n * implementations. Throws on invalid pattern — callers should surface\n * that to the agent so it can refine instead of looping. */\nexport function compileSearchRegex(pattern: string): RegExp {\n let source = pattern\n let flags = 'm'\n if (source.startsWith('(?i)')) {\n source = source.slice(4)\n flags += 'i'\n }\n return new RegExp(source, flags)\n}\n\n/** Truncate string payload deterministically for tool responses.\n * Marker is parseable so downstream consumers can detect truncation\n * and decide whether to fetch surgically. */\nexport function truncateForBudget(value: string, byteCap: number): string {\n // We measure UTF-8 byte length conservatively via Buffer.byteLength;\n // for predictability the truncation point is in CHARS, never inside\n // a code point.\n const original = Buffer.byteLength(value, 'utf8')\n if (original <= byteCap) return value\n\n // Step back from the cap until we're at a valid char boundary.\n // Slice by char count proportional to byte ratio, then re-measure.\n const ratio = byteCap / original\n let cut = Math.max(0, Math.floor(value.length * ratio))\n while (cut > 0 && Buffer.byteLength(value.slice(0, cut), 'utf8') > byteCap) {\n cut -= 1\n }\n return `${value.slice(0, cut)}\\n[trace-analyst truncated: original ${original} bytes]`\n}\n","/**\n * Trace-analyst tool surface — six namespaced AxFunctions the analyst\n * agent calls from generated JS code via `traces.<name>(...)`.\n *\n * Discovery → narrow → deep-read protocol. Tool names + ordering\n * support RLM discovery:\n *\n * 1. `getDatasetOverview` (cheap) — first call, sizes the dataset\n * 2. `queryTraces` — paginated summaries with `raw_jsonl_bytes`\n * 3. `countTraces` — cheap pre-flight before regex\n * 4. `viewTrace` — full span list, oversized → summary\n * 5. `viewSpans` — surgical 16KB-cap reads\n * 6. `searchTrace` / `searchSpan` — bounded regex hits\n *\n * Failure mode. Tool handlers throw on bad input (invalid trace ids,\n * out-of-range pagination, malformed regex). Ax converts thrown errors\n * into actor-visible `[ERROR]` strings so the analyst can adjust on\n * the next turn instead of looping.\n */\n\nimport type { AxFunction } from '@ax-llm/ax'\nimport { f, fn } from '@ax-llm/ax'\n\nimport type { TraceAnalysisStore } from './store'\nimport type { TraceAnalystFilters } from './types'\n\nconst NAMESPACE = 'traces'\n\ninterface BuildTraceAnalystToolsOpts {\n store: TraceAnalysisStore\n /** Override the default sample-trace-id slot count (20). Mostly for tests. */\n sampleTraceLimit?: number\n}\n\nconst filtersField = f\n .json('Filter set. ALL fields are AND-composed. Leave empty to scan everything.')\n .optional()\n\n/**\n * Build the trace-analyst function set. Pass the result into\n * `agent(...).functions.local`.\n */\nexport function buildTraceAnalystTools(opts: BuildTraceAnalystToolsOpts): AxFunction[] {\n const { store } = opts\n\n const getDatasetOverview = fn('getDatasetOverview')\n .description(\n 'Dataset rollup: total traces, raw_jsonl_bytes, services, agents, ' +\n 'models, tools, and sample_trace_ids (real ids passable to ' +\n 'view/search). Always call this FIRST without a regex_pattern.',\n )\n .namespace(NAMESPACE)\n .arg('filters', filtersField)\n .returns(f.json('DatasetOverview'))\n .handler(async ({ filters }) => store.getOverview(parseFilters(filters)))\n .build()\n\n const queryTraces = fn('queryTraces')\n .description(\n 'Paginated trace summaries. Each summary carries raw_jsonl_bytes — ' +\n 'use it to size traces BEFORE calling viewTrace. Narrow with indexed ' +\n 'filters before adding regex_pattern.',\n )\n .namespace(NAMESPACE)\n .arg('filters', filtersField)\n .arg('limit', f.number('Page size, 1..200'))\n .arg('offset', f.number('Page offset; default 0').optional())\n .returns(f.json('QueryTracesPage'))\n .handler(async ({ filters, limit, offset }) =>\n store.queryTraces({\n filters: parseFilters(filters),\n limit: assertPageLimit(limit),\n offset: assertOffset(offset),\n }),\n )\n .build()\n\n const countTraces = fn('countTraces')\n .description(\n 'Count traces matching `filters`. Use as a cheap pre-flight ' +\n 'before opting into a regex_pattern scan.',\n )\n .namespace(NAMESPACE)\n .arg('filters', filtersField)\n .returns(f.number('count'))\n .handler(async ({ filters }) => store.countTraces(parseFilters(filters)))\n .build()\n\n const viewTrace = fn('viewTrace')\n .description(\n 'Return ALL spans for a single trace, with each attribute capped at ' +\n '~4KB. If the response would exceed the per-call ceiling the result ' +\n 'carries `oversized` instead of `spans` — DO NOT retry with the same ' +\n 'trace_id; switch to searchTrace / viewSpans.',\n )\n .namespace(NAMESPACE)\n .arg('trace_id', f.string('Real trace id from a prior overview/query'))\n .returns(f.json('ViewTraceResult'))\n .handler(async ({ trace_id }) =>\n store.viewTrace({ trace_id: assertString(trace_id, 'trace_id') }),\n )\n .build()\n\n const viewSpans = fn('viewSpans')\n .description(\n 'Surgical read of specific spans within a trace, with each ' +\n 'attribute capped at ~16KB (4× the discovery cap). Use after ' +\n 'searchTrace narrows to specific span_ids.',\n )\n .namespace(NAMESPACE)\n .arg('trace_id', f.string('Real trace id'))\n .arg('span_ids', f.string('Span ids to fetch').array())\n .returns(f.json('ViewSpansResult'))\n .handler(async ({ trace_id, span_ids }) =>\n store.viewSpans({\n trace_id: assertString(trace_id, 'trace_id'),\n span_ids: assertStringArray(span_ids, 'span_ids'),\n }),\n )\n .build()\n\n const searchTrace = fn('searchTrace')\n .description(\n 'Regex search across all spans of one trace. Returns ' +\n '`{trace_id, hits: SpanMatchRecord[], total_matches, has_more}`. ' +\n '**Iterate `result.hits`, NOT `result.matches`** — the field is ' +\n '`hits`. Each hit has `{span_id, span_name, span_kind, ' +\n 'attribute_path, matched_text, context_before, context_after, ' +\n 'match_offset}`. Bounded regardless of trace size by max_matches ' +\n '(1..500, default 50). If has_more=true, REFINE the regex rather ' +\n 'than blindly raising max_matches.',\n )\n .namespace(NAMESPACE)\n .arg('trace_id', f.string('Real trace id'))\n .arg('regex_pattern', f.string('JS-compatible regex, multiline'))\n .arg('max_matches', f.number('Max records returned, 1..500; default 50').optional())\n .returns(f.json('SearchTraceResult'))\n .handler(async ({ trace_id, regex_pattern, max_matches }) =>\n store.searchTrace({\n trace_id: assertString(trace_id, 'trace_id'),\n regex_pattern: assertRegex(regex_pattern),\n max_matches: assertMaxMatches(max_matches),\n }),\n )\n .build()\n\n const searchSpan = fn('searchSpan')\n .description(\n 'Regex search inside a single span. Use when viewSpans returned ' +\n 'a 16KB-truncated payload and you need to narrow further. ' +\n 'Returns `{trace_id, span_id, hits: SpanMatchRecord[], ' +\n 'total_matches, has_more}` — iterate `result.hits`, NOT ' +\n '`result.matches`.',\n )\n .namespace(NAMESPACE)\n .arg('trace_id', f.string('Real trace id'))\n .arg('span_id', f.string('Real span id within trace'))\n .arg('regex_pattern', f.string('JS-compatible regex, multiline'))\n .arg('max_matches', f.number('Max records, 1..500; default 50').optional())\n .returns(f.json('SearchSpanResult'))\n .handler(async ({ trace_id, span_id, regex_pattern, max_matches }) =>\n store.searchSpan({\n trace_id: assertString(trace_id, 'trace_id'),\n span_id: assertString(span_id, 'span_id'),\n regex_pattern: assertRegex(regex_pattern),\n max_matches: assertMaxMatches(max_matches),\n }),\n )\n .build()\n\n return [\n getDatasetOverview,\n queryTraces,\n countTraces,\n viewTrace,\n viewSpans,\n searchTrace,\n searchSpan,\n ]\n}\n\n/**\n * Convenience: same shape as `buildTraceAnalystTools` but returns the\n * grouped form expected when registering trace tools alongside other\n * agent function modules. */\nexport function traceAnalystFunctionGroup(opts: BuildTraceAnalystToolsOpts): {\n namespace: string\n title: string\n selectionCriteria: string\n description: string\n functions: AxFunction[]\n} {\n return {\n namespace: NAMESPACE,\n title: 'Trace Analysis',\n selectionCriteria: 'Use for any inspection of OTLP-shaped trace data.',\n description:\n 'Discovery → narrow → deep-read tools over a JSONL trace dataset. ' +\n 'Always call getDatasetOverview first.',\n functions: buildTraceAnalystTools(opts),\n }\n}\n\n// ─── Argument validation ─────────────────────────────────────────────\n\nfunction parseFilters(input: unknown): TraceAnalystFilters | undefined {\n if (input == null) return undefined\n if (typeof input !== 'object' || Array.isArray(input)) {\n throw new TypeError(`filters must be an object, got ${typeof input}`)\n }\n const f = input as Record<string, unknown>\n const out: TraceAnalystFilters = {}\n if (typeof f.has_errors === 'boolean') out.has_errors = f.has_errors\n out.service_names = stringArrayOrUndefined(f.service_names, 'service_names')\n out.agent_names = stringArrayOrUndefined(f.agent_names, 'agent_names')\n out.model_names = stringArrayOrUndefined(f.model_names, 'model_names')\n out.tool_names = stringArrayOrUndefined(f.tool_names, 'tool_names')\n if (typeof f.start_time_after === 'string') out.start_time_after = f.start_time_after\n if (typeof f.start_time_before === 'string') out.start_time_before = f.start_time_before\n if (typeof f.regex_pattern === 'string') {\n if (f.regex_pattern.length === 0) {\n throw new TypeError('filters.regex_pattern cannot be empty')\n }\n out.regex_pattern = f.regex_pattern\n }\n return out\n}\n\nfunction stringArrayOrUndefined(v: unknown, label: string): string[] | undefined {\n if (v === undefined || v === null) return undefined\n if (!Array.isArray(v)) throw new TypeError(`${label} must be an array of strings`)\n if (v.some((x) => typeof x !== 'string')) {\n throw new TypeError(`${label} entries must be strings`)\n }\n return v as string[]\n}\n\nfunction assertPageLimit(limit: unknown): number {\n if (typeof limit !== 'number' || !Number.isInteger(limit) || limit < 1 || limit > 200) {\n throw new RangeError(`limit must be an integer 1..200`)\n }\n return limit\n}\nfunction assertOffset(offset: unknown): number | undefined {\n if (offset === undefined) return undefined\n if (typeof offset !== 'number' || !Number.isInteger(offset) || offset < 0) {\n throw new RangeError(`offset must be a non-negative integer`)\n }\n return offset\n}\nfunction assertRegex(pattern: unknown): string {\n if (typeof pattern !== 'string' || pattern.length === 0) {\n throw new TypeError(`regex_pattern must be a non-empty string`)\n }\n // Compile-and-discard to fail fast — store will recompile, but we\n // want a deterministic error from the agent's side rather than\n // a downstream exception.\n // eslint-disable-next-line no-new\n new RegExp(pattern, 'm')\n return pattern\n}\nfunction assertMaxMatches(n: unknown): number | undefined {\n if (n === undefined) return undefined\n if (typeof n !== 'number' || !Number.isInteger(n) || n < 1 || n > 500) {\n throw new RangeError(`max_matches must be an integer 1..500`)\n }\n return n\n}\n\nfunction assertString(v: unknown, label: string): string {\n if (typeof v !== 'string' || v.length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n return v\n}\n\nfunction assertStringArray(v: unknown, label: string): string[] {\n if (!Array.isArray(v)) throw new TypeError(`${label} must be an array of strings`)\n if (v.some((x) => typeof x !== 'string')) {\n throw new TypeError(`${label} entries must be strings`)\n }\n return v as string[]\n}\n","import { type AxActorTurn, type AxAIService, type AxFunction, AxJSRuntime, agent } from '@ax-llm/ax'\nimport {\n TRACE_ANALYST_ACTOR_DESCRIPTION,\n TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION,\n TRACE_ANALYST_SUBAGENT_DESCRIPTION,\n} from './prompts'\nimport type { TraceAnalysisStore } from './store'\nimport { OtlpFileTraceStore, TraceFileMissingError } from './store-otlp'\nimport { buildTraceAnalystTools } from './tools'\n\nexport interface AnalyzeTracesInput {\n /** The user-facing question. Domain framing belongs here, not in the\n * actor description. */\n question: string\n}\n\nexport interface AnalyzeTracesResult {\n /** The responder's prose answer. */\n answer: string\n /** Bulleted findings extracted from the responder's structured output. */\n findings: string[]\n /** Per-actor-turn snapshots captured via `actorTurnCallback`. */\n turns: AnalyzeTracesTurnSnapshot[]\n /** Total turns the actor took. */\n turnCount: number\n /** Token usage by role. */\n usage: TraceAnalystUsage\n /** Full system + assistant + tool message log by role. */\n chatLog: TraceAnalystChatLog\n /** Prompt version that produced this run. */\n actorPromptVersion: string\n}\n\nexport interface TraceAnalystUsage {\n actor: TraceAnalystUsageEntry[]\n responder: TraceAnalystUsageEntry[]\n}\n\nexport interface TraceAnalystUsageEntry {\n [key: string]: unknown\n}\n\nexport interface TraceAnalystChatLog {\n actor: TraceAnalystChatMessage[]\n responder: TraceAnalystChatMessage[]\n}\n\nexport interface TraceAnalystChatMessage {\n [key: string]: unknown\n}\n\nexport interface AnalyzeTracesTurnSnapshot {\n turn: number\n isError: boolean\n /** The JS code the actor produced for this turn. */\n code: string\n /** The formatted action-log entry the actor sees on the next turn. */\n output: string\n /** Provider thought (when `actorOptions.showThoughts` is true and the\n * provider returns it). */\n thought?: string\n}\n\nexport interface AnalyzeTracesOptions {\n /** Trace data source. Pass either an OTLP-JSONL path or a custom store. */\n source: string | TraceAnalysisStore\n /** Caller-provided AxAIService. */\n ai: AxAIService\n /** Model id forwarded to actor + responder. */\n model?: string\n /** Recursion depth. 0 = no sub-agent dispatch. Default 1. */\n maxDepth?: number\n /** Maximum actor turns. Default 12. */\n maxTurns?: number\n /** Maximum parallel sub-agent calls in batched llmQuery. Default 2. */\n maxParallelSubagents?: number\n /** Override the actor description. */\n actorDescription?: string\n /** Override the subagent description. */\n subagentDescription?: string\n /** Per-turn observability hook. */\n onTurn?: (turn: AnalyzeTracesTurnSnapshot) => void | Promise<void>\n /** Override max runtime characters per turn. Default 6000. */\n maxRuntimeChars?: number\n /** When set, every turn's snapshot is appended to this JSONL file\n * immediately. If the analyst crashes mid-loop (provider 503,\n * network error, validator reject) the partial reasoning is still\n * on disk. Replay the file with the responder afterward to recover\n * evidence. */\n progressLogPath?: string\n}\n\n/**\n * Run the trace analyst.\n *\n * Throws:\n * - `TraceFileMissingError` if `source` is a path and doesn't exist.\n * - `AxAgentClarificationError` if the analyst asks for clarification.\n * - Provider errors (auth, rate limits) propagate from the AI service.\n */\nexport async function analyzeTraces(\n input: AnalyzeTracesInput,\n options: AnalyzeTracesOptions,\n): Promise<AnalyzeTracesResult> {\n if (!input.question || typeof input.question !== 'string') {\n throw new TypeError('analyzeTraces: input.question must be a non-empty string')\n }\n\n const store: TraceAnalysisStore =\n typeof options.source === 'string'\n ? new OtlpFileTraceStore({ path: options.source })\n : options.source\n\n // Pre-warm file stores so missing inputs fail before the RLM starts.\n if (store instanceof OtlpFileTraceStore) {\n await store.ensureIndexed()\n }\n\n const tools: AxFunction[] = buildTraceAnalystTools({ store })\n const turns: AnalyzeTracesTurnSnapshot[] = []\n\n // Persist each turn as JSONL so interrupted analyst runs keep useful evidence.\n let progressFs: import('node:fs').WriteStream | undefined\n if (options.progressLogPath) {\n const { createWriteStream } = await import('node:fs')\n const { mkdir } = await import('node:fs/promises')\n const { dirname } = await import('node:path')\n await mkdir(dirname(options.progressLogPath), { recursive: true })\n progressFs = createWriteStream(options.progressLogPath, { flags: 'a' })\n }\n\n const actorTurnCallback = async (turn: AxActorTurn): Promise<void> => {\n const snap: AnalyzeTracesTurnSnapshot = {\n turn: turn.turn,\n isError: turn.isError,\n code: turn.code,\n output: turn.output,\n thought: turn.thought,\n }\n turns.push(snap)\n if (progressFs) {\n try {\n progressFs.write(`${JSON.stringify({ ...snap, ts: Date.now() })}\\n`)\n } catch {\n // Progress logging must never fail the analyst.\n }\n }\n if (options.onTurn) await options.onTurn(snap)\n }\n\n const maxDepth = options.maxDepth ?? 1\n const maxTurns = options.maxTurns ?? 12\n const maxParallelSubagents = options.maxParallelSubagents ?? 2\n const maxRuntimeChars = options.maxRuntimeChars ?? 6000\n\n const analyst = agent<{ question: string }, { answer: string; findings: string[] }>(\n 'question:string -> answer:string, findings:string[]',\n {\n agentIdentity: {\n name: 'TraceAnalyst',\n description:\n 'Analyzes OTLP-shaped JSONL traces using bounded discovery tools to identify systemic failure modes.',\n },\n contextFields: ['question'],\n runtime: new AxJSRuntime({\n permissions: [],\n blockDynamicImport: true,\n allowedModules: [],\n freezeIntrinsics: true,\n blockShadowRealm: true,\n // RLM stdout mode relies on runtime bindings persisting across turns.\n preventGlobalThisExtensions: false,\n }),\n mode: maxDepth > 0 ? 'advanced' : 'simple',\n recursionOptions: maxDepth > 0 ? { maxDepth } : undefined,\n maxTurns,\n maxRuntimeChars,\n maxBatchedLlmQueryConcurrency: maxParallelSubagents,\n promptLevel: 'detailed',\n // Trace analysis depends on exact prior tool results and runtime variables.\n contextPolicy: { preset: 'full', budget: 'balanced' },\n functions: { local: tools },\n actorOptions: {\n description: options.actorDescription ?? TRACE_ANALYST_ACTOR_DESCRIPTION,\n ...(options.model ? { model: options.model } : {}),\n // Keep actor messages tool-call/content shaped across reasoning models.\n showThoughts: false,\n thinkingTokenBudget: 'none' as unknown as number,\n },\n responderOptions: {\n ...(options.model ? { model: options.model } : {}),\n description: options.subagentDescription ?? TRACE_ANALYST_SUBAGENT_DESCRIPTION,\n showThoughts: false,\n },\n actorTurnCallback,\n bubbleErrors: [TraceFileMissingError],\n },\n )\n\n let result: { answer: unknown; findings: unknown }\n try {\n result = await analyst.forward(options.ai, { question: input.question })\n } finally {\n if (progressFs) {\n await new Promise<void>((resolve) => progressFs!.end(() => resolve()))\n }\n }\n\n return {\n answer: typeof result.answer === 'string' ? result.answer : String(result.answer ?? ''),\n findings: Array.isArray(result.findings)\n ? result.findings.filter((s): s is string => typeof s === 'string')\n : [],\n turns,\n turnCount: turns.length,\n usage: normalizeRoleArrays(analyst.getUsage()),\n chatLog: normalizeRoleArrays(analyst.getChatLog()),\n actorPromptVersion: TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION,\n }\n}\n\nfunction normalizeRoleArrays(value: unknown): {\n actor: Record<string, unknown>[]\n responder: Record<string, unknown>[]\n} {\n const record = value && typeof value === 'object' ? (value as Record<string, unknown>) : {}\n return {\n actor: normalizeRecordArray(record.actor),\n responder: normalizeRecordArray(record.responder),\n }\n}\n\nfunction normalizeRecordArray(value: unknown): Record<string, unknown>[] {\n if (!Array.isArray(value)) return []\n return value.map((item) =>\n item && typeof item === 'object' ? { ...(item as Record<string, unknown>) } : { value: item },\n )\n}\n","/**\n * TraceStore — persistence + query over the TraceSchema v1 corpus.\n *\n * Two implementations ship in the core:\n * - InMemoryTraceStore: dev + tests, fully in-process\n * - FileSystemTraceStore: NDJSON append-only files per entity, suitable\n * for long-running CI jobs; rolled over at 32MB\n *\n * Downstream adapters (DuckDB, Langfuse, R2 parquet) implement this same\n * interface — the rest of the framework is storage-agnostic.\n */\n\nimport type {\n Artifact,\n BudgetLedgerEntry,\n EventKind,\n Run,\n RunStatus,\n Span,\n SpanKind,\n TraceEvent,\n} from './schema'\n\nexport interface RunFilter {\n scenarioId?: string\n variantId?: string\n status?: RunStatus\n since?: number\n until?: number\n tag?: { key: string; value: string }\n parentRunId?: string\n projectId?: string\n chatId?: string\n layer?: import('./schema').RunLayer\n}\n\nexport interface SpanFilter {\n runId?: string\n parentSpanId?: string\n kind?: SpanKind\n name?: string\n toolName?: string\n judgeId?: string\n since?: number\n until?: number\n}\n\nexport interface EventFilter {\n runId?: string\n spanId?: string\n kind?: EventKind\n since?: number\n until?: number\n}\n\nexport interface TraceStore {\n appendRun(run: Run): Promise<void>\n updateRun(runId: string, patch: Partial<Run>): Promise<void>\n appendSpan(span: Span): Promise<void>\n updateSpan(spanId: string, patch: Partial<Span>): Promise<void>\n appendEvent(event: TraceEvent): Promise<void>\n appendArtifact(artifact: Artifact): Promise<void>\n appendBudgetEntry(entry: BudgetLedgerEntry): Promise<void>\n\n getRun(runId: string): Promise<Run | undefined>\n listRuns(filter?: RunFilter): Promise<Run[]>\n spans(filter?: SpanFilter): Promise<Span[]>\n events(filter?: EventFilter): Promise<TraceEvent[]>\n budget(runId: string): Promise<BudgetLedgerEntry[]>\n artifacts(runId: string): Promise<Artifact[]>\n}\n\n// ── In-memory ────────────────────────────────────────────────────────\n\nexport class InMemoryTraceStore implements TraceStore {\n private runs = new Map<string, Run>()\n private allSpans: Span[] = []\n private allEvents: TraceEvent[] = []\n private allArtifacts: Artifact[] = []\n private allBudget: BudgetLedgerEntry[] = []\n\n async appendRun(run: Run): Promise<void> {\n if (this.runs.has(run.runId)) throw new Error(`run ${run.runId} already exists`)\n this.runs.set(run.runId, { ...run })\n }\n\n async updateRun(runId: string, patch: Partial<Run>): Promise<void> {\n const existing = this.runs.get(runId)\n if (!existing) throw new Error(`run ${runId} not found`)\n this.runs.set(runId, { ...existing, ...patch })\n }\n\n async appendSpan(span: Span): Promise<void> {\n this.allSpans.push({ ...span })\n }\n\n async updateSpan(spanId: string, patch: Partial<Span>): Promise<void> {\n const idx = this.allSpans.findIndex((s) => s.spanId === spanId)\n if (idx < 0) throw new Error(`span ${spanId} not found`)\n this.allSpans[idx] = { ...this.allSpans[idx], ...patch } as Span\n }\n\n async appendEvent(event: TraceEvent): Promise<void> {\n this.allEvents.push({ ...event })\n }\n\n async appendArtifact(artifact: Artifact): Promise<void> {\n this.allArtifacts.push({ ...artifact })\n }\n\n async appendBudgetEntry(entry: BudgetLedgerEntry): Promise<void> {\n this.allBudget.push({ ...entry })\n }\n\n async getRun(runId: string): Promise<Run | undefined> {\n const r = this.runs.get(runId)\n return r ? { ...r } : undefined\n }\n\n async listRuns(filter: RunFilter = {}): Promise<Run[]> {\n return [...this.runs.values()].filter((r) => matchesRun(r, filter))\n }\n\n async spans(filter: SpanFilter = {}): Promise<Span[]> {\n return this.allSpans.filter((s) => matchesSpan(s, filter)).map((s) => ({ ...s }))\n }\n\n async events(filter: EventFilter = {}): Promise<TraceEvent[]> {\n return this.allEvents.filter((e) => matchesEvent(e, filter)).map((e) => ({ ...e }))\n }\n\n async budget(runId: string): Promise<BudgetLedgerEntry[]> {\n return this.allBudget.filter((b) => b.runId === runId).map((b) => ({ ...b }))\n }\n\n async artifacts(runId: string): Promise<Artifact[]> {\n return this.allArtifacts.filter((a) => a.runId === runId).map((a) => ({ ...a }))\n }\n}\n\nfunction matchesRun(r: Run, f: RunFilter): boolean {\n if (f.scenarioId && r.scenarioId !== f.scenarioId) return false\n if (f.variantId && r.variantId !== f.variantId) return false\n if (f.status && r.status !== f.status) return false\n if (f.since !== undefined && r.startedAt < f.since) return false\n if (f.until !== undefined && r.startedAt > f.until) return false\n if (f.tag && r.tags?.[f.tag.key] !== f.tag.value) return false\n if (f.parentRunId && r.parentRunId !== f.parentRunId) return false\n if (f.projectId && r.projectId !== f.projectId) return false\n if (f.chatId && r.chatId !== f.chatId) return false\n if (f.layer && r.layer !== f.layer) return false\n return true\n}\n\nfunction matchesSpan(s: Span, f: SpanFilter): boolean {\n if (f.runId && s.runId !== f.runId) return false\n if (f.parentSpanId && s.parentSpanId !== f.parentSpanId) return false\n if (f.kind && s.kind !== f.kind) return false\n if (f.name && s.name !== f.name) return false\n if (f.toolName && (s.kind !== 'tool' || s.toolName !== f.toolName)) return false\n if (f.judgeId && (s.kind !== 'judge' || s.judgeId !== f.judgeId)) return false\n if (f.since !== undefined && s.startedAt < f.since) return false\n if (f.until !== undefined && s.startedAt > f.until) return false\n return true\n}\n\nfunction matchesEvent(e: TraceEvent, f: EventFilter): boolean {\n if (f.runId && e.runId !== f.runId) return false\n if (f.spanId && e.spanId !== f.spanId) return false\n if (f.kind && e.kind !== f.kind) return false\n if (f.since !== undefined && e.timestamp < f.since) return false\n if (f.until !== undefined && e.timestamp > f.until) return false\n return true\n}\n\n// ── Filesystem (NDJSON append-only, one file per entity) ─────────────\n\nexport interface FileSystemTraceStoreOptions {\n dir: string\n /** Roll over NDJSON files when they exceed this size in bytes. Default 32 MB. */\n maxBytes?: number\n}\n\nexport class FileSystemTraceStore implements TraceStore {\n private dir: string\n private maxBytes: number\n /** Lazy in-memory index for queries — populated on first read. */\n private index?: InMemoryTraceStore\n private loaded = false\n\n constructor(options: FileSystemTraceStoreOptions) {\n this.dir = options.dir\n this.maxBytes = options.maxBytes ?? 32 * 1024 * 1024\n }\n\n private async ensureDir(): Promise<void> {\n const fs = await import('node:fs/promises')\n await fs.mkdir(this.dir, { recursive: true })\n }\n\n private async append(name: string, record: unknown): Promise<void> {\n await this.ensureDir()\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const active = path.join(this.dir, `${name}.ndjson`)\n try {\n const stat = await fs.stat(active)\n if (stat.size >= this.maxBytes) {\n const rolled = path.join(this.dir, `${name}.${Date.now()}.ndjson`)\n await fs.rename(active, rolled)\n }\n } catch {\n /* file doesn't exist yet */\n }\n await fs.appendFile(active, `${JSON.stringify(record)}\\n`, 'utf8')\n // Mirror genuinely-new rows into the lazy index. Update rows (marked\n // with `_update: true` by updateRun/updateSpan) are applied by those\n // methods directly via the index's update* APIs — re-inserting them\n // here triggers a duplicate-id error once the first read populates\n // the index.\n if (this.index && !(record as { _update?: boolean })?._update) {\n void this.insertInto(name, record)\n }\n }\n\n private async insertInto(name: string, record: unknown): Promise<void> {\n if (!this.index) return\n switch (name) {\n case 'runs':\n await this.index.appendRun(record as Run)\n break\n case 'spans':\n await this.index.appendSpan(record as Span)\n break\n case 'events':\n await this.index.appendEvent(record as TraceEvent)\n break\n case 'artifacts':\n await this.index.appendArtifact(record as Artifact)\n break\n case 'budget':\n await this.index.appendBudgetEntry(record as BudgetLedgerEntry)\n break\n }\n }\n\n private async load(): Promise<InMemoryTraceStore> {\n if (this.loaded && this.index) return this.index\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const store = new InMemoryTraceStore()\n try {\n const entries = await fs.readdir(this.dir)\n for (const file of entries) {\n if (!file.endsWith('.ndjson')) continue\n const full = path.join(this.dir, file)\n const content = await fs.readFile(full, 'utf8')\n const base = file.split('.')[0]\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue\n const record = JSON.parse(line)\n if (base === 'runs') {\n // Allow re-loading without duplicate error\n try {\n await store.appendRun(record)\n } catch {\n await store.updateRun(record.runId, record)\n }\n } else if (base === 'spans') {\n // `updateSpan` appends an `_update: true` patch row instead of\n // rewriting the original span. On reload we must collapse those\n // patches onto the original span — otherwise a fresh\n // FileSystemTraceStore reading the same dir reports duplicate\n // spans (one full, one fragment with no runId/kind/name), which\n // breaks any downstream consumer that re-opens the store\n // cross-process (e.g. the OTLP converter).\n if (record?._update) {\n try {\n await store.updateSpan(record.spanId, record)\n } catch {\n // Patch row arrived before the original — should not happen\n // with locked append order, but fall through to append so we\n // don't lose data.\n await store.appendSpan(record)\n }\n } else {\n await store.appendSpan(record)\n }\n } else if (base === 'events') {\n await store.appendEvent(record)\n } else if (base === 'artifacts') {\n await store.appendArtifact(record)\n } else if (base === 'budget') {\n await store.appendBudgetEntry(record)\n }\n }\n }\n } catch {\n /* empty dir, first run */\n }\n this.index = store\n this.loaded = true\n return store\n }\n\n async appendRun(run: Run): Promise<void> {\n await this.append('runs', run)\n }\n async updateRun(runId: string, patch: Partial<Run>): Promise<void> {\n // NDJSON is append-only; record updates as new rows with the same runId —\n // readers collapse by last-write-wins on load.\n await this.append('runs', { runId, ...patch, _update: true })\n if (this.index) await this.index.updateRun(runId, patch)\n }\n async appendSpan(span: Span): Promise<void> {\n await this.append('spans', span)\n }\n async updateSpan(spanId: string, patch: Partial<Span>): Promise<void> {\n await this.append('spans', { spanId, ...patch, _update: true })\n if (this.index) await this.index.updateSpan(spanId, patch)\n }\n async appendEvent(event: TraceEvent): Promise<void> {\n await this.append('events', event)\n }\n async appendArtifact(artifact: Artifact): Promise<void> {\n await this.append('artifacts', artifact)\n }\n async appendBudgetEntry(entry: BudgetLedgerEntry): Promise<void> {\n await this.append('budget', entry)\n }\n\n async getRun(runId: string): Promise<Run | undefined> {\n return (await this.load()).getRun(runId)\n }\n async listRuns(filter?: RunFilter): Promise<Run[]> {\n return (await this.load()).listRuns(filter)\n }\n async spans(filter?: SpanFilter): Promise<Span[]> {\n return (await this.load()).spans(filter)\n }\n async events(filter?: EventFilter): Promise<TraceEvent[]> {\n return (await this.load()).events(filter)\n }\n async budget(runId: string): Promise<BudgetLedgerEntry[]> {\n return (await this.load()).budget(runId)\n }\n async artifacts(runId: string): Promise<Artifact[]> {\n return (await this.load()).artifacts(runId)\n }\n}\n","/**\n * OpenTelemetry JSON export — maps TraceSchema v1 to OTLP/JSON so\n * traces render natively in Jaeger / Honeycomb / Langfuse / Grafana.\n *\n * Wire format only. We do NOT depend on the @opentelemetry SDK — that\n * would drag in polyfills incompatible with Workers/Edge. Consumers\n * push the JSON to their collector of choice via HTTP.\n *\n * Reference: OTLP 1.3.2 (ResourceSpans / ScopeSpans / Span).\n */\n\nimport type { Run, Span, TraceEvent } from './schema'\nimport type { TraceStore } from './store'\n\nexport const OTEL_AGENT_EVAL_SCOPE = { name: '@tangle-network/agent-eval', version: '0.3.0' }\n\nexport interface OtlpSpan {\n traceId: string\n spanId: string\n parentSpanId?: string\n name: string\n kind: number\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<{\n key: string\n value: { stringValue?: string; intValue?: string; doubleValue?: number; boolValue?: boolean }\n }>\n events?: Array<{ timeUnixNano: string; name: string; attributes?: OtlpSpan['attributes'] }>\n status?: { code: number; message?: string }\n}\n\nexport interface OtlpResourceSpans {\n resource: { attributes: OtlpSpan['attributes'] }\n scopeSpans: Array<{ scope: typeof OTEL_AGENT_EVAL_SCOPE; spans: OtlpSpan[] }>\n}\n\nexport interface OtlpExport {\n resourceSpans: OtlpResourceSpans[]\n}\n\n/** Export a single run's spans + events in OTLP/JSON. */\nexport async function exportRunAsOtlp(\n store: TraceStore,\n runId: string,\n resourceAttrs: Record<string, string | number | boolean> = {},\n): Promise<OtlpExport> {\n const run = await store.getRun(runId)\n if (!run) throw new Error(`run ${runId} not found`)\n const spans = await store.spans({ runId })\n const events = await store.events({ runId })\n const eventsBySpan = new Map<string, TraceEvent[]>()\n for (const e of events) {\n if (!e.spanId) continue\n const arr = eventsBySpan.get(e.spanId) ?? []\n arr.push(e)\n eventsBySpan.set(e.spanId, arr)\n }\n const traceId = runToTraceId(run)\n const otlpSpans: OtlpSpan[] = spans.map((s) =>\n spanToOtlp(s, traceId, eventsBySpan.get(s.spanId) ?? []),\n )\n return {\n resourceSpans: [\n {\n resource: {\n attributes: toAttributes({\n 'service.name': 'agent-eval',\n 'run.id': run.runId,\n 'run.scenario_id': run.scenarioId,\n 'run.variant_id': run.variantId ?? '',\n 'run.dataset_version': run.datasetVersion ?? '',\n 'run.code_sha': run.codeSha ?? '',\n 'run.model_fingerprint': run.modelFingerprint ?? '',\n ...resourceAttrs,\n }),\n },\n scopeSpans: [{ scope: OTEL_AGENT_EVAL_SCOPE, spans: otlpSpans }],\n },\n ],\n }\n}\n\nfunction spanToOtlp(span: Span, traceId: string, events: TraceEvent[]): OtlpSpan {\n const endedAt = span.endedAt ?? span.startedAt\n return {\n traceId,\n spanId: padSpanId(span.spanId),\n parentSpanId: span.parentSpanId ? padSpanId(span.parentSpanId) : undefined,\n name: span.name,\n kind: 1, // SPAN_KIND_INTERNAL\n startTimeUnixNano: msToNs(span.startedAt),\n endTimeUnixNano: msToNs(endedAt),\n attributes: toAttributes(flattenSpanAttributes(span)),\n events: events.map((e) => ({\n timeUnixNano: msToNs(e.timestamp),\n name: e.kind,\n attributes: toAttributes(flattenPayload(e.payload)),\n })),\n status: span.status === 'error' ? { code: 2, message: span.error } : { code: 1 },\n }\n}\n\nfunction flattenSpanAttributes(span: Span): Record<string, string | number | boolean> {\n const base: Record<string, string | number | boolean> = {\n 'span.kind': span.kind,\n }\n if (span.kind === 'llm') {\n base['llm.model'] = span.model\n if (span.inputTokens !== undefined) base['llm.input_tokens'] = span.inputTokens\n if (span.outputTokens !== undefined) base['llm.output_tokens'] = span.outputTokens\n if (span.costUsd !== undefined) base['llm.cost_usd'] = span.costUsd\n if (span.finishReason) base['llm.finish_reason'] = span.finishReason\n } else if (span.kind === 'tool') {\n base['tool.name'] = span.toolName\n if (span.latencyMs !== undefined) base['tool.latency_ms'] = span.latencyMs\n } else if (span.kind === 'retrieval') {\n base['retrieval.query'] = span.query\n base['retrieval.hits'] = span.hits.length\n } else if (span.kind === 'judge') {\n base['judge.id'] = span.judgeId\n base['judge.dimension'] = span.dimension\n base['judge.score'] = span.score\n base['judge.target_span_id'] = span.targetSpanId\n } else if (span.kind === 'sandbox') {\n if (span.image) base['sandbox.image'] = span.image\n if (span.exitCode !== undefined) base['sandbox.exit_code'] = span.exitCode\n if (span.testsPassed !== undefined) base['sandbox.tests_passed'] = span.testsPassed\n if (span.testsTotal !== undefined) base['sandbox.tests_total'] = span.testsTotal\n }\n if (span.attributes) {\n for (const [k, v] of Object.entries(span.attributes)) {\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') base[k] = v\n }\n }\n return base\n}\n\nfunction flattenPayload(\n payload: Record<string, unknown>,\n): Record<string, string | number | boolean> {\n const out: Record<string, string | number | boolean> = {}\n for (const [k, v] of Object.entries(payload)) {\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') out[k] = v\n else out[k] = JSON.stringify(v)\n }\n return out\n}\n\nfunction toAttributes(record: Record<string, string | number | boolean>): OtlpSpan['attributes'] {\n return Object.entries(record).map(([key, value]) => ({\n key,\n value:\n typeof value === 'number'\n ? Number.isInteger(value)\n ? { intValue: value.toString() }\n : { doubleValue: value }\n : typeof value === 'boolean'\n ? { boolValue: value }\n : { stringValue: value },\n }))\n}\n\nfunction msToNs(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString()\n}\n\nfunction padSpanId(id: string): string {\n // OTLP wants 16-hex spanIds. UUIDs are 32-hex; strip dashes and take first 16.\n const cleaned = id.replace(/-/g, '')\n return cleaned.slice(0, 16).padEnd(16, '0')\n}\n\nfunction runToTraceId(run: Run): string {\n // OTLP wants 32-hex traceIds. Use runId directly when it's 32-hex already,\n // else SHA-ish truncate.\n const cleaned = run.runId.replace(/-/g, '')\n return cleaned.slice(0, 32).padEnd(32, '0')\n}\n","/**\n * Redaction — remove PII / secrets from trace payloads before persist.\n *\n * Pre-persistence rules mean raw traces in storage are already scrubbed.\n * Unredacted variants (for debugging / post-mortems) live in a separate\n * storage layer with stricter access controls; this module only covers\n * the default scrub-then-persist path.\n *\n * Rules compose: pass an array of `RedactionRule`, each is applied in\n * order. Strings that match get replaced with a tagged sentinel so the\n * eval framework can count how many redactions happened per run\n * (surfaced via `redaction_applied` events).\n */\n\nexport interface RedactionRule {\n id: string\n pattern: RegExp\n /** Replacement — e.g. '[PII:email]'. Defaults to `[redacted:{id}]`. */\n replacement?: string\n}\n\nexport interface RedactionReport {\n redactionCount: number\n byRule: Record<string, number>\n}\n\n/** OWASP / common-sense defaults — extend per-domain. */\nexport const DEFAULT_REDACTION_RULES: RedactionRule[] = [\n { id: 'email', pattern: /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi },\n { id: 'ssn', pattern: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g },\n { id: 'credit-card', pattern: /\\b(?:\\d[ -]*?){13,16}\\b/g },\n { id: 'phone-us', pattern: /\\b(?:\\+?1[-.\\s]?)?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}\\b/g },\n { id: 'ipv4', pattern: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g },\n { id: 'aws-access-key', pattern: /\\bAKIA[0-9A-Z]{16}\\b/g },\n { id: 'bearer', pattern: /\\bBearer\\s+[A-Za-z0-9._~+/=-]{10,}/gi },\n { id: 'sk-key', pattern: /\\bsk-[A-Za-z0-9_-]{10,}\\b/g },\n {\n id: 'private-key-block',\n pattern: /-----BEGIN (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\\s\\S]*?-----END[^-]*-----/g,\n },\n]\n\nexport const REDACTION_VERSION = '1.0.0'\n\n/**\n * Redact a single string. Returns the new string and a per-rule count of\n * how many substitutions fired.\n */\nexport function redactString(\n input: string,\n rules: RedactionRule[] = DEFAULT_REDACTION_RULES,\n): { output: string; report: RedactionReport } {\n const byRule: Record<string, number> = {}\n let redactionCount = 0\n let output = input\n for (const rule of rules) {\n let hits = 0\n output = output.replace(rule.pattern, () => {\n hits++\n return rule.replacement ?? `[redacted:${rule.id}]`\n })\n if (hits > 0) {\n byRule[rule.id] = hits\n redactionCount += hits\n }\n }\n return { output, report: { redactionCount, byRule } }\n}\n\n/**\n * Walk a JSON-ish value applying `redactString` to every string leaf.\n * Arrays and plain objects are recursed; other types pass through\n * untouched. Circular references throw — traces should be tree-shaped.\n */\nexport function redactValue(\n value: unknown,\n rules: RedactionRule[] = DEFAULT_REDACTION_RULES,\n report: RedactionReport = { redactionCount: 0, byRule: {} },\n): { value: unknown; report: RedactionReport } {\n if (typeof value === 'string') {\n const { output, report: r } = redactString(value, rules)\n report.redactionCount += r.redactionCount\n for (const [k, v] of Object.entries(r.byRule)) {\n report.byRule[k] = (report.byRule[k] ?? 0) + v\n }\n return { value: output, report }\n }\n if (Array.isArray(value)) {\n return {\n value: value.map((v) => redactValue(v, rules, report).value),\n report,\n }\n }\n if (value !== null && typeof value === 'object') {\n const next: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value)) {\n next[k] = redactValue(v, rules, report).value\n }\n return { value: next, report }\n }\n return { value, report }\n}\n","/**\n * Replay-from-raw-events — turn every captured campaign run into a\n * re-runnable artifact.\n *\n * `RawProviderSink` captures every provider HTTP envelope; `runEvalCampaign`\n * makes that capture the default. Together they make every past run a\n * complete fingerprint of what happened on the wire — enough to replay\n * the run without burning new LLM cost.\n *\n * Three use cases this primitive enables:\n *\n * 1. **Post-hoc judging** — apply a new judge / rubric / scoring callback\n * to last week's runs without re-calling any LLM. The cost of trying\n * a new rubric drops from \"another full sweep\" to a CPU-bound replay.\n * 2. **Determinism audits** — replay the same campaign and verify the\n * raw responses match byte-for-byte. Any drift is a non-determinism\n * bug (in the harness, the prompt builder, the sandbox, …).\n * 3. **Free judge calibration** — run two judges on identical responses\n * and measure inter-judge agreement without doubling LLM spend.\n *\n * The interface is deliberately fetch-shaped. Inject `createReplayFetch`\n * into `LlmClientOptions.fetch` and every `callLlm` transparently reads\n * from the cache instead of calling the network. No new code path through\n * the LLM client is needed; the cache hit is invisible to the runner.\n */\n\nimport { ReplayError } from './errors'\nimport { canonicalize, hashJson } from './pre-registration'\nimport type { RawProviderEvent, RawProviderSink } from './trace/raw-provider-sink'\n\nexport class ReplayCacheMissError extends ReplayError {\n constructor(\n public readonly url: string,\n public readonly requestKey: string,\n message?: string,\n ) {\n super(message ?? `replay cache miss for ${url} (key=${requestKey})`)\n }\n}\n\nexport interface ReplayCacheEntry {\n request: RawProviderEvent\n response: RawProviderEvent\n}\n\nexport interface ReplayCacheStats {\n total: number\n byProvider: Record<string, number>\n byModel: Record<string, number>\n /** Spans for which we have a request but no response (run aborted mid-call). */\n orphanRequests: number\n}\n\n/**\n * In-memory deterministic cache of (request → response) keyed on a stable\n * hash of the request body. Built from a `RawProviderSink` containing\n * paired `request` and `response` events from a previous run.\n *\n * The cache is the source of truth for replay; `createReplayFetch` is a\n * thin wrapper that reads from it.\n */\nexport class ReplayCache {\n private byKey = new Map<string, ReplayCacheEntry>()\n private orphans = 0\n private byProvider: Record<string, number> = {}\n private byModel: Record<string, number> = {}\n\n /**\n * Build a cache from a sink's events. The sink must implement `list()`.\n * Filter by `runId` / `spanId` to scope to a specific replay.\n */\n static async fromSink(\n sink: RawProviderSink,\n filter: { runId?: string; spanId?: string } = {},\n ): Promise<ReplayCache> {\n if (!sink.list) {\n throw new ReplayError('ReplayCache.fromSink: sink must implement list() to be replayable.')\n }\n const events = await sink.list(filter)\n return ReplayCache.fromEvents(events)\n }\n\n /** Build a cache from an in-memory event list. */\n static async fromEvents(events: RawProviderEvent[]): Promise<ReplayCache> {\n const cache = new ReplayCache()\n // Group by (runId, spanId, attemptIndex) so request/response/error pairs are matched.\n // A cell can have many spans; each retry attempt within a span is a separate group.\n type GroupKey = string\n const groups = new Map<GroupKey, { req?: RawProviderEvent; res?: RawProviderEvent }>()\n for (const e of events) {\n const k = `${e.runId ?? ''}::${e.spanId ?? ''}::${e.attemptIndex}`\n const g = groups.get(k) ?? {}\n if (e.direction === 'request') g.req = e\n else g.res = e\n groups.set(k, g)\n }\n for (const g of groups.values()) {\n if (!g.req) continue\n if (!g.res) {\n cache.orphans += 1\n continue\n }\n const key = await requestKey(g.req)\n cache.byKey.set(key, { request: g.req, response: g.res })\n cache.byProvider[g.req.provider] = (cache.byProvider[g.req.provider] ?? 0) + 1\n cache.byModel[g.req.model] = (cache.byModel[g.req.model] ?? 0) + 1\n }\n return cache\n }\n\n /** Number of cacheable (request, response) pairs in the cache. */\n size(): number {\n return this.byKey.size\n }\n\n stats(): ReplayCacheStats {\n return {\n total: this.byKey.size,\n byProvider: { ...this.byProvider },\n byModel: { ...this.byModel },\n orphanRequests: this.orphans,\n }\n }\n\n /** Iterate every cached `(request, response)` pair in insertion order. */\n *entries(): IterableIterator<ReplayCacheEntry> {\n for (const entry of this.byKey.values()) yield entry\n }\n\n /**\n * Look up a cached response by hashing the (model, messages, temperature,\n * maxTokens, response_format) shape. Returns `undefined` on miss; the\n * caller decides whether to throw, fall back to the network, or skip.\n */\n async lookup(requestBody: unknown): Promise<ReplayCacheEntry | undefined> {\n const key = await keyFromBody(requestBody)\n return this.byKey.get(key)\n }\n}\n\nexport interface ReplayFetchOptions {\n /**\n * Behaviour on cache miss. Default `'throw'`. `'fallback'` calls the\n * `fallbackFetch` (typically `globalThis.fetch`) so a partial replay can\n * still complete; `'fail-closed'` returns a synthetic 599 response so the\n * call site sees a non-retriable failure.\n */\n onMiss?: 'throw' | 'fallback' | 'fail-closed'\n fallbackFetch?: typeof fetch\n /** Optional callback fired once per replayed call (for telemetry / counters). */\n onHit?: (info: { url: string; provider: string; model: string }) => void\n /** Optional callback fired on cache miss before the `onMiss` policy applies. */\n onMissNotify?: (info: { url: string; requestBody: unknown }) => void\n}\n\n/**\n * Build a `fetch`-shaped function that serves cached responses out of a\n * `ReplayCache` for any URL ending in `/chat/completions`. Pass through\n * `LlmClientOptions.fetch` and `callLlm` becomes free.\n *\n * Non-`/chat/completions` URLs are passed straight to the fallback fetch\n * (default: `globalThis.fetch`). This matters because non-LLM HTTP work\n * (judge HTTP servers, sandbox callbacks) sometimes flows through the same\n * `fetch` and shouldn't be intercepted.\n */\nexport function createReplayFetch(cache: ReplayCache, opts: ReplayFetchOptions = {}): typeof fetch {\n const onMiss = opts.onMiss ?? 'throw'\n const fallback = opts.fallbackFetch ?? globalThis.fetch?.bind(globalThis)\n\n return (async (input: RequestInfo | URL, init?: RequestInit) => {\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url\n if (!/\\/chat\\/completions(?:[?#].*)?$/.test(url)) {\n if (!fallback)\n throw new ReplayError(\n `replay fetch: non-completions URL ${url} but no fallbackFetch configured`,\n )\n return fallback(input as RequestInfo, init)\n }\n let bodyParsed: unknown\n if (init?.body && typeof init.body === 'string') {\n try {\n bodyParsed = JSON.parse(init.body)\n } catch {\n /* raw body, not JSON */\n }\n }\n const hit = bodyParsed === undefined ? undefined : await cache.lookup(bodyParsed)\n if (hit) {\n opts.onHit?.({ url, provider: hit.request.provider, model: hit.request.model })\n const status = hit.response.statusCode ?? 200\n const headers = new Headers(\n Object.entries(hit.response.responseHeaders ?? { 'Content-Type': 'application/json' }),\n )\n const bodyText =\n typeof hit.response.responseBody === 'string'\n ? hit.response.responseBody\n : JSON.stringify(hit.response.responseBody ?? {})\n return new Response(bodyText, { status, headers })\n }\n opts.onMissNotify?.({ url, requestBody: bodyParsed })\n if (onMiss === 'throw') {\n const key = bodyParsed === undefined ? '<unparseable>' : await keyFromBody(bodyParsed)\n throw new ReplayCacheMissError(url, key)\n }\n if (onMiss === 'fail-closed') {\n return new Response(JSON.stringify({ error: 'replay_cache_miss' }), { status: 599 })\n }\n if (!fallback)\n throw new ReplayError('replay fetch: onMiss=fallback but no fallbackFetch configured')\n return fallback(input as RequestInfo, init)\n }) as typeof fetch\n}\n\n/**\n * Convenience iterator over `(request, response)` pairs in a sink — for\n * post-hoc scoring that doesn't need a `fetch` shim. The judge or scorer\n * runs purely in-process over cached LLM outputs.\n */\nexport async function* iterateRawCalls(\n sink: RawProviderSink,\n filter: { runId?: string; spanId?: string } = {},\n): AsyncGenerator<ReplayCacheEntry> {\n if (!sink.list) {\n throw new ReplayError('iterateRawCalls: sink must implement list().')\n }\n const events = await sink.list(filter)\n const cache = await ReplayCache.fromEvents(events)\n for (const entry of cache.entries()) yield entry\n}\n\n// ── Hashing ──────────────────────────────────────────────────────────────\n\n/**\n * Canonical request key.\n *\n * `model + messages + temperature + max_tokens|max_completion_tokens +\n * response_format` are the dimensions that affect the response shape.\n * Other fields (timestamp headers, provider-specific metadata) are\n * intentionally excluded so a request hashes the same across re-runs.\n */\nasync function requestKey(event: RawProviderEvent): Promise<string> {\n return keyFromBody(event.requestBody)\n}\n\nasync function keyFromBody(body: unknown): Promise<string> {\n if (body == null || typeof body !== 'object') return hashJson({ raw: String(body) })\n const b = body as Record<string, unknown>\n const reduced = canonicalize({\n model: b.model ?? null,\n messages: b.messages ?? null,\n temperature: b.temperature ?? null,\n max_tokens: b.max_tokens ?? null,\n max_completion_tokens: b.max_completion_tokens ?? null,\n response_format: b.response_format ?? null,\n })\n return hashJson(reduced)\n}\n"],"mappings":"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","names":["f","f","f","stat","requestKey"]}
@@ -50,4 +50,4 @@ export {
50
50
  verifyManifest,
51
51
  evaluateHypothesis
52
52
  };
53
- //# sourceMappingURL=chunk-4F5DQN55.js.map
53
+ //# sourceMappingURL=chunk-VSMTAMNK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pre-registration.ts"],"sourcesContent":["/**\n * Pre-registered hypotheses — declare what you're testing BEFORE the\n * run, check it AFTER. Prevents p-hacking, optional stopping, and the\n * \"we ran until it looked good\" failure mode.\n *\n * Manifest is a plain JSON-friendly object. Sign it with a content hash\n * + timestamp; the registered record becomes immutable. Post-run,\n * evaluate the manifest against observed results — the library refuses\n * to let you re-interpret a different metric as the declared one.\n */\n\nexport interface HypothesisManifest {\n id: string\n /** Human prose — goes into the audit trail. */\n hypothesis: string\n /** Metric the hypothesis claims to move. */\n metric: string\n /** 'increase' = candidate should score higher than baseline; 'decrease' = lower. */\n direction: 'increase' | 'decrease'\n /** Minimum effect size to count (same units as the metric). */\n minEffect: number\n /** Alpha threshold. */\n alpha: number\n /** Target statistical power at which sample size was pre-computed. */\n power: number\n /** Declared N per arm before running. */\n preRegisteredN: number\n /** ISO8601 timestamp the manifest was registered. */\n registeredAt: string\n /** Optional identifiers to tie into the trace corpus. */\n baselineLabel?: string\n candidateLabel?: string\n}\n\n/**\n * Identifier for the hashing scheme used to produce `contentHash`.\n *\n * `'sha256-content'` — sha256 hex over the canonicalized manifest with\n * the `contentHash` and `algo` fields stripped. Held as a string union\n * so future schemes can be added without breaking parsers; SignedManifest\n * values without `algo` deserialize cleanly because the field is optional.\n */\nexport type SignedManifestAlgo = 'sha256-content'\n\nexport interface SignedManifest extends HypothesisManifest {\n /** sha256 hex of canonicalized manifest (everything except contentHash and algo). */\n contentHash: string\n /**\n * Algorithm string describing how `contentHash` was produced.\n *\n * Optional on the type so serialized manifests without it still parse,\n * but ALWAYS populated by {@link signManifest}. Consumers that want to\n * enforce a known algorithm should reject manifests where this field\n * is missing or unrecognized.\n */\n algo?: SignedManifestAlgo\n}\n\nexport interface HypothesisResult {\n manifest: SignedManifest\n observedN: number\n observedEffect: number\n observedPValue: number\n /** True iff the observed effect hits the pre-declared direction with\n * magnitude ≥ minEffect AND p < alpha. */\n confirmed: boolean\n /** Enumerated reasons the hypothesis was rejected (each a machine-tag). */\n rejectionReasons: Array<\n 'wrong_direction' | 'effect_too_small' | 'not_significant' | 'undersampled'\n >\n notes?: string\n}\n\n/**\n * Deterministic JSON canonicalization — sort object keys recursively.\n *\n * Two semantically-equal objects produce byte-identical canonicalized output;\n * this is what makes a content-hash stable across encoders, key insertion\n * orders, and runtime versions. Exported for any consumer that needs the same\n * canonicalization guarantee outside the manifest-signing path (e.g., signing\n * an artifact bundle, hashing a dataset version, etc.).\n */\nexport function canonicalize(v: unknown): unknown {\n if (v === null || typeof v !== 'object') return v\n if (Array.isArray(v)) return v.map(canonicalize)\n const keys = Object.keys(v as Record<string, unknown>).sort()\n const out: Record<string, unknown> = {}\n for (const k of keys) out[k] = canonicalize((v as Record<string, unknown>)[k])\n return out\n}\n\n/**\n * SHA-256 hex (full 64 chars) over the canonicalized JSON encoding of `obj`.\n *\n * The same primitive `signManifest` and `verifyManifest` are built on, exposed\n * directly so consumers signing arbitrary structured content (artifact bundles,\n * production packets, dataset manifests, etc.) don't have to re-derive\n * canonicalize+sha256 from scratch.\n *\n * Stable across:\n * - object key insertion order (canonicalization sorts keys recursively)\n * - encoder choice (UTF-8 via TextEncoder, fixed)\n * - runtime (uses the Web Crypto subtle digest, present in Node ≥18 and browsers)\n *\n * Named `hashJson` to disambiguate from `prompt-registry.ts`'s `hashContent`,\n * which takes a string input and returns a truncated 12-char prompt id.\n * Use `hashJson` when you mean \"canonicalize then hash.\"\n *\n * @example\n * const hash = await hashJson({ id: '1', kind: 'spec' })\n * // 'a3f1...' (64 hex chars)\n */\nexport async function hashJson<T>(obj: T): Promise<string> {\n const canonical = canonicalize(obj)\n const bytes = new TextEncoder().encode(JSON.stringify(canonical))\n const digest = await globalThis.crypto.subtle.digest('SHA-256', bytes)\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Sign a manifest with a SHA-256 content hash.\n *\n * The hash covers the canonicalized manifest with the `contentHash`\n * and `algo` fields stripped; this lets verifiers re-sign the rest and\n * compare. Returned manifest always carries `algo: 'sha256-content'`\n * so downstream consumers can identify the scheme; manifests without\n * `algo` still verify because it is stripped before hashing on both sides.\n */\nexport async function signManifest(m: HypothesisManifest): Promise<SignedManifest> {\n const hash = await hashJson(m)\n return { ...m, contentHash: hash, algo: 'sha256-content' }\n}\n\n/**\n * Verify that a signed manifest has not been tampered with.\n *\n * Strips `contentHash` and `algo` before re-signing so manifests without\n * `algo` verify identically to ones that carry it.\n */\nexport async function verifyManifest(m: SignedManifest): Promise<boolean> {\n const { contentHash, algo: _algo, ...rest } = m\n void _algo\n const resigned = await signManifest(rest)\n return resigned.contentHash === contentHash\n}\n\n/**\n * Evaluate a pre-registered hypothesis against observed results.\n * Mechanical — no re-interpretation permitted.\n */\nexport async function evaluateHypothesis(\n manifest: SignedManifest,\n observed: { n: number; effect: number; pValue: number },\n): Promise<HypothesisResult> {\n if (!(await verifyManifest(manifest))) {\n throw new Error('evaluateHypothesis: manifest content hash mismatch (tampered)')\n }\n const reasons: HypothesisResult['rejectionReasons'] = []\n const directionOk = manifest.direction === 'increase' ? observed.effect > 0 : observed.effect < 0\n if (!directionOk) reasons.push('wrong_direction')\n if (Math.abs(observed.effect) < manifest.minEffect) reasons.push('effect_too_small')\n if (observed.pValue >= manifest.alpha) reasons.push('not_significant')\n if (observed.n < manifest.preRegisteredN) reasons.push('undersampled')\n return {\n manifest,\n observedN: observed.n,\n observedEffect: observed.effect,\n observedPValue: observed.pValue,\n confirmed: reasons.length === 0,\n rejectionReasons: reasons,\n }\n}\n"],"mappings":";AAkFO,SAAS,aAAa,GAAqB;AAChD,MAAI,MAAM,QAAQ,OAAO,MAAM,SAAU,QAAO;AAChD,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,IAAI,YAAY;AAC/C,QAAM,OAAO,OAAO,KAAK,CAA4B,EAAE,KAAK;AAC5D,QAAM,MAA+B,CAAC;AACtC,aAAW,KAAK,KAAM,KAAI,CAAC,IAAI,aAAc,EAA8B,CAAC,CAAC;AAC7E,SAAO;AACT;AAuBA,eAAsB,SAAY,KAAyB;AACzD,QAAM,YAAY,aAAa,GAAG;AAClC,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,SAAS,CAAC;AAChE,QAAM,SAAS,MAAM,WAAW,OAAO,OAAO,OAAO,WAAW,KAAK;AACrE,SAAO,MAAM,KAAK,IAAI,WAAW,MAAM,CAAC,EACrC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACZ;AAWA,eAAsB,aAAa,GAAgD;AACjF,QAAM,OAAO,MAAM,SAAS,CAAC;AAC7B,SAAO,EAAE,GAAG,GAAG,aAAa,MAAM,MAAM,iBAAiB;AAC3D;AAQA,eAAsB,eAAe,GAAqC;AACxE,QAAM,EAAE,aAAa,MAAM,OAAO,GAAG,KAAK,IAAI;AAC9C,OAAK;AACL,QAAM,WAAW,MAAM,aAAa,IAAI;AACxC,SAAO,SAAS,gBAAgB;AAClC;AAMA,eAAsB,mBACpB,UACA,UAC2B;AAC3B,MAAI,CAAE,MAAM,eAAe,QAAQ,GAAI;AACrC,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,QAAM,UAAgD,CAAC;AACvD,QAAM,cAAc,SAAS,cAAc,aAAa,SAAS,SAAS,IAAI,SAAS,SAAS;AAChG,MAAI,CAAC,YAAa,SAAQ,KAAK,iBAAiB;AAChD,MAAI,KAAK,IAAI,SAAS,MAAM,IAAI,SAAS,UAAW,SAAQ,KAAK,kBAAkB;AACnF,MAAI,SAAS,UAAU,SAAS,MAAO,SAAQ,KAAK,iBAAiB;AACrE,MAAI,SAAS,IAAI,SAAS,eAAgB,SAAQ,KAAK,cAAc;AACrE,SAAO;AAAA,IACL;AAAA,IACA,WAAW,SAAS;AAAA,IACpB,gBAAgB,SAAS;AAAA,IACzB,gBAAgB,SAAS;AAAA,IACzB,WAAW,QAAQ,WAAW;AAAA,IAC9B,kBAAkB;AAAA,EACpB;AACF;","names":[]}
@@ -974,4 +974,4 @@ export {
974
974
  createApp,
975
975
  startServer
976
976
  };
977
- //# sourceMappingURL=chunk-5LBB5B3Z.js.map
977
+ //# sourceMappingURL=chunk-XFZCM5Z3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wire/schemas.ts","../src/wire/rubrics.ts","../src/wire/handlers.ts","../src/wire/openapi.ts","../src/wire/rpc.ts","../src/wire/server.ts"],"sourcesContent":["/**\n * Wire-protocol schemas.\n *\n * These Zod schemas are the contract between the agent-eval runtime and\n * any non-TypeScript client (Python, Rust, Go, …). They get rendered to\n * OpenAPI by `wire/openapi.ts` and code-generators consume that spec to\n * produce typed clients in other languages.\n *\n * Rule: if it's not in this file, it isn't on the wire. Keep names and\n * shapes self-explanatory — every field has a `.describe()` so the\n * generated docs are useful without reading the source.\n */\nimport { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi'\nimport { z } from 'zod'\n\nextendZodWithOpenApi(z)\n\n// ── Building blocks ─────────────────────────────────────────────────\n\nexport const RubricDimensionSchema = z\n .object({\n id: z\n .string()\n .min(1)\n .describe('Short stable id like \"buyer_quality\" — used as the key in scoring output.'),\n description: z\n .string()\n .min(1)\n .describe('One-line plain-English meaning. Read by humans reviewing low scores.'),\n weight: z\n .number()\n .min(0)\n .default(1)\n .describe('Relative weight in the composite score. Default 1; 0 disables.'),\n min: z.number().default(0).describe('Lower bound of valid score for this dimension.'),\n max: z.number().default(1).describe('Upper bound of valid score for this dimension.'),\n })\n .openapi('RubricDimension')\n\nexport const FailureModeSchema = z\n .object({\n id: z.string().min(1).describe('Short stable id like \"ai-cadence\" — used in detection lists.'),\n description: z.string().min(1).describe('Plain-English description of the failure pattern.'),\n })\n .openapi('FailureMode')\n\n// ── Rubric ──────────────────────────────────────────────────────────\n\nexport const RubricSchema = z\n .object({\n name: z\n .string()\n .min(1)\n .describe('Stable name like \"anti-slop\" — used by clients to invoke this rubric.'),\n description: z\n .string()\n .min(1)\n .describe('What this rubric measures. Shown in /v1/rubrics listing.'),\n systemPrompt: z\n .string()\n .min(1)\n .describe(\n 'Instructs the judging LLM. Should explain the persona (e.g. \"senior engineer reviewing voice\"), what to score on, and what to return.',\n ),\n dimensions: z\n .array(RubricDimensionSchema)\n .min(1)\n .describe('Scoring axes. The composite score is a weighted sum of these.'),\n failureModes: z\n .array(FailureModeSchema)\n .default([])\n .describe('Patterns to detect; each detected mode appears in the result.failureModes list.'),\n wins: z\n .array(FailureModeSchema)\n .default([])\n .describe('Positive patterns; each detected one appears in the result.wins list.'),\n })\n .openapi('Rubric')\n\n// ── Judge call ──────────────────────────────────────────────────────\n\nexport const JudgeRequestSchema = z\n .object({\n rubricName: z\n .string()\n .optional()\n .describe('Use a built-in rubric by name. Mutually exclusive with `rubric`.'),\n rubric: RubricSchema.optional().describe(\n 'Inline rubric definition. Mutually exclusive with `rubricName`.',\n ),\n content: z\n .string()\n .min(1)\n .describe('The text being judged — a tweet, a blog post, a code snippet, anything stringly.'),\n context: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Free-form metadata for the rubric to use — analytics, source URL, author, etc. Surfaced to the LLM.',\n ),\n model: z\n .string()\n .optional()\n .describe('Override the judge model (default routes via tcloud). e.g. \"claude-opus-4-7\".'),\n })\n .refine((v) => Boolean(v.rubricName) !== Boolean(v.rubric), {\n message: 'Provide exactly one of `rubricName` or `rubric`.',\n })\n .openapi('JudgeRequest')\n\nexport const JudgeResultSchema = z\n .object({\n composite: z\n .number()\n .min(0)\n .max(1)\n .describe('Weighted combination of dimension scores in 0..1. The single number to gate on.'),\n dimensions: z\n .record(z.string(), z.number())\n .describe('Per-dimension score, keyed by RubricDimension.id.'),\n failureModes: z\n .array(z.string())\n .default([])\n .describe('Failure-mode ids detected in the content (subset of rubric.failureModes ids).'),\n wins: z\n .array(z.string())\n .default([])\n .describe('Win ids detected in the content (subset of rubric.wins ids).'),\n rationale: z\n .string()\n .describe('Plain-English explanation of the score. Surfaced to the human reviewer.'),\n rubricVersion: z\n .string()\n .describe(\n 'Stable hash of the rubric used. Scores are only comparable across runs when this matches.',\n ),\n model: z.string().describe('Model that produced the judgement, for reproducibility.'),\n durationMs: z.number().int().nonnegative().describe('End-to-end wall time for this call.'),\n })\n .openapi('JudgeResult')\n\n// ── Rubric listing ──────────────────────────────────────────────────\n\nexport const RubricInfoSchema = z\n .object({\n name: z.string().describe('Pass this to /v1/judge as `rubricName`.'),\n description: z.string().describe('What this rubric measures.'),\n dimensions: z\n .array(z.object({ id: z.string(), description: z.string(), weight: z.number() }))\n .describe('The scoring axes this rubric uses, with weights.'),\n failureModes: z.array(z.string()).default([]).describe('Failure-mode ids this rubric detects.'),\n rubricVersion: z.string().describe('Stable hash — match this to compare scores across runs.'),\n })\n .openapi('RubricInfo')\n\nexport const ListRubricsResponseSchema = z\n .object({\n rubrics: z.array(RubricInfoSchema),\n })\n .openapi('ListRubricsResponse')\n\n// ── Version / health ────────────────────────────────────────────────\n\nexport const VersionResponseSchema = z\n .object({\n package: z.string().describe('Package name (always \"@tangle-network/agent-eval\").'),\n version: z.string().describe('Semver of the running server. Match your client to this.'),\n wireVersion: z\n .string()\n .describe(\n 'Wire-protocol semver. Bumps separately from package version when the schema changes.',\n ),\n apiSurface: z.array(z.string()).describe('List of supported method names.'),\n })\n .openapi('VersionResponse')\n\nexport const HealthResponseSchema = z\n .object({\n status: z.literal('ok'),\n uptimeSec: z.number(),\n })\n .openapi('HealthResponse')\n\n// ── Ingestion: production traces + user feedback ────────────────────\n\n/**\n * Minimal `TraceEvent` shape that the production runtime emits.\n * Matches `trace/schema.ts` `TraceEvent` but is duplicated here as a\n * wire schema so non-TypeScript clients can validate without depending\n * on internal types.\n */\nexport const TraceEventSchema = z\n .object({\n eventId: z.string().min(1).describe('Stable id for the event. Use ULID or UUID.'),\n runId: z.string().min(1).describe('Run this event belongs to.'),\n spanId: z.string().optional().describe('Span that emitted the event, if any.'),\n kind: z\n .enum([\n 'log',\n 'error',\n 'budget_decrement',\n 'budget_breach',\n 'state_mutation',\n 'policy_violation',\n 'redaction_applied',\n 'custom',\n ])\n .describe('Coarse event category — matches the TraceSchema v1 EventKind enum.'),\n timestamp: z\n .number()\n .int()\n .nonnegative()\n .describe('Unix millis. Must be monotonically non-decreasing within a span.'),\n payload: z\n .record(z.string(), z.unknown())\n .describe('Free-form payload — the runtime owns the shape.'),\n })\n .openapi('TraceEvent')\n\nexport const TracesIngestRequestSchema = z\n .object({\n events: z\n .array(TraceEventSchema)\n .min(1)\n .max(10_000)\n .describe('Batch of events. Max 10k per call — bigger streams should be chunked.'),\n })\n .openapi('TracesIngestRequest')\n\nexport const TracesIngestResponseSchema = z\n .object({\n accepted: z.number().int().nonnegative().describe('Number of events persisted.'),\n rejected: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of events the store refused — see `errors[]` for reasons.'),\n errors: z\n .array(\n z.object({\n eventId: z.string().describe('Event id this error applies to.'),\n message: z.string().describe('Why the event was rejected.'),\n }),\n )\n .default([]),\n })\n .openapi('TracesIngestResponse')\n\nexport const FeedbackLabelSchema = z\n .object({\n id: z.string().optional(),\n source: z.enum(['user', 'judge', 'environment', 'metric', 'policy', 'system']),\n kind: z.enum([\n 'approve',\n 'reject',\n 'select',\n 'edit',\n 'rank',\n 'rate',\n 'comment',\n 'metric_outcome',\n 'policy_block',\n 'revision_request',\n ]),\n value: z.unknown(),\n reason: z.string().optional(),\n severity: z.enum(['info', 'warning', 'error', 'critical']).optional(),\n createdAt: z.string().describe('ISO-8601 UTC.'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('FeedbackLabel')\n\nexport const FeedbackAttemptSchema = z\n .object({\n id: z.string().min(1),\n stepIndex: z.number().int().nonnegative(),\n artifactType: z.enum([\n 'text',\n 'code',\n 'plan',\n 'research',\n 'action',\n 'ui',\n 'decision',\n 'data',\n 'other',\n ]),\n artifact: z.unknown(),\n options: z.array(z.unknown()).optional(),\n proposedAction: z\n .object({\n type: z.string(),\n risk: z.enum(['low', 'medium', 'high']).optional(),\n costUsd: z.number().optional(),\n externalSideEffect: z.boolean().optional(),\n requiresApproval: z.boolean().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n feedback: z.array(FeedbackLabelSchema).optional(),\n createdAt: z.string(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('FeedbackAttempt')\n\nexport const FeedbackTrajectorySchema = z\n .object({\n id: z.string().min(1).describe('Stable id; idempotency key for the trajectory.'),\n projectId: z.string().optional(),\n scenarioId: z.string().optional(),\n task: z.object({\n intent: z.string().min(1),\n context: z.unknown().optional(),\n }),\n attempts: z.array(FeedbackAttemptSchema).default([]),\n labels: z.array(FeedbackLabelSchema).default([]),\n outcome: z\n .object({\n success: z.boolean().optional(),\n score: z.number().optional(),\n metrics: z.record(z.string(), z.number()).optional(),\n costUsd: z.number().optional(),\n detail: z.string().optional(),\n observedAt: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n split: z.enum(['train', 'dev', 'test', 'holdout']).optional(),\n tags: z.record(z.string(), z.string()).optional(),\n createdAt: z.string().describe('ISO-8601 UTC.'),\n updatedAt: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('FeedbackTrajectory')\n\nexport const FeedbackIngestResponseSchema = z\n .object({\n id: z.string().describe('Trajectory id that was persisted.'),\n persisted: z.boolean().describe('True when the trajectory was saved (idempotent on id).'),\n })\n .openapi('FeedbackIngestResponse')\n\nexport type TraceEvent = z.infer<typeof TraceEventSchema>\nexport type TracesIngestRequest = z.infer<typeof TracesIngestRequestSchema>\nexport type TracesIngestResponse = z.infer<typeof TracesIngestResponseSchema>\nexport type FeedbackTrajectory = z.infer<typeof FeedbackTrajectorySchema>\nexport type FeedbackIngestResponse = z.infer<typeof FeedbackIngestResponseSchema>\n\n// ── Errors ──────────────────────────────────────────────────────────\n\nexport const ErrorResponseSchema = z\n .object({\n error: z\n .object({\n code: z\n .string()\n .describe(\n 'Machine-readable code: \"validation_error\", \"rubric_not_found\", \"judge_error\".',\n ),\n message: z.string().describe('Human-readable message.'),\n details: z.unknown().optional().describe('Optional structured detail.'),\n })\n .describe('Errors are always wrapped in this shape across all endpoints.'),\n })\n .openapi('ErrorResponse')\n\n// ── Type exports for callers in the same package ────────────────────\n\nexport type RubricDimension = z.infer<typeof RubricDimensionSchema>\nexport type FailureMode = z.infer<typeof FailureModeSchema>\nexport type Rubric = z.infer<typeof RubricSchema>\nexport type JudgeRequest = z.infer<typeof JudgeRequestSchema>\nexport type JudgeResult = z.infer<typeof JudgeResultSchema>\nexport type RubricInfo = z.infer<typeof RubricInfoSchema>\nexport type ListRubricsResponse = z.infer<typeof ListRubricsResponseSchema>\nexport type VersionResponse = z.infer<typeof VersionResponseSchema>\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>\n\n// ── Wire-protocol version ───────────────────────────────────────────\n\n/**\n * Bump on any breaking change to a request/response schema.\n * Non-breaking (additive) changes don't require a bump.\n */\nexport const WIRE_VERSION = '1.0.0'\n\n/**\n * Stable hash of a rubric. Used to make scores comparable across runs:\n * if the rubricVersion matches, the rubric was identical.\n */\nexport function hashRubric(rubric: Rubric): string {\n const stable = stableStringify(rubric)\n let h = 5381\n for (let i = 0; i < stable.length; i++) {\n h = (h * 33) ^ stable.charCodeAt(i)\n }\n // Unsigned 32-bit hex, prefixed with rubric name + version slot\n return `${rubric.name}@${(h >>> 0).toString(16).padStart(8, '0')}`\n}\n\nfunction stableStringify(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(',')}]`\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)\n return `{${entries.join(',')}}`\n }\n return JSON.stringify(value)\n}\n","/**\n * Built-in rubrics shipped with agent-eval.\n *\n * A rubric is a set of scoring axes plus a system prompt that tells the\n * judging LLM how to grade against those axes. Built-in rubrics are\n * curated for use cases that recur across Tangle projects — call them\n * by name from any client.\n *\n * Adding a rubric:\n * 1. Define the Rubric object below with a clear `description` and\n * named `dimensions`.\n * 2. Register it in `BUILTIN_RUBRICS` at the bottom.\n * 3. Add a test in `tests/wire/rubrics.test.ts`.\n *\n * Custom rubrics: callers pass `rubric` inline to /v1/judge instead of\n * `rubricName` — see schemas.ts.\n */\nimport type { Rubric } from './schemas'\nimport { hashRubric } from './schemas'\n\n// ── anti-slop ───────────────────────────────────────────────────────\n// Voice/style judge tuned for technical-buyer audiences. Used by the\n// Postiz autoresearch loop and any content-quality gate.\n\nconst ANTI_SLOP: Rubric = {\n name: 'anti-slop',\n description:\n 'Voice and signal quality for content aimed at senior engineers. Catches AI cadence, marketing tone, and engagement-bait shapes.',\n systemPrompt: `You are evaluating a piece of content written for senior engineers and technical founders.\n\nYou score three things:\n- buyer_quality (0..1): would a senior engineer in the target ICP find this worth their attention? High = specific, earned, technically interesting. Low = generic, hyped, off-target.\n- voice (0..1): does it read like a person who built the thing, or like AI/marketing copy?\n- signal (0..1): does it contain a non-obvious detail, constraint, or claim a reader couldn't get from the public docs?\n\nDetect failure modes (return ids matching):\n- ai-cadence: rule-of-three openings, em-dash flourish, \"Let me explain\", \"Here's the thing\", AI rhythm\n- marketing-tone: \"We're excited to announce\", \"thrilled\", \"delighted\", \"game-changer\", buzzword stack\n- vague-claim: technical claim without a specific component, file, or measurement\n- no-hook: opening doesn't earn attention from the target reader\n- engagement-bait: \"agree?\", \"thoughts?\", listicles, controversy-fishing, hook-detail-pitch\n- off-icp: content shape would attract motivational/grift/hype audiences instead of buyers\n- stale-claim: repeats a positioning line we've used many times this month\n\nDetect wins (return ids matching):\n- specific-component: names a real file, component, or measurement\n- earned-detail: shares a non-obvious detail not derivable from public docs\n- constraint-articulated: names a real tradeoff and the side chosen\n- honest-failure: describes a real failure mode and what was done about it\n\nReturn ONLY JSON matching the response schema. Be conservative — most content has 0-1 wins and 1-2 failure modes, not many of each.`,\n dimensions: [\n {\n id: 'buyer_quality',\n description: 'Would the target buyer find this worth attention?',\n weight: 0.5,\n min: 0,\n max: 1,\n },\n {\n id: 'voice',\n description: 'Does it sound like a builder, not AI or marketing?',\n weight: 0.3,\n min: 0,\n max: 1,\n },\n {\n id: 'signal',\n description: 'Non-obvious detail, constraint, or claim?',\n weight: 0.2,\n min: 0,\n max: 1,\n },\n ],\n failureModes: [\n { id: 'ai-cadence', description: 'AI-rhythm openings and transitions' },\n { id: 'marketing-tone', description: 'Buzzwords, hype, corporate-PR voice' },\n { id: 'vague-claim', description: 'Technical claim without specifics' },\n { id: 'no-hook', description: 'Opening fails to earn attention' },\n { id: 'engagement-bait', description: 'Listicle/controversy/agree-pattern' },\n { id: 'off-icp', description: 'Voice attracts the wrong audience' },\n { id: 'stale-claim', description: 'Reuses an over-used positioning line' },\n ],\n wins: [\n { id: 'specific-component', description: 'Names a real file/component/number' },\n { id: 'earned-detail', description: 'Detail not in public docs' },\n { id: 'constraint-articulated', description: 'Names a real tradeoff' },\n { id: 'honest-failure', description: 'Describes a real failure honestly' },\n ],\n}\n\n// ── Registry ────────────────────────────────────────────────────────\n\nexport const BUILTIN_RUBRICS: Record<string, Rubric> = {\n 'anti-slop': ANTI_SLOP,\n}\n\n/** Get a built-in rubric by name, or undefined. */\nexport function getBuiltinRubric(name: string): Rubric | undefined {\n return BUILTIN_RUBRICS[name]\n}\n\n/** List built-in rubrics with their stable versions. */\nexport function listBuiltinRubrics() {\n return Object.values(BUILTIN_RUBRICS).map((r) => ({\n name: r.name,\n description: r.description,\n dimensions: r.dimensions.map((d) => ({\n id: d.id,\n description: d.description,\n weight: d.weight,\n })),\n failureModes: r.failureModes.map((f) => f.id),\n rubricVersion: hashRubric(r),\n }))\n}\n","/**\n * Pure handler functions — the \"business logic\" behind every wire-protocol\n * method. The HTTP server (`server.ts`) and the stdio RPC (`rpc.ts`) both\n * call these. Tests call these directly without spinning a server.\n *\n * Each handler:\n * - Takes a parsed request (already Zod-validated by the transport).\n * - Returns a result that matches the response schema.\n * - Throws `WireError` for caller-fixable errors (404, 400, 422).\n * - Lets unexpected errors bubble — the transport maps them to 500.\n */\nimport type { FeedbackTrajectoryStore } from '../feedback-trajectory'\nimport { callLlmJson } from '../llm-client'\nimport type { TraceEvent as InternalTraceEvent } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\nimport { getBuiltinRubric, listBuiltinRubrics } from './rubrics'\nimport {\n type FeedbackIngestResponse,\n hashRubric,\n type JudgeRequest,\n type JudgeResult,\n type ListRubricsResponse,\n type Rubric,\n type TracesIngestRequest,\n type TracesIngestResponse,\n type VersionResponse,\n WIRE_VERSION,\n type FeedbackTrajectory as WireFeedbackTrajectory,\n} from './schemas'\n\n/** Caller-fixable error. The transport renders this to 4xx + ErrorResponse. */\nexport class WireError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly status: number = 400,\n public readonly details?: unknown,\n ) {\n super(message)\n this.name = 'WireError'\n }\n}\n\n// ── judge ───────────────────────────────────────────────────────────\n\n/** The JSON schema we ask the judging LLM to fill in. */\nfunction judgeOutputSchema(rubric: Rubric) {\n return {\n name: 'JudgeOutput',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n dimensions: {\n type: 'object',\n additionalProperties: false,\n properties: Object.fromEntries(\n rubric.dimensions.map((d) => [\n d.id,\n { type: 'number', minimum: d.min, maximum: d.max },\n ]),\n ),\n required: rubric.dimensions.map((d) => d.id),\n },\n failureModes: {\n type: 'array',\n items: { type: 'string', enum: rubric.failureModes.map((f) => f.id) },\n },\n wins: {\n type: 'array',\n items: { type: 'string', enum: rubric.wins.map((w) => w.id) },\n },\n rationale: { type: 'string' },\n },\n required: ['dimensions', 'rationale'],\n } as Record<string, unknown>,\n }\n}\n\ninterface JudgeOutput {\n dimensions: Record<string, number>\n failureModes?: string[]\n wins?: string[]\n rationale: string\n}\n\nfunction validateJudgeOutput(value: unknown, rubric: Rubric): JudgeOutput {\n if (!value || typeof value !== 'object') {\n throw new WireError('judge_error', 'Judge returned malformed output.', 500, value)\n }\n const raw = value as Record<string, unknown>\n const rawDimensions = raw.dimensions\n if (!rawDimensions || typeof rawDimensions !== 'object' || Array.isArray(rawDimensions)) {\n throw new WireError('judge_error', 'Judge returned malformed dimensions.', 500, value)\n }\n\n const dimensions: Record<string, number> = {}\n const dimensionRecord = rawDimensions as Record<string, unknown>\n for (const dim of rubric.dimensions) {\n const score = dimensionRecord[dim.id]\n if (\n typeof score !== 'number' ||\n !Number.isFinite(score) ||\n score < dim.min ||\n score > dim.max\n ) {\n throw new WireError(\n 'judge_error',\n `Judge returned invalid score for dimension \"${dim.id}\".`,\n 500,\n value,\n )\n }\n dimensions[dim.id] = score\n }\n\n const allowedFailures = new Set(rubric.failureModes.map((mode) => mode.id))\n const allowedWins = new Set(rubric.wins.map((win) => win.id))\n const failureModes = validateIdArray(raw.failureModes, allowedFailures, 'failureModes', value)\n const wins = validateIdArray(raw.wins, allowedWins, 'wins', value)\n if (typeof raw.rationale !== 'string' || raw.rationale.trim().length === 0) {\n throw new WireError('judge_error', 'Judge returned missing rationale.', 500, value)\n }\n\n return { dimensions, failureModes, wins, rationale: raw.rationale }\n}\n\nfunction validateIdArray(\n raw: unknown,\n allowed: Set<string>,\n field: 'failureModes' | 'wins',\n original: unknown,\n): string[] {\n if (raw === undefined) return []\n if (!Array.isArray(raw)) {\n throw new WireError('judge_error', `Judge returned non-array ${field}.`, 500, original)\n }\n const out: string[] = []\n for (const item of raw) {\n if (typeof item !== 'string' || !allowed.has(item)) {\n throw new WireError(\n 'judge_error',\n `Judge returned unknown ${field} id \"${String(item)}\".`,\n 500,\n original,\n )\n }\n out.push(item)\n }\n return out\n}\n\nfunction compositeScore(dimensions: Record<string, number>, rubric: Rubric): number {\n let weighted = 0\n let totalWeight = 0\n for (const dim of rubric.dimensions) {\n const raw = dimensions[dim.id] ?? 0\n const range = dim.max - dim.min || 1\n const normalized = Math.max(0, Math.min(1, (raw - dim.min) / range))\n weighted += normalized * dim.weight\n totalWeight += dim.weight\n }\n return totalWeight > 0 ? weighted / totalWeight : 0\n}\n\nfunction buildJudgePrompt(content: string, context: unknown): string {\n const ctx = context && Object.keys(context as object).length ? JSON.stringify(context) : ''\n return [\n `CONTENT TO JUDGE:`,\n content,\n '',\n ctx ? `CONTEXT (metadata, analytics, etc.):` : '',\n ctx ? ctx : '',\n ]\n .filter(Boolean)\n .join('\\n')\n}\n\nconst DEFAULT_JUDGE_MODEL = 'claude-sonnet-4-6'\n\nexport async function handleJudge(req: JudgeRequest): Promise<JudgeResult> {\n // Resolve rubric\n let rubric: Rubric\n if (req.rubricName) {\n const found = getBuiltinRubric(req.rubricName)\n if (!found) {\n throw new WireError('rubric_not_found', `No built-in rubric named \"${req.rubricName}\".`, 404)\n }\n rubric = found\n } else if (req.rubric) {\n rubric = req.rubric\n } else {\n // refine() in the schema should already have caught this — defense in depth\n throw new WireError('validation_error', 'Provide either `rubricName` or `rubric`.', 422)\n }\n\n const startedAt = Date.now()\n const model = req.model ?? DEFAULT_JUDGE_MODEL\n\n const { value, result } = await callLlmJson<JudgeOutput>({\n model,\n messages: [\n { role: 'system', content: rubric.systemPrompt },\n { role: 'user', content: buildJudgePrompt(req.content, req.context) },\n ],\n jsonSchema: judgeOutputSchema(rubric),\n temperature: 0.0,\n timeoutMs: 60_000,\n })\n\n const output = validateJudgeOutput(value, rubric)\n\n const composite = compositeScore(output.dimensions, rubric)\n const durationMs = Date.now() - startedAt\n\n return {\n composite,\n dimensions: output.dimensions,\n failureModes: output.failureModes ?? [],\n wins: output.wins ?? [],\n rationale: output.rationale,\n rubricVersion: hashRubric(rubric),\n model: result.model,\n durationMs,\n }\n}\n\n// ── listRubrics ─────────────────────────────────────────────────────\n\nexport function handleListRubrics(): ListRubricsResponse {\n return { rubrics: listBuiltinRubrics() }\n}\n\n// ── version ─────────────────────────────────────────────────────────\n\nimport { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nlet CACHED_VERSION: string | undefined\n\nfunction readPackageVersion(): string {\n if (CACHED_VERSION) return CACHED_VERSION\n // Walk up from this file looking for the nearest package.json.\n // In dist/ this is dist/.., in src/wire/ this is ../../package.json.\n const here = dirname(fileURLToPath(import.meta.url))\n const candidates = [\n resolve(here, '..', '..', 'package.json'), // src/wire → repo root\n resolve(here, '..', 'package.json'), // dist → repo root\n ]\n for (const path of candidates) {\n try {\n const pkg = JSON.parse(readFileSync(path, 'utf-8')) as { version?: string }\n if (pkg.version) {\n CACHED_VERSION = pkg.version\n return pkg.version\n }\n } catch {\n // try next\n }\n }\n return '0.0.0-unknown'\n}\n\nexport function handleVersion(): VersionResponse {\n return {\n package: '@tangle-network/agent-eval',\n version: readPackageVersion(),\n wireVersion: WIRE_VERSION,\n apiSurface: ['judge', 'listRubrics', 'version', 'feedback.ingest', 'traces.ingest'],\n }\n}\n\n// ── Ingestion handlers ───────────────────────────────────────────────\n\n/**\n * Pluggable stores the wire layer routes ingestion writes into. Both\n * are optional — when omitted, the corresponding endpoint returns 503.\n *\n * Production deployments wire a `FileSystemTraceStore` and\n * `FileSystemFeedbackTrajectoryStore` here. Tests substitute in-memory\n * stores.\n */\nexport interface IngestionStores {\n traceStore?: TraceStore\n feedbackStore?: FeedbackTrajectoryStore\n}\n\n/**\n * `POST /v1/traces/ingest` — accept a batch of `TraceEvent`s from the\n * production runtime. Best-effort: each event is appended independently;\n * one bad event does not poison the batch.\n *\n * Idempotency: the underlying store is append-only; consumers retrying\n * the same payload will get duplicate events. Consumers should\n * de-duplicate by `eventId` downstream — production traces frequently\n * land via at-least-once buses (Kafka, SQS) where dedup is unavoidable.\n */\nexport async function handleTracesIngest(\n req: TracesIngestRequest,\n stores: IngestionStores,\n): Promise<TracesIngestResponse> {\n if (!stores.traceStore) {\n throw new WireError(\n 'service_unavailable',\n 'No trace store configured on this server. Pass `traceStore` to `createApp`.',\n 503,\n )\n }\n const errors: Array<{ eventId: string; message: string }> = []\n let accepted = 0\n for (const event of req.events) {\n try {\n // The wire `TraceEvent` is structurally identical to the internal one.\n await stores.traceStore.appendEvent(event as InternalTraceEvent)\n accepted++\n } catch (err) {\n errors.push({\n eventId: event.eventId,\n message: err instanceof Error ? err.message : String(err),\n })\n }\n }\n return { accepted, rejected: errors.length, errors }\n}\n\n/**\n * `POST /v1/feedback` — accept a single `FeedbackTrajectory` from the\n * production runtime. Idempotent on `id`: re-posting the same trajectory\n * replaces the prior record.\n */\nexport async function handleFeedbackIngest(\n req: WireFeedbackTrajectory,\n stores: IngestionStores,\n): Promise<FeedbackIngestResponse> {\n if (!stores.feedbackStore) {\n throw new WireError(\n 'service_unavailable',\n 'No feedback store configured on this server. Pass `feedbackStore` to `createApp`.',\n 503,\n )\n }\n // The wire `FeedbackTrajectory` aligns 1:1 with the internal type;\n // cast through `unknown` since the wire schema is a Zod-inferred\n // structural type with optional fields the internal store consumes.\n await stores.feedbackStore.save(req as unknown as Parameters<FeedbackTrajectoryStore['save']>[0])\n return { id: req.id, persisted: true }\n}\n","/**\n * Build an OpenAPI spec from the wire schemas.\n *\n * The spec is the contract that other-language clients (Python, Rust,\n * Go, …) generate from. There is no hand-written client — clients are\n * derived artifacts of this file plus `schemas.ts`.\n *\n * Run `pnpm openapi` (defined in package.json) to write the spec to\n * `dist/openapi.json`. CI uses that file to regenerate the Python\n * client and gate the dual-publish workflow.\n */\nimport { OpenAPIRegistry, OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi'\nimport type { OpenAPIObject } from 'openapi3-ts/oas31'\n\nimport {\n ErrorResponseSchema,\n FeedbackIngestResponseSchema,\n FeedbackTrajectorySchema,\n HealthResponseSchema,\n JudgeRequestSchema,\n JudgeResultSchema,\n ListRubricsResponseSchema,\n TracesIngestRequestSchema,\n TracesIngestResponseSchema,\n VersionResponseSchema,\n WIRE_VERSION,\n} from './schemas'\n\nexport function buildOpenApi(packageVersion: string): OpenAPIObject {\n const registry = new OpenAPIRegistry()\n\n // Components — each schema becomes a $ref-able component\n registry.register('JudgeRequest', JudgeRequestSchema)\n registry.register('JudgeResult', JudgeResultSchema)\n registry.register('ListRubricsResponse', ListRubricsResponseSchema)\n registry.register('VersionResponse', VersionResponseSchema)\n registry.register('HealthResponse', HealthResponseSchema)\n registry.register('ErrorResponse', ErrorResponseSchema)\n registry.register('TracesIngestRequest', TracesIngestRequestSchema)\n registry.register('TracesIngestResponse', TracesIngestResponseSchema)\n registry.register('FeedbackTrajectory', FeedbackTrajectorySchema)\n registry.register('FeedbackIngestResponse', FeedbackIngestResponseSchema)\n\n // Routes\n registry.registerPath({\n method: 'post',\n path: '/v1/judge',\n summary: 'Score a piece of content against a rubric',\n description:\n 'Runs the judging LLM with the named (or inline) rubric and returns dimension scores, detected failure modes, wins, and a composite score in 0..1.',\n request: {\n body: {\n content: {\n 'application/json': { schema: JudgeRequestSchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Successful judgement',\n content: { 'application/json': { schema: JudgeResultSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 404: {\n description: 'Rubric not found',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 500: {\n description: 'Judge error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/v1/rubrics',\n summary: 'List built-in rubrics',\n description:\n 'Returns every rubric registered server-side, with their dimensions and stable rubricVersion hash.',\n responses: {\n 200: {\n description: 'Listing',\n content: { 'application/json': { schema: ListRubricsResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/v1/version',\n summary: 'Server and wire-protocol version',\n description: 'Match your client version to `version`; check `wireVersion` for compatibility.',\n responses: {\n 200: {\n description: 'Version info',\n content: { 'application/json': { schema: VersionResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/healthz',\n summary: 'Liveness check',\n responses: {\n 200: {\n description: 'OK',\n content: { 'application/json': { schema: HealthResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'post',\n path: '/v1/traces/ingest',\n summary: 'Ingest a batch of production TraceEvents',\n description:\n 'Append a batch of TraceEvents to the configured TraceStore. Accepts application/json ({events:[...]}) or application/x-ndjson (one event per line). Returns counts of accepted + rejected events.',\n request: {\n body: {\n content: {\n 'application/json': { schema: TracesIngestRequestSchema },\n 'application/x-ndjson': { schema: TracesIngestRequestSchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Ingestion summary',\n content: { 'application/json': { schema: TracesIngestResponseSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 401: {\n description: 'Unauthorized (when bearer auth is configured)',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 503: {\n description: 'No trace store configured',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'post',\n path: '/v1/feedback',\n summary: 'Ingest a FeedbackTrajectory from production',\n description:\n 'Persist a single FeedbackTrajectory. Idempotent on trajectory.id — re-posting replaces the prior record. Used by production runtimes to forward user 👍/👎/edits into the eval substrate.',\n request: {\n body: {\n content: {\n 'application/json': { schema: FeedbackTrajectorySchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Persisted',\n content: { 'application/json': { schema: FeedbackIngestResponseSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 401: {\n description: 'Unauthorized (when bearer auth is configured)',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 503: {\n description: 'No feedback store configured',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n const generator = new OpenApiGeneratorV31(registry.definitions)\n const doc = generator.generateDocument({\n openapi: '3.1.0',\n info: {\n title: '@tangle-network/agent-eval — wire protocol',\n version: packageVersion,\n description: `HTTP and stdio RPC interface to agent-eval. The TypeScript runtime is the source of truth; this spec is the contract that cross-language clients (Python, Rust, Go) generate from.\n\nWire-protocol version: ${WIRE_VERSION}. Bumps on breaking changes to request/response schemas.`,\n contact: { name: 'Tangle Network', url: 'https://github.com/tangle-network/agent-eval' },\n license: { name: 'MIT' },\n },\n servers: [{ url: 'http://localhost:5005', description: 'Local agent-eval serve' }],\n })\n const rubricRef = { $ref: '#/components/schemas/Rubric' } as const\n const commonJudgeFields = {\n content: { type: 'string', minLength: 1 },\n context: { type: 'object', additionalProperties: true },\n model: { type: 'string' },\n } as const\n doc.components ??= {}\n doc.components.schemas ??= {}\n doc.components.schemas.JudgeRequest = {\n oneOf: [\n {\n type: 'object',\n additionalProperties: false,\n required: ['rubricName', 'content'],\n properties: {\n rubricName: { type: 'string', minLength: 1 },\n ...commonJudgeFields,\n },\n },\n {\n type: 'object',\n additionalProperties: false,\n required: ['rubric', 'content'],\n properties: {\n rubric: rubricRef,\n ...commonJudgeFields,\n },\n },\n ],\n description: 'Judge request. Provide exactly one of rubricName or rubric.',\n }\n return doc\n}\n","/**\n * stdio RPC transport.\n *\n * For batch / cron use without a running server. The Python client falls\n * back to this when no server is reachable.\n *\n * Protocol (line-delimited JSON over stdin/stdout):\n * IN: one JSON object on stdin: {\"method\":\"judge\",\"params\":{...}}\n * OUT: one JSON object on stdout: {\"result\":{...}} or {\"error\":{...}}\n *\n * One request per process invocation. To pipeline many calls, the client\n * writes JSONL to stdin and reads JSONL from stdout — see batch mode below.\n */\nimport { handleJudge, handleListRubrics, handleVersion, WireError } from './handlers'\nimport { JudgeRequestSchema } from './schemas'\n\ninterface RpcRequest {\n method: 'judge' | 'listRubrics' | 'version'\n params?: unknown\n}\n\ninterface RpcSuccess {\n result: unknown\n}\n\ninterface RpcError {\n error: { code: string; message: string; details?: unknown }\n}\n\nexport async function dispatchRpc(req: RpcRequest): Promise<RpcSuccess | RpcError> {\n try {\n switch (req.method) {\n case 'judge': {\n const parsed = JudgeRequestSchema.safeParse(req.params)\n if (!parsed.success) {\n return {\n error: {\n code: 'validation_error',\n message: 'params did not match JudgeRequest schema.',\n details: parsed.error.issues,\n },\n }\n }\n return { result: await handleJudge(parsed.data) }\n }\n case 'listRubrics':\n return { result: handleListRubrics() }\n case 'version':\n return { result: handleVersion() }\n default:\n return {\n error: {\n code: 'unknown_method',\n message: `No such method: ${(req as { method: string }).method}`,\n },\n }\n }\n } catch (err) {\n if (err instanceof WireError) {\n return { error: { code: err.code, message: err.message, details: err.details } }\n }\n const message = err instanceof Error ? err.message : String(err)\n return { error: { code: 'internal_error', message } }\n }\n}\n\n// ── stdin/stdout driver ─────────────────────────────────────────────\n\nasync function readAll(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = []\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as string))\n }\n return Buffer.concat(chunks).toString('utf-8')\n}\n\n/** Read one JSON request from stdin, write one JSON response to stdout. */\nexport async function runRpcOnce(method?: string): Promise<number> {\n const raw = await readAll(process.stdin)\n let req: RpcRequest\n try {\n const body = JSON.parse(raw)\n req = method ? { method: method as RpcRequest['method'], params: body } : (body as RpcRequest)\n } catch (err) {\n process.stdout.write(\n `${JSON.stringify({\n error: {\n code: 'parse_error',\n message: `stdin was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n })}\\n`,\n )\n return 1\n }\n const out = await dispatchRpc(req)\n process.stdout.write(`${JSON.stringify(out)}\\n`)\n return 'error' in out ? 1 : 0\n}\n\n/** Read JSONL requests from stdin, write JSONL responses to stdout. */\nexport async function runRpcBatch(method?: string): Promise<number> {\n const raw = await readAll(process.stdin)\n const lines = raw.split('\\n').filter((l) => l.trim().length > 0)\n let exitCode = 0\n for (const line of lines) {\n let req: RpcRequest\n try {\n const body = JSON.parse(line)\n req = method ? { method: method as RpcRequest['method'], params: body } : (body as RpcRequest)\n } catch (err) {\n process.stdout.write(\n `${JSON.stringify({\n error: {\n code: 'parse_error',\n message: `line was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n })}\\n`,\n )\n exitCode = 1\n continue\n }\n const out = await dispatchRpc(req)\n process.stdout.write(`${JSON.stringify(out)}\\n`)\n if ('error' in out) exitCode = 1\n }\n return exitCode\n}\n","/**\n * HTTP transport for the wire protocol.\n *\n * Hono + @hono/node-server. Every endpoint:\n * 1. Validates the request against its Zod schema.\n * 2. Calls the matching handler in `handlers.ts`.\n * 3. Renders 4xx for `WireError` with structured body, 500 for unexpected.\n *\n * The server holds optional `IngestionStores` (passed to `createApp`)\n * to receive production traces and user feedback. With no stores wired,\n * the ingestion endpoints return 503 — read endpoints (`/v1/judge`,\n * `/v1/rubrics`, `/v1/version`) remain fully functional.\n *\n * Run via `agent-eval serve --port 5005`.\n */\nimport { type ServerType, serve } from '@hono/node-server'\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\n\nimport {\n handleFeedbackIngest,\n handleJudge,\n handleListRubrics,\n handleTracesIngest,\n handleVersion,\n type IngestionStores,\n WireError,\n} from './handlers'\nimport { buildOpenApi } from './openapi'\nimport { FeedbackTrajectorySchema, JudgeRequestSchema, TracesIngestRequestSchema } from './schemas'\n\nconst STARTED_AT = Date.now()\n\nexport interface CreateAppOptions {\n /** Stores wired to the ingestion endpoints. */\n stores?: IngestionStores\n /**\n * Bearer-token auth. When provided, every endpoint EXCEPT `/healthz`\n * and `/v1/version` requires `Authorization: Bearer <token>`. The\n * token may be a static string OR a function for time-bounded /\n * rotating tokens.\n *\n * Recommended for any server that accepts ingestion writes from the\n * public internet. Read-only deployments may omit it.\n */\n auth?: {\n bearer: string | ((token: string) => boolean | Promise<boolean>)\n }\n}\n\nconst AUTH_EXEMPT_PATHS = new Set(['/healthz', '/v1/version', '/openapi.json'])\n\nexport function createApp(opts: CreateAppOptions = {}) {\n const app = new Hono()\n\n app.use('*', cors())\n\n // Bearer-token middleware (only attached when configured).\n if (opts.auth) {\n const verify = opts.auth.bearer\n app.use('*', async (c, next) => {\n const path = new URL(c.req.url).pathname\n if (AUTH_EXEMPT_PATHS.has(path)) return next()\n const raw = c.req.header('authorization') ?? ''\n const match = raw.match(/^Bearer\\s+(.+)$/i)\n if (!match) {\n throw new WireError('unauthorized', 'Missing or malformed Authorization header.', 401)\n }\n const token = match[1] as string\n const ok = typeof verify === 'string' ? token === verify : await verify(token)\n if (!ok) {\n throw new WireError('unauthorized', 'Invalid bearer token.', 401)\n }\n return next()\n })\n }\n\n app.onError((err, c) => {\n if (err instanceof WireError) {\n const status = err.status as 400 | 401 | 404 | 422 | 500 | 503\n return c.json(\n { error: { code: err.code, message: err.message, details: err.details } },\n status,\n )\n }\n // Unexpected — log and return generic 500 without leaking internals.\n console.error('[agent-eval] unhandled error:', err)\n return c.json({ error: { code: 'internal_error', message: 'Internal server error.' } }, 500)\n })\n\n // ── Health ──\n app.get('/healthz', (c) =>\n c.json({ status: 'ok' as const, uptimeSec: (Date.now() - STARTED_AT) / 1000 }),\n )\n\n // ── Version ──\n app.get('/v1/version', (c) => c.json(handleVersion()))\n\n // ── Rubrics ──\n app.get('/v1/rubrics', (c) => c.json(handleListRubrics()))\n\n // ── Judge ──\n app.post('/v1/judge', async (c) => {\n const raw = await c.req.json().catch(() => null)\n if (raw == null) {\n throw new WireError('validation_error', 'Request body must be JSON.', 400)\n }\n const parsed = JudgeRequestSchema.safeParse(raw)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match JudgeRequest schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleJudge(parsed.data)\n return c.json(result)\n })\n\n // ── Traces ingest (NDJSON-friendly: accepts either {events:[...]} or NDJSON) ──\n app.post('/v1/traces/ingest', async (c) => {\n const contentType = c.req.header('content-type') ?? ''\n let payload: unknown\n if (contentType.includes('application/x-ndjson')) {\n const text = await c.req.text()\n const events = text\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n try {\n return JSON.parse(line)\n } catch {\n throw new WireError(\n 'validation_error',\n 'NDJSON line did not parse as JSON.',\n 400,\n line.slice(0, 200),\n )\n }\n })\n payload = { events }\n } else {\n payload = await c.req.json().catch(() => null)\n }\n if (payload == null) {\n throw new WireError('validation_error', 'Request body must be JSON or NDJSON.', 400)\n }\n const parsed = TracesIngestRequestSchema.safeParse(payload)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match TracesIngestRequest schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleTracesIngest(parsed.data, opts.stores ?? {})\n return c.json(result)\n })\n\n // ── Feedback ingest ──\n app.post('/v1/feedback', async (c) => {\n const raw = await c.req.json().catch(() => null)\n if (raw == null) {\n throw new WireError('validation_error', 'Request body must be JSON.', 400)\n }\n const parsed = FeedbackTrajectorySchema.safeParse(raw)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match FeedbackTrajectory schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleFeedbackIngest(parsed.data, opts.stores ?? {})\n return c.json(result)\n })\n\n // ── OpenAPI spec ──\n app.get('/openapi.json', (c) => c.json(buildOpenApi(handleVersion().version)))\n\n return app\n}\n\nexport interface ServeOptions extends CreateAppOptions {\n /** Default 5005. */\n port?: number\n /** Default '127.0.0.1'. Set to '0.0.0.0' to listen on all interfaces. */\n host?: string\n}\n\nexport function startServer(opts: ServeOptions = {}): ServerType {\n const app = createApp(opts)\n const port = opts.port ?? 5005\n const host = opts.host ?? '127.0.0.1'\n return serve({ fetch: app.fetch, port, hostname: host }, ({ address, port: actualPort }) => {\n // eslint-disable-next-line no-console\n console.log(`[agent-eval] serving on http://${address}:${actualPort}`)\n })\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  runRpcBatch,
6
6
  runRpcOnce,
7
7
  startServer
8
- } from "./chunk-5LBB5B3Z.js";
8
+ } from "./chunk-XFZCM5Z3.js";
9
9
  import "./chunk-4S4BM3QQ.js";
10
10
  import "./chunk-PC4UYEBM.js";
11
11
  import "./chunk-NG236HPC.js";
@@ -1,7 +1,7 @@
1
- import { b as FeedbackLabel, p as ProposedSideEffect } from './feedback-trajectory-DfFdrraJ.js';
2
- import { C as ControlEvalResult, a as ControlRunResult, h as ControlRuntimeConfig } from './control-runtime-BuJHoLg0.js';
3
- import { T as TraceEmitter } from './emitter-DP_cSSiw.js';
4
- import { T as TraceStore, F as FailureClass } from './store-Db2Bv8Cf.js';
1
+ import { b as FeedbackLabel, p as ProposedSideEffect } from './feedback-trajectory-j0nJFgC6.js';
2
+ import { C as ControlEvalResult, a as ControlRunResult, h as ControlRuntimeConfig } from './control-runtime-BRdQ0wrx.js';
3
+ import { T as TraceEmitter } from './emitter-BqjeOvJh.js';
4
+ import { T as TraceStore, F as FailureClass } from './store-BP5be6s7.js';
5
5
  import { a as RunSplitTag, b as RunTokenUsage, R as RunRecord } from './run-record-CqzahIbx.js';
6
6
 
7
7
  interface ActionExecutionPolicy {