@tangle-network/agent-eval 0.120.2 → 0.120.3

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 (171) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/analyst/index.d.ts +3111 -0
  3. package/dist/analyst/index.js +403 -0
  4. package/dist/analyst/index.js.map +1 -0
  5. package/dist/authenticity/index.d.ts +161 -0
  6. package/dist/authenticity/index.js +215 -0
  7. package/dist/authenticity/index.js.map +1 -0
  8. package/dist/belief-state/index.d.ts +1301 -0
  9. package/dist/belief-state/index.js +2152 -0
  10. package/dist/belief-state/index.js.map +1 -0
  11. package/dist/benchmarks/index.d.ts +974 -0
  12. package/dist/benchmarks/index.js +60 -0
  13. package/dist/benchmarks/index.js.map +1 -0
  14. package/dist/builder-eval/index.d.ts +695 -0
  15. package/dist/builder-eval/index.js +366 -0
  16. package/dist/builder-eval/index.js.map +1 -0
  17. package/dist/campaign/index.d.ts +7454 -0
  18. package/dist/campaign/index.js +272 -0
  19. package/dist/campaign/index.js.map +1 -0
  20. package/dist/chunk-3CDFMEMO.js +3878 -0
  21. package/dist/chunk-3CDFMEMO.js.map +1 -0
  22. package/dist/chunk-3RF76KTD.js +84 -0
  23. package/dist/chunk-3RF76KTD.js.map +1 -0
  24. package/dist/chunk-3XH4Y2SS.js +750 -0
  25. package/dist/chunk-3XH4Y2SS.js.map +1 -0
  26. package/dist/chunk-3YYRZDON.js +45 -0
  27. package/dist/chunk-3YYRZDON.js.map +1 -0
  28. package/dist/chunk-5BYTIDZ7.js +550 -0
  29. package/dist/chunk-5BYTIDZ7.js.map +1 -0
  30. package/dist/chunk-5CVUPHJ4.js +2668 -0
  31. package/dist/chunk-5CVUPHJ4.js.map +1 -0
  32. package/dist/chunk-ARU2PZFM.js +312 -0
  33. package/dist/chunk-ARU2PZFM.js.map +1 -0
  34. package/dist/chunk-BOD4O7OF.js +40 -0
  35. package/dist/chunk-BOD4O7OF.js.map +1 -0
  36. package/dist/chunk-CVJP5TMD.js +766 -0
  37. package/dist/chunk-CVJP5TMD.js.map +1 -0
  38. package/dist/chunk-DPZAEKA6.js +880 -0
  39. package/dist/chunk-DPZAEKA6.js.map +1 -0
  40. package/dist/chunk-DTJ6QUQB.js +131 -0
  41. package/dist/chunk-DTJ6QUQB.js.map +1 -0
  42. package/dist/chunk-GGE4NNQT.js +65 -0
  43. package/dist/chunk-GGE4NNQT.js.map +1 -0
  44. package/dist/chunk-H5UD2323.js +286 -0
  45. package/dist/chunk-H5UD2323.js.map +1 -0
  46. package/dist/chunk-HHWE3POT.js +94 -0
  47. package/dist/chunk-HHWE3POT.js.map +1 -0
  48. package/dist/chunk-HKUCJ437.js +787 -0
  49. package/dist/chunk-HKUCJ437.js.map +1 -0
  50. package/dist/chunk-JHCHEVET.js +274 -0
  51. package/dist/chunk-JHCHEVET.js.map +1 -0
  52. package/dist/chunk-K4DBDHLK.js +158 -0
  53. package/dist/chunk-K4DBDHLK.js.map +1 -0
  54. package/dist/chunk-K6N6XJJX.js +306 -0
  55. package/dist/chunk-K6N6XJJX.js.map +1 -0
  56. package/dist/chunk-MA6HLL3S.js +65 -0
  57. package/dist/chunk-MA6HLL3S.js.map +1 -0
  58. package/dist/chunk-MAZ26DC7.js +99 -0
  59. package/dist/chunk-MAZ26DC7.js.map +1 -0
  60. package/dist/chunk-MOXWMGPC.js +577 -0
  61. package/dist/chunk-MOXWMGPC.js.map +1 -0
  62. package/dist/chunk-NJC7U437.js +626 -0
  63. package/dist/chunk-NJC7U437.js.map +1 -0
  64. package/dist/chunk-NMN4WGSJ.js +1030 -0
  65. package/dist/chunk-NMN4WGSJ.js.map +1 -0
  66. package/dist/chunk-NPCTHQIO.js +91 -0
  67. package/dist/chunk-NPCTHQIO.js.map +1 -0
  68. package/dist/chunk-ONWEPEDO.js +57 -0
  69. package/dist/chunk-ONWEPEDO.js.map +1 -0
  70. package/dist/chunk-OYZAPX5G.js +1526 -0
  71. package/dist/chunk-OYZAPX5G.js.map +1 -0
  72. package/dist/chunk-P5MGQ2FY.js +7958 -0
  73. package/dist/chunk-P5MGQ2FY.js.map +1 -0
  74. package/dist/chunk-PC4UYEBM.js +166 -0
  75. package/dist/chunk-PC4UYEBM.js.map +1 -0
  76. package/dist/chunk-PJQFMIOX.js +1182 -0
  77. package/dist/chunk-PJQFMIOX.js.map +1 -0
  78. package/dist/chunk-PXD6ZFNY.js +1107 -0
  79. package/dist/chunk-PXD6ZFNY.js.map +1 -0
  80. package/dist/chunk-PXE2VKMX.js +140 -0
  81. package/dist/chunk-PXE2VKMX.js.map +1 -0
  82. package/dist/chunk-PZ5AY32C.js +10 -0
  83. package/dist/chunk-PZ5AY32C.js.map +1 -0
  84. package/dist/chunk-QBRSJK47.js +622 -0
  85. package/dist/chunk-QBRSJK47.js.map +1 -0
  86. package/dist/chunk-S3UZOQ5Y.js +328 -0
  87. package/dist/chunk-S3UZOQ5Y.js.map +1 -0
  88. package/dist/chunk-SQQED7ZH.js +998 -0
  89. package/dist/chunk-SQQED7ZH.js.map +1 -0
  90. package/dist/chunk-SYV364BL.js +1266 -0
  91. package/dist/chunk-SYV364BL.js.map +1 -0
  92. package/dist/chunk-T4SQEITX.js +95 -0
  93. package/dist/chunk-T4SQEITX.js.map +1 -0
  94. package/dist/chunk-TT4KNT67.js +124 -0
  95. package/dist/chunk-TT4KNT67.js.map +1 -0
  96. package/dist/chunk-U5CHZ5M3.js +357 -0
  97. package/dist/chunk-U5CHZ5M3.js.map +1 -0
  98. package/dist/chunk-ULOKLHIQ.js +1937 -0
  99. package/dist/chunk-ULOKLHIQ.js.map +1 -0
  100. package/dist/chunk-VI2UW6B6.js +162 -0
  101. package/dist/chunk-VI2UW6B6.js.map +1 -0
  102. package/dist/chunk-VQMK5FMP.js +247 -0
  103. package/dist/chunk-VQMK5FMP.js.map +1 -0
  104. package/dist/chunk-VSMTAMNK.js +53 -0
  105. package/dist/chunk-VSMTAMNK.js.map +1 -0
  106. package/dist/chunk-VZSRQ272.js +149 -0
  107. package/dist/chunk-VZSRQ272.js.map +1 -0
  108. package/dist/chunk-WW2A73HW.js +159 -0
  109. package/dist/chunk-WW2A73HW.js.map +1 -0
  110. package/dist/chunk-X4UCIOTZ.js +136 -0
  111. package/dist/chunk-X4UCIOTZ.js.map +1 -0
  112. package/dist/chunk-XJYR7XFV.js +317 -0
  113. package/dist/chunk-XJYR7XFV.js.map +1 -0
  114. package/dist/chunk-ZET2UAYW.js +89 -0
  115. package/dist/chunk-ZET2UAYW.js.map +1 -0
  116. package/dist/chunk-ZMXDQ4K7.js +870 -0
  117. package/dist/chunk-ZMXDQ4K7.js.map +1 -0
  118. package/dist/chunk-ZZUXHH3R.js +99 -0
  119. package/dist/chunk-ZZUXHH3R.js.map +1 -0
  120. package/dist/cli.d.ts +1 -0
  121. package/dist/cli.js +112 -0
  122. package/dist/cli.js.map +1 -0
  123. package/dist/contract/index.d.ts +4972 -0
  124. package/dist/contract/index.js +1654 -0
  125. package/dist/contract/index.js.map +1 -0
  126. package/dist/control.d.ts +1013 -0
  127. package/dist/control.js +34 -0
  128. package/dist/control.js.map +1 -0
  129. package/dist/fuzz.d.ts +759 -0
  130. package/dist/fuzz.js +714 -0
  131. package/dist/fuzz.js.map +1 -0
  132. package/dist/hosted/index.d.ts +730 -0
  133. package/dist/hosted/index.js +14 -0
  134. package/dist/hosted/index.js.map +1 -0
  135. package/dist/index.d.ts +16780 -0
  136. package/dist/index.js +12168 -0
  137. package/dist/index.js.map +1 -0
  138. package/dist/matrix/index.d.ts +155 -0
  139. package/dist/matrix/index.js +8 -0
  140. package/dist/matrix/index.js.map +1 -0
  141. package/dist/meta-eval/index.d.ts +1030 -0
  142. package/dist/meta-eval/index.js +417 -0
  143. package/dist/meta-eval/index.js.map +1 -0
  144. package/dist/multishot/index.d.ts +579 -0
  145. package/dist/multishot/index.js +589 -0
  146. package/dist/multishot/index.js.map +1 -0
  147. package/dist/openapi.json +992 -0
  148. package/dist/pipelines/index.d.ts +567 -0
  149. package/dist/pipelines/index.js +515 -0
  150. package/dist/pipelines/index.js.map +1 -0
  151. package/dist/reporting.d.ts +1277 -0
  152. package/dist/reporting.js +48 -0
  153. package/dist/reporting.js.map +1 -0
  154. package/dist/rl.d.ts +4092 -0
  155. package/dist/rl.js +1724 -0
  156. package/dist/rl.js.map +1 -0
  157. package/dist/run-campaign-75RTPVV5.js +14 -0
  158. package/dist/run-campaign-75RTPVV5.js.map +1 -0
  159. package/dist/storyboard/index.d.ts +279 -0
  160. package/dist/storyboard/index.js +767 -0
  161. package/dist/storyboard/index.js.map +1 -0
  162. package/dist/trace-attributes.d.ts +52 -0
  163. package/dist/trace-attributes.js +62 -0
  164. package/dist/trace-attributes.js.map +1 -0
  165. package/dist/traces.d.ts +2343 -0
  166. package/dist/traces.js +249 -0
  167. package/dist/traces.js.map +1 -0
  168. package/dist/wire/index.d.ts +1252 -0
  169. package/dist/wire/index.js +81 -0
  170. package/dist/wire/index.js.map +1 -0
  171. package/package.json +1 -1
