@tangle-network/agent-eval 1.0.0 → 1.0.2

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 (221) hide show
  1. package/CHANGELOG.md +242 -0
  2. package/README.md +2 -1
  3. package/dist/adapters/http.d.ts +2 -2
  4. package/dist/{agreement-irr-BTjDN0i6.js → agreement-irr-w-t3XUTD.js} +2 -2
  5. package/dist/{agreement-irr-BTjDN0i6.js.map → agreement-irr-w-t3XUTD.js.map} +1 -1
  6. package/dist/analyst/index.d.ts +7 -7
  7. package/dist/analyst/index.js +11 -11
  8. package/dist/{analyze-runs-C-pP1sK9.d.ts → analyze-runs-BYyMShsj.d.ts} +2 -2
  9. package/dist/{analyze-runs-C-pP1sK9.d.ts.map → analyze-runs-BYyMShsj.d.ts.map} +1 -1
  10. package/dist/{analyze-runs-Ck68mbgj.js → analyze-runs-Da7P_Mc5.js} +9 -10
  11. package/dist/{analyze-runs-Ck68mbgj.js.map → analyze-runs-Da7P_Mc5.js.map} +1 -1
  12. package/dist/{benchmark-command-DWkc5mzq.js → benchmark-command-BeDZB3BQ.js} +11 -11
  13. package/dist/{benchmark-command-DWkc5mzq.js.map → benchmark-command-BeDZB3BQ.js.map} +1 -1
  14. package/dist/benchmarks/index.d.ts +4 -4
  15. package/dist/benchmarks/index.js +5 -5
  16. package/dist/builder-eval/index.js +1 -1
  17. package/dist/{calibration-6usfVYYo.js → calibration-DLzckXnn.js} +2 -2
  18. package/dist/{calibration-6usfVYYo.js.map → calibration-DLzckXnn.js.map} +1 -1
  19. package/dist/campaign/index.d.ts +5 -5
  20. package/dist/campaign/index.js +10 -10
  21. package/dist/{campaign-DdOgQfp8.js → campaign-DKZiYHUq.js} +15 -15
  22. package/dist/{campaign-DdOgQfp8.js.map → campaign-DKZiYHUq.js.map} +1 -1
  23. package/dist/{campaign-evidence-MjCjkb5a.js → campaign-evidence-BICB3a9Z.js} +3 -3
  24. package/dist/{campaign-evidence-MjCjkb5a.js.map → campaign-evidence-BICB3a9Z.js.map} +1 -1
  25. package/dist/{chat-client-CO3uB33i.js → chat-client-D0me8iwq.js} +2 -2
  26. package/dist/{chat-client-CO3uB33i.js.map → chat-client-D0me8iwq.js.map} +1 -1
  27. package/dist/{chat-json-call-8yUv4LFO.js → chat-json-call-C473CwTt.js} +2 -2
  28. package/dist/{chat-json-call-8yUv4LFO.js.map → chat-json-call-C473CwTt.js.map} +1 -1
  29. package/dist/cli.js +7 -7
  30. package/dist/{cluster-bootstrap-SbaeM44s.js → cluster-bootstrap-hNXESoc1.js} +2 -2
  31. package/dist/{cluster-bootstrap-SbaeM44s.js.map → cluster-bootstrap-hNXESoc1.js.map} +1 -1
  32. package/dist/{completion-verifier-rqbMh5-4.js → completion-verifier-ClmJV_Yc.js} +2 -2
  33. package/dist/{completion-verifier-rqbMh5-4.js.map → completion-verifier-ClmJV_Yc.js.map} +1 -1
  34. package/dist/contract/index.d.ts +8 -8
  35. package/dist/contract/index.js +13 -13
  36. package/dist/{decision-point-lhMgODOR.js → decision-point-CErE7GnP.js} +6 -6
  37. package/dist/decision-point-CErE7GnP.js.map +1 -0
  38. package/dist/{default-registry-B1DstPYg.d.ts → default-registry-DKlKVXMx.d.ts} +22 -6
  39. package/dist/default-registry-DKlKVXMx.d.ts.map +1 -0
  40. package/dist/{default-registry-C1tPEjZ4.js → default-registry-gmDeN0KT.js} +38 -7
  41. package/dist/default-registry-gmDeN0KT.js.map +1 -0
  42. package/dist/{define-agent-eval-CAffiFbN.d.ts → define-agent-eval-B9zPWFSK.d.ts} +6 -6
  43. package/dist/{define-agent-eval-CAffiFbN.d.ts.map → define-agent-eval-B9zPWFSK.d.ts.map} +1 -1
  44. package/dist/{define-agent-eval-Cc15qGik.js → define-agent-eval-BVhGn7VV.js} +6 -6
  45. package/dist/{define-agent-eval-Cc15qGik.js.map → define-agent-eval-BVhGn7VV.js.map} +1 -1
  46. package/dist/{descriptive-cPwITVfy.js → descriptive-BTzLL-aj.js} +46 -3
  47. package/dist/descriptive-BTzLL-aj.js.map +1 -0
  48. package/dist/diagnosis/index.d.ts +2 -2
  49. package/dist/diagnosis/index.js +2 -2
  50. package/dist/{dspy-rlm-engine-jDiWkul6.js → dspy-rlm-engine-C0zR2xiM.js} +2 -2
  51. package/dist/{dspy-rlm-engine-jDiWkul6.js.map → dspy-rlm-engine-C0zR2xiM.js.map} +1 -1
  52. package/dist/{eval-campaign-C_mNDshv.js → eval-campaign-DVqiBoXR.js} +3 -3
  53. package/dist/{eval-campaign-C_mNDshv.js.map → eval-campaign-DVqiBoXR.js.map} +1 -1
  54. package/dist/{evaluation-BPqUvZ66.d.ts → evaluation-B0-KVXaV.d.ts} +4 -2
  55. package/dist/evaluation-B0-KVXaV.d.ts.map +1 -0
  56. package/dist/{evaluation-B8H3GYej.js → evaluation-BBI37mRe.js} +2 -1
  57. package/dist/evaluation-BBI37mRe.js.map +1 -0
  58. package/dist/evaluation.d.ts +1 -1
  59. package/dist/evaluation.js +1 -1
  60. package/dist/{exact-types-D98BKpxo.d.ts → exact-types-CIViGj98.d.ts} +3 -3
  61. package/dist/{exact-types-D98BKpxo.d.ts.map → exact-types-CIViGj98.d.ts.map} +1 -1
  62. package/dist/experiment/index.d.ts +1 -1
  63. package/dist/experiment/index.js +9 -8
  64. package/dist/experiment/index.js.map +1 -1
  65. package/dist/{exporters-B5Ze_RKh.d.ts → exporters-BYBG9b1n.d.ts} +2 -2
  66. package/dist/{exporters-B5Ze_RKh.d.ts.map → exporters-BYBG9b1n.d.ts.map} +1 -1
  67. package/dist/{external-optimizer-process-BRVmaDFe.js → external-optimizer-process-DKgrrX0J.js} +2 -2
  68. package/dist/{external-optimizer-process-BRVmaDFe.js.map → external-optimizer-process-DKgrrX0J.js.map} +1 -1
  69. package/dist/{external-optimizer-subprocess-U616hV_l.js → external-optimizer-subprocess-wzMaA0oN.js} +2 -2
  70. package/dist/{external-optimizer-subprocess-U616hV_l.js.map → external-optimizer-subprocess-wzMaA0oN.js.map} +1 -1
  71. package/dist/{feedback-trajectory-SBGncrCP.d.ts → feedback-trajectory-Ck7K7AhK.d.ts} +2 -2
  72. package/dist/{feedback-trajectory-SBGncrCP.d.ts.map → feedback-trajectory-Ck7K7AhK.d.ts.map} +1 -1
  73. package/dist/{findings-store-B75Dspaq.js → findings-store-DNSvmy8U.js} +4 -4
  74. package/dist/{findings-store-B75Dspaq.js.map → findings-store-DNSvmy8U.js.map} +1 -1
  75. package/dist/fuzz.js +1 -1
  76. package/dist/{index-CUjeTDPv.d.ts → index-Bn-P_XAl.d.ts} +4 -4
  77. package/dist/{index-CUjeTDPv.d.ts.map → index-Bn-P_XAl.d.ts.map} +1 -1
  78. package/dist/{index-B7v2QHlD.d.ts → index-BwutH5i7.d.ts} +4 -4
  79. package/dist/{index-B7v2QHlD.d.ts.map → index-BwutH5i7.d.ts.map} +1 -1
  80. package/dist/{index-aDPVYBIM.d.ts → index-ByJ20lyu.d.ts} +7 -7
  81. package/dist/{index-aDPVYBIM.d.ts.map → index-ByJ20lyu.d.ts.map} +1 -1
  82. package/dist/{index-DUn0GNiZ.d.ts → index-CtcCSO1Y.d.ts} +4 -4
  83. package/dist/{index-DUn0GNiZ.d.ts.map → index-CtcCSO1Y.d.ts.map} +1 -1
  84. package/dist/index.d.ts +17 -17
  85. package/dist/index.js +38 -43
  86. package/dist/index.js.map +1 -1
  87. package/dist/{judge-calibration-DGqlfWW8.js → judge-calibration-D93UCm1k.js} +2 -2
  88. package/dist/{judge-calibration-DGqlfWW8.js.map → judge-calibration-D93UCm1k.js.map} +1 -1
  89. package/dist/{judge-gate-Di_6bifh.js → judge-gate-C9sLLJ-v.js} +3 -3
  90. package/dist/{judge-gate-Di_6bifh.js.map → judge-gate-C9sLLJ-v.js.map} +1 -1
  91. package/dist/kind-factory-VKysp1ds.js.map +1 -1
  92. package/dist/{llm-client-kJ9EOqjt.js → llm-client-BdSiZ4qz.js} +2 -2
  93. package/dist/{llm-client-kJ9EOqjt.js.map → llm-client-BdSiZ4qz.js.map} +1 -1
  94. package/dist/{llm-judge-D6JtIqiU.js → llm-judge-BYBLxREr.js} +14 -14
  95. package/dist/{llm-judge-D6JtIqiU.js.map → llm-judge-BYBLxREr.js.map} +1 -1
  96. package/dist/{matrix-CBUzIZs4.d.ts → matrix-4DcRFJ7Q.d.ts} +2 -2
  97. package/dist/{matrix-CBUzIZs4.d.ts.map → matrix-4DcRFJ7Q.d.ts.map} +1 -1
  98. package/dist/{internal-v6XfOeJW.js → mean-DDFhslBt.js} +48 -2
  99. package/dist/mean-DDFhslBt.js.map +1 -0
  100. package/dist/meta-eval/index.js +7 -7
  101. package/dist/multishot/golden/index.d.ts +1 -1
  102. package/dist/multishot/index.d.ts +2 -2
  103. package/dist/openapi.json +1 -1
  104. package/dist/{outcome-observations-D4snOtUb.js → outcome-observations-ahbNtxuP.js} +3 -3
  105. package/dist/{outcome-observations-D4snOtUb.js.map → outcome-observations-ahbNtxuP.js.map} +1 -1
  106. package/dist/{paired-arms-D5H_58e8.js → paired-arms-C0Vd9bGG.js} +4 -4
  107. package/dist/{paired-arms-D5H_58e8.js.map → paired-arms-C0Vd9bGG.js.map} +1 -1
  108. package/dist/{paired-binary-BR0nwHOA.js → paired-binary-B477lksS.js} +2 -2
  109. package/dist/{paired-binary-BR0nwHOA.js.map → paired-binary-B477lksS.js.map} +1 -1
  110. package/dist/{paired-promotion-decision-BiVumgvM.js → paired-promotion-decision-5Pl_qJLX.js} +3 -3
  111. package/dist/{paired-promotion-decision-BiVumgvM.js.map → paired-promotion-decision-5Pl_qJLX.js.map} +1 -1
  112. package/dist/{paired-tests-C2zUqgUW.js → paired-tests-kASEKpc-.js} +3 -37
  113. package/dist/paired-tests-kASEKpc-.js.map +1 -0
  114. package/dist/{pareto-7_LEmYGG.js → pareto-DY_x3HHg.js} +7 -7
  115. package/dist/{pareto-7_LEmYGG.js.map → pareto-DY_x3HHg.js.map} +1 -1
  116. package/dist/pipelines/index.d.ts +1 -1
  117. package/dist/pipelines/index.js +1 -1
  118. package/dist/{power-and-mde-CHvyDO_H.js → power-and-mde-CRxepy8y.js} +3 -3
  119. package/dist/{power-and-mde-CHvyDO_H.js.map → power-and-mde-CRxepy8y.js.map} +1 -1
  120. package/dist/{promotion-policy-D7B4_jEZ.js → promotion-policy-f79oklG_.js} +4 -4
  121. package/dist/{promotion-policy-D7B4_jEZ.js.map → promotion-policy-f79oklG_.js.map} +1 -1
  122. package/dist/{proposal-findings-WFQrxnfe.js → proposal-findings-duV5flPv.js} +2 -2
  123. package/dist/{proposal-findings-WFQrxnfe.js.map → proposal-findings-duV5flPv.js.map} +1 -1
  124. package/dist/{raw-provider-sink-DDLkP_eF.js → raw-provider-sink-RbaEv2vB.js} +2 -2
  125. package/dist/{raw-provider-sink-DDLkP_eF.js.map → raw-provider-sink-RbaEv2vB.js.map} +1 -1
  126. package/dist/{redact-C_wzC4c_.d.ts → redact-jrT0APTU.d.ts} +50 -35
  127. package/dist/redact-jrT0APTU.d.ts.map +1 -0
  128. package/dist/{redact-D6APJS1d.js → redact-zp_ILC4l.js} +92 -33
  129. package/dist/redact-zp_ILC4l.js.map +1 -0
  130. package/dist/redaction.d.ts +2 -0
  131. package/dist/redaction.js +1 -0
  132. package/dist/{registry-dhdDoAV8.d.ts → registry-CMtGAxOw.d.ts} +2 -2
  133. package/dist/{registry-dhdDoAV8.d.ts.map → registry-CMtGAxOw.d.ts.map} +1 -1
  134. package/dist/{release-confidence-CTUJz5mM.js → release-confidence--1iP-d3x.js} +2 -2
  135. package/dist/{release-confidence-CTUJz5mM.js.map → release-confidence--1iP-d3x.js.map} +1 -1
  136. package/dist/{render-pfAZ7IR4.js → render-CFrJ7M0o.js} +26 -26
  137. package/dist/render-CFrJ7M0o.js.map +1 -0
  138. package/dist/reporting.js +5 -5
  139. package/dist/{reward-hacking-Bjk3MAjh.js → reward-hacking-D-Vi9-fE.js} +3 -3
  140. package/dist/{reward-hacking-Bjk3MAjh.js.map → reward-hacking-D-Vi9-fE.js.map} +1 -1
  141. package/dist/rl.d.ts +3 -3
  142. package/dist/rl.js +9 -9
  143. package/dist/rollout/index.d.ts +4 -4
  144. package/dist/rollout/index.js +1 -1
  145. package/dist/{rollout-BhkMpAJT.js → rollout-BC4u-d_I.js} +3 -3
  146. package/dist/{rollout-BhkMpAJT.js.map → rollout-BC4u-d_I.js.map} +1 -1
  147. package/dist/{rubric-predictive-validity-CQp_M0vy.js → rubric-predictive-validity-BdxXDN6h.js} +2 -2
  148. package/dist/{rubric-predictive-validity-CQp_M0vy.js.map → rubric-predictive-validity-BdxXDN6h.js.map} +1 -1
  149. package/dist/{run-record-BUm-Jggo.js → run-record-B-G2Tu11.js} +2 -2
  150. package/dist/{run-record-BUm-Jggo.js.map → run-record-B-G2Tu11.js.map} +1 -1
  151. package/dist/{schema-DkFJr3Y8.d.ts → schema-CfoA9U_U.d.ts} +28 -2
  152. package/dist/schema-CfoA9U_U.d.ts.map +1 -0
  153. package/dist/search/index.d.ts +2 -2
  154. package/dist/search/index.js +2 -2
  155. package/dist/{search-kernel-CBdwFZ05.d.ts → search-kernel-BjR2Sr7w.d.ts} +2 -2
  156. package/dist/{search-kernel-CBdwFZ05.d.ts.map → search-kernel-BjR2Sr7w.d.ts.map} +1 -1
  157. package/dist/{search-summary-Bt3uuK53.js → search-summary-DedyTdiM.js} +4 -4
  158. package/dist/{search-summary-Bt3uuK53.js.map → search-summary-DedyTdiM.js.map} +1 -1
  159. package/dist/{sequential-De7BTAlV.js → sequential-Zp1tsxqI.js} +2 -2
  160. package/dist/{sequential-De7BTAlV.js.map → sequential-Zp1tsxqI.js.map} +1 -1
  161. package/dist/{server-DA6h3co5.js → server-CPKyf3bz.js} +2 -2
  162. package/dist/{server-DA6h3co5.js.map → server-CPKyf3bz.js.map} +1 -1
  163. package/dist/{skillopt-optimization-method-BKFbJEyz.js → skillopt-optimization-method-DmfZz-2d.js} +9 -9
  164. package/dist/{skillopt-optimization-method-BKFbJEyz.js.map → skillopt-optimization-method-DmfZz-2d.js.map} +1 -1
  165. package/dist/{spans-vZoW__3q.d.ts → spans-CGjHouKM.d.ts} +2 -2
  166. package/dist/{spans-vZoW__3q.d.ts.map → spans-CGjHouKM.d.ts.map} +1 -1
  167. package/dist/{statistical-heldout-C9hz_AF9.js → statistical-heldout-DYF5f10K.js} +3 -3
  168. package/dist/{statistical-heldout-C9hz_AF9.js.map → statistical-heldout-DYF5f10K.js.map} +1 -1
  169. package/dist/{statistical-heldout-Cei036nE.d.ts → statistical-heldout-bU7FBNjR.d.ts} +2 -2
  170. package/dist/{statistical-heldout-Cei036nE.d.ts.map → statistical-heldout-bU7FBNjR.d.ts.map} +1 -1
  171. package/dist/{store-tool-spans-C2g8UYm-.js → store-tool-spans-GGaCijFy.js} +19 -62
  172. package/dist/store-tool-spans-GGaCijFy.js.map +1 -0
  173. package/dist/{store-tool-spans-B3i3fl0A.d.ts → store-tool-spans-lWf6INTH.d.ts} +3 -44
  174. package/dist/store-tool-spans-lWf6INTH.d.ts.map +1 -0
  175. package/dist/{summary-report-BLnTyQKH.js → summary-report-BstMpOfy.js} +6 -7
  176. package/dist/{summary-report-BLnTyQKH.js.map → summary-report-BstMpOfy.js.map} +1 -1
  177. package/dist/supervisor-run/index.d.ts +12 -2
  178. package/dist/supervisor-run/index.d.ts.map +1 -1
  179. package/dist/supervisor-run/index.js +1 -1
  180. package/dist/{systemone-Cw2txK5m.d.ts → systemone-BDVgb6XV.d.ts} +7 -9
  181. package/dist/systemone-BDVgb6XV.d.ts.map +1 -0
  182. package/dist/systemone.d.ts +2 -2
  183. package/dist/systemone.js +2 -2
  184. package/dist/{tool-waste-CLJ46AbT.js → tool-waste-CRJqOASv.js} +3 -3
  185. package/dist/{tool-waste-CLJ46AbT.js.map → tool-waste-CRJqOASv.js.map} +1 -1
  186. package/dist/trace-repair/index.js +2 -2
  187. package/dist/traces.d.ts +18 -39
  188. package/dist/traces.d.ts.map +1 -1
  189. package/dist/traces.js +51 -57
  190. package/dist/traces.js.map +1 -1
  191. package/dist/{tree-DnBkWXun.js → tree-C2N31CoI.js} +5 -6
  192. package/dist/{tree-DnBkWXun.js.map → tree-C2N31CoI.js.map} +1 -1
  193. package/dist/{types-C54Uk_a1.d.ts → types-BF-xQGQn.d.ts} +2 -2
  194. package/dist/{types-C54Uk_a1.d.ts.map → types-BF-xQGQn.d.ts.map} +1 -1
  195. package/dist/{types-C-aOqgt2.d.ts → types-DNB9hIXa.d.ts} +2 -2
  196. package/dist/{types-C-aOqgt2.d.ts.map → types-DNB9hIXa.d.ts.map} +1 -1
  197. package/dist/{types-0oMg7zee.d.ts → types-yofaDmQa.d.ts} +2 -2
  198. package/dist/{types-0oMg7zee.d.ts.map → types-yofaDmQa.d.ts.map} +1 -1
  199. package/dist/wire/index.d.ts +7 -7
  200. package/dist/wire/index.js +1 -1
  201. package/docs/design/statistics-decisions.md +1 -0
  202. package/docs/redaction.md +24 -1
  203. package/docs/systemone.md +6 -0
  204. package/package.json +7 -2
  205. package/dist/decision-point-lhMgODOR.js.map +0 -1
  206. package/dist/default-registry-B1DstPYg.d.ts.map +0 -1
  207. package/dist/default-registry-C1tPEjZ4.js.map +0 -1
  208. package/dist/descriptive-cPwITVfy.js.map +0 -1
  209. package/dist/evaluation-B8H3GYej.js.map +0 -1
  210. package/dist/evaluation-BPqUvZ66.d.ts.map +0 -1
  211. package/dist/internal-v6XfOeJW.js.map +0 -1
  212. package/dist/mean-BPuUNznQ.js +0 -16
  213. package/dist/mean-BPuUNznQ.js.map +0 -1
  214. package/dist/paired-tests-C2zUqgUW.js.map +0 -1
  215. package/dist/redact-C_wzC4c_.d.ts.map +0 -1
  216. package/dist/redact-D6APJS1d.js.map +0 -1
  217. package/dist/render-pfAZ7IR4.js.map +0 -1
  218. package/dist/schema-DkFJr3Y8.d.ts.map +0 -1
  219. package/dist/store-tool-spans-B3i3fl0A.d.ts.map +0 -1
  220. package/dist/store-tool-spans-C2g8UYm-.js.map +0 -1
  221. package/dist/systemone-Cw2txK5m.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tool-waste-CLJ46AbT.js","names":[],"sources":["../src/pipelines/budget-breach.ts","../src/pipelines/failure-cluster.ts","../src/pipelines/judge-agreement.ts","../src/tool-use-metrics.ts","../src/pipelines/tool-waste.ts"],"sourcesContent":["/**\n * BudgetBreachView — aggregates breach events across the corpus.\n *\n * Answers: which dimensions get hit most often? Which scenarios are\n * underbudgeted? Which variants trigger the most breaches?\n */\n\nimport type { BudgetSpec } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface BudgetBreachFinding {\n runId: string\n scenarioId: string\n variantId?: string\n dimension: keyof BudgetSpec\n limit: number\n consumed: number\n excessRatio: number\n timestamp: number\n}\n\nexport interface BudgetBreachReport {\n findings: BudgetBreachFinding[]\n byDimension: Record<string, number>\n byScenario: Record<string, number>\n byVariant: Record<string, number>\n totalRuns: number\n breachedRunRatio: number\n}\n\nexport async function budgetBreachView(\n store: TraceStore,\n options: { scenarioId?: string; variantId?: string } = {},\n): Promise<BudgetBreachReport> {\n const runs = await store.listRuns({\n scenarioId: options.scenarioId,\n variantId: options.variantId,\n })\n const findings: BudgetBreachFinding[] = []\n const byDimension: Record<string, number> = {}\n const byScenario: Record<string, number> = {}\n const byVariant: Record<string, number> = {}\n\n for (const run of runs) {\n const entries = await store.budget(run.runId)\n for (const e of entries) {\n if (!e.breached) continue\n const excessRatio = e.limit > 0 ? e.consumed / e.limit : Infinity\n findings.push({\n runId: run.runId,\n scenarioId: run.scenarioId,\n variantId: run.variantId,\n dimension: e.dimension,\n limit: e.limit,\n consumed: e.consumed,\n excessRatio,\n timestamp: e.timestamp,\n })\n byDimension[e.dimension] = (byDimension[e.dimension] ?? 0) + 1\n byScenario[run.scenarioId] = (byScenario[run.scenarioId] ?? 0) + 1\n if (run.variantId) byVariant[run.variantId] = (byVariant[run.variantId] ?? 0) + 1\n }\n }\n\n const breachedRuns = new Set(findings.map((f) => f.runId))\n return {\n findings,\n byDimension,\n byScenario,\n byVariant,\n totalRuns: runs.length,\n breachedRunRatio: runs.length > 0 ? breachedRuns.size / runs.length : 0,\n }\n}\n","/**\n * FailureClusterView — groups failed runs by (failureClass, triggerTool,\n * argHash-prefix) so weekly reviews can prioritize the top-N clusters.\n *\n * Each cluster includes: N runs, scenarios affected, representative\n * error message, a proposed mitigation hint (rule → action table).\n */\n\nimport { classifyFailure, DEFAULT_RULES, type FailureRule } from '../failure-taxonomy'\nimport { argHash, hasCapturedToolArgs, toolSpans } from '../trace/query'\nimport type { FailureClass, Span } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface FailureCluster {\n failureClass: FailureClass\n /** Tool name when the trigger was a tool span, else undefined. */\n toolName?: string\n /** First 16 chars of argHash — clusters similar args. */\n argPrefix?: string\n /**\n * Source dimension when the trigger was a judge span (e.g. `'format'`,\n * `'safety'`, `'correctness'`). Lets cross-template aggregators\n * group failures by the dimension that fired without overloading\n * `argPrefix`. Optional — clusters without this field deserialize cleanly.\n */\n dimension?: string\n runCount: number\n scenarioIds: string[]\n exampleError?: string\n exampleRunId: string\n}\n\nexport interface FailureClusterReport {\n clusters: FailureCluster[]\n totalFailures: number\n totalRuns: number\n}\n\nexport async function failureClusterView(\n store: TraceStore,\n options: { rules?: FailureRule[]; minClusterSize?: number } = {},\n): Promise<FailureClusterReport> {\n const rules = options.rules ?? DEFAULT_RULES\n const minSize = options.minClusterSize ?? 1\n const runs = await store.listRuns()\n\n type Key = string\n const clusters = new Map<Key, FailureCluster>()\n let totalFailures = 0\n\n for (const run of runs) {\n if (run.status === 'completed' && run.outcome?.pass !== false) continue\n totalFailures++\n const spans = await store.spans({ runId: run.runId })\n const events = await store.events({ runId: run.runId })\n const cls = classifyFailure({ run, spans, events }, rules)\n\n let toolName: string | undefined\n let argPrefix: string | undefined\n let dimension: string | undefined\n if (cls.triggerSpanId) {\n const trig = spans.find((s) => s.spanId === cls.triggerSpanId)\n if (trig?.kind === 'tool') {\n toolName = trig.toolName\n if (hasCapturedToolArgs(trig)) argPrefix = argHash(trig.args).slice(0, 16)\n } else if (trig?.kind === 'judge') {\n dimension = trig.dimension\n }\n }\n // Fallback: look at the last errored tool span\n if (!toolName) {\n const ts = await toolSpans(store, run.runId)\n const errored = ts.filter((t) => t.status === 'error').pop()\n if (errored) {\n toolName = errored.toolName\n if (hasCapturedToolArgs(errored)) argPrefix = argHash(errored.args).slice(0, 16)\n }\n }\n // Secondary signal: any judge span on the failed run carries a\n // dimension. Useful when the rule classified by judge score but\n // didn't surface the trigger span (or surfaced a non-judge span).\n if (!dimension) {\n const judge = spans.find((s) => s.kind === 'judge' && typeof s.dimension === 'string')\n if (judge?.kind === 'judge') dimension = judge.dimension\n }\n\n const key = `${cls.failureClass}|${toolName ?? ''}|${argPrefix ?? ''}|${dimension ?? ''}`\n let cluster = clusters.get(key)\n if (!cluster) {\n cluster = {\n failureClass: cls.failureClass,\n toolName,\n argPrefix,\n dimension,\n runCount: 0,\n scenarioIds: [],\n exampleRunId: run.runId,\n exampleError: firstErrorMessage(spans) ?? cls.reason,\n }\n clusters.set(key, cluster)\n }\n cluster.runCount++\n if (!cluster.scenarioIds.includes(run.scenarioId)) cluster.scenarioIds.push(run.scenarioId)\n }\n\n const arr = [...clusters.values()]\n .filter((c) => c.runCount >= minSize)\n .sort((a, b) => b.runCount - a.runCount)\n\n return { clusters: arr, totalFailures, totalRuns: runs.length }\n}\n\nfunction firstErrorMessage(spans: Span[]): string | undefined {\n const errored = spans.find((s) => s.status === 'error')\n return errored?.error\n}\n","/**\n * JudgeAgreementView — pairwise agreement between judges across the\n * corpus, grouped by dimension.\n *\n * Output drives two workflows:\n * - Judge robustness audit: \"does Claude agree with GPT at κ ≥ 0.6?\"\n * - Calibration tracking: κ vs golden human labels over time (by\n * providing a `humanGoldenJudgeId`).\n */\n\nimport { interRaterReliability, pearsonR } from '../statistics'\nimport type { JudgeSpan } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface JudgePair {\n judgeA: string\n judgeB: string\n dimension: string\n /** Number of (targetSpanId, dimension) tuples both judges scored. */\n commonItems: number\n pearson: number\n krippendorff: number\n}\n\nexport interface JudgeAgreementReport {\n pairs: JudgePair[]\n dimensions: string[]\n judgeIds: string[]\n}\n\nexport async function judgeAgreementView(store: TraceStore): Promise<JudgeAgreementReport> {\n const all = (await store.spans({ kind: 'judge' })).filter(\n (s): s is JudgeSpan => s.kind === 'judge',\n )\n if (all.length === 0) return { pairs: [], dimensions: [], judgeIds: [] }\n\n const byDimension = new Map<string, JudgeSpan[]>()\n for (const s of all) {\n const arr = byDimension.get(s.dimension) ?? []\n arr.push(s)\n byDimension.set(s.dimension, arr)\n }\n\n const judgeIds = [...new Set(all.map((s) => s.judgeId))].sort()\n const pairs: JudgePair[] = []\n for (const [dim, spans] of byDimension) {\n const byJudge = new Map<string, Map<string, number>>()\n for (const s of spans) {\n const m = byJudge.get(s.judgeId) ?? new Map<string, number>()\n m.set(s.targetSpanId, s.score)\n byJudge.set(s.judgeId, m)\n }\n const judgesHere = [...byJudge.keys()]\n for (let i = 0; i < judgesHere.length; i++) {\n for (let j = i + 1; j < judgesHere.length; j++) {\n const judgeI = judgesHere[i]!\n const judgeJ = judgesHere[j]!\n const a = byJudge.get(judgeI)!\n const b = byJudge.get(judgeJ)!\n const common: Array<[number, number]> = []\n for (const [target, scoreA] of a) {\n const scoreB = b.get(target)\n if (scoreB !== undefined) common.push([scoreA, scoreB])\n }\n if (common.length < 2) continue\n const judgeScores = common.map(\n ([scoreA, scoreB]) =>\n [\n { judgeName: judgeI, dimension: dim, score: scoreA, reasoning: '' },\n { judgeName: judgeJ, dimension: dim, score: scoreB, reasoning: '' },\n ] as const,\n )\n const k = interRaterReliability(\n judgeScores[0]!.map((_, k2) => judgeScores.map((pair) => pair[k2]!)),\n )\n pairs.push({\n judgeA: judgeI,\n judgeB: judgeJ,\n dimension: dim,\n commonItems: common.length,\n pearson: pearsonR(\n common.map((c) => c[0]),\n common.map((c) => c[1]),\n ),\n krippendorff: k,\n })\n }\n }\n }\n\n return {\n pairs: pairs.sort((a, b) => b.commonItems - a.commonItems),\n dimensions: [...byDimension.keys()].sort(),\n judgeIds,\n }\n}\n","/**\n * Tool-use metrics — derived purely from trace data.\n *\n * No scoring assumptions: consumers supply optional ground-truth tool\n * selections per turn + optional \"information used downstream\" signals.\n * Without those, we still compute descriptive metrics (error rate,\n * retry rate, duplicate-call rate) that are useful on their own.\n */\n\nimport { argHash, groupBy, hasCapturedToolArgs, toolSpans } from './trace/query'\nimport type { Span } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport interface ToolUseMetrics {\n runId: string\n totalCalls: number\n /** Calls whose arguments were captured and can be compared for duplication. */\n callsWithCapturedArgs: number\n byTool: Record<string, ToolStats>\n errorRate: number\n /** Ratio of captured-argument calls already seen with the same tool name and arguments. */\n duplicateRate: number\n /** Ratio of error calls followed by ≥1 retry on same tool. */\n retryRate: number\n /** Optional: of the calls agent made, fraction the evaluator marked as \"correct selection\". */\n selectionAccuracy?: number\n}\n\nexport interface ToolStats {\n calls: number\n callsWithCapturedArgs: number\n errors: number\n avgLatencyMs: number\n duplicates: number\n}\n\nexport interface ToolUseOptions {\n /** Map of spanId → whether the evaluator judged the tool selection correct. Optional. */\n selectionLabels?: Record<string, boolean>\n}\n\nexport async function computeToolUseMetrics(\n store: TraceStore,\n runId: string,\n options: ToolUseOptions = {},\n): Promise<ToolUseMetrics> {\n const tools = await toolSpans(store, runId)\n if (tools.length === 0) {\n return {\n runId,\n totalCalls: 0,\n callsWithCapturedArgs: 0,\n byTool: {},\n errorRate: 0,\n duplicateRate: 0,\n retryRate: 0,\n }\n }\n\n const byTool: Record<string, ToolStats> = {}\n let totalErrors = 0\n let totalDuplicates = 0\n let callsWithCapturedArgs = 0\n const sortedTools = [...tools].sort((a, b) => a.startedAt - b.startedAt)\n const seenSignatures = new Set<string>()\n\n // duplicate detection + per-tool aggregation\n for (const t of sortedTools) {\n byTool[t.toolName] ??= {\n calls: 0,\n callsWithCapturedArgs: 0,\n errors: 0,\n avgLatencyMs: 0,\n duplicates: 0,\n }\n const stat = byTool[t.toolName]!\n stat.calls += 1\n if (t.status === 'error') {\n stat.errors += 1\n totalErrors += 1\n }\n if (typeof t.latencyMs === 'number') stat.avgLatencyMs += t.latencyMs\n if (hasCapturedToolArgs(t)) {\n callsWithCapturedArgs += 1\n stat.callsWithCapturedArgs += 1\n const sig = `${t.toolName}|${argHash(t.args)}`\n if (seenSignatures.has(sig)) {\n stat.duplicates += 1\n totalDuplicates += 1\n }\n seenSignatures.add(sig)\n }\n }\n\n for (const stat of Object.values(byTool)) {\n stat.avgLatencyMs = stat.calls > 0 ? stat.avgLatencyMs / stat.calls : 0\n }\n\n // retry detection: per-tool chronological adjacency where error → next same-tool call\n let retryOpportunities = 0\n let retriesFollowed = 0\n for (const [, arr] of groupBy(sortedTools, (t) => t.toolName)) {\n for (let i = 0; i < arr.length; i++) {\n if (arr[i]!.status !== 'error') continue\n retryOpportunities += 1\n if (arr[i + 1]) retriesFollowed += 1\n }\n }\n const retryRate = retryOpportunities > 0 ? retriesFollowed / retryOpportunities : 0\n\n let selectionAccuracy: number | undefined\n if (options.selectionLabels) {\n const labeled = sortedTools.filter((t) => t.spanId in options.selectionLabels!)\n if (labeled.length > 0) {\n selectionAccuracy =\n labeled.filter((t) => options.selectionLabels![t.spanId]).length / labeled.length\n }\n }\n\n return {\n runId,\n totalCalls: sortedTools.length,\n callsWithCapturedArgs,\n byTool,\n errorRate: totalErrors / sortedTools.length,\n duplicateRate: callsWithCapturedArgs > 0 ? totalDuplicates / callsWithCapturedArgs : 0,\n retryRate,\n selectionAccuracy,\n }\n}\n\nexport type { Span }\n","/**\n * ToolWasteView — fraction of tool calls whose results weren't used\n * downstream. Without a \"used\" signal we fall back to structural\n * proxies: error calls, duplicate calls, and tool calls followed by\n * zero subsequent LLM spans are all considered waste.\n *\n * Consumers can pass a `usageOracle` that inspects a tool span and\n * returns true iff the tool's result appears in a later LLM message,\n * artifact, or state mutation — that's the canonical definition; the\n * default heuristic is a reasonable fallback.\n */\n\nimport { computeToolUseMetrics } from '../tool-use-metrics'\nimport { llmSpans, toolSpans } from '../trace/query'\nimport type { LlmSpan, ToolSpan } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface ToolWasteFinding {\n runId: string\n wastedCalls: number\n totalCalls: number\n wasteRate: number\n}\n\nexport interface ToolWasteReport {\n byRun: ToolWasteFinding[]\n overallWasteRate: number\n}\n\nexport interface ToolWasteOptions {\n runId?: string\n usageOracle?: (tool: ToolSpan, later: { llm: Awaited<ReturnType<typeof llmSpans>> }) => boolean\n}\n\nexport async function toolWasteView(\n store: TraceStore,\n options: ToolWasteOptions = {},\n): Promise<ToolWasteReport> {\n const runs = options.runId ? [options.runId] : (await store.listRuns()).map((r) => r.runId)\n\n const byRun: ToolWasteFinding[] = []\n let totalCalls = 0\n let totalWasted = 0\n for (const runId of runs) {\n const tools = await toolSpans(store, runId)\n if (tools.length === 0) {\n byRun.push({ runId, wastedCalls: 0, totalCalls: 0, wasteRate: 0 })\n continue\n }\n const llms = await llmSpans(store, runId)\n // Sort LLM spans once by start time, then build a suffix index of the\n // concatenated message text. `suffixText[i]` is the haystack of every\n // string message content in spans[i..]. Per tool we binary-search the\n // first span started strictly after the tool, then test that one suffix\n // — turning the per-tool O(llms × messages × content) scan into a single\n // O(log llms) lookup over precomputed text.\n const sortedLlm = [...llms].sort((a, b) => a.startedAt - b.startedAt)\n const startTimes = sortedLlm.map((l) => l.startedAt)\n const suffixText = buildSuffixText(sortedLlm)\n let wasted = 0\n for (const t of tools) {\n if (t.status === 'error') {\n wasted++\n continue\n }\n // First LLM span started strictly after this tool (upper-bound search).\n const cutoff = upperBound(startTimes, t.startedAt)\n if (options.usageOracle) {\n if (!options.usageOracle(t, { llm: sortedLlm.slice(cutoff) })) wasted++\n } else {\n // Default heuristic: a tool whose result is NOT mentioned in any\n // later LLM input message is likely wasted. An empty/null result has\n // no payload to propagate downstream — there is nothing to find in a\n // later message, so it is not evidence of waste; skip it.\n const resultStr = stringify(t.result)\n if (resultStr === '') continue\n const haystack = suffixText[cutoff] ?? ''\n const used = haystack.includes(resultStr.slice(0, 120))\n if (!used) wasted++\n }\n }\n const wasteRate = wasted / tools.length\n byRun.push({ runId, wastedCalls: wasted, totalCalls: tools.length, wasteRate })\n totalCalls += tools.length\n totalWasted += wasted\n }\n return { byRun, overallWasteRate: totalCalls > 0 ? totalWasted / totalCalls : 0 }\n}\n\n/**\n * Build per-position suffix haystacks: result[i] is the concatenation of every\n * string message content in spans[i..end]. Built back-to-front so each entry\n * reuses the next one — O(total message text) rather than O(spans²).\n */\nfunction buildSuffixText(spans: LlmSpan[]): string[] {\n const result = new Array<string>(spans.length + 1)\n result[spans.length] = ''\n for (let i = spans.length - 1; i >= 0; i--) {\n const own = spans[i]!.messages.map((m) =>\n typeof m.content === 'string' ? m.content : '',\n ).join('\\n')\n result[i] = `${own}\\n${result[i + 1]}`\n }\n return result\n}\n\n/** Index of the first element strictly greater than `target` in a sorted array. */\nfunction upperBound(sorted: number[], target: number): number {\n let lo = 0\n let hi = sorted.length\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (sorted[mid]! <= target) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\nfunction stringify(v: unknown): string {\n if (v === null || v === undefined) return ''\n if (typeof v === 'string') return v\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n\n// Re-export for convenience in consumers that want both descriptive and usage metrics.\nexport { computeToolUseMetrics }\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-waste-CRJqOASv.js","names":[],"sources":["../src/pipelines/budget-breach.ts","../src/pipelines/failure-cluster.ts","../src/pipelines/judge-agreement.ts","../src/tool-use-metrics.ts","../src/pipelines/tool-waste.ts"],"sourcesContent":["/**\n * BudgetBreachView — aggregates breach events across the corpus.\n *\n * Answers: which dimensions get hit most often? Which scenarios are\n * underbudgeted? Which variants trigger the most breaches?\n */\n\nimport type { BudgetSpec } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface BudgetBreachFinding {\n runId: string\n scenarioId: string\n variantId?: string\n dimension: keyof BudgetSpec\n limit: number\n consumed: number\n excessRatio: number\n timestamp: number\n}\n\nexport interface BudgetBreachReport {\n findings: BudgetBreachFinding[]\n byDimension: Record<string, number>\n byScenario: Record<string, number>\n byVariant: Record<string, number>\n totalRuns: number\n breachedRunRatio: number\n}\n\nexport async function budgetBreachView(\n store: TraceStore,\n options: { scenarioId?: string; variantId?: string } = {},\n): Promise<BudgetBreachReport> {\n const runs = await store.listRuns({\n scenarioId: options.scenarioId,\n variantId: options.variantId,\n })\n const findings: BudgetBreachFinding[] = []\n const byDimension: Record<string, number> = {}\n const byScenario: Record<string, number> = {}\n const byVariant: Record<string, number> = {}\n\n for (const run of runs) {\n const entries = await store.budget(run.runId)\n for (const e of entries) {\n if (!e.breached) continue\n const excessRatio = e.limit > 0 ? e.consumed / e.limit : Infinity\n findings.push({\n runId: run.runId,\n scenarioId: run.scenarioId,\n variantId: run.variantId,\n dimension: e.dimension,\n limit: e.limit,\n consumed: e.consumed,\n excessRatio,\n timestamp: e.timestamp,\n })\n byDimension[e.dimension] = (byDimension[e.dimension] ?? 0) + 1\n byScenario[run.scenarioId] = (byScenario[run.scenarioId] ?? 0) + 1\n if (run.variantId) byVariant[run.variantId] = (byVariant[run.variantId] ?? 0) + 1\n }\n }\n\n const breachedRuns = new Set(findings.map((f) => f.runId))\n return {\n findings,\n byDimension,\n byScenario,\n byVariant,\n totalRuns: runs.length,\n breachedRunRatio: runs.length > 0 ? breachedRuns.size / runs.length : 0,\n }\n}\n","/**\n * FailureClusterView — groups failed runs by (failureClass, triggerTool,\n * argHash-prefix) so weekly reviews can prioritize the top-N clusters.\n *\n * Each cluster includes: N runs, scenarios affected, representative\n * error message, a proposed mitigation hint (rule → action table).\n */\n\nimport { classifyFailure, DEFAULT_RULES, type FailureRule } from '../failure-taxonomy'\nimport { argHash, hasCapturedToolArgs, toolSpans } from '../trace/query'\nimport type { FailureClass, Span } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface FailureCluster {\n failureClass: FailureClass\n /** Tool name when the trigger was a tool span, else undefined. */\n toolName?: string\n /** First 16 chars of argHash — clusters similar args. */\n argPrefix?: string\n /**\n * Source dimension when the trigger was a judge span (e.g. `'format'`,\n * `'safety'`, `'correctness'`). Lets cross-template aggregators\n * group failures by the dimension that fired without overloading\n * `argPrefix`. Optional — clusters without this field deserialize cleanly.\n */\n dimension?: string\n runCount: number\n scenarioIds: string[]\n exampleError?: string\n exampleRunId: string\n}\n\nexport interface FailureClusterReport {\n clusters: FailureCluster[]\n totalFailures: number\n totalRuns: number\n}\n\nexport async function failureClusterView(\n store: TraceStore,\n options: { rules?: FailureRule[]; minClusterSize?: number } = {},\n): Promise<FailureClusterReport> {\n const rules = options.rules ?? DEFAULT_RULES\n const minSize = options.minClusterSize ?? 1\n const runs = await store.listRuns()\n\n type Key = string\n const clusters = new Map<Key, FailureCluster>()\n let totalFailures = 0\n\n for (const run of runs) {\n if (run.status === 'completed' && run.outcome?.pass !== false) continue\n totalFailures++\n const spans = await store.spans({ runId: run.runId })\n const events = await store.events({ runId: run.runId })\n const cls = classifyFailure({ run, spans, events }, rules)\n\n let toolName: string | undefined\n let argPrefix: string | undefined\n let dimension: string | undefined\n if (cls.triggerSpanId) {\n const trig = spans.find((s) => s.spanId === cls.triggerSpanId)\n if (trig?.kind === 'tool') {\n toolName = trig.toolName\n if (hasCapturedToolArgs(trig)) argPrefix = argHash(trig.args).slice(0, 16)\n } else if (trig?.kind === 'judge') {\n dimension = trig.dimension\n }\n }\n // Fallback: look at the last errored tool span\n if (!toolName) {\n const ts = await toolSpans(store, run.runId)\n const errored = ts.filter((t) => t.status === 'error').pop()\n if (errored) {\n toolName = errored.toolName\n if (hasCapturedToolArgs(errored)) argPrefix = argHash(errored.args).slice(0, 16)\n }\n }\n // Secondary signal: any judge span on the failed run carries a\n // dimension. Useful when the rule classified by judge score but\n // didn't surface the trigger span (or surfaced a non-judge span).\n if (!dimension) {\n const judge = spans.find((s) => s.kind === 'judge' && typeof s.dimension === 'string')\n if (judge?.kind === 'judge') dimension = judge.dimension\n }\n\n const key = `${cls.failureClass}|${toolName ?? ''}|${argPrefix ?? ''}|${dimension ?? ''}`\n let cluster = clusters.get(key)\n if (!cluster) {\n cluster = {\n failureClass: cls.failureClass,\n toolName,\n argPrefix,\n dimension,\n runCount: 0,\n scenarioIds: [],\n exampleRunId: run.runId,\n exampleError: firstErrorMessage(spans) ?? cls.reason,\n }\n clusters.set(key, cluster)\n }\n cluster.runCount++\n if (!cluster.scenarioIds.includes(run.scenarioId)) cluster.scenarioIds.push(run.scenarioId)\n }\n\n const arr = [...clusters.values()]\n .filter((c) => c.runCount >= minSize)\n .sort((a, b) => b.runCount - a.runCount)\n\n return { clusters: arr, totalFailures, totalRuns: runs.length }\n}\n\nfunction firstErrorMessage(spans: Span[]): string | undefined {\n const errored = spans.find((s) => s.status === 'error')\n return errored?.error\n}\n","/**\n * JudgeAgreementView — pairwise agreement between judges across the\n * corpus, grouped by dimension.\n *\n * Output drives two workflows:\n * - Judge robustness audit: \"does Claude agree with GPT at κ ≥ 0.6?\"\n * - Calibration tracking: κ vs golden human labels over time (by\n * providing a `humanGoldenJudgeId`).\n */\n\nimport { interRaterReliability, pearsonR } from '../statistics'\nimport type { JudgeSpan } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface JudgePair {\n judgeA: string\n judgeB: string\n dimension: string\n /** Number of (targetSpanId, dimension) tuples both judges scored. */\n commonItems: number\n pearson: number\n krippendorff: number\n}\n\nexport interface JudgeAgreementReport {\n pairs: JudgePair[]\n dimensions: string[]\n judgeIds: string[]\n}\n\nexport async function judgeAgreementView(store: TraceStore): Promise<JudgeAgreementReport> {\n const all = (await store.spans({ kind: 'judge' })).filter(\n (s): s is JudgeSpan => s.kind === 'judge',\n )\n if (all.length === 0) return { pairs: [], dimensions: [], judgeIds: [] }\n\n const byDimension = new Map<string, JudgeSpan[]>()\n for (const s of all) {\n const arr = byDimension.get(s.dimension) ?? []\n arr.push(s)\n byDimension.set(s.dimension, arr)\n }\n\n const judgeIds = [...new Set(all.map((s) => s.judgeId))].sort()\n const pairs: JudgePair[] = []\n for (const [dim, spans] of byDimension) {\n const byJudge = new Map<string, Map<string, number>>()\n for (const s of spans) {\n const m = byJudge.get(s.judgeId) ?? new Map<string, number>()\n m.set(s.targetSpanId, s.score)\n byJudge.set(s.judgeId, m)\n }\n const judgesHere = [...byJudge.keys()]\n for (let i = 0; i < judgesHere.length; i++) {\n for (let j = i + 1; j < judgesHere.length; j++) {\n const judgeI = judgesHere[i]!\n const judgeJ = judgesHere[j]!\n const a = byJudge.get(judgeI)!\n const b = byJudge.get(judgeJ)!\n const common: Array<[number, number]> = []\n for (const [target, scoreA] of a) {\n const scoreB = b.get(target)\n if (scoreB !== undefined) common.push([scoreA, scoreB])\n }\n if (common.length < 2) continue\n const judgeScores = common.map(\n ([scoreA, scoreB]) =>\n [\n { judgeName: judgeI, dimension: dim, score: scoreA, reasoning: '' },\n { judgeName: judgeJ, dimension: dim, score: scoreB, reasoning: '' },\n ] as const,\n )\n const k = interRaterReliability(\n judgeScores[0]!.map((_, k2) => judgeScores.map((pair) => pair[k2]!)),\n )\n pairs.push({\n judgeA: judgeI,\n judgeB: judgeJ,\n dimension: dim,\n commonItems: common.length,\n pearson: pearsonR(\n common.map((c) => c[0]),\n common.map((c) => c[1]),\n ),\n krippendorff: k,\n })\n }\n }\n }\n\n return {\n pairs: pairs.sort((a, b) => b.commonItems - a.commonItems),\n dimensions: [...byDimension.keys()].sort(),\n judgeIds,\n }\n}\n","/**\n * Tool-use metrics — derived purely from trace data.\n *\n * No scoring assumptions: consumers supply optional ground-truth tool\n * selections per turn + optional \"information used downstream\" signals.\n * Without those, we still compute descriptive metrics (error rate,\n * retry rate, duplicate-call rate) that are useful on their own.\n */\n\nimport { argHash, groupBy, hasCapturedToolArgs, toolSpans } from './trace/query'\nimport type { Span } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport interface ToolUseMetrics {\n runId: string\n totalCalls: number\n /** Calls whose arguments were captured and can be compared for duplication. */\n callsWithCapturedArgs: number\n byTool: Record<string, ToolStats>\n errorRate: number\n /** Ratio of captured-argument calls already seen with the same tool name and arguments. */\n duplicateRate: number\n /** Ratio of error calls followed by ≥1 retry on same tool. */\n retryRate: number\n /** Optional: of the calls agent made, fraction the evaluator marked as \"correct selection\". */\n selectionAccuracy?: number\n}\n\nexport interface ToolStats {\n calls: number\n callsWithCapturedArgs: number\n errors: number\n avgLatencyMs: number\n duplicates: number\n}\n\nexport interface ToolUseOptions {\n /** Map of spanId → whether the evaluator judged the tool selection correct. Optional. */\n selectionLabels?: Record<string, boolean>\n}\n\nexport async function computeToolUseMetrics(\n store: TraceStore,\n runId: string,\n options: ToolUseOptions = {},\n): Promise<ToolUseMetrics> {\n const tools = await toolSpans(store, runId)\n if (tools.length === 0) {\n return {\n runId,\n totalCalls: 0,\n callsWithCapturedArgs: 0,\n byTool: {},\n errorRate: 0,\n duplicateRate: 0,\n retryRate: 0,\n }\n }\n\n const byTool: Record<string, ToolStats> = {}\n let totalErrors = 0\n let totalDuplicates = 0\n let callsWithCapturedArgs = 0\n const sortedTools = [...tools].sort((a, b) => a.startedAt - b.startedAt)\n const seenSignatures = new Set<string>()\n\n // duplicate detection + per-tool aggregation\n for (const t of sortedTools) {\n byTool[t.toolName] ??= {\n calls: 0,\n callsWithCapturedArgs: 0,\n errors: 0,\n avgLatencyMs: 0,\n duplicates: 0,\n }\n const stat = byTool[t.toolName]!\n stat.calls += 1\n if (t.status === 'error') {\n stat.errors += 1\n totalErrors += 1\n }\n if (typeof t.latencyMs === 'number') stat.avgLatencyMs += t.latencyMs\n if (hasCapturedToolArgs(t)) {\n callsWithCapturedArgs += 1\n stat.callsWithCapturedArgs += 1\n const sig = `${t.toolName}|${argHash(t.args)}`\n if (seenSignatures.has(sig)) {\n stat.duplicates += 1\n totalDuplicates += 1\n }\n seenSignatures.add(sig)\n }\n }\n\n for (const stat of Object.values(byTool)) {\n stat.avgLatencyMs = stat.calls > 0 ? stat.avgLatencyMs / stat.calls : 0\n }\n\n // retry detection: per-tool chronological adjacency where error → next same-tool call\n let retryOpportunities = 0\n let retriesFollowed = 0\n for (const [, arr] of groupBy(sortedTools, (t) => t.toolName)) {\n for (let i = 0; i < arr.length; i++) {\n if (arr[i]!.status !== 'error') continue\n retryOpportunities += 1\n if (arr[i + 1]) retriesFollowed += 1\n }\n }\n const retryRate = retryOpportunities > 0 ? retriesFollowed / retryOpportunities : 0\n\n let selectionAccuracy: number | undefined\n if (options.selectionLabels) {\n const labeled = sortedTools.filter((t) => t.spanId in options.selectionLabels!)\n if (labeled.length > 0) {\n selectionAccuracy =\n labeled.filter((t) => options.selectionLabels![t.spanId]).length / labeled.length\n }\n }\n\n return {\n runId,\n totalCalls: sortedTools.length,\n callsWithCapturedArgs,\n byTool,\n errorRate: totalErrors / sortedTools.length,\n duplicateRate: callsWithCapturedArgs > 0 ? totalDuplicates / callsWithCapturedArgs : 0,\n retryRate,\n selectionAccuracy,\n }\n}\n\nexport type { Span }\n","/**\n * ToolWasteView — fraction of tool calls whose results weren't used\n * downstream. Without a \"used\" signal we fall back to structural\n * proxies: error calls, duplicate calls, and tool calls followed by\n * zero subsequent LLM spans are all considered waste.\n *\n * Consumers can pass a `usageOracle` that inspects a tool span and\n * returns true iff the tool's result appears in a later LLM message,\n * artifact, or state mutation — that's the canonical definition; the\n * default heuristic is a reasonable fallback.\n */\n\nimport { computeToolUseMetrics } from '../tool-use-metrics'\nimport { llmSpans, toolSpans } from '../trace/query'\nimport type { LlmSpan, ToolSpan } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface ToolWasteFinding {\n runId: string\n wastedCalls: number\n totalCalls: number\n wasteRate: number\n}\n\nexport interface ToolWasteReport {\n byRun: ToolWasteFinding[]\n overallWasteRate: number\n}\n\nexport interface ToolWasteOptions {\n runId?: string\n usageOracle?: (tool: ToolSpan, later: { llm: Awaited<ReturnType<typeof llmSpans>> }) => boolean\n}\n\nexport async function toolWasteView(\n store: TraceStore,\n options: ToolWasteOptions = {},\n): Promise<ToolWasteReport> {\n const runs = options.runId ? [options.runId] : (await store.listRuns()).map((r) => r.runId)\n\n const byRun: ToolWasteFinding[] = []\n let totalCalls = 0\n let totalWasted = 0\n for (const runId of runs) {\n const tools = await toolSpans(store, runId)\n if (tools.length === 0) {\n byRun.push({ runId, wastedCalls: 0, totalCalls: 0, wasteRate: 0 })\n continue\n }\n const llms = await llmSpans(store, runId)\n // Sort LLM spans once by start time, then build a suffix index of the\n // concatenated message text. `suffixText[i]` is the haystack of every\n // string message content in spans[i..]. Per tool we binary-search the\n // first span started strictly after the tool, then test that one suffix\n // — turning the per-tool O(llms × messages × content) scan into a single\n // O(log llms) lookup over precomputed text.\n const sortedLlm = [...llms].sort((a, b) => a.startedAt - b.startedAt)\n const startTimes = sortedLlm.map((l) => l.startedAt)\n const suffixText = buildSuffixText(sortedLlm)\n let wasted = 0\n for (const t of tools) {\n if (t.status === 'error') {\n wasted++\n continue\n }\n // First LLM span started strictly after this tool (upper-bound search).\n const cutoff = upperBound(startTimes, t.startedAt)\n if (options.usageOracle) {\n if (!options.usageOracle(t, { llm: sortedLlm.slice(cutoff) })) wasted++\n } else {\n // Default heuristic: a tool whose result is NOT mentioned in any\n // later LLM input message is likely wasted. An empty/null result has\n // no payload to propagate downstream — there is nothing to find in a\n // later message, so it is not evidence of waste; skip it.\n const resultStr = stringify(t.result)\n if (resultStr === '') continue\n const haystack = suffixText[cutoff] ?? ''\n const used = haystack.includes(resultStr.slice(0, 120))\n if (!used) wasted++\n }\n }\n const wasteRate = wasted / tools.length\n byRun.push({ runId, wastedCalls: wasted, totalCalls: tools.length, wasteRate })\n totalCalls += tools.length\n totalWasted += wasted\n }\n return { byRun, overallWasteRate: totalCalls > 0 ? totalWasted / totalCalls : 0 }\n}\n\n/**\n * Build per-position suffix haystacks: result[i] is the concatenation of every\n * string message content in spans[i..end]. Built back-to-front so each entry\n * reuses the next one — O(total message text) rather than O(spans²).\n */\nfunction buildSuffixText(spans: LlmSpan[]): string[] {\n const result = new Array<string>(spans.length + 1)\n result[spans.length] = ''\n for (let i = spans.length - 1; i >= 0; i--) {\n const own = spans[i]!.messages.map((m) =>\n typeof m.content === 'string' ? m.content : '',\n ).join('\\n')\n result[i] = `${own}\\n${result[i + 1]}`\n }\n return result\n}\n\n/** Index of the first element strictly greater than `target` in a sorted array. */\nfunction upperBound(sorted: number[], target: number): number {\n let lo = 0\n let hi = sorted.length\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (sorted[mid]! <= target) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\nfunction stringify(v: unknown): string {\n if (v === null || v === undefined) return ''\n if (typeof v === 'string') return v\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n\n// Re-export for convenience in consumers that want both descriptive and usage metrics.\nexport { computeToolUseMetrics }\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { c as errorMessage, n as CaptureIntegrityError, s as ValidationError } from "../errors-DeEEV9Vx.js";
2
2
  import { i as compareCodeUnits } from "../canonical-CicJlINA.js";
3
- import { r as pairedBootstrap } from "../paired-tests-C2zUqgUW.js";
4
- import { t as mean } from "../mean-BPuUNznQ.js";
3
+ import { t as mean } from "../mean-DDFhslBt.js";
4
+ import { r as pairedBootstrap } from "../paired-tests-kASEKpc-.js";
5
5
  import { n as contentHash } from "../verdict-cache-BVH-fl18.js";
6
6
  import { n as isRecord } from "../json-DtvZNAU9.js";
7
7
  import { t as certificationEvidenceDigest } from "../verdict-C8TcdwfD.js";
package/dist/traces.d.ts CHANGED
@@ -6,28 +6,15 @@ import { G as InMemoryRawProviderSink, J as ProviderRedactor, K as InMemoryRawPr
6
6
  import { a as RunFilter, i as InMemoryTraceStore, n as FileSystemTraceStore, o as SpanFilter, r as FileSystemTraceStoreOptions, s as TraceStore, t as EventFilter } from "./store-CMs5wGXP.js";
7
7
  import { d as BuildTraceAnalysisToolsOptions, f as TRACE_ANALYST_TOOL_NAMESPACE, h as buildTraceAnalysisToolDescriptors, m as UNTRUSTED_TRACE_TEXT, p as TraceAnalysisToolDescriptor } from "./engine-CaHaCc3W.js";
8
8
  import { a as SpanHandle, i as RunCompleteHookContext, n as CaptureWrite, o as TraceEmitter, r as RunCompleteHook, s as TraceEmitterOptions, t as CaptureErrorHandler } from "./emitter-mAXC5PSN.js";
9
- import { _ as shareAllowed, a as RedactionProfile, c as ShareSafetyFinding, d as assessShareSafety, f as combineVerdicts, g as redactText, h as redactForShare, i as RedactionFinding, l as ShareSafetyStatus, m as redact, n as REDACTION_VERSION, o as RedactionReport, p as emptyRedactionReport, r as RedactOptions, s as SafetyCategory, t as AssessOptions, u as ShareSafetyVerdict } from "./redact-C_wzC4c_.js";
10
- import { A as TraceInsightReadiness, B as isTraceInsightEvidence, C as TraceInsightContext, D as TraceInsightPromptInput, E as TraceInsightPanelRole, F as describeTraceInsightScope, G as AnalyzeTracesResult, H as tokenizeDomainWords, I as domainEvidencePattern, K as analyzeTraces, L as inferDomainKeywords, M as TraceInsightTask, N as buildTraceInsightContext, O as TraceInsightQualityGate, P as buildTraceInsightPrompt, R as isTraceInsightArtifact, S as TraceInsightAttribution, T as TraceInsightFinding, U as AnalyzeTracesInput, V as scoreTraceInsightReadiness, W as AnalyzeTracesOptions, _ as ToolSpansToTraceAnalysisStoreOptions, a as captureFetchToRawSink, b as OtlpSpan, c as ExtractedUsage, d as extractUsageFromSse, f as OtlpFileTraceStore, g as spanRecordsToTraceAnalysisStore, h as otlpTextToTraceAnalysisStore, i as CaptureFetchOptions, j as TraceInsightSuite, k as TraceInsightQuestion, l as SseUsageMode, m as SpanRecordsToTraceAnalysisStoreOptions, n as toolSpansToTraceAnalysisStore, o as OtlpFlatLine, p as OtlpFileTraceStoreOptions, r as CaptureFetchContext, s as ExtractUsageFromSseOptions, t as ToolTraceMissingError, u as extractUsage, v as OtlpExport, w as TraceInsightEvidence, x as exportRunAsOtlp, y as OtlpResourceSpans, z as isTraceInsightAttribution } from "./store-tool-spans-B3i3fl0A.js";
9
+ import { C as classifyKey, E as normalizeKey, _ as redactText, a as RedactionFinding, c as SafetyCategory, d as ShareSafetyVerdict, f as assessShareSafety, g as redactForShare, h as redact, i as RedactOptions, l as ShareSafetyFinding, m as emptyRedactionReport, o as RedactionProfile, p as combineVerdicts, r as REDACTION_VERSION, s as RedactionReport, t as AssessOptions, u as ShareSafetyStatus, v as shareAllowed, w as detectCredential } from "./redact-jrT0APTU.js";
10
+ import { A as TraceInsightReadiness, B as isTraceInsightEvidence, C as TraceInsightContext, D as TraceInsightPromptInput, E as TraceInsightPanelRole, F as describeTraceInsightScope, G as AnalyzeTracesResult, H as tokenizeDomainWords, I as domainEvidencePattern, K as analyzeTraces, L as inferDomainKeywords, M as TraceInsightTask, N as buildTraceInsightContext, O as TraceInsightQualityGate, P as buildTraceInsightPrompt, R as isTraceInsightArtifact, S as TraceInsightAttribution, T as TraceInsightFinding, U as AnalyzeTracesInput, V as scoreTraceInsightReadiness, W as AnalyzeTracesOptions, _ as ToolSpansToTraceAnalysisStoreOptions, a as captureFetchToRawSink, b as OtlpSpan, c as ExtractedUsage, d as extractUsageFromSse, f as OtlpFileTraceStore, g as spanRecordsToTraceAnalysisStore, h as otlpTextToTraceAnalysisStore, i as CaptureFetchOptions, j as TraceInsightSuite, k as TraceInsightQuestion, l as SseUsageMode, m as SpanRecordsToTraceAnalysisStoreOptions, n as toolSpansToTraceAnalysisStore, o as OtlpFlatLine, p as OtlpFileTraceStoreOptions, r as CaptureFetchContext, s as ExtractUsageFromSseOptions, t as ToolTraceMissingError, u as extractUsage, v as OtlpExport, w as TraceInsightEvidence, x as exportRunAsOtlp, y as OtlpResourceSpans, z as isTraceInsightAttribution } from "./store-tool-spans-lWf6INTH.js";
11
11
  import { a as RunIntegrityReport, i as RunIntegrityIssueCode, n as RunIntegrityExpectations, o as assertRunCaptured, r as RunIntegrityIssue, t as RunIntegrityError } from "./integrity-BAdVzT8u.js";
12
12
  import { D as asNumber, E as applyLlmSpanOtlpAttributes, O as contextInputTokens, T as TOOL_NAME_ATTR_KEYS, _ as LlmSpanOtlpInput, a as LLM_CACHE_WRITE_TOKEN_ATTR_KEYS, c as LLM_COST_USD, d as LLM_MODEL_ATTR_KEYS, f as LLM_MODEL_NAME, g as LLM_REASONING_TOKEN_ATTR_KEYS, h as LLM_REASONING_TOKENS, i as LLM_CACHE_WRITE_TOKENS, k as firstNumberAttr, l as LLM_INPUT_TOKENS, m as LLM_OUTPUT_TOKEN_ATTR_KEYS, n as LLM_CACHED_TOKENS, o as LLM_CONTEXT_TOKENS, p as LLM_OUTPUT_TOKENS, r as LLM_CACHED_TOKEN_ATTR_KEYS, s as LLM_COST_ATTR_KEYS, t as INPUT_VALUE, u as LLM_INPUT_TOKEN_ATTR_KEYS, v as OPENINFERENCE_SPAN_KIND, w as TOOL_NAME, x as SPAN_KIND_ATTR_KEYS, y as OUTPUT_VALUE } from "./attribute-vocabulary-5oo8ykIx.js";
13
13
  import { a as llmSpans, c as toolSpans, i as judgeSpans, n as argHash, o as runFailureClass, r as groupBy, s as runsForScenario, t as RunMetric } from "./query-UD0B08Sb.js";
14
14
  import { SpanKind as SpanKind$1 } from "@tangle-network/agent-trace-contract";
15
+ import { OtlpFlatSpan } from "@tangle-network/agent-trace-contract/otlp";
15
16
  type ToolSpanOtlpInput = Pick<ToolSpan, 'toolName' | 'args' | 'argsCaptured' | 'result' | 'latencyMs'>;
16
17
  export declare function applyToolSpanOtlpAttributes(attributes: Record<string, unknown>, span: ToolSpanOtlpInput): void;
17
- /**
18
- * Canonical snake_case form of a field name, so camelCase, kebab-case, dotted
19
- * and snake_case spellings match one list: `userPassword`, `user-password` and
20
- * `user.password` all become `user_password`.
21
- */
22
- export declare function normalizeKey(key: string): string;
23
- /**
24
- * The safety category a field name puts its value in, or undefined for an
25
- * ordinary field. Token counts and model limits (`inputTokens`, `max_tokens`,
26
- * `token_count`) and names such as `author` are not credentials.
27
- */
28
- export declare function classifyKey(key: string): SafetyCategory | undefined;
29
- /** The first credential detector that matches, or undefined. */
30
- export declare function detectCredential(text: string): string | undefined;
31
18
  interface TracesToOtlpResult {
32
19
  /** Total spans emitted across every cell. */
33
20
  spanCount: number;
@@ -162,32 +149,24 @@ interface FlattenOtlpOptions {
162
149
  attributeVocabulary?: 'openinference' | 'none';
163
150
  /** Override the numeric-kind → otlp-string mapping. */
164
151
  kindMap?: Partial<Record<number, string>>;
152
+ /** `'scalar'` (default) is the analyst line below. `'collector'` returns
153
+ * agent-trace-contract's lossless rows: the export's own nanosecond strings
154
+ * and merged resource + span attributes. */
155
+ projection?: 'scalar' | 'collector';
165
156
  }
166
- export declare function flattenOtlpExportToNdjson(otlpExport: OtlpExport, opts?: FlattenOtlpOptions): OtlpFlatLine[];
167
157
  /**
168
- * The structural fields a flat OTLP-JSONL line projects to. `attributes`
169
- * is the merged resource+span attribute map (span overrides resource);
170
- * the named fields are the pivots every reader of a trace needs without
171
- * paying the full attribute materialisation.
158
+ * By default, the analyst's line: scalar attribute values, ISO times, named
159
+ * kind and status codes, and the OpenInference vocabulary. With
160
+ * `{ projection: 'collector' }`, `decodeOtlpTraceExport`'s rows unchanged.
172
161
  */
173
- interface ProjectedOtlpSpan {
174
- trace_id: string;
175
- span_id: string;
176
- parent_span_id: string | null;
177
- name: string;
178
- kind: TraceAnalystSpanKind;
179
- start_time: string;
180
- end_time: string;
181
- duration_ms: number;
182
- status: TraceAnalystSpanStatus;
162
+ export declare function flattenOtlpExportToNdjson(otlpExport: unknown, opts: FlattenOtlpOptions & {
163
+ projection: 'collector';
164
+ }): OtlpFlatSpan[];
165
+ export declare function flattenOtlpExportToNdjson(otlpExport: OtlpExport, opts?: FlattenOtlpOptions): OtlpFlatLine[];
166
+ /** The structural fields a flat OTLP-JSONL line projects to: the analyst's span view. */
167
+ type ProjectedOtlpSpan = TraceAnalystSpan & {
183
168
  status_message: string | undefined;
184
- service_name: string | null;
185
- agent_name: string | null;
186
- model_name: string | null;
187
- tool_name: string | null;
188
- /** Merged resource + span attributes, span winning on overlap. */
189
- attributes: Record<string, unknown>;
190
- }
169
+ };
191
170
  /**
192
171
  * Project one parsed OTLP-JSONL object to `ProjectedOtlpSpan`, or `null`
193
172
  * when the line is missing the mandatory `trace_id` + `span_id`.
@@ -301,5 +280,5 @@ export declare function otlpToRunRecords(otlpJsonl: string, opts: OtlpToRunRecor
301
280
  * paths share projection, reconciliation, validation, and ordering.
302
281
  */
303
282
  export declare function otlpRowsToRunRecords(rows: Iterable<object>, opts: OtlpToRunRecordsOptions): RunRecord[];
304
- export { type AnalyzeTracesInput, type AnalyzeTracesOptions, type AnalyzeTracesResult, type Artifact, type AssessOptions, type BoundedTraceAnalysisStoreOptions, type BudgetLedgerEntry, type BudgetSpec, type BuildTraceAnalysisToolsOptions, type CaptureErrorHandler, type CaptureFetchContext, type CaptureFetchOptions, type CaptureWrite, DEFAULT_TRACE_ANALYST_BUDGETS, type DatasetOverview, type ErrorCluster, type EventFilter, type EventKind, type ExtractUsageFromSseOptions, type ExtractedUsage, FAILURE_CLASSES, type FailureClass, FileSystemRawProviderSink, type FileSystemRawProviderSinkOptions, FileSystemTraceStore, type FileSystemTraceStoreOptions, type FlattenOtlpOptions, type GenericSpan, INPUT_VALUE, InMemoryRawProviderSink, type InMemoryRawProviderSinkOptions, InMemoryTraceStore, type JudgeSpan, LLM_CACHED_TOKENS, LLM_CACHED_TOKEN_ATTR_KEYS, LLM_CACHE_WRITE_TOKENS, LLM_CACHE_WRITE_TOKEN_ATTR_KEYS, LLM_CONTEXT_TOKENS, LLM_COST_ATTR_KEYS, LLM_COST_USD, LLM_INPUT_TOKENS, LLM_INPUT_TOKEN_ATTR_KEYS, LLM_MODEL_ATTR_KEYS, LLM_MODEL_NAME, LLM_OUTPUT_TOKENS, LLM_OUTPUT_TOKEN_ATTR_KEYS, LLM_REASONING_TOKENS, LLM_REASONING_TOKEN_ATTR_KEYS, type LlmSpan, type LlmSpanOtlpInput, type Message, NoopRawProviderSink, OPENINFERENCE_SPAN_KIND, OUTPUT_VALUE, type OtlpExport, OtlpFileTraceStore, type OtlpFileTraceStoreOptions, type OtlpFlatLine, type OtlpResourceSpans, type OtlpSpan, type OtlpToRunRecordsOptions, type OtlpTraceRunRecord, type ProjectedOtlpSpan, type ProviderRedactor, type QueryTracesPage, REDACTION_VERSION, type RawProviderDirection, type RawProviderEvent, type RawProviderSink, type RawProviderSinkFilter, type ReadSpanSourceInput, type ReadSpanSourceResult, type RedactOptions, type RedactionFinding, type RedactionProfile, type RedactionReport, type RetrievalSpan, type Run, type RunCaptureReport, type RunCompleteHook, type RunCompleteHookContext, type RunFilter, RunIntegrityError, type RunIntegrityExpectations, type RunIntegrityIssue, type RunIntegrityIssueCode, type RunIntegrityReport, type RunLayer, type RunMetric, type RunStatus, SPAN_KIND_ATTR_KEYS, type SafetyCategory, type SandboxSpan, type SearchSpanResult, type SearchTraceResult, type ShareSafetyFinding, type ShareSafetyStatus, type ShareSafetyVerdict, type Span, type SpanBase, type SpanFilter, type SpanHandle, type SpanKind, type SpanMatchRecord, type SpanRecordsToTraceAnalysisStoreOptions, type SpanSourceReader, type SpanStatus, type SseUsageMode, TOOL_NAME, TOOL_NAME_ATTR_KEYS, TRACE_ANALYSIS_LIMITS, TRACE_ANALYST_TOOL_NAMESPACE, type ToolSpan, type ToolSpanOtlpInput, type ToolSpansToTraceAnalysisStoreOptions, ToolTraceMissingError, type TraceAggregate, type TraceAnalysisStore, type TraceAnalysisStoreContext, type TraceAnalysisToolDescriptor, type TraceAnalystByteBudgets, type TraceAnalystFilters, type TraceAnalystHookOptions, type TraceAnalystSpan, type TraceAnalystSpanKind, type TraceAnalystSpanStatus, type TraceAnalystTraceSummary, TraceEmitter, type TraceEmitterOptions, type TraceEvent, type TraceInsightAttribution, type TraceInsightContext, type TraceInsightEvidence, type TraceInsightFinding, type TraceInsightPanelRole, type TraceInsightPromptInput, type TraceInsightQualityGate, type TraceInsightQuestion, type TraceInsightReadiness, type TraceInsightSuite, type TraceInsightTask, type TraceRunOutcome, type TraceStore, type TraceStoreSource, type TraceStoreToOtlpOptions, type TracesToOtlpResult, UNTRUSTED_TRACE_TEXT, type ViewSpansResult, type ViewTraceOversized, type ViewTraceResult, analyzeTraces, applyLlmSpanOtlpAttributes, argHash, asNumber, assertRunCaptured, assessShareSafety, buildTraceAnalysisToolDescriptors, buildTraceInsightContext, buildTraceInsightPrompt, captureFetchToRawSink, combineVerdicts, contextInputTokens, createBoundedTraceAnalysisStore, describeTraceInsightScope, domainEvidencePattern, emptyRedactionReport, exportRunAsOtlp, extractUsage, extractUsageFromSse, firstNumberAttr, groupBy, inferDomainKeywords, isJudgeSpan, isLlmSpan, isToolSpan, isTraceInsightArtifact, isTraceInsightAttribution, isTraceInsightEvidence, judgeSpans, llmSpans, otlpTextToTraceAnalysisStore, redact, redactForShare, redactText, runFailureClass, runsForScenario, scoreTraceInsightReadiness, shareAllowed, spanRecordsToTraceAnalysisStore, tokenizeDomainWords, toolSpans, toolSpansToTraceAnalysisStore };
283
+ export { type AnalyzeTracesInput, type AnalyzeTracesOptions, type AnalyzeTracesResult, type Artifact, type AssessOptions, type BoundedTraceAnalysisStoreOptions, type BudgetLedgerEntry, type BudgetSpec, type BuildTraceAnalysisToolsOptions, type CaptureErrorHandler, type CaptureFetchContext, type CaptureFetchOptions, type CaptureWrite, DEFAULT_TRACE_ANALYST_BUDGETS, type DatasetOverview, type ErrorCluster, type EventFilter, type EventKind, type ExtractUsageFromSseOptions, type ExtractedUsage, FAILURE_CLASSES, type FailureClass, FileSystemRawProviderSink, type FileSystemRawProviderSinkOptions, FileSystemTraceStore, type FileSystemTraceStoreOptions, type FlattenOtlpOptions, type GenericSpan, INPUT_VALUE, InMemoryRawProviderSink, type InMemoryRawProviderSinkOptions, InMemoryTraceStore, type JudgeSpan, LLM_CACHED_TOKENS, LLM_CACHED_TOKEN_ATTR_KEYS, LLM_CACHE_WRITE_TOKENS, LLM_CACHE_WRITE_TOKEN_ATTR_KEYS, LLM_CONTEXT_TOKENS, LLM_COST_ATTR_KEYS, LLM_COST_USD, LLM_INPUT_TOKENS, LLM_INPUT_TOKEN_ATTR_KEYS, LLM_MODEL_ATTR_KEYS, LLM_MODEL_NAME, LLM_OUTPUT_TOKENS, LLM_OUTPUT_TOKEN_ATTR_KEYS, LLM_REASONING_TOKENS, LLM_REASONING_TOKEN_ATTR_KEYS, type LlmSpan, type LlmSpanOtlpInput, type Message, NoopRawProviderSink, OPENINFERENCE_SPAN_KIND, OUTPUT_VALUE, type OtlpExport, OtlpFileTraceStore, type OtlpFileTraceStoreOptions, type OtlpFlatLine, type OtlpResourceSpans, type OtlpSpan, type OtlpToRunRecordsOptions, type OtlpTraceRunRecord, type ProjectedOtlpSpan, type ProviderRedactor, type QueryTracesPage, REDACTION_VERSION, type RawProviderDirection, type RawProviderEvent, type RawProviderSink, type RawProviderSinkFilter, type ReadSpanSourceInput, type ReadSpanSourceResult, type RedactOptions, type RedactionFinding, type RedactionProfile, type RedactionReport, type RetrievalSpan, type Run, type RunCaptureReport, type RunCompleteHook, type RunCompleteHookContext, type RunFilter, RunIntegrityError, type RunIntegrityExpectations, type RunIntegrityIssue, type RunIntegrityIssueCode, type RunIntegrityReport, type RunLayer, type RunMetric, type RunStatus, SPAN_KIND_ATTR_KEYS, type SafetyCategory, type SandboxSpan, type SearchSpanResult, type SearchTraceResult, type ShareSafetyFinding, type ShareSafetyStatus, type ShareSafetyVerdict, type Span, type SpanBase, type SpanFilter, type SpanHandle, type SpanKind, type SpanMatchRecord, type SpanRecordsToTraceAnalysisStoreOptions, type SpanSourceReader, type SpanStatus, type SseUsageMode, TOOL_NAME, TOOL_NAME_ATTR_KEYS, TRACE_ANALYSIS_LIMITS, TRACE_ANALYST_TOOL_NAMESPACE, type ToolSpan, type ToolSpanOtlpInput, type ToolSpansToTraceAnalysisStoreOptions, ToolTraceMissingError, type TraceAggregate, type TraceAnalysisStore, type TraceAnalysisStoreContext, type TraceAnalysisToolDescriptor, type TraceAnalystByteBudgets, type TraceAnalystFilters, type TraceAnalystHookOptions, type TraceAnalystSpan, type TraceAnalystSpanKind, type TraceAnalystSpanStatus, type TraceAnalystTraceSummary, TraceEmitter, type TraceEmitterOptions, type TraceEvent, type TraceInsightAttribution, type TraceInsightContext, type TraceInsightEvidence, type TraceInsightFinding, type TraceInsightPanelRole, type TraceInsightPromptInput, type TraceInsightQualityGate, type TraceInsightQuestion, type TraceInsightReadiness, type TraceInsightSuite, type TraceInsightTask, type TraceRunOutcome, type TraceStore, type TraceStoreSource, type TraceStoreToOtlpOptions, type TracesToOtlpResult, UNTRUSTED_TRACE_TEXT, type ViewSpansResult, type ViewTraceOversized, type ViewTraceResult, analyzeTraces, applyLlmSpanOtlpAttributes, argHash, asNumber, assertRunCaptured, assessShareSafety, buildTraceAnalysisToolDescriptors, buildTraceInsightContext, buildTraceInsightPrompt, captureFetchToRawSink, classifyKey, combineVerdicts, contextInputTokens, createBoundedTraceAnalysisStore, describeTraceInsightScope, detectCredential, domainEvidencePattern, emptyRedactionReport, exportRunAsOtlp, extractUsage, extractUsageFromSse, firstNumberAttr, groupBy, inferDomainKeywords, isJudgeSpan, isLlmSpan, isToolSpan, isTraceInsightArtifact, isTraceInsightAttribution, isTraceInsightEvidence, judgeSpans, llmSpans, normalizeKey, otlpTextToTraceAnalysisStore, redact, redactForShare, redactText, runFailureClass, runsForScenario, scoreTraceInsightReadiness, shareAllowed, spanRecordsToTraceAnalysisStore, tokenizeDomainWords, toolSpans, toolSpansToTraceAnalysisStore };
305
284
  //# sourceMappingURL=traces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"traces.d.ts","names":[],"sources":["../src/trace/otlp-attributes.ts","../src/trace/redaction/detectors.ts","../src/trace/store-to-otlp.ts","../src/trace-analyst/errors.ts","../src/trace-analyst/hook.ts","../src/trace-analyst/otlp-flatten.ts","../src/trace-analyst/otlp-span.ts","../src/trace-analyst/otlp-to-run-records.ts"],"mappings":";;;;;;;;;;;;;;KAsBY,oBAAoB,KAC9B;wBAkBc,4BACd,YAAY,yBACZ,MAAM;;;;;;wBClCQ,aAAa;;;;;;wBAmNb,YAAY,cAAc;;wBAyN1B,iBAAiB;UChZhB;;EAEf;;EAEA;;EAEA;;;EAGA;;;;;;;;;;;;UAae;;EAEf;;EAEA;;EAEA;;;;UAKe;;;EAGf;;;EAGA,sBAAsB,KAAK,QAAQ;;EAEnC,iBAAiB,KAAK,QAAQ;;;;;;;;;;;wBAYhB,yBACd,iBAAiB,4BAA4B,oBAC7C,iBACA,OAAM,0BACL;;qBCrFU,qCAAqC;WAC/B;;;qBAIN,gCAAgC;WAC1B;WACR;WACA;WACA;EAEG,YAAA,mBAAmB,gBAAgB,eAAe;;;qBASnD,wCAAwC;WAClC;WACR;EAEG,YAAA,mBAAmB,iBAAiB;IAAY;;;qBAMjD,8BAA8B;WACxB;WACR;EAEG,YAAA;;qBAMD,+BAA+B;WACjC;WACA;WACA;EAEG,YAAA,cAAc,oBAAoB;;qBA2BnC,2BAA2B;WACrB;WACR;EAEG,YAAA;;qBAMD,0BAA0B;WACpB;WACR;WACA;EAEG,YAAA,kBAAkB;;UC1Ef;;;;;;EAMf,SAAS,KAAK;IAAoC,SAAS;;;;;;;EAM3D;;;;;;EAMA,QAAQ,QAAQ,qBAAqB,KAAK,2BAA2B;;;;;EAKrE,aAAa,KAAK;;;;;;EAMlB,UAAU,QAAQ,qBAAqB,KAAK;;wBAM9B,0BAA0B,MAAM,0BAA0B;UCnCzD;;;;EAIf;;EAEA,UAAU,QAAQ;;wBA+DJ,0BACd,YAAY,YACZ,OAAM,qBACL;;;;;;;UC7Dc;EACf;EACA;EACA;EACA;EACA,MAAM;EACN;EACA;EACA;EACA,QAAQ;EACR;EACA;EACA;EACA;EACA;;EAEA,YAAY;;;;;;wBAOE,oBAAoB,KAAK,0BAA0B;wBAoHnD,SAAS;;wBAKT,gBACd,OAAO,yBACP;UChHe;;EAEf;;;EAGA;;;EAGA,WAAW;;EAEX;;EAEA;;EAEA;;EAEA;;;;;;;EAOA;;;;;;EAMA;;;;;;;;;EASA,wBAAwB;;;;;;;;;EASxB,iBAAiB,eAAe,MAAM;;;;;EAKtC,yBAAyB,kBAAkB;;;;;;UAO5B;EACf,QAAQ;;EAER;;EAEA;;;UAIe;EACf;;EAEA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;;EAEZ;EACA;EACA;EACA;EACA;;EAEA,iBAAiB;;;;;;;wBAeH,iBAAiB,mBAAmB,MAAM,0BAA0B;;;;;;wBASpE,qBACd,MAAM,kBACN,MAAM,0BACL"}
1
+ {"version":3,"file":"traces.d.ts","names":[],"sources":["../src/trace/otlp-attributes.ts","../src/trace/store-to-otlp.ts","../src/trace-analyst/errors.ts","../src/trace-analyst/hook.ts","../src/trace-analyst/otlp-flatten.ts","../src/trace-analyst/otlp-span.ts","../src/trace-analyst/otlp-to-run-records.ts"],"mappings":";;;;;;;;;;;;;;;KAsBY,oBAAoB,KAC9B;wBAkBc,4BACd,YAAY,yBACZ,MAAM;UCNS;;EAEf;;EAEA;;EAEA;;;EAGA;;;;;;;;;;;;UAae;;EAEf;;EAEA;;EAEA;;;;UAKe;;;EAGf;;;EAGA,sBAAsB,KAAK,QAAQ;;EAEnC,iBAAiB,KAAK,QAAQ;;;;;;;;;;;wBAYhB,yBACd,iBAAiB,4BAA4B,oBAC7C,iBACA,OAAM,0BACL;;qBCrFU,qCAAqC;WAC/B;;;qBAIN,gCAAgC;WAC1B;WACR;WACA;WACA;EAEG,YAAA,mBAAmB,gBAAgB,eAAe;;;qBASnD,wCAAwC;WAClC;WACR;EAEG,YAAA,mBAAmB,iBAAiB;IAAY;;;qBAMjD,8BAA8B;WACxB;WACR;EAEG,YAAA;;qBAMD,+BAA+B;WACjC;WACA;WACA;EAEG,YAAA,cAAc,oBAAoB;;qBA2BnC,2BAA2B;WACrB;WACR;EAEG,YAAA;;qBAMD,0BAA0B;WACpB;WACR;WACA;EAEG,YAAA,kBAAkB;;UC1Ef;;;;;;EAMf,SAAS,KAAK;IAAoC,SAAS;;;;;;;EAM3D;;;;;;EAMA,QAAQ,QAAQ,qBAAqB,KAAK,2BAA2B;;;;;EAKrE,aAAa,KAAK;;;;;;EAMlB,UAAU,QAAQ,qBAAqB,KAAK;;wBAM9B,0BAA0B,MAAM,0BAA0B;UClCzD;;;;EAIf;;EAEA,UAAU,QAAQ;;;;EAIlB;;;;;;;wBA6Cc,0BACd,qBACA,MAAM;EAAuB;IAC5B;wBACa,0BACd,YAAY,YACZ,OAAO,qBACN;;KCzDS,oBAAoB;EAAqB;;;;;;wBAMrC,oBAAoB,KAAK,0BAA0B;wBAqHnD,SAAS;;wBAKT,gBACd,OAAO,yBACP;UC3Fe;;EAEf;;;EAGA;;;EAGA,WAAW;;EAEX;;EAEA;;EAEA;;EAEA;;;;;;;EAOA;;;;;;EAMA;;;;;;;;;EASA,wBAAwB;;;;;;;;;EASxB,iBAAiB,eAAe,MAAM;;;;;EAKtC,yBAAyB,kBAAkB;;;;;;UAO5B;EACf,QAAQ;;EAER;;EAEA;;;UAIe;EACf;;EAEA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;;EAEZ;EACA;EACA;EACA;EACA;;EAEA,iBAAiB;;;;;;;wBAeH,iBAAiB,mBAAmB,MAAM,0BAA0B;;;;;;wBASpE,qBACd,MAAM,kBACN,MAAM,0BACL"}
package/dist/traces.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { i as isToolSpan, n as isJudgeSpan, r as isLlmSpan, t as FAILURE_CLASSES } from "./schema-D-xu3MU_.js";
2
2
  import { c as validateRunRecord, i as modelHasSnapshot } from "./run-record-DEjx43cI.js";
3
3
  import { a as llmSpans, c as runsForScenario, i as judgeSpans, l as toolSpans, n as groupBy, o as runFailureClass, t as argHash } from "./query-CGXzO9d4.js";
4
- import { a as redact, c as shareAllowed, f as normalizeKey, i as emptyRedactionReport, l as classifyKey, n as assessShareSafety, o as redactForShare, r as combineVerdicts, s as redactText, t as REDACTION_VERSION, u as detectCredential } from "./redact-D6APJS1d.js";
4
+ import { a as emptyRedactionReport, c as redactText, f as classifyKey, g as normalizeKey, i as combineVerdicts, l as shareAllowed, n as REDACTION_VERSION, o as redact, p as detectCredential, r as assessShareSafety, s as redactForShare } from "./redact-zp_ILC4l.js";
5
5
  import { C as asString, D as projectOtlpFlatLine, E as firstStringAttr, O as spanEpochMillis, S as TraceNotFoundError, _ as TraceAnalysisStoreContractError, a as UNTRUSTED_TRACE_TEXT, b as TraceFileMissingError, c as createBoundedTraceAnalysisStore, g as TraceAnalysisLimitError, h as SpanNotFoundError, i as TRACE_ANALYST_TOOL_NAMESPACE, m as TRACE_ANALYSIS_LIMITS, o as buildTraceAnalysisToolDescriptors, p as DEFAULT_TRACE_ANALYST_BUDGETS, v as TraceAnalysisValidationError, w as compareSpanTime, x as TraceFileTooLargeError } from "./kind-factory-VKysp1ds.js";
6
6
  import { INPUT_VALUE, LLM_CACHED_TOKENS, LLM_CACHED_TOKEN_ATTR_KEYS, LLM_CACHE_WRITE_TOKENS, LLM_CACHE_WRITE_TOKEN_ATTR_KEYS, LLM_CONTEXT_TOKENS, LLM_COST_ATTR_KEYS, LLM_COST_USD, LLM_INPUT_TOKENS, LLM_INPUT_TOKEN_ATTR_KEYS, LLM_MODEL_ATTR_KEYS, LLM_MODEL_NAME, LLM_OUTPUT_TOKENS, LLM_OUTPUT_TOKEN_ATTR_KEYS, LLM_REASONING_TOKENS, LLM_REASONING_TOKEN_ATTR_KEYS, OPENINFERENCE_SPAN_KIND, OUTPUT_VALUE, SPAN_KIND_ATTR_KEYS, TOOL_NAME, TOOL_NAME_ATTR_KEYS, applyLlmSpanOtlpAttributes, asNumber, contextInputTokens, firstNumberAttr } from "./trace-attributes.js";
7
7
  import { n as extractUsageFromSse, t as extractUsage } from "./extract-usage-ISFqhfDz.js";
8
- import { n as InMemoryRawProviderSink, r as NoopRawProviderSink, t as FileSystemRawProviderSink } from "./raw-provider-sink-DDLkP_eF.js";
9
- import { _ as exportRunAsOtlp, a as spanStatusToOtlp, b as captureFetchToRawSink, c as describeTraceInsightScope, d as isTraceInsightArtifact, f as isTraceInsightAttribution, g as analyzeTraces, h as tokenizeDomainWords, i as epochMillisToIso, l as domainEvidencePattern, m as scoreTraceInsightReadiness, n as toolSpansToTraceAnalysisStore, o as buildTraceInsightContext, p as isTraceInsightEvidence, r as createOtlpFlatLine, s as buildTraceInsightPrompt, t as ToolTraceMissingError, u as inferDomainKeywords, v as spanIdForWire, y as traceIdForWire } from "./store-tool-spans-C2g8UYm-.js";
8
+ import { n as InMemoryRawProviderSink, r as NoopRawProviderSink, t as FileSystemRawProviderSink } from "./raw-provider-sink-RbaEv2vB.js";
9
+ import { _ as exportRunAsOtlp, a as spanStatusToOtlp, c as describeTraceInsightScope, d as isTraceInsightArtifact, f as isTraceInsightAttribution, g as analyzeTraces, h as tokenizeDomainWords, i as epochMillisToIso, l as domainEvidencePattern, m as scoreTraceInsightReadiness, n as toolSpansToTraceAnalysisStore, o as buildTraceInsightContext, p as isTraceInsightEvidence, r as createOtlpFlatLine, s as buildTraceInsightPrompt, t as ToolTraceMissingError, u as inferDomainKeywords, v as captureFetchToRawSink } from "./store-tool-spans-GGaCijFy.js";
10
10
  import { t as TraceEmitter } from "./emitter-DhQ65mza.js";
11
11
  import { n as assertRunCaptured, t as RunIntegrityError } from "./integrity-DOHt1mwU.js";
12
12
  import { n as traceSpanKindToOpenInferenceKind, t as applyToolSpanOtlpAttributes } from "./otlp-attributes-Boeb7gtH.js";
@@ -15,7 +15,8 @@ import { a as spanRecordsToTraceAnalysisStore, i as otlpTextToTraceAnalysisStore
15
15
  import { i as summarizeTraceErrors, n as recordAggregateMeasurements, r as summarizeExecutionMeasurements, t as readTaskFailureLabels } from "./task-failure-attributes-CC6VuIpk.js";
16
16
  import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
17
17
  import { join } from "node:path";
18
- import { resolveSpanKind } from "@tangle-network/agent-trace-contract";
18
+ import { resolveSpanKind, toW3CSpanId, toW3CTraceId } from "@tangle-network/agent-trace-contract";
19
+ import { decodeOtlpTraceExport } from "@tangle-network/agent-trace-contract/otlp";
19
20
  // src/trace/store-to-otlp.ts
20
21
  /**
21
22
  * Convert agent-eval's internal trace shape (`FileSystemTraceStore` → `Run`,
@@ -147,7 +148,7 @@ function projectCell(args) {
147
148
  eventsBySpanId.set(e.spanId, arr);
148
149
  }
149
150
  for (const run of runByRunId.values()) {
150
- const traceId = traceIdForWire(run.runId);
151
+ const traceId = toW3CTraceId(run.runId);
151
152
  const agentName = run.variantId ?? run.scenarioId;
152
153
  const sharedResource = { attributes: {
153
154
  "service.name": serviceName,
@@ -156,7 +157,7 @@ function projectCell(args) {
156
157
  "run.status": run.status,
157
158
  ...resourceAttributes(run)
158
159
  } };
159
- const runSpanId = spanIdForWire(`run-${run.runId}`);
160
+ const runSpanId = toW3CSpanId(`run-${run.runId}`);
160
161
  const runStart = msToIso(run.startedAt);
161
162
  const runEnd = msToIso(run.endedAt ?? run.startedAt);
162
163
  const runStatus = run.outcome?.failureClass && run.outcome.failureClass !== "success" ? "STATUS_CODE_ERROR" : "STATUS_CODE_OK";
@@ -186,8 +187,8 @@ function projectCell(args) {
186
187
  const statusCode = spanStatusToOtlp(span.status, span.error, "STATUS_CODE_OK");
187
188
  lines.push(JSON.stringify(toLine({
188
189
  traceId,
189
- spanId: spanIdForWire(span.spanId),
190
- parentSpanId: span.parentSpanId ? spanIdForWire(span.parentSpanId) : runSpanId,
190
+ spanId: toW3CSpanId(span.spanId),
191
+ parentSpanId: span.parentSpanId ? toW3CSpanId(span.parentSpanId) : runSpanId,
191
192
  name: span.name,
192
193
  kind: spanKindToOtlpKind(span.kind),
193
194
  startTime: msToIso(span.startedAt),
@@ -350,6 +351,15 @@ function traceAnalystOnRunComplete(opts) {
350
351
  };
351
352
  }
352
353
  // src/trace-analyst/otlp-flatten.ts
354
+ /**
355
+ * `flattenOtlpExportToNdjson` — flatten an `OtlpExport` (the shape
356
+ * `exportRunAsOtlp` produces) into the per-line JSON the analyst's
357
+ * `OtlpFileTraceStore` index reads. The SDK owns OTLP decoding; this module
358
+ * selects its collector output or applies the analyst vocabulary and ISO times.
359
+ *
360
+ * Pure function, no I/O — the caller does `.map(JSON.stringify).join('\n')`
361
+ * and writes the file (consumers want control over rotation + naming).
362
+ */
353
363
  const DEFAULT_KIND_MAP = {
354
364
  0: "SPAN_KIND_UNSPECIFIED",
355
365
  1: "SPAN_KIND_INTERNAL",
@@ -363,67 +373,51 @@ const STATUS_MAP = {
363
373
  1: "STATUS_CODE_OK",
364
374
  2: "STATUS_CODE_ERROR"
365
375
  };
366
- /** Unwrap an OTLP attribute-value union to a scalar. */
367
- function attrValue(v) {
368
- if (v.stringValue !== void 0) return v.stringValue;
369
- if (v.intValue !== void 0) return Number(v.intValue);
370
- if (v.doubleValue !== void 0) return v.doubleValue;
371
- if (v.boolValue !== void 0) return v.boolValue;
372
- return "";
373
- }
374
- function attrsToRecord(attrs) {
375
- const out = {};
376
- for (const a of attrs) out[a.key] = attrValue(a.value);
377
- return out;
378
- }
379
376
  function nanoToIso(nano) {
380
377
  const ms = Number(nano) / 1e6;
381
378
  return Number.isFinite(ms) ? new Date(ms).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
382
379
  }
383
380
  /** Mirror selected attributes into the OpenInference vocabulary in place. */
384
381
  function applyOpenInference(attrs) {
385
- if ("llm.model" in attrs && !("llm.model_name" in attrs)) attrs[LLM_MODEL_NAME] = attrs["llm.model"];
386
- if ("llm.input_tokens" in attrs && !("llm.token_count.prompt" in attrs)) attrs[LLM_INPUT_TOKENS] = attrs["llm.input_tokens"];
387
- if ("inference.llm.input_tokens" in attrs && !("llm.token_count.prompt" in attrs)) attrs[LLM_INPUT_TOKENS] = attrs["inference.llm.input_tokens"];
388
- if ("llm.output_tokens" in attrs && !("llm.token_count.completion" in attrs)) attrs[LLM_OUTPUT_TOKENS] = attrs["llm.output_tokens"];
389
- if ("inference.llm.output_tokens" in attrs && !("llm.token_count.completion" in attrs)) attrs[LLM_OUTPUT_TOKENS] = attrs["inference.llm.output_tokens"];
390
- if ("tool.name" in attrs && !("inference.tool.name" in attrs)) attrs["inference.tool.name"] = attrs[TOOL_NAME];
382
+ for (const [source, target] of [
383
+ ["llm.model", LLM_MODEL_NAME],
384
+ ["llm.input_tokens", LLM_INPUT_TOKENS],
385
+ ["inference.llm.input_tokens", LLM_INPUT_TOKENS],
386
+ ["llm.output_tokens", LLM_OUTPUT_TOKENS],
387
+ ["inference.llm.output_tokens", LLM_OUTPUT_TOKENS],
388
+ [TOOL_NAME, "inference.tool.name"]
389
+ ]) if (source in attrs && !(target in attrs)) attrs[target] = attrs[source];
391
390
  if ("span.kind" in attrs && !(OPENINFERENCE_SPAN_KIND in attrs)) attrs[OPENINFERENCE_SPAN_KIND] = String(attrs["span.kind"]).toUpperCase();
392
391
  }
393
392
  function flattenOtlpExportToNdjson(otlpExport, opts = {}) {
394
- const vocab = opts.attributeVocabulary ?? "openinference";
393
+ if (opts.projection === "collector") return decodeOtlpTraceExport(otlpExport);
394
+ const legacy = opts;
395
395
  const kindMap = {
396
396
  ...DEFAULT_KIND_MAP,
397
- ...opts.kindMap
397
+ ...legacy.kindMap
398
398
  };
399
- const lines = [];
400
- for (const rs of otlpExport.resourceSpans ?? []) {
401
- const resource = { attributes: attrsToRecord(rs.resource?.attributes ?? []) };
402
- for (const scope of rs.scopeSpans ?? []) for (const span of scope.spans ?? []) {
403
- const attributes = attrsToRecord(span.attributes ?? []);
404
- if (vocab === "openinference") applyOpenInference(attributes);
405
- const line = createOtlpFlatLine({
406
- traceId: span.traceId,
407
- spanId: span.spanId,
408
- parentSpanId: span.parentSpanId ?? null,
409
- name: span.name,
410
- kind: kindMap[span.kind] ?? "SPAN_KIND_UNSPECIFIED",
411
- startTime: nanoToIso(span.startTimeUnixNano),
412
- endTime: nanoToIso(span.endTimeUnixNano),
413
- statusCode: STATUS_MAP[span.status?.code ?? 0] ?? "STATUS_CODE_UNSET",
414
- statusMessage: span.status?.message,
415
- resource,
416
- attributes,
417
- events: span.events?.map((e) => ({
418
- name: e.name,
419
- timeUnixNano: e.timeUnixNano,
420
- ...e.attributes ? { attributes: attrsToRecord(e.attributes) } : {}
421
- }))
422
- });
423
- lines.push(line);
424
- }
425
- }
426
- return lines;
399
+ return decodeOtlpTraceExport(otlpExport, { attributeValues: "scalar" }).map((span) => {
400
+ const attributes = span.span_attributes;
401
+ if ((legacy.attributeVocabulary ?? "openinference") === "openinference") applyOpenInference(attributes);
402
+ return createOtlpFlatLine({
403
+ traceId: span.trace_id,
404
+ spanId: span.span_id,
405
+ parentSpanId: span.parent_span_id,
406
+ name: span.name,
407
+ kind: (span.kind === void 0 ? void 0 : kindMap[span.kind]) ?? "SPAN_KIND_UNSPECIFIED",
408
+ startTime: nanoToIso(span.start_time_unix_nano ?? ""),
409
+ endTime: nanoToIso(span.end_time_unix_nano ?? ""),
410
+ statusCode: STATUS_MAP[span.status_code ?? 0] ?? "STATUS_CODE_UNSET",
411
+ statusMessage: span.status_message,
412
+ resource: { attributes: span.resource_attributes },
413
+ attributes,
414
+ events: span.events?.map((event) => ({
415
+ name: event.name,
416
+ timeUnixNano: event.time_unix_nano,
417
+ ...event.attributes ? { attributes: event.attributes } : {}
418
+ }))
419
+ });
420
+ });
427
421
  }
428
422
  // src/trace-analyst/otlp-to-run-records.ts
429
423
  /**