@@ -0,0 +1,622 @@
1
+ import {
2
+ cohensD
3
+ } from "./chunk-PJQFMIOX.js";
4
+ import {
5
+ argHash,
6
+ groupBy,
7
+ hasCapturedToolArgs,
8
+ toolSpans
9
+ } from "./chunk-ZET2UAYW.js";
10
+
11
+ // src/failure-taxonomy.ts
12
+ var DEFAULT_RULES = [
13
+ // Outcome already named? Respect it.
14
+ {
15
+ id: "explicit-outcome",
16
+ match: ({ run }) => {
17
+ const fc = run.outcome?.failureClass;
18
+ if (fc && fc !== "unknown")
19
+ return { failureClass: fc, reason: "outcome.failureClass set explicitly" };
20
+ return null;
21
+ }
22
+ },
23
+ {
24
+ id: "knowledge-readiness-blocked",
25
+ match: ({ events }) => {
26
+ const event = events.find(
27
+ (e) => e.kind === "custom" && e.payload.kind === "readiness_scored" && e.payload.passed === false
28
+ );
29
+ return event ? {
30
+ failureClass: "knowledge_readiness_blocked",
31
+ reason: "knowledge readiness report blocked execution",
32
+ triggerEventId: event.eventId
33
+ } : null;
34
+ }
35
+ },
36
+ {
37
+ id: "bad-integration-manifest",
38
+ match: ({ events }) => {
39
+ const event = events.find(
40
+ (e) => e.kind === "custom" && (e.payload.kind === "integration_manifest_validated" && e.payload.valid === false || e.payload.kind === "integration_invoke_failed" && e.payload.code === "manifest_invalid")
41
+ );
42
+ return event ? {
43
+ failureClass: "bad_integration_manifest",
44
+ reason: "integration manifest validation failed before launch",
45
+ triggerEventId: event.eventId
46
+ } : null;
47
+ }
48
+ },
49
+ {
50
+ id: "missing-integration-connection",
51
+ match: ({ events }) => {
52
+ const event = events.find(
53
+ (e) => e.kind === "custom" && e.payload.kind === "integration_manifest_resolved" && hasResolutionStatus(e.payload, "missing_connection")
54
+ );
55
+ return event ? {
56
+ failureClass: "missing_integration_connection",
57
+ reason: "required integration connection was missing",
58
+ triggerEventId: event.eventId
59
+ } : null;
60
+ }
61
+ },
62
+ {
63
+ id: "missing-integration-scope",
64
+ match: ({ events }) => {
65
+ const event = events.find(
66
+ (e) => e.kind === "custom" && (e.payload.kind === "integration_manifest_resolved" && hasMissingScopes(e.payload) || e.payload.kind === "integration_invoke_failed" && e.payload.code === "scope_denied")
67
+ );
68
+ return event ? {
69
+ failureClass: "missing_integration_scope",
70
+ reason: "integration grant or connection lacks required scopes",
71
+ triggerEventId: event.eventId
72
+ } : null;
73
+ }
74
+ },
75
+ {
76
+ id: "integration-approval-required",
77
+ match: ({ events }) => {
78
+ const event = events.find(
79
+ (e) => e.kind === "custom" && (e.payload.kind === "integration_invoke" && e.payload.status === "approval_required" || e.payload.kind === "integration_invoke_failed" && e.payload.code === "approval_required" || e.payload.kind === "integration_approval_required")
80
+ );
81
+ return event ? {
82
+ failureClass: "integration_approval_required",
83
+ reason: "integration write paused for user approval",
84
+ triggerEventId: event.eventId
85
+ } : null;
86
+ }
87
+ },
88
+ {
89
+ id: "integration-auth-expired",
90
+ match: ({ events }) => {
91
+ const event = events.find(
92
+ (e) => e.kind === "custom" && e.payload.kind === "integration_invoke_failed" && (e.payload.code === "auth_expired" || e.payload.code === "connection_not_active" || e.payload.code === "capability_expired" || e.payload.status === "expired")
93
+ );
94
+ return event ? {
95
+ failureClass: "integration_auth_expired",
96
+ reason: "integration connection or capability expired",
97
+ triggerEventId: event.eventId
98
+ } : null;
99
+ }
100
+ },
101
+ {
102
+ id: "unsafe-integration-write-denied",
103
+ match: ({ events }) => {
104
+ const event = events.find(
105
+ (e) => e.kind === "custom" && e.payload.kind === "integration_invoke_failed" && (e.payload.code === "unsafe_write_denied" || e.payload.code === "policy_denied" || e.payload.code === "action_denied")
106
+ );
107
+ return event ? {
108
+ failureClass: "unsafe_integration_write_denied",
109
+ reason: "integration write was denied by policy or capability scope",
110
+ triggerEventId: event.eventId
111
+ } : null;
112
+ }
113
+ },
114
+ {
115
+ id: "integration-provider-failure",
116
+ match: ({ events }) => {
117
+ const event = events.find(
118
+ (e) => e.kind === "custom" && e.payload.kind === "integration_invoke_failed" && ![
119
+ "scope_denied",
120
+ "approval_required",
121
+ "auth_expired",
122
+ "connection_not_active",
123
+ "capability_expired",
124
+ "unsafe_write_denied",
125
+ "policy_denied",
126
+ "action_denied",
127
+ "manifest_invalid"
128
+ ].includes(String(e.payload.code))
129
+ );
130
+ return event ? {
131
+ failureClass: "integration_provider_failure",
132
+ reason: "integration provider invocation failed",
133
+ triggerEventId: event.eventId
134
+ } : null;
135
+ }
136
+ },
137
+ {
138
+ id: "missing-credentials",
139
+ match: ({ events }) => {
140
+ const event = events.find(
141
+ (e) => e.kind === "custom" && e.payload.kind === "knowledge_gap" && e.payload.category === "credential_or_secret"
142
+ );
143
+ return event ? {
144
+ failureClass: "missing_credentials",
145
+ reason: "required credential or secret was missing",
146
+ triggerEventId: event.eventId
147
+ } : null;
148
+ }
149
+ },
150
+ {
151
+ id: "bad-retrieval",
152
+ match: ({ run, spans }) => {
153
+ if (run.outcome?.pass !== false) return null;
154
+ const retrieval = spans.find(
155
+ (s) => s.kind === "retrieval" && (s.hits.length === 0 || s.hits.every((hit) => hit.score <= 0))
156
+ );
157
+ return retrieval ? {
158
+ failureClass: "bad_retrieval",
159
+ reason: "retrieval returned no useful hits for a failed run",
160
+ triggerSpanId: retrieval.spanId
161
+ } : null;
162
+ }
163
+ },
164
+ {
165
+ id: "insufficient-evidence",
166
+ match: ({ events }) => {
167
+ const event = events.find(
168
+ (e) => e.kind === "custom" && e.payload.kind === "knowledge_gap" && e.payload.reason === "insufficient_evidence"
169
+ );
170
+ return event ? {
171
+ failureClass: "insufficient_evidence",
172
+ reason: "task proceeded with insufficient supporting evidence",
173
+ triggerEventId: event.eventId
174
+ } : null;
175
+ }
176
+ },
177
+ {
178
+ id: "contradictory-evidence",
179
+ match: ({ events }) => {
180
+ const event = events.find(
181
+ (e) => e.kind === "custom" && e.payload.kind === "knowledge_gap" && e.payload.reason === "contradictory_evidence"
182
+ );
183
+ return event ? {
184
+ failureClass: "contradictory_evidence",
185
+ reason: "supporting evidence contradicted itself",
186
+ triggerEventId: event.eventId
187
+ } : null;
188
+ }
189
+ },
190
+ // Budget breach events
191
+ {
192
+ id: "budget-breach",
193
+ match: ({ events }) => {
194
+ const breach = events.find((e) => e.kind === "budget_breach");
195
+ return breach ? {
196
+ failureClass: "budget_exceeded",
197
+ reason: `budget breached on ${breach.payload.dimension ?? "unknown dimension"}`,
198
+ triggerEventId: breach.eventId
199
+ } : null;
200
+ }
201
+ },
202
+ // Policy violations
203
+ {
204
+ id: "policy-violation",
205
+ match: ({ events }) => {
206
+ const e = events.find((x) => x.kind === "policy_violation");
207
+ return e ? {
208
+ failureClass: "policy_violation",
209
+ reason: "policy_violation event emitted",
210
+ triggerEventId: e.eventId
211
+ } : null;
212
+ }
213
+ },
214
+ // Sandbox non-zero exit code
215
+ {
216
+ id: "sandbox-failure",
217
+ match: ({ spans }) => {
218
+ const s = spans.find(
219
+ (x) => x.kind === "sandbox" && typeof x.exitCode === "number" && x.exitCode !== 0
220
+ );
221
+ if (!s) return null;
222
+ return {
223
+ failureClass: "sandbox_failure",
224
+ reason: `sandbox exited ${s.exitCode}`,
225
+ triggerSpanId: s.spanId
226
+ };
227
+ }
228
+ },
229
+ // Timeout: run aborted by external signal
230
+ {
231
+ id: "timeout",
232
+ match: ({ run, events }) => {
233
+ if (run.status !== "aborted") return null;
234
+ const hasTimeout = events.some(
235
+ (e) => e.kind === "error" && String(e.payload.reason ?? "").toLowerCase().includes("timeout")
236
+ );
237
+ const note = (run.outcome?.notes ?? "").toLowerCase();
238
+ if (hasTimeout || note.includes("timeout") || note.includes("deadline")) {
239
+ return { failureClass: "timeout", reason: "timeout signal observed" };
240
+ }
241
+ return null;
242
+ }
243
+ },
244
+ // Tool recovery failure: many consecutive tool errors on the same tool
245
+ {
246
+ id: "tool-recovery-failure",
247
+ match: ({ spans }) => {
248
+ const tools = spans.filter((s) => s.kind === "tool");
249
+ const byTool = /* @__PURE__ */ new Map();
250
+ for (const t of tools) {
251
+ const name = t.toolName;
252
+ const arr = byTool.get(name) ?? [];
253
+ arr.push(t);
254
+ byTool.set(name, arr);
255
+ }
256
+ for (const [name, arr] of byTool) {
257
+ const errs = arr.filter((s) => s.status === "error");
258
+ if (errs.length >= 3 && errs.length === arr.length) {
259
+ return {
260
+ failureClass: "tool_recovery_failure",
261
+ reason: `${errs.length} consecutive errors on tool "${name}"`,
262
+ triggerSpanId: errs[errs.length - 1].spanId
263
+ };
264
+ }
265
+ }
266
+ return null;
267
+ }
268
+ },
269
+ // Tool selection error: the run failed and agent called zero tools despite having them
270
+ {
271
+ id: "tool-selection-error",
272
+ match: ({ run, spans }) => {
273
+ if (run.outcome?.pass !== false) return null;
274
+ const hasToolsAvailable = spans.some(
275
+ (s) => s.kind === "agent" && s.attributes?.toolsAvailable !== void 0 && s.attributes?.toolsAvailable > 0
276
+ );
277
+ const tools = spans.filter((s) => s.kind === "tool");
278
+ if (hasToolsAvailable && tools.length === 0) {
279
+ return {
280
+ failureClass: "tool_selection_error",
281
+ reason: "tools were available but none were called"
282
+ };
283
+ }
284
+ return null;
285
+ }
286
+ },
287
+ // Format drift: scored by a judge with dimension='format' below threshold
288
+ {
289
+ id: "format-drift",
290
+ match: ({ spans }) => {
291
+ const judge = spans.find(
292
+ (s) => s.kind === "judge" && s.dimension === "format" && s.score < 0.5
293
+ );
294
+ return judge ? {
295
+ failureClass: "format_drift",
296
+ reason: "format judge scored below 0.5",
297
+ triggerSpanId: judge.spanId
298
+ } : null;
299
+ }
300
+ }
301
+ ];
302
+ function hasResolutionStatus(payload, status) {
303
+ if (status === "missing_connection" && stringArray(payload.missingConnections).length > 0)
304
+ return true;
305
+ return resolutionItems(payload).some((item) => item.status === status);
306
+ }
307
+ function hasMissingScopes(payload) {
308
+ if (stringArray(payload.missingScopes).length > 0) return true;
309
+ return resolutionItems(payload).some(
310
+ (item) => Array.isArray(item.missingScopes) && item.missingScopes.length > 0
311
+ );
312
+ }
313
+ function resolutionItems(payload) {
314
+ return [
315
+ ...records(payload.missing),
316
+ ...records(payload.optionalMissing),
317
+ ...records(payload.ready)
318
+ ];
319
+ }
320
+ function records(value) {
321
+ if (!Array.isArray(value)) return [];
322
+ return value.filter(
323
+ (item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)
324
+ );
325
+ }
326
+ function stringArray(value) {
327
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
328
+ }
329
+ function classifyFailure(ctx, rules = DEFAULT_RULES) {
330
+ if (ctx.run.outcome?.pass !== false && ctx.run.status === "completed") {
331
+ return { failureClass: "success", reason: "run completed with pass=true (or no explicit fail)" };
332
+ }
333
+ for (const rule of rules) {
334
+ const hit = rule.match(ctx);
335
+ if (hit) return hit;
336
+ }
337
+ return { failureClass: "unknown", reason: "no rule matched; run failed for unclassified reason" };
338
+ }
339
+
340
+ // src/tool-use-metrics.ts
341
+ async function computeToolUseMetrics(store, runId, options = {}) {
342
+ const tools = await toolSpans(store, runId);
343
+ if (tools.length === 0) {
344
+ return {
345
+ runId,
346
+ totalCalls: 0,
347
+ callsWithCapturedArgs: 0,
348
+ byTool: {},
349
+ errorRate: 0,
350
+ duplicateRate: 0,
351
+ retryRate: 0
352
+ };
353
+ }
354
+ const byTool = {};
355
+ let totalErrors = 0;
356
+ let totalDuplicates = 0;
357
+ let callsWithCapturedArgs = 0;
358
+ const sortedTools = [...tools].sort((a, b) => a.startedAt - b.startedAt);
359
+ const seenSignatures = /* @__PURE__ */ new Set();
360
+ for (const t of sortedTools) {
361
+ byTool[t.toolName] ??= {
362
+ calls: 0,
363
+ callsWithCapturedArgs: 0,
364
+ errors: 0,
365
+ avgLatencyMs: 0,
366
+ duplicates: 0
367
+ };
368
+ const stat = byTool[t.toolName];
369
+ stat.calls += 1;
370
+ if (t.status === "error") {
371
+ stat.errors += 1;
372
+ totalErrors += 1;
373
+ }
374
+ if (typeof t.latencyMs === "number") stat.avgLatencyMs += t.latencyMs;
375
+ if (hasCapturedToolArgs(t)) {
376
+ callsWithCapturedArgs += 1;
377
+ stat.callsWithCapturedArgs += 1;
378
+ const sig = `${t.toolName}|${argHash(t.args)}`;
379
+ if (seenSignatures.has(sig)) {
380
+ stat.duplicates += 1;
381
+ totalDuplicates += 1;
382
+ }
383
+ seenSignatures.add(sig);
384
+ }
385
+ }
386
+ for (const stat of Object.values(byTool)) {
387
+ stat.avgLatencyMs = stat.calls > 0 ? stat.avgLatencyMs / stat.calls : 0;
388
+ }
389
+ let retryOpportunities = 0;
390
+ let retriesFollowed = 0;
391
+ for (const [, arr] of groupBy(sortedTools, (t) => t.toolName)) {
392
+ for (let i = 0; i < arr.length; i++) {
393
+ if (arr[i].status !== "error") continue;
394
+ retryOpportunities += 1;
395
+ if (arr[i + 1]) retriesFollowed += 1;
396
+ }
397
+ }
398
+ const retryRate = retryOpportunities > 0 ? retriesFollowed / retryOpportunities : 0;
399
+ let selectionAccuracy;
400
+ if (options.selectionLabels) {
401
+ const labeled = sortedTools.filter((t) => t.spanId in options.selectionLabels);
402
+ if (labeled.length > 0) {
403
+ selectionAccuracy = labeled.filter((t) => options.selectionLabels[t.spanId]).length / labeled.length;
404
+ }
405
+ }
406
+ return {
407
+ runId,
408
+ totalCalls: sortedTools.length,
409
+ callsWithCapturedArgs,
410
+ byTool,
411
+ errorRate: totalErrors / sortedTools.length,
412
+ duplicateRate: callsWithCapturedArgs > 0 ? totalDuplicates / callsWithCapturedArgs : 0,
413
+ retryRate,
414
+ selectionAccuracy
415
+ };
416
+ }
417
+
418
+ // src/trajectory.ts
419
+ async function buildTrajectory(store, runId) {
420
+ const spans = await store.spans({ runId });
421
+ const events = await store.events({ runId });
422
+ const childrenOf = /* @__PURE__ */ new Map();
423
+ for (const s of spans) {
424
+ const arr = childrenOf.get(s.parentSpanId) ?? [];
425
+ arr.push(s);
426
+ childrenOf.set(s.parentSpanId, arr);
427
+ }
428
+ for (const arr of childrenOf.values()) arr.sort((a, b) => a.startedAt - b.startedAt);
429
+ const eventsBySpan = /* @__PURE__ */ new Map();
430
+ for (const e of events) {
431
+ if (!e.spanId) continue;
432
+ const arr = eventsBySpan.get(e.spanId) ?? [];
433
+ arr.push(e);
434
+ eventsBySpan.set(e.spanId, arr);
435
+ }
436
+ const steps = [];
437
+ const walk = (spanId, depth) => {
438
+ const kids = childrenOf.get(spanId) ?? [];
439
+ for (const child of kids) {
440
+ steps.push({
441
+ index: steps.length,
442
+ span: child,
443
+ depth,
444
+ events: eventsBySpan.get(child.spanId) ?? []
445
+ });
446
+ walk(child.spanId, depth + 1);
447
+ }
448
+ };
449
+ walk(void 0, 0);
450
+ const llmTurns = steps.filter((s) => s.span.kind === "llm").length;
451
+ const toolCalls = steps.filter((s) => s.span.kind === "tool").length;
452
+ const judgeVerdicts = steps.filter((s) => s.span.kind === "judge").length;
453
+ const retrievals = steps.filter((s) => s.span.kind === "retrieval").length;
454
+ let totalDurationMs = 0;
455
+ if (steps.length > 0) {
456
+ const starts = spans.map((s) => s.startedAt);
457
+ const ends = spans.map((s) => s.endedAt ?? s.startedAt);
458
+ totalDurationMs = Math.max(...ends) - Math.min(...starts);
459
+ }
460
+ return { runId, steps, llmTurns, toolCalls, judgeVerdicts, retrievals, totalDurationMs };
461
+ }
462
+
463
+ // src/baseline.ts
464
+ function compareToBaseline(samples, options = {}) {
465
+ const effectThreshold = options.effectThreshold ?? 0.5;
466
+ const alpha = options.alpha ?? 0.05;
467
+ const cvThreshold = options.unstableCvThreshold ?? 0.3;
468
+ const metrics = samples.map((s) => {
469
+ if (s.baseline.length < 2 || s.candidate.length < 2) {
470
+ throw new Error(`compareToBaseline: need \u22652 samples per side for "${s.metric}"`);
471
+ }
472
+ const bMean = mean(s.baseline);
473
+ const cMean = mean(s.candidate);
474
+ const delta = cMean - bMean;
475
+ const d = cohensD(s.baseline, s.candidate);
476
+ const { t, df, p } = welchsTTest(s.baseline, s.candidate);
477
+ const baselineIqr = iqr(s.baseline);
478
+ const candidateIqr = iqr(s.candidate);
479
+ const baselineStable = baselineIqr / Math.max(Math.abs(bMean), 1e-9) <= cvThreshold;
480
+ const candidateStable = candidateIqr / Math.max(Math.abs(cMean), 1e-9) <= cvThreshold;
481
+ const stable = baselineStable && candidateStable;
482
+ const reportedIqr = Math.max(baselineIqr, candidateIqr);
483
+ let verdict;
484
+ if (!stable) {
485
+ verdict = "unstable";
486
+ } else if (p < alpha && Math.abs(d) >= effectThreshold) {
487
+ const candidateIsBetter = s.higherIsBetter ? delta > 0 : delta < 0;
488
+ verdict = candidateIsBetter ? "improved" : "regressed";
489
+ } else {
490
+ verdict = "stable";
491
+ }
492
+ return {
493
+ metric: s.metric,
494
+ baselineMean: bMean,
495
+ candidateMean: cMean,
496
+ delta,
497
+ cohensD: d,
498
+ welchT: t,
499
+ welchDf: df,
500
+ welchP: p,
501
+ stable,
502
+ iqr: reportedIqr,
503
+ verdict
504
+ };
505
+ });
506
+ return {
507
+ metrics,
508
+ hasRegression: metrics.some((m) => m.verdict === "regressed"),
509
+ hasUnstable: metrics.some((m) => m.verdict === "unstable")
510
+ };
511
+ }
512
+ function mean(xs) {
513
+ return xs.reduce((a, b) => a + b, 0) / xs.length;
514
+ }
515
+ function iqr(xs) {
516
+ if (xs.length === 0) return 0;
517
+ const sorted = [...xs].sort((a, b) => a - b);
518
+ const q = (p) => {
519
+ const idx = p * (sorted.length - 1);
520
+ const lo = Math.floor(idx);
521
+ const hi = Math.ceil(idx);
522
+ return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);
523
+ };
524
+ return q(0.75) - q(0.25);
525
+ }
526
+ function welchsTTest(a, b) {
527
+ if (a.length < 2 || b.length < 2) return { t: 0, df: 0, p: 1 };
528
+ const mA = mean(a);
529
+ const mB = mean(b);
530
+ const vA = variance(a, mA);
531
+ const vB = variance(b, mB);
532
+ const seSquared = vA / a.length + vB / b.length;
533
+ if (seSquared === 0) return { t: mA === mB ? 0 : Infinity, df: 0, p: mA === mB ? 1 : 0 };
534
+ const t = (mB - mA) / Math.sqrt(seSquared);
535
+ const df = seSquared * seSquared / ((vA / a.length) ** 2 / (a.length - 1) + (vB / b.length) ** 2 / (b.length - 1));
536
+ const p = 2 * (1 - studentTCdf(Math.abs(t), df));
537
+ return { t, df, p };
538
+ }
539
+ function variance(xs, m) {
540
+ return xs.reduce((acc, x) => acc + (x - m) ** 2, 0) / (xs.length - 1);
541
+ }
542
+ function studentTCdf(t, df) {
543
+ if (df <= 0) return 0.5;
544
+ if (df > 100) return normalCdf(t);
545
+ const x = df / (df + t * t);
546
+ const ib = incompleteBeta(x, df / 2, 0.5);
547
+ return t >= 0 ? 1 - 0.5 * ib : 0.5 * ib;
548
+ }
549
+ function incompleteBeta(x, a, b) {
550
+ if (x <= 0) return 0;
551
+ if (x >= 1) return 1;
552
+ const lnBeta = lnGamma(a) + lnGamma(b) - lnGamma(a + b);
553
+ const front = Math.exp(Math.log(x) * a + Math.log(1 - x) * b - lnBeta) / a;
554
+ let c = 1;
555
+ let d = 1 - (a + b) * x / (a + 1);
556
+ if (Math.abs(d) < 1e-30) d = 1e-30;
557
+ d = 1 / d;
558
+ let f = d;
559
+ for (let m = 1; m <= 200; m++) {
560
+ const m2 = 2 * m;
561
+ let num = m * (b - m) * x / ((a + m2 - 1) * (a + m2));
562
+ d = 1 + num * d;
563
+ if (Math.abs(d) < 1e-30) d = 1e-30;
564
+ c = 1 + num / c;
565
+ if (Math.abs(c) < 1e-30) c = 1e-30;
566
+ d = 1 / d;
567
+ f *= d * c;
568
+ num = -((a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
569
+ d = 1 + num * d;
570
+ if (Math.abs(d) < 1e-30) d = 1e-30;
571
+ c = 1 + num / c;
572
+ if (Math.abs(c) < 1e-30) c = 1e-30;
573
+ d = 1 / d;
574
+ const delta = d * c;
575
+ f *= delta;
576
+ if (Math.abs(delta - 1) < 3e-7) break;
577
+ }
578
+ return front * f;
579
+ }
580
+ function lnGamma(z) {
581
+ const coefs = [
582
+ 0.9999999999998099,
583
+ 676.5203681218851,
584
+ -1259.1392167224028,
585
+ 771.3234287776531,
586
+ -176.6150291621406,
587
+ 12.507343278686905,
588
+ -0.13857109526572012,
589
+ 9984369578019572e-21,
590
+ 15056327351493116e-23
591
+ ];
592
+ if (z < 0.5) return Math.log(Math.PI / Math.sin(Math.PI * z)) - lnGamma(1 - z);
593
+ z -= 1;
594
+ let x = coefs[0];
595
+ for (let i = 1; i < 9; i++) x += coefs[i] / (z + i);
596
+ const t = z + 7.5;
597
+ return 0.5 * Math.log(2 * Math.PI) + (z + 0.5) * Math.log(t) - t + Math.log(x);
598
+ }
599
+ function normalCdf(x) {
600
+ const a1 = 0.254829592;
601
+ const a2 = -0.284496736;
602
+ const a3 = 1.421413741;
603
+ const a4 = -1.453152027;
604
+ const a5 = 1.061405429;
605
+ const p = 0.3275911;
606
+ const sign = x < 0 ? -1 : 1;
607
+ const absX = Math.abs(x);
608
+ const t = 1 / (1 + p * absX);
609
+ const y = 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-absX * absX / 2);
610
+ return 0.5 * (1 + sign * y);
611
+ }
612
+
613
+ export {
614
+ DEFAULT_RULES,
615
+ classifyFailure,
616
+ computeToolUseMetrics,
617
+ buildTrajectory,
618
+ compareToBaseline,
619
+ iqr,
620
+ welchsTTest
621
+ };
622
+ //# sourceMappingURL=chunk-QBRSJK47.js.map