@tangle-network/agent-eval 0.115.1 → 0.115.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.
- package/CHANGELOG.md +20 -0
- package/dist/analyst/index.d.ts +7 -7
- package/dist/analyst/index.js +5 -5
- package/dist/{analyze-runs-Dmz6LA9e.d.ts → analyze-runs-BYHg6Irm.d.ts} +3 -3
- package/dist/belief-state/index.d.ts +3 -3
- package/dist/belief-state/index.js +1 -1
- package/dist/benchmarks/index.d.ts +3 -3
- package/dist/benchmarks/index.js +6 -6
- package/dist/campaign/index.d.ts +12 -12
- package/dist/campaign/index.js +6 -6
- package/dist/{chunk-DRPIZQIT.js → chunk-4D5RVB3W.js} +2 -2
- package/dist/{chunk-DWLIGZBX.js → chunk-5S5NJ63F.js} +2 -2
- package/dist/{chunk-VK6HBGAE.js → chunk-5UF54T55.js} +53 -1
- package/dist/chunk-5UF54T55.js.map +1 -0
- package/dist/{chunk-N6MTC3GK.js → chunk-ADYLPOSX.js} +2 -2
- package/dist/{chunk-IMWDSFUM.js → chunk-DXZRATT5.js} +2 -2
- package/dist/{chunk-S42AWHMP.js → chunk-E4BUPP7Z.js} +135 -17
- package/dist/chunk-E4BUPP7Z.js.map +1 -0
- package/dist/{chunk-FUCQVFMU.js → chunk-GY4SYVPJ.js} +12 -3
- package/dist/chunk-GY4SYVPJ.js.map +1 -0
- package/dist/{chunk-LVTGFSHF.js → chunk-I6LVHOV3.js} +2 -2
- package/dist/{chunk-WBOGKYM4.js → chunk-J6P6PK2R.js} +48 -7
- package/dist/chunk-J6P6PK2R.js.map +1 -0
- package/dist/{chunk-KDCMEZDI.js → chunk-KG4TD7EQ.js} +6 -6
- package/dist/{chunk-LOBMT6SB.js → chunk-ONM6PEAE.js} +3 -3
- package/dist/{chunk-AN5UYSVD.js → chunk-QMXXSNC4.js} +2 -2
- package/dist/{chunk-RSVSSZKF.js → chunk-TLDB7WRY.js} +2 -2
- package/dist/{chunk-I2HNIE6N.js → chunk-WSBUZMBU.js} +4 -4
- package/dist/cli.js +2 -2
- package/dist/{code-agent-session-yitf9I-F.d.ts → code-agent-session-D-g04tcy.d.ts} +8 -1
- package/dist/contract/index.d.ts +15 -15
- package/dist/contract/index.js +7 -7
- package/dist/{control-U8LBKUES.d.ts → control-CcBiAEnn.d.ts} +1 -1
- package/dist/control.d.ts +2 -2
- package/dist/control.js +2 -2
- package/dist/{default-registry-Bcf1uKVI.d.ts → default-registry-DltpYR5u.d.ts} +1 -1
- package/dist/{gepa-DolL_Fko.d.ts → gepa-dne9JDPL.d.ts} +1 -1
- package/dist/hosted/index.d.ts +4 -4
- package/dist/{index-CWr5SIG-.d.ts → index-BTEpx9He.d.ts} +2 -2
- package/dist/index.d.ts +22 -22
- package/dist/index.js +14 -12
- package/dist/index.js.map +1 -1
- package/dist/{insight-report-D4cXFsLt.d.ts → insight-report-IwwvqZZv.d.ts} +20 -2
- package/dist/{kind-factory-20hcaYpf.d.ts → kind-factory-DcNg13sZ.d.ts} +1 -1
- package/dist/meta-eval/index.d.ts +2 -2
- package/dist/multishot/index.d.ts +2 -2
- package/dist/openapi.json +1 -1
- package/dist/{policy-edit-az2qRmvN.d.ts → policy-edit-RLn8GWof.d.ts} +2 -2
- package/dist/{pre-registration-oNItiRBb.d.ts → pre-registration-D8h7ZxNL.d.ts} +3 -3
- package/dist/{provenance-BZmpWmn4.d.ts → provenance-Bibyg1U9.d.ts} +3 -3
- package/dist/{release-report-oBfOz8ku.d.ts → release-report-CCtzajxP.d.ts} +2 -2
- package/dist/reporting.d.ts +4 -4
- package/dist/{researcher-CaH0CwFC.d.ts → researcher-Dq-EtpbE.d.ts} +2 -2
- package/dist/rl.d.ts +6 -6
- package/dist/rl.js +3 -3
- package/dist/{rubric-predictive-validity-C-fMteAW.d.ts → rubric-predictive-validity-DYTLjGWu.d.ts} +1 -1
- package/dist/{run-record-DksGsfgv.d.ts → run-record-B7RTi_ix.d.ts} +34 -2
- package/dist/{runtime-trajectory-h5i0SZUj.d.ts → runtime-trajectory-Dws7Kpgi.d.ts} +1 -1
- package/dist/{semantic-concept-judge-CpzbtwD0.d.ts → semantic-concept-judge-DxJmRkyJ.d.ts} +1 -1
- package/dist/{summary-report-Bz-0-t8v.d.ts → summary-report-BJ5aNwZ1.d.ts} +1 -1
- package/dist/traces.d.ts +1 -1
- package/dist/traces.js +2 -2
- package/dist/{types-CgSlO6wT.d.ts → types-C5gJrOVT.d.ts} +1 -1
- package/dist/wire/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-FUCQVFMU.js.map +0 -1
- package/dist/chunk-S42AWHMP.js.map +0 -1
- package/dist/chunk-VK6HBGAE.js.map +0 -1
- package/dist/chunk-WBOGKYM4.js.map +0 -1
- /package/dist/{chunk-DRPIZQIT.js.map → chunk-4D5RVB3W.js.map} +0 -0
- /package/dist/{chunk-DWLIGZBX.js.map → chunk-5S5NJ63F.js.map} +0 -0
- /package/dist/{chunk-N6MTC3GK.js.map → chunk-ADYLPOSX.js.map} +0 -0
- /package/dist/{chunk-IMWDSFUM.js.map → chunk-DXZRATT5.js.map} +0 -0
- /package/dist/{chunk-LVTGFSHF.js.map → chunk-I6LVHOV3.js.map} +0 -0
- /package/dist/{chunk-KDCMEZDI.js.map → chunk-KG4TD7EQ.js.map} +0 -0
- /package/dist/{chunk-LOBMT6SB.js.map → chunk-ONM6PEAE.js.map} +0 -0
- /package/dist/{chunk-AN5UYSVD.js.map → chunk-QMXXSNC4.js.map} +0 -0
- /package/dist/{chunk-RSVSSZKF.js.map → chunk-TLDB7WRY.js.map} +0 -0
- /package/dist/{chunk-I2HNIE6N.js.map → chunk-WSBUZMBU.js.map} +0 -0
|
@@ -52,6 +52,7 @@ function fromCodeAgentSession(source, options) {
|
|
|
52
52
|
hasQualityLabel: false,
|
|
53
53
|
hasTokenUsage: false,
|
|
54
54
|
hasCost: false,
|
|
55
|
+
costKind: "uncaptured",
|
|
55
56
|
warnings: ["no parseable session entries"]
|
|
56
57
|
}
|
|
57
58
|
],
|
|
@@ -66,8 +67,7 @@ function fromCodeAgentSession(source, options) {
|
|
|
66
67
|
output: metrics.outputTokens,
|
|
67
68
|
...metrics.cachedTokens > 0 ? { cached: metrics.cachedTokens } : {}
|
|
68
69
|
};
|
|
69
|
-
const
|
|
70
|
-
const costUsd = metrics.observedCostUsd > 0 ? metrics.observedCostUsd : estimatedCostUsd;
|
|
70
|
+
const { costUsd, costProvenance } = resolveSessionCost(options.costProvenance, metrics, model);
|
|
71
71
|
const score = clamp01(options.score ?? metrics.processScore);
|
|
72
72
|
const promptHash = options.promptHash ?? hashString(`prompt:${source}:${firstUserText(entries) ?? ""}`);
|
|
73
73
|
const configHash = options.configHash ?? hashJson({
|
|
@@ -83,7 +83,7 @@ function fromCodeAgentSession(source, options) {
|
|
|
83
83
|
explicitTerminal,
|
|
84
84
|
malformedLines: options.malformedLines ?? 0,
|
|
85
85
|
scoreOverridden: options.score !== void 0,
|
|
86
|
-
|
|
86
|
+
costKind: costProvenance.kind
|
|
87
87
|
});
|
|
88
88
|
const run = {
|
|
89
89
|
runId: `${source}:${sessionId}`,
|
|
@@ -96,6 +96,7 @@ function fromCodeAgentSession(source, options) {
|
|
|
96
96
|
commitSha: options.commitSha ?? "local-session",
|
|
97
97
|
wallMs: metrics.wallMs,
|
|
98
98
|
costUsd,
|
|
99
|
+
costProvenance,
|
|
99
100
|
tokenUsage,
|
|
100
101
|
outcome: {
|
|
101
102
|
holdoutScore: score,
|
|
@@ -127,11 +128,16 @@ function fromCodeAgentSession(source, options) {
|
|
|
127
128
|
output_tokens: metrics.outputTokens,
|
|
128
129
|
cached_tokens: metrics.cachedTokens,
|
|
129
130
|
observed_cost_usd: metrics.observedCostUsd,
|
|
131
|
+
observed_cost_captured: metrics.observedCostCaptured ? 1 : 0,
|
|
132
|
+
estimated_cost_usd: costProvenance.kind === "estimated" ? costUsd : 0,
|
|
130
133
|
process_score: score,
|
|
131
134
|
inferred_score: options.score === void 0 ? 1 : 0,
|
|
132
135
|
explicit_terminal_signal: explicitTerminal ? 1 : 0,
|
|
133
136
|
quality_label_present: options.score !== void 0 ? 1 : 0,
|
|
134
|
-
|
|
137
|
+
cost_observed: costProvenance.kind === "observed" ? 1 : 0,
|
|
138
|
+
cost_estimated: costProvenance.kind === "estimated" ? 1 : 0,
|
|
139
|
+
cost_uncaptured: costProvenance.kind === "uncaptured" ? 1 : 0,
|
|
140
|
+
cost_unknown: costProvenance.kind === "uncaptured" ? 1 : 0
|
|
135
141
|
}
|
|
136
142
|
},
|
|
137
143
|
splitTag: options.splitTag ?? "holdout",
|
|
@@ -151,7 +157,8 @@ function fromCodeAgentSession(source, options) {
|
|
|
151
157
|
hasExplicitTerminalSignal: explicitTerminal,
|
|
152
158
|
hasQualityLabel: options.score !== void 0,
|
|
153
159
|
hasTokenUsage: metrics.inputTokens > 0 || metrics.outputTokens > 0,
|
|
154
|
-
hasCost:
|
|
160
|
+
hasCost: costProvenance.kind !== "uncaptured",
|
|
161
|
+
costKind: costProvenance.kind,
|
|
155
162
|
warnings
|
|
156
163
|
}
|
|
157
164
|
],
|
|
@@ -174,6 +181,7 @@ function metricsFor(source, entries) {
|
|
|
174
181
|
}
|
|
175
182
|
function codexMetrics(entries) {
|
|
176
183
|
const metrics = emptyMetrics(entries.length);
|
|
184
|
+
const startedToolIds = /* @__PURE__ */ new Set();
|
|
177
185
|
let startedAt;
|
|
178
186
|
let completedAt;
|
|
179
187
|
for (const entry of entries) {
|
|
@@ -185,6 +193,17 @@ function codexMetrics(entries) {
|
|
|
185
193
|
startedAt = startedAt === void 0 ? timestamp : Math.min(startedAt, timestamp);
|
|
186
194
|
completedAt = completedAt === void 0 ? timestamp : Math.max(completedAt, timestamp);
|
|
187
195
|
}
|
|
196
|
+
if (entryType === "turn.started") metrics.turnsStarted += 1;
|
|
197
|
+
if (entryType === "turn.completed") {
|
|
198
|
+
metrics.turnsCompleted += 1;
|
|
199
|
+
addCodexExecUsage(metrics, record(entry.usage));
|
|
200
|
+
}
|
|
201
|
+
if (entryType === "turn.failed") metrics.turnsAborted += 1;
|
|
202
|
+
if (entryType === "error") metrics.toolErrors += 1;
|
|
203
|
+
const item = record(entry.item);
|
|
204
|
+
if (item && (entryType === "item.started" || entryType === "item.completed")) {
|
|
205
|
+
addCodexExecItem(metrics, startedToolIds, entryType, item);
|
|
206
|
+
}
|
|
188
207
|
if (entryType === "response_item") {
|
|
189
208
|
if (payloadType === "function_call" || payloadType === "custom_tool_call")
|
|
190
209
|
metrics.toolCalls += 1;
|
|
@@ -230,7 +249,7 @@ function codexMetrics(entries) {
|
|
|
230
249
|
}
|
|
231
250
|
}
|
|
232
251
|
if (payloadType === "token_count")
|
|
233
|
-
|
|
252
|
+
setCodexCumulativeUsage(metrics, record(record(payload.info)?.total_token_usage));
|
|
234
253
|
const result = record(payload.result);
|
|
235
254
|
if (result && "Err" in result) metrics.toolErrors += 1;
|
|
236
255
|
}
|
|
@@ -241,6 +260,66 @@ function codexMetrics(entries) {
|
|
|
241
260
|
metrics.processScore = codexProcessScore(metrics);
|
|
242
261
|
return metrics;
|
|
243
262
|
}
|
|
263
|
+
function addCodexExecItem(metrics, startedToolIds, eventType, item) {
|
|
264
|
+
const itemType = stringField(item, "type");
|
|
265
|
+
const itemId = stringField(item, "id");
|
|
266
|
+
const isTool = itemType === "command_execution" || itemType === "mcp_tool_call" || itemType === "collab_tool_call" || itemType === "web_search";
|
|
267
|
+
if (eventType === "item.started" && isTool) {
|
|
268
|
+
metrics.toolCalls += 1;
|
|
269
|
+
if (itemId) startedToolIds.add(itemId);
|
|
270
|
+
}
|
|
271
|
+
if (eventType === "item.completed" && isTool) {
|
|
272
|
+
if (!itemId || !startedToolIds.has(itemId)) metrics.toolCalls += 1;
|
|
273
|
+
metrics.toolOutputs += 1;
|
|
274
|
+
}
|
|
275
|
+
if (eventType !== "item.completed") return;
|
|
276
|
+
if (itemType === "agent_message" || itemType === "message") metrics.assistantMessages += 1;
|
|
277
|
+
if (itemType === "reasoning") metrics.reasoningItems += 1;
|
|
278
|
+
if (itemType === "file_change") {
|
|
279
|
+
metrics.patchAttempts += 1;
|
|
280
|
+
const status = stringField(item, "status");
|
|
281
|
+
if (status === "completed") metrics.patchSuccesses += 1;
|
|
282
|
+
if (status === "failed") {
|
|
283
|
+
metrics.patchFailures += 1;
|
|
284
|
+
metrics.toolErrors += 1;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (itemType === "error" || codexExecToolFailed(itemType, item)) metrics.toolErrors += 1;
|
|
288
|
+
}
|
|
289
|
+
function codexExecToolFailed(itemType, item) {
|
|
290
|
+
const status = stringField(item, "status");
|
|
291
|
+
if (itemType === "command_execution") {
|
|
292
|
+
const exitCode = numberField(item, "exit_code");
|
|
293
|
+
return status === "failed" || status === "declined" || exitCode !== void 0 && exitCode !== 0;
|
|
294
|
+
}
|
|
295
|
+
if (itemType === "mcp_tool_call") return status === "failed" || record(item.error) !== null;
|
|
296
|
+
return itemType === "collab_tool_call" && status === "failed";
|
|
297
|
+
}
|
|
298
|
+
function addCodexExecUsage(metrics, usage) {
|
|
299
|
+
const parsed = readCodexUsage(usage);
|
|
300
|
+
metrics.inputTokens += parsed.input;
|
|
301
|
+
metrics.outputTokens += parsed.output;
|
|
302
|
+
metrics.cachedTokens += parsed.cached;
|
|
303
|
+
}
|
|
304
|
+
function setCodexCumulativeUsage(metrics, usage) {
|
|
305
|
+
const parsed = readCodexUsage(usage);
|
|
306
|
+
metrics.inputTokens = Math.max(metrics.inputTokens, parsed.input);
|
|
307
|
+
metrics.outputTokens = Math.max(metrics.outputTokens, parsed.output);
|
|
308
|
+
metrics.cachedTokens = Math.max(metrics.cachedTokens, parsed.cached);
|
|
309
|
+
}
|
|
310
|
+
function readCodexUsage(usage) {
|
|
311
|
+
if (!usage) return { input: 0, output: 0, cached: 0 };
|
|
312
|
+
return {
|
|
313
|
+
input: alternativeNumericUsage(usage, ["input_tokens", "inputTokens"]),
|
|
314
|
+
output: alternativeNumericUsage(usage, ["output_tokens", "outputTokens"]),
|
|
315
|
+
cached: alternativeNumericUsage(usage, [
|
|
316
|
+
"cached_input_tokens",
|
|
317
|
+
"cachedInputTokens",
|
|
318
|
+
"cache_read_input_tokens",
|
|
319
|
+
"cacheReadInputTokens"
|
|
320
|
+
])
|
|
321
|
+
};
|
|
322
|
+
}
|
|
244
323
|
function claudeCodeMetrics(entries) {
|
|
245
324
|
const metrics = emptyMetrics(entries.length);
|
|
246
325
|
let startedAt;
|
|
@@ -282,6 +361,8 @@ function openCodeMetrics(entries) {
|
|
|
282
361
|
const partUsage = emptyTokenTotals();
|
|
283
362
|
let messageCost = 0;
|
|
284
363
|
let partCost = 0;
|
|
364
|
+
let messageCostCaptured = false;
|
|
365
|
+
let partCostCaptured = false;
|
|
285
366
|
let startedAt;
|
|
286
367
|
let completedAt;
|
|
287
368
|
for (const entry of entries) {
|
|
@@ -318,17 +399,24 @@ function openCodeMetrics(entries) {
|
|
|
318
399
|
const cost = numberField(entry, "cost");
|
|
319
400
|
if (record(entry.tokens) && role) {
|
|
320
401
|
addUsageTo(messageUsage, record(entry.tokens));
|
|
321
|
-
if (cost !== void 0)
|
|
402
|
+
if (cost !== void 0) {
|
|
403
|
+
messageCost += cost;
|
|
404
|
+
messageCostCaptured = true;
|
|
405
|
+
}
|
|
322
406
|
} else if (record(entry.tokens)) {
|
|
323
407
|
addUsageTo(partUsage, record(entry.tokens));
|
|
324
|
-
if (cost !== void 0)
|
|
408
|
+
if (cost !== void 0) {
|
|
409
|
+
partCost += cost;
|
|
410
|
+
partCostCaptured = true;
|
|
411
|
+
}
|
|
325
412
|
}
|
|
326
413
|
}
|
|
327
414
|
const usage = messageUsage.input + messageUsage.output > 0 ? messageUsage : partUsage;
|
|
328
415
|
metrics.inputTokens = usage.input;
|
|
329
416
|
metrics.outputTokens = usage.output;
|
|
330
417
|
metrics.cachedTokens = usage.cached;
|
|
331
|
-
metrics.observedCostUsd =
|
|
418
|
+
metrics.observedCostUsd = messageCostCaptured ? messageCost : partCost;
|
|
419
|
+
metrics.observedCostCaptured = messageCostCaptured || partCostCaptured;
|
|
332
420
|
if (metrics.wallMs === 0 && startedAt !== void 0 && completedAt !== void 0)
|
|
333
421
|
metrics.wallMs = Math.max(0, completedAt - startedAt);
|
|
334
422
|
metrics.processScore = terminalProcessScore(metrics);
|
|
@@ -453,6 +541,7 @@ function emptyMetrics(entries) {
|
|
|
453
541
|
outputTokens: 0,
|
|
454
542
|
cachedTokens: 0,
|
|
455
543
|
observedCostUsd: 0,
|
|
544
|
+
observedCostCaptured: false,
|
|
456
545
|
wallMs: 0,
|
|
457
546
|
processScore: 0
|
|
458
547
|
};
|
|
@@ -491,12 +580,6 @@ function addUsageTo(totals, usage) {
|
|
|
491
580
|
totals.output += parsed.output;
|
|
492
581
|
totals.cached += parsed.cached;
|
|
493
582
|
}
|
|
494
|
-
function setCumulativeUsage(metrics, usage) {
|
|
495
|
-
const parsed = readUsage(usage);
|
|
496
|
-
metrics.inputTokens = Math.max(metrics.inputTokens, parsed.input);
|
|
497
|
-
metrics.outputTokens = Math.max(metrics.outputTokens, parsed.output);
|
|
498
|
-
metrics.cachedTokens = Math.max(metrics.cachedTokens, parsed.cached);
|
|
499
|
-
}
|
|
500
583
|
function readUsage(usage) {
|
|
501
584
|
if (!usage) return { input: 0, output: 0, cached: 0 };
|
|
502
585
|
return {
|
|
@@ -539,12 +622,45 @@ function numericUsage(obj, names) {
|
|
|
539
622
|
}
|
|
540
623
|
return total;
|
|
541
624
|
}
|
|
625
|
+
function alternativeNumericUsage(obj, names) {
|
|
626
|
+
for (const name of names) {
|
|
627
|
+
const value = obj[name];
|
|
628
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
629
|
+
}
|
|
630
|
+
return 0;
|
|
631
|
+
}
|
|
632
|
+
function resolveSessionCost(explicit, metrics, model) {
|
|
633
|
+
if (explicit) {
|
|
634
|
+
if (explicit.kind === "uncaptured") {
|
|
635
|
+
if (explicit.usd !== null) throw new Error("uncaptured cost must have usd: null");
|
|
636
|
+
return { costUsd: 0, costProvenance: explicit };
|
|
637
|
+
}
|
|
638
|
+
if (!Number.isFinite(explicit.usd) || explicit.usd < 0) {
|
|
639
|
+
throw new Error(`${explicit.kind} cost must be a finite, non-negative USD amount`);
|
|
640
|
+
}
|
|
641
|
+
return { costUsd: explicit.usd, costProvenance: explicit };
|
|
642
|
+
}
|
|
643
|
+
if (metrics.observedCostCaptured) {
|
|
644
|
+
const costProvenance = { kind: "observed", usd: metrics.observedCostUsd };
|
|
645
|
+
return { costUsd: metrics.observedCostUsd, costProvenance };
|
|
646
|
+
}
|
|
647
|
+
const hasUsage = metrics.inputTokens > 0 || metrics.outputTokens > 0;
|
|
648
|
+
if (hasUsage && isModelPriced(model)) {
|
|
649
|
+
const costUsd = estimateCost(metrics.inputTokens, metrics.outputTokens, model);
|
|
650
|
+
return { costUsd, costProvenance: { kind: "estimated", usd: costUsd } };
|
|
651
|
+
}
|
|
652
|
+
return { costUsd: 0, costProvenance: { kind: "uncaptured", usd: null } };
|
|
653
|
+
}
|
|
542
654
|
function diagnosticsFor(metrics, options) {
|
|
543
655
|
const warnings = [];
|
|
544
656
|
if (!options.scoreOverridden) warnings.push("outcome score is inferred from process telemetry");
|
|
545
657
|
if (!options.explicitTerminal) warnings.push("no explicit terminal success/failure signal");
|
|
546
658
|
if (metrics.inputTokens === 0 && metrics.outputTokens === 0) warnings.push("missing token usage");
|
|
547
|
-
if (options.
|
|
659
|
+
if (options.costKind === "estimated")
|
|
660
|
+
warnings.push("USD cost estimated from token usage and model pricing");
|
|
661
|
+
if (options.costKind === "uncaptured") warnings.push("USD cost uncaptured");
|
|
662
|
+
if (options.costKind === "uncaptured" && !isModelPriced(options.model))
|
|
663
|
+
warnings.push("model pricing unknown");
|
|
548
664
|
if (options.malformedLines > 0)
|
|
549
665
|
warnings.push(`${options.malformedLines} malformed JSONL lines skipped`);
|
|
550
666
|
return warnings;
|
|
@@ -559,6 +675,8 @@ function hasExplicitTerminalSignal(source, metrics) {
|
|
|
559
675
|
function sessionIdFromEntries(source, entries) {
|
|
560
676
|
for (const entry of entries) {
|
|
561
677
|
if (source === "codex") {
|
|
678
|
+
const threadId = stringField(entry, "thread_id");
|
|
679
|
+
if (threadId) return threadId;
|
|
562
680
|
const payload2 = record(entry.payload);
|
|
563
681
|
const id = payload2 ? stringField(payload2, "id") : void 0;
|
|
564
682
|
if (id) return id;
|
|
@@ -694,4 +812,4 @@ export {
|
|
|
694
812
|
fromPiSession,
|
|
695
813
|
fromPigraphSession
|
|
696
814
|
};
|
|
697
|
-
//# sourceMappingURL=chunk-
|
|
815
|
+
//# sourceMappingURL=chunk-E4BUPP7Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contract/intake/code-agent-session.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { estimateCost, isModelPriced } from '../../metrics'\nimport type { RunCostProvenance, RunRecord, RunSplitTag, RunTokenUsage } from '../../run-record'\n\nexport type CodeAgentSessionSource = 'codex' | 'claude-code' | 'opencode' | 'kimi-code' | 'pi'\n\nexport interface ParsedCodeAgentJsonl {\n entries: unknown[]\n malformedLines: number\n}\n\nexport interface CodeAgentSessionMetrics {\n entries: number\n userMessages: number\n assistantMessages: number\n reasoningItems: number\n toolCalls: number\n toolOutputs: number\n toolErrors: number\n patchAttempts: number\n patchSuccesses: number\n patchFailures: number\n turnsStarted: number\n turnsCompleted: number\n turnsAborted: number\n contextCompactions: number\n prLinks: number\n fileSnapshots: number\n graphNodes: number\n graphEdges: number\n actionCandidates: number\n verificationReports: number\n completionDecisions: number\n reliabilityRows: number\n reliabilityLift: number\n inputTokens: number\n outputTokens: number\n cachedTokens: number\n observedCostUsd: number\n observedCostCaptured?: boolean\n wallMs: number\n processScore: number\n}\n\nexport interface CodeAgentSessionDiagnostic {\n source: CodeAgentSessionSource\n sessionId: string\n sourcePath?: string\n entries: number\n malformedLines: number\n inferredScore: boolean\n hasExplicitTerminalSignal: boolean\n hasQualityLabel: boolean\n hasTokenUsage: boolean\n hasCost: boolean\n costKind?: RunCostProvenance['kind']\n warnings: string[]\n}\n\nexport interface CodeAgentSessionIntakeResult {\n runs: RunRecord[]\n diagnostics: CodeAgentSessionDiagnostic[]\n metrics: CodeAgentSessionMetrics[]\n}\n\nexport interface CodeAgentSessionIntakeOptions {\n entries: unknown[]\n malformedLines?: number\n sourcePath?: string\n experimentId?: string\n candidateId?: string\n seed?: number\n splitTag?: RunSplitTag\n scenarioId?: string\n model?: string\n promptHash?: string\n configHash?: string\n commitSha?: string\n score?: number\n /** Explicit cost receipt. Use `uncaptured` when the source says dollars\n * were not captured; the adapter will not relabel its compatibility $0\n * sentinel as observed. When omitted, source-reported cost wins, then a\n * token-priced estimate, then uncaptured. */\n costProvenance?: RunCostProvenance\n}\n\nexport function parseCodeAgentJsonl(jsonl: string): ParsedCodeAgentJsonl {\n const entries: unknown[] = []\n let malformedLines = 0\n for (const line of jsonl.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n entries.push(JSON.parse(trimmed))\n } catch {\n malformedLines += 1\n }\n }\n return { entries, malformedLines }\n}\n\nexport function fromCodexSession(\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n return fromCodeAgentSession('codex', options)\n}\n\nexport function fromClaudeCodeSession(\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n return fromCodeAgentSession('claude-code', options)\n}\n\nexport function fromOpenCodeSession(\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n return fromCodeAgentSession('opencode', options)\n}\n\nexport function fromKimiCodeSession(\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n return fromCodeAgentSession('kimi-code', options)\n}\n\nexport function fromPiSession(\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n return fromCodeAgentSession('pi', options)\n}\n\nexport const fromPigraphSession = fromPiSession\n\nfunction fromCodeAgentSession(\n source: CodeAgentSessionSource,\n options: CodeAgentSessionIntakeOptions,\n): CodeAgentSessionIntakeResult {\n const entries = options.entries.filter(isRecord)\n if (entries.length === 0) {\n return {\n runs: [],\n diagnostics: [\n {\n source,\n sessionId: fallbackSessionId(source, options.sourcePath),\n sourcePath: options.sourcePath,\n entries: 0,\n malformedLines: options.malformedLines ?? 0,\n inferredScore: true,\n hasExplicitTerminalSignal: false,\n hasQualityLabel: false,\n hasTokenUsage: false,\n hasCost: false,\n costKind: 'uncaptured',\n warnings: ['no parseable session entries'],\n },\n ],\n metrics: [],\n }\n }\n\n const metrics = metricsFor(source, entries)\n const sessionId =\n sessionIdFromEntries(source, entries) ?? fallbackSessionId(source, options.sourcePath)\n const model = withSnapshot(options.model ?? modelFromEntries(source, entries) ?? source)\n const tokenUsage: RunTokenUsage = {\n input: metrics.inputTokens,\n output: metrics.outputTokens,\n ...(metrics.cachedTokens > 0 ? { cached: metrics.cachedTokens } : {}),\n }\n const { costUsd, costProvenance } = resolveSessionCost(options.costProvenance, metrics, model)\n const score = clamp01(options.score ?? metrics.processScore)\n const promptHash =\n options.promptHash ?? hashString(`prompt:${source}:${firstUserText(entries) ?? ''}`)\n const configHash =\n options.configHash ??\n hashJson({\n source,\n model,\n sourcePath: options.sourcePath,\n cwd: cwdFromEntries(entries),\n entryCount: entries.length,\n })\n const explicitTerminal = hasExplicitTerminalSignal(source, metrics)\n const warnings = diagnosticsFor(metrics, {\n model,\n explicitTerminal,\n malformedLines: options.malformedLines ?? 0,\n scoreOverridden: options.score !== undefined,\n costKind: costProvenance.kind,\n })\n\n const run: RunRecord = {\n runId: `${source}:${sessionId}`,\n experimentId: options.experimentId ?? `${source}-local-sessions`,\n candidateId: options.candidateId ?? model,\n seed: options.seed ?? stableSeed(sessionId),\n model,\n promptHash,\n configHash,\n commitSha: options.commitSha ?? 'local-session',\n wallMs: metrics.wallMs,\n costUsd,\n costProvenance,\n tokenUsage,\n outcome: {\n holdoutScore: score,\n raw: {\n entries: metrics.entries,\n user_messages: metrics.userMessages,\n assistant_messages: metrics.assistantMessages,\n reasoning_items: metrics.reasoningItems,\n tool_calls: metrics.toolCalls,\n tool_outputs: metrics.toolOutputs,\n tool_errors: metrics.toolErrors,\n patch_attempts: metrics.patchAttempts,\n patch_successes: metrics.patchSuccesses,\n patch_failures: metrics.patchFailures,\n turns_started: metrics.turnsStarted,\n turns_completed: metrics.turnsCompleted,\n turns_aborted: metrics.turnsAborted,\n context_compactions: metrics.contextCompactions,\n pr_links: metrics.prLinks,\n file_snapshots: metrics.fileSnapshots,\n graph_nodes: metrics.graphNodes,\n graph_edges: metrics.graphEdges,\n action_candidates: metrics.actionCandidates,\n verification_reports: metrics.verificationReports,\n completion_decisions: metrics.completionDecisions,\n reliability_rows: metrics.reliabilityRows,\n reliability_lift: metrics.reliabilityLift,\n input_tokens: metrics.inputTokens,\n output_tokens: metrics.outputTokens,\n cached_tokens: metrics.cachedTokens,\n observed_cost_usd: metrics.observedCostUsd,\n observed_cost_captured: metrics.observedCostCaptured ? 1 : 0,\n estimated_cost_usd: costProvenance.kind === 'estimated' ? costUsd : 0,\n process_score: score,\n inferred_score: options.score === undefined ? 1 : 0,\n explicit_terminal_signal: explicitTerminal ? 1 : 0,\n quality_label_present: options.score !== undefined ? 1 : 0,\n cost_observed: costProvenance.kind === 'observed' ? 1 : 0,\n cost_estimated: costProvenance.kind === 'estimated' ? 1 : 0,\n cost_uncaptured: costProvenance.kind === 'uncaptured' ? 1 : 0,\n cost_unknown: costProvenance.kind === 'uncaptured' ? 1 : 0,\n },\n },\n splitTag: options.splitTag ?? 'holdout',\n ...(options.scenarioId ? { scenarioId: options.scenarioId } : {}),\n ...(metrics.toolErrors > 0 || metrics.turnsAborted > 0\n ? { failureMode: metrics.turnsAborted > 0 ? 'turn_aborted' : 'tool_error' }\n : {}),\n }\n\n return {\n runs: [run],\n diagnostics: [\n {\n source,\n sessionId,\n sourcePath: options.sourcePath,\n entries: entries.length,\n malformedLines: options.malformedLines ?? 0,\n inferredScore: options.score === undefined,\n hasExplicitTerminalSignal: explicitTerminal,\n hasQualityLabel: options.score !== undefined,\n hasTokenUsage: metrics.inputTokens > 0 || metrics.outputTokens > 0,\n hasCost: costProvenance.kind !== 'uncaptured',\n costKind: costProvenance.kind,\n warnings,\n },\n ],\n metrics: [metrics],\n }\n}\n\nfunction metricsFor(\n source: CodeAgentSessionSource,\n entries: Record<string, unknown>[],\n): CodeAgentSessionMetrics {\n switch (source) {\n case 'codex':\n return codexMetrics(entries)\n case 'claude-code':\n return claudeCodeMetrics(entries)\n case 'opencode':\n return openCodeMetrics(entries)\n case 'kimi-code':\n return kimiCodeMetrics(entries)\n case 'pi':\n return piMetrics(entries)\n }\n}\n\nfunction codexMetrics(entries: Record<string, unknown>[]): CodeAgentSessionMetrics {\n const metrics = emptyMetrics(entries.length)\n const startedToolIds = new Set<string>()\n let startedAt: number | undefined\n let completedAt: number | undefined\n\n for (const entry of entries) {\n const payload = record(entry.payload) ?? {}\n const entryType = stringField(entry, 'type')\n const payloadType = stringField(payload, 'type')\n const timestamp = timestampMs(entry.timestamp)\n if (timestamp !== undefined) {\n startedAt = startedAt === undefined ? timestamp : Math.min(startedAt, timestamp)\n completedAt = completedAt === undefined ? timestamp : Math.max(completedAt, timestamp)\n }\n\n if (entryType === 'turn.started') metrics.turnsStarted += 1\n if (entryType === 'turn.completed') {\n metrics.turnsCompleted += 1\n addCodexExecUsage(metrics, record(entry.usage))\n }\n if (entryType === 'turn.failed') metrics.turnsAborted += 1\n if (entryType === 'error') metrics.toolErrors += 1\n\n const item = record(entry.item)\n if (item && (entryType === 'item.started' || entryType === 'item.completed')) {\n addCodexExecItem(metrics, startedToolIds, entryType, item)\n }\n\n if (entryType === 'response_item') {\n if (payloadType === 'function_call' || payloadType === 'custom_tool_call')\n metrics.toolCalls += 1\n if (payloadType === 'function_call_output' || payloadType === 'custom_tool_call_output')\n metrics.toolOutputs += 1\n if (payloadType === 'reasoning') metrics.reasoningItems += 1\n if (payloadType === 'message' && stringField(payload, 'role') === 'assistant')\n metrics.assistantMessages += 1\n }\n\n if (entryType === 'event_msg') {\n if (payloadType === 'user_message') metrics.userMessages += 1\n if (payloadType === 'agent_message') metrics.assistantMessages += 1\n if (payloadType === 'task_started') {\n metrics.turnsStarted += 1\n const started = timestampMs(payload.started_at)\n if (started !== undefined) {\n startedAt = startedAt === undefined ? started : Math.min(startedAt, started)\n }\n }\n if (payloadType === 'task_complete') {\n metrics.turnsCompleted += 1\n const completed = timestampMs(payload.completed_at)\n if (completed !== undefined) {\n completedAt = completedAt === undefined ? completed : Math.max(completedAt, completed)\n }\n const duration = numberField(payload, 'duration_ms')\n if (duration !== undefined) metrics.wallMs = Math.max(metrics.wallMs, duration)\n }\n if (payloadType === 'turn_aborted') {\n metrics.turnsAborted += 1\n const completed = timestampMs(payload.completed_at)\n if (completed !== undefined) {\n completedAt = completedAt === undefined ? completed : Math.max(completedAt, completed)\n }\n }\n if (payloadType === 'context_compacted') metrics.contextCompactions += 1\n if (payloadType === 'patch_apply_end') {\n metrics.patchAttempts += 1\n if (payload.success === true) metrics.patchSuccesses += 1\n else {\n metrics.patchFailures += 1\n metrics.toolErrors += 1\n }\n }\n if (payloadType === 'token_count')\n setCodexCumulativeUsage(metrics, record(record(payload.info)?.total_token_usage))\n const result = record(payload.result)\n if (result && 'Err' in result) metrics.toolErrors += 1\n }\n }\n\n if (metrics.wallMs === 0 && startedAt !== undefined && completedAt !== undefined) {\n metrics.wallMs = Math.max(0, completedAt - startedAt)\n }\n metrics.processScore = codexProcessScore(metrics)\n return metrics\n}\n\nfunction addCodexExecItem(\n metrics: CodeAgentSessionMetrics,\n startedToolIds: Set<string>,\n eventType: 'item.started' | 'item.completed',\n item: Record<string, unknown>,\n): void {\n const itemType = stringField(item, 'type')\n const itemId = stringField(item, 'id')\n const isTool =\n itemType === 'command_execution' ||\n itemType === 'mcp_tool_call' ||\n itemType === 'collab_tool_call' ||\n itemType === 'web_search'\n\n if (eventType === 'item.started' && isTool) {\n metrics.toolCalls += 1\n if (itemId) startedToolIds.add(itemId)\n }\n if (eventType === 'item.completed' && isTool) {\n if (!itemId || !startedToolIds.has(itemId)) metrics.toolCalls += 1\n metrics.toolOutputs += 1\n }\n if (eventType !== 'item.completed') return\n\n if (itemType === 'agent_message' || itemType === 'message') metrics.assistantMessages += 1\n if (itemType === 'reasoning') metrics.reasoningItems += 1\n if (itemType === 'file_change') {\n metrics.patchAttempts += 1\n const status = stringField(item, 'status')\n if (status === 'completed') metrics.patchSuccesses += 1\n if (status === 'failed') {\n metrics.patchFailures += 1\n metrics.toolErrors += 1\n }\n }\n if (itemType === 'error' || codexExecToolFailed(itemType, item)) metrics.toolErrors += 1\n}\n\nfunction codexExecToolFailed(itemType: string | undefined, item: Record<string, unknown>): boolean {\n const status = stringField(item, 'status')\n if (itemType === 'command_execution') {\n const exitCode = numberField(item, 'exit_code')\n return (\n status === 'failed' || status === 'declined' || (exitCode !== undefined && exitCode !== 0)\n )\n }\n if (itemType === 'mcp_tool_call') return status === 'failed' || record(item.error) !== null\n return itemType === 'collab_tool_call' && status === 'failed'\n}\n\nfunction addCodexExecUsage(\n metrics: CodeAgentSessionMetrics,\n usage: Record<string, unknown> | null,\n): void {\n const parsed = readCodexUsage(usage)\n metrics.inputTokens += parsed.input\n metrics.outputTokens += parsed.output\n metrics.cachedTokens += parsed.cached\n}\n\nfunction setCodexCumulativeUsage(\n metrics: CodeAgentSessionMetrics,\n usage: Record<string, unknown> | null,\n): void {\n const parsed = readCodexUsage(usage)\n metrics.inputTokens = Math.max(metrics.inputTokens, parsed.input)\n metrics.outputTokens = Math.max(metrics.outputTokens, parsed.output)\n metrics.cachedTokens = Math.max(metrics.cachedTokens, parsed.cached)\n}\n\nfunction readCodexUsage(usage: Record<string, unknown> | null): {\n input: number\n output: number\n cached: number\n} {\n if (!usage) return { input: 0, output: 0, cached: 0 }\n return {\n input: alternativeNumericUsage(usage, ['input_tokens', 'inputTokens']),\n output: alternativeNumericUsage(usage, ['output_tokens', 'outputTokens']),\n cached: alternativeNumericUsage(usage, [\n 'cached_input_tokens',\n 'cachedInputTokens',\n 'cache_read_input_tokens',\n 'cacheReadInputTokens',\n ]),\n }\n}\n\nfunction claudeCodeMetrics(entries: Record<string, unknown>[]): CodeAgentSessionMetrics {\n const metrics = emptyMetrics(entries.length)\n let startedAt: number | undefined\n let completedAt: number | undefined\n\n for (const entry of entries) {\n const type = stringField(entry, 'type')\n const timestamp = timestampMs(entry.timestamp)\n if (timestamp !== undefined) {\n startedAt = startedAt === undefined ? timestamp : Math.min(startedAt, timestamp)\n completedAt = completedAt === undefined ? timestamp : Math.max(completedAt, timestamp)\n }\n\n if (type === 'user') metrics.userMessages += 1\n if (type === 'assistant') metrics.assistantMessages += 1\n if (type === 'pr-link') metrics.prLinks += 1\n if (type === 'file-history-snapshot') metrics.fileSnapshots += 1\n\n const message = record(entry.message)\n if (message) addUsage(metrics, record(message.usage))\n const content = Array.isArray(message?.content) ? message.content : []\n for (const item of content) {\n const part = record(item)\n if (!part) continue\n const partType = stringField(part, 'type')\n if (partType === 'thinking') metrics.reasoningItems += 1\n if (partType === 'tool_use') metrics.toolCalls += 1\n if (partType === 'tool_result') {\n metrics.toolOutputs += 1\n if (part.is_error === true) metrics.toolErrors += 1\n }\n }\n }\n\n if (startedAt !== undefined && completedAt !== undefined)\n metrics.wallMs = Math.max(0, completedAt - startedAt)\n metrics.processScore = claudeProcessScore(metrics)\n return metrics\n}\n\nfunction openCodeMetrics(entries: Record<string, unknown>[]): CodeAgentSessionMetrics {\n const metrics = emptyMetrics(entries.length)\n const messageUsage = emptyTokenTotals()\n const partUsage = emptyTokenTotals()\n let messageCost = 0\n let partCost = 0\n let messageCostCaptured = false\n let partCostCaptured = false\n let startedAt: number | undefined\n let completedAt: number | undefined\n\n for (const entry of entries) {\n const time = record(entry.time)\n const created = timestampMs(time?.created)\n const completed = timestampMs(time?.completed)\n if (created !== undefined)\n startedAt = startedAt === undefined ? created : Math.min(startedAt, created)\n if (completed !== undefined)\n completedAt = completedAt === undefined ? completed : Math.max(completedAt, completed)\n\n const role = stringField(entry, 'role')\n if (role === 'user') metrics.userMessages += 1\n if (role === 'assistant') {\n metrics.assistantMessages += 1\n const finish = stringField(entry, 'finish')\n if (finish === 'stop') metrics.turnsCompleted += 1\n if (finish === 'error') metrics.turnsAborted += 1\n }\n\n const type = stringField(entry, 'type')\n if (type === 'reasoning') metrics.reasoningItems += 1\n if (type === 'tool') {\n metrics.toolCalls += 1\n const status = stringField(record(entry.state) ?? {}, 'status')\n if (status === 'completed') metrics.toolOutputs += 1\n if (status === 'error') {\n metrics.toolOutputs += 1\n metrics.toolErrors += 1\n }\n }\n if (type === 'patch') {\n metrics.patchAttempts += 1\n metrics.patchSuccesses += 1\n }\n\n const cost = numberField(entry, 'cost')\n if (record(entry.tokens) && role) {\n addUsageTo(messageUsage, record(entry.tokens))\n if (cost !== undefined) {\n messageCost += cost\n messageCostCaptured = true\n }\n } else if (record(entry.tokens)) {\n addUsageTo(partUsage, record(entry.tokens))\n if (cost !== undefined) {\n partCost += cost\n partCostCaptured = true\n }\n }\n }\n\n const usage = messageUsage.input + messageUsage.output > 0 ? messageUsage : partUsage\n metrics.inputTokens = usage.input\n metrics.outputTokens = usage.output\n metrics.cachedTokens = usage.cached\n metrics.observedCostUsd = messageCostCaptured ? messageCost : partCost\n metrics.observedCostCaptured = messageCostCaptured || partCostCaptured\n if (metrics.wallMs === 0 && startedAt !== undefined && completedAt !== undefined)\n metrics.wallMs = Math.max(0, completedAt - startedAt)\n metrics.processScore = terminalProcessScore(metrics)\n return metrics\n}\n\nfunction kimiCodeMetrics(entries: Record<string, unknown>[]): CodeAgentSessionMetrics {\n const metrics = emptyMetrics(entries.length)\n let startedAt: number | undefined\n let completedAt: number | undefined\n\n for (const entry of entries) {\n const timestamp = timestampMs(entry.timestamp)\n if (timestamp !== undefined) {\n startedAt = startedAt === undefined ? timestamp : Math.min(startedAt, timestamp)\n completedAt = completedAt === undefined ? timestamp : Math.max(completedAt, timestamp)\n }\n\n const role = stringField(entry, 'role')\n if (role === 'user') metrics.userMessages += 1\n if (role === 'assistant') metrics.assistantMessages += 1\n if (role === '_usage') addUsage(metrics, entry)\n\n const message = record(entry.message)\n const messageType = message ? stringField(message, 'type') : undefined\n const payload = record(message?.payload) ?? {}\n if (messageType === 'TurnBegin') {\n metrics.userMessages += 1\n metrics.turnsStarted += 1\n }\n if (messageType === 'TurnEnd') metrics.turnsCompleted += 1\n if (messageType === 'StepInterrupted') metrics.turnsAborted += 1\n if (messageType === 'StepBegin') metrics.reasoningItems += 1\n if (messageType === 'ContentPart') {\n const payloadType = stringField(payload, 'type')\n if (payloadType === 'think') metrics.reasoningItems += 1\n if (payloadType === 'text') metrics.assistantMessages += 1\n }\n if (messageType === 'ToolCall') metrics.toolCalls += 1\n if (messageType === 'ToolResult') {\n metrics.toolOutputs += 1\n if (record(payload.return_value)?.is_error === true) metrics.toolErrors += 1\n }\n if (messageType === 'StatusUpdate') addUsage(metrics, record(payload.token_usage))\n if (messageType === 'Notification') {\n const notification = record(payload.payload)\n const exitCode = numberField(notification ?? {}, 'exit_code')\n if (notification?.timed_out === true || (exitCode !== undefined && exitCode !== 0)) {\n metrics.toolErrors += 1\n }\n }\n }\n\n if (startedAt !== undefined && completedAt !== undefined)\n metrics.wallMs = Math.max(0, completedAt - startedAt)\n metrics.processScore = terminalProcessScore(metrics)\n return metrics\n}\n\nfunction piMetrics(entries: Record<string, unknown>[]): CodeAgentSessionMetrics {\n const metrics = emptyMetrics(entries.length)\n let bestReliabilityScore: number | undefined\n\n for (const entry of entries) {\n const nodes = Array.isArray(entry.nodes) ? entry.nodes : []\n const edges = Array.isArray(entry.edges) ? entry.edges : []\n metrics.graphNodes += nodes.length\n metrics.graphEdges += edges.length\n\n for (const node of nodes) {\n const obj = record(node)\n const ir = record(obj?.ir) ?? obj\n const kind = stringField(ir ?? {}, 'kind')\n if (kind === 'ActionCandidate') metrics.actionCandidates += 1\n if (kind === 'ToolInvocation') metrics.toolCalls += 1\n if (kind === 'ToolResult') metrics.toolOutputs += 1\n if (kind === 'VerificationReport') metrics.verificationReports += 1\n if (kind === 'CompletionDecision') {\n metrics.completionDecisions += 1\n metrics.turnsCompleted += 1\n }\n }\n\n const averageReliability = numberField(entry, 'averageNodeReliability')\n if (averageReliability !== undefined)\n bestReliabilityScore = maxOptional(bestReliabilityScore, averageReliability)\n const pessimisticPath = numberField(entry, 'pessimisticPathEstimate')\n if (pessimisticPath !== undefined)\n bestReliabilityScore = maxOptional(bestReliabilityScore, pessimisticPath)\n\n const rows = Array.isArray(entry.rows) ? entry.rows : []\n metrics.reliabilityRows += rows.length\n for (const row of rows) {\n const obj = record(row)\n if (!obj) continue\n const lift = numberField(obj, 'lift')\n if (lift !== undefined) metrics.reliabilityLift = Math.max(metrics.reliabilityLift, lift)\n const validated = numberField(obj, 'validatedSuccessEstimate')\n if (validated !== undefined)\n bestReliabilityScore = maxOptional(bestReliabilityScore, validated)\n }\n }\n\n metrics.processScore =\n bestReliabilityScore !== undefined\n ? clamp01(bestReliabilityScore)\n : metrics.completionDecisions > 0\n ? 1\n : 0\n return metrics\n}\n\nfunction emptyMetrics(entries: number): CodeAgentSessionMetrics {\n return {\n entries,\n userMessages: 0,\n assistantMessages: 0,\n reasoningItems: 0,\n toolCalls: 0,\n toolOutputs: 0,\n toolErrors: 0,\n patchAttempts: 0,\n patchSuccesses: 0,\n patchFailures: 0,\n turnsStarted: 0,\n turnsCompleted: 0,\n turnsAborted: 0,\n contextCompactions: 0,\n prLinks: 0,\n fileSnapshots: 0,\n graphNodes: 0,\n graphEdges: 0,\n actionCandidates: 0,\n verificationReports: 0,\n completionDecisions: 0,\n reliabilityRows: 0,\n reliabilityLift: 0,\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n observedCostUsd: 0,\n observedCostCaptured: false,\n wallMs: 0,\n processScore: 0,\n }\n}\n\nfunction codexProcessScore(metrics: CodeAgentSessionMetrics): number {\n const terminalTurns = metrics.turnsCompleted + metrics.turnsAborted\n const base =\n terminalTurns > 0\n ? metrics.turnsCompleted / terminalTurns\n : metrics.assistantMessages > 0\n ? 0.5\n : 0\n return penalizeErrors(base, metrics)\n}\n\nfunction claudeProcessScore(metrics: CodeAgentSessionMetrics): number {\n const base = metrics.prLinks > 0 ? 1 : metrics.assistantMessages > 0 ? 0.75 : 0\n return penalizeErrors(base, metrics)\n}\n\nfunction terminalProcessScore(metrics: CodeAgentSessionMetrics): number {\n const terminalTurns = metrics.turnsCompleted + metrics.turnsAborted\n const base =\n terminalTurns > 0\n ? metrics.turnsCompleted / terminalTurns\n : metrics.assistantMessages > 0\n ? 0.75\n : metrics.toolCalls > 0\n ? 0.5\n : 0\n return penalizeErrors(base, metrics)\n}\n\nfunction penalizeErrors(base: number, metrics: CodeAgentSessionMetrics): number {\n const operations = Math.max(1, metrics.toolCalls + metrics.patchAttempts)\n const errorRate = Math.min(1, (metrics.toolErrors + metrics.patchFailures) / operations)\n return clamp01(base * (1 - 0.5 * errorRate))\n}\n\nfunction emptyTokenTotals(): { input: number; output: number; cached: number } {\n return { input: 0, output: 0, cached: 0 }\n}\n\nfunction addUsage(\n metrics: CodeAgentSessionMetrics,\n usage: Record<string, unknown> | null | undefined,\n): void {\n const parsed = readUsage(usage)\n metrics.inputTokens += parsed.input\n metrics.outputTokens += parsed.output\n metrics.cachedTokens += parsed.cached\n}\n\nfunction addUsageTo(\n totals: { input: number; output: number; cached: number },\n usage: Record<string, unknown> | null | undefined,\n): void {\n const parsed = readUsage(usage)\n totals.input += parsed.input\n totals.output += parsed.output\n totals.cached += parsed.cached\n}\n\nfunction readUsage(usage: Record<string, unknown> | null | undefined): {\n input: number\n output: number\n cached: number\n} {\n if (!usage) return { input: 0, output: 0, cached: 0 }\n return {\n input: numericUsage(usage, [\n 'input',\n 'input_tokens',\n 'inputTokens',\n 'prompt_tokens',\n 'promptTokens',\n 'input_other',\n ]),\n output: numericUsage(usage, [\n 'output',\n 'output_tokens',\n 'outputTokens',\n 'completion_tokens',\n 'completionTokens',\n 'reasoning',\n 'reasoning_tokens',\n 'reasoningTokens',\n ]),\n cached: numericUsage(usage, [\n 'cache',\n 'cached_tokens',\n 'cachedTokens',\n 'cache_read_input_tokens',\n 'cacheReadInputTokens',\n 'cache_creation_input_tokens',\n 'cacheCreationInputTokens',\n 'input_cache_read',\n 'input_cache_creation',\n ]),\n }\n}\n\nfunction numericUsage(obj: Record<string, unknown>, names: string[]): number {\n let total = 0\n for (const name of names) {\n const value = obj[name]\n if (typeof value === 'number' && Number.isFinite(value)) total += value\n }\n return total\n}\n\nfunction alternativeNumericUsage(obj: Record<string, unknown>, names: string[]): number {\n for (const name of names) {\n const value = obj[name]\n if (typeof value === 'number' && Number.isFinite(value)) return value\n }\n return 0\n}\n\nfunction resolveSessionCost(\n explicit: RunCostProvenance | undefined,\n metrics: CodeAgentSessionMetrics,\n model: string,\n): { costUsd: number; costProvenance: RunCostProvenance } {\n if (explicit) {\n if (explicit.kind === 'uncaptured') {\n if (explicit.usd !== null) throw new Error('uncaptured cost must have usd: null')\n return { costUsd: 0, costProvenance: explicit }\n }\n if (!Number.isFinite(explicit.usd) || explicit.usd < 0) {\n throw new Error(`${explicit.kind} cost must be a finite, non-negative USD amount`)\n }\n return { costUsd: explicit.usd, costProvenance: explicit }\n }\n\n if (metrics.observedCostCaptured) {\n const costProvenance = { kind: 'observed', usd: metrics.observedCostUsd } as const\n return { costUsd: metrics.observedCostUsd, costProvenance }\n }\n\n const hasUsage = metrics.inputTokens > 0 || metrics.outputTokens > 0\n if (hasUsage && isModelPriced(model)) {\n const costUsd = estimateCost(metrics.inputTokens, metrics.outputTokens, model)\n return { costUsd, costProvenance: { kind: 'estimated', usd: costUsd } }\n }\n\n return { costUsd: 0, costProvenance: { kind: 'uncaptured', usd: null } }\n}\n\nfunction diagnosticsFor(\n metrics: CodeAgentSessionMetrics,\n options: {\n model: string\n explicitTerminal: boolean\n malformedLines: number\n scoreOverridden: boolean\n costKind: RunCostProvenance['kind']\n },\n): string[] {\n const warnings: string[] = []\n if (!options.scoreOverridden) warnings.push('outcome score is inferred from process telemetry')\n if (!options.explicitTerminal) warnings.push('no explicit terminal success/failure signal')\n if (metrics.inputTokens === 0 && metrics.outputTokens === 0) warnings.push('missing token usage')\n if (options.costKind === 'estimated')\n warnings.push('USD cost estimated from token usage and model pricing')\n if (options.costKind === 'uncaptured') warnings.push('USD cost uncaptured')\n if (options.costKind === 'uncaptured' && !isModelPriced(options.model))\n warnings.push('model pricing unknown')\n if (options.malformedLines > 0)\n warnings.push(`${options.malformedLines} malformed JSONL lines skipped`)\n return warnings\n}\n\nfunction hasExplicitTerminalSignal(\n source: CodeAgentSessionSource,\n metrics: CodeAgentSessionMetrics,\n): boolean {\n if (source === 'codex') return metrics.turnsCompleted + metrics.turnsAborted > 0\n if (source === 'opencode' || source === 'kimi-code')\n return metrics.turnsCompleted + metrics.turnsAborted > 0\n if (source === 'pi') return metrics.completionDecisions > 0 || metrics.reliabilityRows > 0\n return metrics.prLinks > 0 || metrics.toolErrors > 0\n}\n\nfunction sessionIdFromEntries(\n source: CodeAgentSessionSource,\n entries: Record<string, unknown>[],\n): string | undefined {\n for (const entry of entries) {\n if (source === 'codex') {\n const threadId = stringField(entry, 'thread_id')\n if (threadId) return threadId\n const payload = record(entry.payload)\n const id = payload ? stringField(payload, 'id') : undefined\n if (id) return id\n }\n const message = record(entry.message)\n const payload = record(message?.payload)\n const sessionId =\n stringField(entry, 'sessionID') ??\n stringField(entry, 'sessionId') ??\n stringField(entry, 'session_id') ??\n stringField(payload ?? {}, 'session_id')\n if (sessionId) return sessionId\n }\n return undefined\n}\n\nfunction modelFromEntries(\n source: CodeAgentSessionSource,\n entries: Record<string, unknown>[],\n): string | undefined {\n let providerModel: string | undefined\n for (const entry of entries) {\n if (source === 'codex') {\n const payload = record(entry.payload)\n const model = payload ? stringField(payload, 'model') : undefined\n if (model) return model\n providerModel =\n providerModel ?? (payload ? stringField(payload, 'model_provider') : undefined)\n }\n const openCodeModel = stringField(entry, 'modelID')\n if (openCodeModel) {\n const provider = stringField(entry, 'providerID')\n return provider ? `${provider}/${openCodeModel}` : openCodeModel\n }\n const modelObject = record(entry.model)\n const nestedModel = stringField(modelObject ?? {}, 'modelID')\n if (nestedModel) {\n const provider = stringField(modelObject ?? {}, 'providerID')\n return provider ? `${provider}/${nestedModel}` : nestedModel\n }\n const message = record(entry.message)\n const model = message ? stringField(message, 'model') : undefined\n if (model) return model\n }\n return providerModel\n}\n\nfunction cwdFromEntries(entries: Record<string, unknown>[]): string | undefined {\n for (const entry of entries) {\n const path = record(entry.path)\n const cwd =\n stringField(entry, 'cwd') ??\n stringField(path ?? {}, 'cwd') ??\n stringField(path ?? {}, 'root') ??\n (record(entry.payload) ? stringField(record(entry.payload)!, 'cwd') : undefined)\n if (cwd) return cwd\n }\n return undefined\n}\n\nfunction firstUserText(entries: Record<string, unknown>[]): string | undefined {\n for (const entry of entries) {\n const payload = record(entry.payload)\n const payloadType = payload ? stringField(payload, 'type') : undefined\n if (payloadType === 'user_message') return stringField(payload!, 'message')\n\n if (stringField(entry, 'role') === 'user') {\n const content = entry.content\n if (typeof content === 'string') return content\n }\n\n const wirePayload = record(record(entry.message)?.payload)\n const userInput = wirePayload ? stringField(wirePayload, 'user_input') : undefined\n if (userInput) return userInput\n\n const message = record(entry.message)\n if (message && stringField(message, 'role') === 'user') {\n const content = message.content\n if (typeof content === 'string') return content\n if (Array.isArray(content)) {\n const text = content\n .map((part) => {\n const obj = record(part)\n return obj ? stringField(obj, 'text') : undefined\n })\n .filter((part): part is string => part !== undefined)\n .join('\\n')\n if (text) return text\n }\n }\n }\n return undefined\n}\n\nfunction fallbackSessionId(source: CodeAgentSessionSource, sourcePath: string | undefined): string {\n return hashString(`${source}:${sourcePath ?? 'unknown-session'}`).slice(\n 'sha256:'.length,\n 'sha256:'.length + 20,\n )\n}\n\nfunction withSnapshot(model: string): string {\n const trimmed = model.trim() || 'unknown'\n if (trimmed.includes('@') || /-\\d{8}$/.test(trimmed) || /-\\d{4}-\\d{2}-\\d{2}$/.test(trimmed)) {\n return trimmed\n }\n return `${trimmed}@observed-local`\n}\n\nfunction hashJson(value: unknown): string {\n return hashString(JSON.stringify(value))\n}\n\nfunction hashString(value: string): string {\n return `sha256:${createHash('sha256').update(value).digest('hex')}`\n}\n\nfunction stableSeed(value: string): number {\n return createHash('sha256').update(value).digest().readUInt32BE(0)\n}\n\nfunction maxOptional(current: number | undefined, next: number): number {\n return current === undefined ? next : Math.max(current, next)\n}\n\nfunction clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return isRecord(value) ? value : null\n}\n\nfunction stringField(obj: Record<string, unknown>, key: string): string | undefined {\n const value = obj[key]\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction numberField(obj: Record<string, unknown>, key: string): number | undefined {\n const value = obj[key]\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction timestampMs(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value > 1_000_000_000_000 ? value : value * 1000\n }\n if (typeof value === 'string' && value.length > 0) {\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? parsed : undefined\n }\n return undefined\n}\n"],"mappings":"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","names":["payload","model"]}
|
|
@@ -138,6 +138,7 @@ function extractJsonPayload(raw) {
|
|
|
138
138
|
JSON.parse(stripped);
|
|
139
139
|
return stripped;
|
|
140
140
|
} catch {
|
|
141
|
+
if (stripped.startsWith("{") || stripped.startsWith("[")) return stripped;
|
|
141
142
|
}
|
|
142
143
|
const starts = [...stripped.matchAll(/[[{]/g)].map((match) => match.index).filter((index) => index != null);
|
|
143
144
|
for (const start of starts) {
|
|
@@ -411,18 +412,26 @@ function cryptoEventId() {
|
|
|
411
412
|
async function callLlmJson(req, opts = {}) {
|
|
412
413
|
try {
|
|
413
414
|
const result = await callLlm({ ...req, jsonMode: req.jsonMode ?? !req.jsonSchema }, opts);
|
|
414
|
-
const value =
|
|
415
|
+
const value = parseJsonResult(result);
|
|
415
416
|
return { value, result };
|
|
416
417
|
} catch (err) {
|
|
417
418
|
if (err instanceof LlmCallError && isSchemaRejection(err.status, err.body) && req.jsonSchema) {
|
|
418
419
|
const degradedReq = { ...req, jsonMode: true, jsonSchema: void 0 };
|
|
419
420
|
const result = await callLlm(degradedReq, opts);
|
|
420
|
-
const value =
|
|
421
|
+
const value = parseJsonResult(result);
|
|
421
422
|
return { value, result };
|
|
422
423
|
}
|
|
423
424
|
throw err;
|
|
424
425
|
}
|
|
425
426
|
}
|
|
427
|
+
function parseJsonResult(result) {
|
|
428
|
+
if (result.finishReason === "length") {
|
|
429
|
+
throw new Error(
|
|
430
|
+
`LLM returned truncated JSON content (model=${result.model}, finishReason=length)`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
return parseJsonSafely(result.content, result.model);
|
|
434
|
+
}
|
|
426
435
|
function parseJsonSafely(content, model) {
|
|
427
436
|
const stripped = extractJsonPayload(content);
|
|
428
437
|
try {
|
|
@@ -542,4 +551,4 @@ export {
|
|
|
542
551
|
probeLlm,
|
|
543
552
|
LlmClient
|
|
544
553
|
};
|
|
545
|
-
//# sourceMappingURL=chunk-
|
|
554
|
+
//# sourceMappingURL=chunk-GY4SYVPJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/llm-client.ts"],"sourcesContent":["/**\n * LLM client with graceful degrade.\n *\n * OpenAI-compatible `/v1/chat/completions` client with:\n * - Exponential-backoff retry on 429 + 5xx gateway errors (502/503/504).\n * - Retry on transient network errors (fetch failed, AbortError, ECONNRESET).\n * - Graceful json_schema → json_object degrade on 400 with schema-reject body.\n * - Fenced-JSON stripping (```json ... ```) for models that wrap structured output.\n * - Configurable base URL + api key / bearer, works with LiteLLM proxies, OpenAI\n * directly, cli-bridge subscriptions, and any router that speaks the spec.\n *\n * Usage:\n * const { value, result } = await callLlmJson<MyType>(\n * { model: 'gpt-4o', messages: [...], jsonSchema: { name: 'x', schema: {...} } },\n * { baseUrl: 'https://router.tangle.tools/v1', apiKey: process.env.KEY },\n * )\n *\n * This is THE llm-calling seam for agent-eval primitives that need structured\n * output (semantic concept judge, reviewer directives, critic scores). Primitives\n * that need free-form text use `callLlm` and parse output themselves.\n */\n\nimport { AgentEvalError, CaptureIntegrityError } from './errors'\nimport {\n defaultProviderRedactor,\n type ProviderRedactor,\n providerFromBaseUrl,\n type RawProviderEvent,\n type RawProviderSink,\n} from './trace/raw-provider-sink'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface LlmMessage {\n role: 'system' | 'user' | 'assistant'\n /**\n * Either a plain text content string OR a multimodal content array\n * (text + image_url parts) for vision-capable models.\n */\n content:\n | string\n | Array<\n | { type: 'text'; text: string }\n | { type: 'image_url'; image_url: { url: string; detail?: 'auto' | 'low' | 'high' } }\n >\n}\n\nexport interface LlmCallRequest {\n model: string\n messages: LlmMessage[]\n /** Optional JSON-mode response format (response_format: json_object). */\n jsonMode?: boolean\n /** Optional structured output via JSON Schema. Falls back to json_object on 400. */\n jsonSchema?: { name: string; schema: Record<string, unknown> }\n temperature?: number\n maxTokens?: number\n /** Per-call timeout, default 300s. */\n timeoutMs?: number\n}\n\nexport interface LlmUsage {\n promptTokens: number\n completionTokens: number\n totalTokens: number\n /** Proxies populate this when prompt caching is on. */\n cachedPromptTokens?: number\n}\n\nexport interface LlmCallResult {\n /** The text content of the first choice. Empty string if none. */\n content: string\n usage: LlmUsage\n /**\n * Cost in USD. Pulled from proxy's `_response_cost` field when present;\n * `null` when neither the proxy nor the caller can derive it.\n */\n costUsd: number | null\n /** Model name actually used (echoed from response). */\n model: string\n /** Wall-clock duration of the HTTP call (last attempt, if retried). */\n durationMs: number\n /**\n * `finish_reason` echoed from the first choice (`stop`, `length`,\n * `content_filter`, `tool_calls`, ...). `null` when the provider omits it.\n * Exposed so a free-form `callLlm` caller CAN detect a truncated answer\n * (`length`) instead of treating a cut-off completion as complete. Note:\n * `callLlm` does not itself reject on it — acting on this signal is the\n * caller's responsibility (in-repo free-form drivers do not yet enforce it).\n */\n finishReason?: string | null\n /**\n * True when `content.trim()` is empty. An empty completion is a silent zero\n * for free-form `callLlm` callers; this flag is the signal a caller can\n * inspect to fail loud rather than proceed on an empty string. `callLlm`\n * surfaces it but does not throw on it.\n */\n contentEmpty?: boolean\n /** Raw response body. */\n raw: Record<string, unknown>\n}\n\nexport class LlmCallError extends AgentEvalError {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: string,\n public readonly model: string,\n ) {\n super('judge', message)\n }\n}\n\nexport interface LlmClientOptions {\n /** Base URL (without trailing slash). Must end at the `/v1` prefix. */\n baseUrl?: string\n /** Bearer token — either `apiKey` or `bearer` populates `Authorization: Bearer ...`. */\n apiKey?: string\n bearer?: string\n /** Override for the `Authorization` header (e.g. `X-Auth: ...`). Takes precedence over apiKey/bearer. */\n authHeader?: { name: string; value: string }\n /** Default timeout in ms. Per-call can override. */\n defaultTimeoutMs?: number\n /**\n * Caller-supplied abort signal — e.g. a campaign-wide cancel. Linked to\n * each attempt's per-attempt timeout controller, so aborting it cancels\n * the in-flight fetch. A caller abort is FATAL: it is not retried even\n * though an AbortError otherwise matches the transient patterns.\n */\n signal?: AbortSignal\n /**\n * Cross-attempt wall-clock budget in ms, measured from the first attempt.\n * Before launching each attempt the loop checks the remaining budget and\n * stops retrying once it is exhausted, rather than waiting the full\n * per-attempt timeout on every retry. Bounds total time independent of\n * `maxRetries` × `timeoutMs`.\n */\n deadlineMs?: number\n /** Max retry attempts on retriable errors. Default 3 (1 initial + 2 retries). */\n maxRetries?: number\n /** Fetch implementation — defaults to global `fetch`. Override for custom transport (e.g. tests). */\n fetch?: typeof fetch\n /**\n * Optional raw HTTP capture sink. When provided, every request, response,\n * and error (across all retry attempts) is recorded to the sink, with auth\n * headers and credential-shaped body fields redacted by default. This is\n * the layer-1 forensics primitive: structured `LlmSpan`s record intent,\n * raw events record what actually crossed the wire.\n */\n rawSink?: RawProviderSink\n /**\n * Logical provider id attached to raw events. When omitted, derived from\n * `baseUrl` via `providerFromBaseUrl`.\n */\n provider?: string\n /** Trace context attached to raw events; populated by emitter-aware callers. */\n traceContext?: { runId?: string; spanId?: string }\n /** Override the redaction strategy for this call. Defaults to `defaultProviderRedactor`. */\n redactor?: ProviderRedactor\n}\n\n// ─── Internals ──────────────────────────────────────────────────────────\n\nconst DEFAULT_BASE_URL = 'https://router.tangle.tools/v1'\n// Flagship / reasoning models routinely take several minutes on large prompts (a\n// reflection over many failures, a long tool transcript). A tight cap aborts a\n// legitimately-slow but healthy call — and because every retry attempt re-uses\n// the same window, such a model aborts on ALL attempts and the loop throws. The\n// default is generous enough to let those complete, bounded enough that a truly\n// hung call still fails over after retries, and tunable per deployment via\n// TANGLE_LLM_TIMEOUT_MS. Per-call `req.timeoutMs` / `opts.defaultTimeoutMs`\n// still win for callers that know their model's latency.\nconst DEFAULT_TIMEOUT_MS = Number(process.env.TANGLE_LLM_TIMEOUT_MS) || 300_000\nconst DEFAULT_MAX_RETRIES = Number(process.env.TANGLE_LLM_MAX_RETRIES) || 3\n\nconst RETRYABLE_STATUS = new Set([429, 502, 503, 504])\n\n/**\n * Transient transport/network error signatures, matched against an error's\n * name, message, and `code`. Covers fetch/undici network failures, aborts\n * and timeouts, and — critically — HTTP/2 transport faults a keep-alive\n * connection raises mid-response: `terminated`, `NGHTTP2_INTERNAL_ERROR`,\n * `UND_ERR_*`, `other side closed`. Those last ones carry no clean HTTP\n * status; unrecognised, they escape the retry loop and surface as an\n * uncaught rejection.\n */\nconst TRANSIENT_ERROR_PATTERNS: readonly RegExp[] = [\n /AbortError/i,\n /TimeoutError/i,\n /this operation was aborted/i,\n /fetch failed/i,\n /ECONNRESET/i,\n /ETIMEDOUT/i,\n /EAI_AGAIN/i,\n /socket hang up/i,\n /stream.*ended.*unexpectedly/i,\n /terminated/i,\n /other side closed/i,\n /NGHTTP2/i,\n /UND_ERR/i,\n]\n\n/**\n * True when an error is a transient transport/network fault worth retrying,\n * as opposed to a deterministic failure (4xx schema reject, JSON parse) that\n * a retry cannot fix. Inspects `LlmCallError.status`, then the error's\n * name/message/code, then recurses into `error.cause` — undici nests the\n * real socket fault one or more levels under `.cause`.\n *\n * This is THE retry classifier for the package: `callLlm` and\n * `withJudgeRetry` both route through it, so a connection-class error is\n * treated identically whether it surfaces in the HTTP client or a\n * TCloud-backed judge.\n */\nexport function isTransientLlmError(err: unknown): boolean {\n return classifyTransient(err, 0)\n}\n\nfunction classifyTransient(err: unknown, depth: number): boolean {\n if (err instanceof LlmCallError) return RETRYABLE_STATUS.has(err.status)\n if (!(err instanceof Error)) return false\n // Foreign errors (e.g. a TCloud judge SDK error) can carry a numeric HTTP\n // status without being an LlmCallError — a retryable status is decisive.\n const status = (err as { status?: unknown }).status\n if (typeof status === 'number' && RETRYABLE_STATUS.has(status)) return true\n const code = (err as { code?: unknown }).code\n const haystack = `${err.name}\\n${err.message}\\n${typeof code === 'string' ? code : ''}`\n if (TRANSIENT_ERROR_PATTERNS.some((p) => p.test(haystack))) return true\n const cause = (err as { cause?: unknown }).cause\n if (depth < 4 && cause instanceof Error && cause !== err) {\n return classifyTransient(cause, depth + 1)\n }\n return false\n}\n\nfunction parseRetryAfter(headers: Headers): number | null {\n const h = headers.get('retry-after')\n if (!h) return null\n const asNumber = Number(h)\n if (Number.isFinite(asNumber) && asNumber > 0) return asNumber * 1000\n const asDate = Date.parse(h)\n if (Number.isFinite(asDate)) return Math.max(0, asDate - Date.now())\n return null\n}\n\n/** Exponential backoff: 500ms, 1s, 2s, 4s, ... capped at 16s. Attempt is 0-indexed. */\nexport function backoffMs(attempt: number): number {\n return Math.min(500 * 2 ** attempt, 16_000)\n}\n\nfunction buildHeaders(opts: LlmClientOptions): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n }\n if (opts.authHeader) {\n headers[opts.authHeader.name] = opts.authHeader.value\n } else if (opts.bearer || opts.apiKey) {\n headers.Authorization = `Bearer ${opts.bearer ?? opts.apiKey}`\n }\n return headers\n}\n\nfunction isSchemaRejection(status: number, body: string): boolean {\n if (status !== 400) return false\n const lower = body.toLowerCase()\n return (\n lower.includes('response_format') ||\n lower.includes('json_schema') ||\n lower.includes('is unavailable') ||\n lower.includes('not supported')\n )\n}\n\nfunction buildBody(req: LlmCallRequest, forceJsonObject: boolean): Record<string, unknown> {\n const body: Record<string, unknown> = {\n model: req.model,\n messages: req.messages,\n temperature: req.temperature ?? 0,\n }\n if (req.maxTokens != null) {\n if (usesMaxCompletionTokens(req.model)) body.max_completion_tokens = req.maxTokens\n else body.max_tokens = req.maxTokens\n }\n\n if (req.jsonSchema && !forceJsonObject) {\n body.response_format = {\n type: 'json_schema',\n json_schema: { name: req.jsonSchema.name, schema: req.jsonSchema.schema, strict: true },\n }\n } else if (req.jsonMode || req.jsonSchema) {\n body.response_format = { type: 'json_object' }\n }\n\n return body\n}\n\nfunction usesMaxCompletionTokens(model: string): boolean {\n return /^gpt-5(?:[.-]|$)/i.test(model)\n}\n\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Combine the per-attempt timeout signal with an optional caller signal into\n * one signal the fetch listens on. Prefers the native `AbortSignal.any`; falls\n * back to manual wiring on runtimes that predate it. The caller signal is also\n * propagated to the timeout controller so aborting it cancels the in-flight\n * fetch immediately.\n */\nfunction linkSignals(timeoutController: AbortController, caller?: AbortSignal): AbortSignal {\n if (!caller) return timeoutController.signal\n if (typeof (AbortSignal as { any?: unknown }).any === 'function') {\n return AbortSignal.any([timeoutController.signal, caller])\n }\n if (caller.aborted) {\n timeoutController.abort()\n } else {\n caller.addEventListener('abort', () => timeoutController.abort(), { once: true })\n }\n return timeoutController.signal\n}\n\n/** True once the cross-attempt wall-clock budget (if any) is exhausted. */\nfunction deadlineExceeded(start: number, deadlineMs: number | undefined): boolean {\n return deadlineMs != null && Date.now() - start >= deadlineMs\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────\n\n/**\n * Strip a ```json / ``` code fence if the model emitted one.\n * Idempotent for naked JSON. Some models (claude-code via router, certain\n * deepseek models) wrap output even under json_object.\n */\nexport function stripFencedJson(raw: string): string {\n const trimmed = raw.trim()\n const m = trimmed.match(/^```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/)\n return m ? m[1]!.trim() : trimmed\n}\n\nexport function extractJsonPayload(raw: string): string {\n const stripped = stripFencedJson(raw)\n try {\n JSON.parse(stripped)\n return stripped\n } catch {\n // A response that declares a JSON root must parse as that complete root.\n // Scanning onward could turn a truncated object into one of its valid nested\n // arrays or objects and silently change the response schema.\n if (stripped.startsWith('{') || stripped.startsWith('[')) return stripped\n }\n\n // Only prose-leading responses may contain a recoverable JSON payload.\n const starts = [...stripped.matchAll(/[[{]/g)]\n .map((match) => match.index)\n .filter((index) => index != null)\n for (const start of starts) {\n const candidate = extractBalancedJson(stripped, start)\n if (!candidate) continue\n try {\n JSON.parse(candidate)\n return candidate\n } catch {\n // Keep scanning; earlier braces may belong to prose.\n }\n }\n\n return stripped\n}\n\nfunction extractBalancedJson(input: string, start: number): string | null {\n const opener = input[start]\n const closer = opener === '{' ? '}' : opener === '[' ? ']' : null\n if (!closer) return null\n\n const stack: string[] = [closer]\n let isInString = false\n let isEscaped = false\n\n for (let i = start + 1; i < input.length; i++) {\n const char = input[i]!\n if (isEscaped) {\n isEscaped = false\n continue\n }\n if (char === '\\\\') {\n isEscaped = isInString\n continue\n }\n if (char === '\"') {\n isInString = !isInString\n continue\n }\n if (isInString) continue\n\n if (char === '{') stack.push('}')\n else if (char === '[') stack.push(']')\n else if (char === stack[stack.length - 1]) {\n stack.pop()\n if (stack.length === 0) return input.slice(start, i + 1)\n }\n }\n\n return null\n}\n\n/**\n * Low-level call. Returns raw content + usage + cost. Retries on transient\n * failures; does NOT degrade schema here — callers that want graceful\n * degrade use `callLlmJson`.\n */\nexport async function callLlm(\n req: LlmCallRequest,\n opts: LlmClientOptions = {},\n): Promise<LlmCallResult> {\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '')\n const url = `${baseUrl}/chat/completions`\n const endpoint = '/chat/completions'\n const timeoutMs = req.timeoutMs ?? opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS\n const maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES\n const fetchFn = opts.fetch ?? globalThis.fetch\n const headers = buildHeaders(opts)\n const provider = opts.provider ?? providerFromBaseUrl(baseUrl)\n const sink = opts.rawSink\n const redactor = opts.redactor ?? defaultProviderRedactor\n const traceContext = opts.traceContext\n const callerSignal = opts.signal\n const deadlineMs = opts.deadlineMs\n const deadlineStart = Date.now()\n\n let lastErr: unknown\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n // A caller cancel is fatal — never retried. Checking before each attempt\n // means an already-aborted signal short-circuits without firing fetch.\n if (callerSignal?.aborted) {\n throw new DOMException('callLlm aborted by caller signal', 'AbortError')\n }\n // Stop retrying once the cross-attempt budget is spent rather than burning\n // a full per-attempt timeout on each remaining retry.\n if (attempt > 0 && deadlineExceeded(deadlineStart, deadlineMs)) {\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n }\n const controller = new AbortController()\n const attemptSignal = linkSignals(controller, callerSignal)\n const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs)\n const started = Date.now()\n const requestBody = buildBody(req, false)\n let attemptErrorRecorded = false\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'request',\n timestamp: started,\n requestHeaders: headers,\n requestBody,\n redactedFields: [],\n })\n }\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n signal: attemptSignal,\n })\n clearTimeout(timeoutHandle)\n const responseHeaders = sink ? headersToObject(res.headers) : undefined\n\n if (!res.ok) {\n const body = await res.text()\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: body,\n errorMessage: `HTTP ${res.status}`,\n redactedFields: [],\n })\n attemptErrorRecorded = true\n }\n const err = new LlmCallError(\n `LLM call ${res.status}: ${body.slice(0, 300)}`,\n res.status,\n body,\n req.model,\n )\n if (\n RETRYABLE_STATUS.has(res.status) &&\n attempt < maxRetries - 1 &&\n !deadlineExceeded(deadlineStart, deadlineMs)\n ) {\n lastErr = err\n const retryAfter = parseRetryAfter(res.headers)\n await sleep(retryAfter ?? backoffMs(attempt))\n continue\n }\n throw err\n }\n\n const text = await res.text()\n let json: Record<string, unknown>\n try {\n json = JSON.parse(text) as Record<string, unknown>\n } catch (parseErr) {\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: text,\n errorMessage: `non-JSON response: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n redactedFields: [],\n })\n attemptErrorRecorded = true\n }\n throw parseErr\n }\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'response',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: json,\n redactedFields: [],\n })\n }\n const choice = (\n json.choices as\n | Array<{ message?: { content?: string }; finish_reason?: string | null }>\n | undefined\n )?.[0]\n const usageRaw = (json.usage as Record<string, unknown> | undefined) ?? {}\n const costFromProxy = (json._response_cost ?? json.cost_usd) as number | undefined\n const content = choice?.message?.content ?? ''\n\n return {\n content,\n finishReason: choice?.finish_reason ?? null,\n contentEmpty: content.trim().length === 0,\n usage: {\n promptTokens: Number(usageRaw.prompt_tokens ?? 0),\n completionTokens: Number(usageRaw.completion_tokens ?? 0),\n totalTokens: Number(usageRaw.total_tokens ?? 0),\n cachedPromptTokens:\n usageRaw.prompt_tokens_details && typeof usageRaw.prompt_tokens_details === 'object'\n ? Number(\n (usageRaw.prompt_tokens_details as Record<string, unknown>).cached_tokens ?? 0,\n )\n : undefined,\n },\n costUsd: typeof costFromProxy === 'number' ? costFromProxy : null,\n model: (json.model as string) ?? req.model,\n durationMs: Date.now() - started,\n raw: json,\n }\n } catch (err) {\n clearTimeout(timeoutHandle)\n lastErr = err\n // A caller cancel is fatal even though an AbortError matches the\n // transient patterns — a cancelled call must surface immediately, not\n // be retried against the same dead intent.\n if (callerSignal?.aborted) {\n if (sink && !attemptErrorRecorded) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n }\n throw err\n }\n if (sink && !attemptErrorRecorded) {\n // Record only if neither the !res.ok branch nor the JSON.parse catch\n // already produced an error event for this attempt. Covers network\n // failures, timeouts, and aborts.\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n }\n if (\n attempt < maxRetries - 1 &&\n isTransientLlmError(err) &&\n !deadlineExceeded(deadlineStart, deadlineMs)\n ) {\n await sleep(backoffMs(attempt))\n continue\n }\n throw err\n }\n }\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n}\n\nasync function recordRaw(\n sink: RawProviderSink,\n redactor: ProviderRedactor,\n event: RawProviderEvent,\n): Promise<void> {\n // Errors from sinks must not crash the LLM call. Forensic capture is\n // best-effort; the structured trace is the system of record.\n try {\n await sink.record(redactor(event))\n } catch {\n // Intentionally swallowed.\n }\n}\n\nfunction headersToObject(h: Headers): Record<string, string> {\n const out: Record<string, string> = {}\n h.forEach((value, key) => {\n out[key] = value\n })\n return out\n}\n\nfunction cryptoEventId(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') return globalThis.crypto.randomUUID()\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n}\n\n/**\n * Structured-output call. Returns parsed JSON plus the raw result envelope.\n * Degrades `jsonSchema` → `jsonMode` on a 400 that names the schema param —\n * critical for deepseek-v3/v4, kimi-k2.6, and other models that don't accept\n * the `response_format.json_schema` shape but DO accept `json_object`.\n */\nexport async function callLlmJson<T = unknown>(\n req: LlmCallRequest,\n opts: LlmClientOptions = {},\n): Promise<{ value: T; result: LlmCallResult }> {\n try {\n const result = await callLlm({ ...req, jsonMode: req.jsonMode ?? !req.jsonSchema }, opts)\n const value = parseJsonResult<T>(result)\n return { value, result }\n } catch (err) {\n if (err instanceof LlmCallError && isSchemaRejection(err.status, err.body) && req.jsonSchema) {\n // Degrade to json_object + retry.\n const degradedReq: LlmCallRequest = { ...req, jsonMode: true, jsonSchema: undefined }\n const result = await callLlm(degradedReq, opts)\n const value = parseJsonResult<T>(result)\n return { value, result }\n }\n throw err\n }\n}\n\nfunction parseJsonResult<T>(result: LlmCallResult): T {\n if (result.finishReason === 'length') {\n throw new Error(\n `LLM returned truncated JSON content (model=${result.model}, finishReason=length)`,\n )\n }\n return parseJsonSafely<T>(result.content, result.model)\n}\n\nfunction parseJsonSafely<T>(content: string, model: string): T {\n const stripped = extractJsonPayload(content)\n try {\n return JSON.parse(stripped) as T\n } catch (err) {\n throw new Error(\n `LLM returned non-JSON content (model=${model}): ${\n err instanceof Error ? err.message : String(err)\n }\\n--- raw content ---\\n${content.slice(0, 800)}`,\n )\n }\n}\n\n// ─── Route assertion ────────────────────────────────────────────────────\n\nexport type LlmRouteAssertionReason =\n | 'no_explicit_base_url'\n | 'base_url_blocked'\n | 'base_url_not_allowed'\n | 'no_auth'\n | 'wrong_provider'\n\nexport class LlmRouteAssertionError extends CaptureIntegrityError {\n constructor(\n message: string,\n public readonly reason: LlmRouteAssertionReason,\n public readonly baseUrl: string,\n ) {\n super(message)\n }\n}\n\nexport interface LlmRouteRequirements {\n /**\n * Throw if `opts.baseUrl` is undefined, i.e. the call would fall back to\n * `DEFAULT_BASE_URL`. Set this for evaluation runs where silently using\n * the public/free-tier router is a defect — the launch reviewer needs to\n * know exactly which provider answered.\n */\n requireExplicitBaseUrl?: boolean\n /**\n * Allowlist of acceptable base URLs. Strings match by prefix\n * (case-insensitive); RegExps test against the full base URL.\n */\n allowedBaseUrls?: Array<string | RegExp>\n /** Blocklist that takes precedence over `allowedBaseUrls`. */\n blockedBaseUrls?: Array<string | RegExp>\n /** Throw if no auth header / api key is configured. */\n requireAuth?: boolean\n /**\n * Logical provider id the configured `baseUrl` is expected to match (via\n * `providerFromBaseUrl`). Mainly useful when paired with `requireExplicitBaseUrl`.\n */\n expectedProvider?: string\n}\n\n/**\n * Fail-loud assertion that the configured LLM client points at the route\n * the caller intends. Designed for the matrix-runner preflight: invoke\n * once before any LLM call to catch misconfiguration before a sweep burns\n * dollars on the wrong provider.\n *\n * Throws `LlmRouteAssertionError`. Pure — no I/O — so it's safe to call\n * from constructors and CI gates.\n */\nexport function assertLlmRoute(opts: LlmClientOptions, req: LlmRouteRequirements = {}): void {\n const baseUrlExplicit = opts.baseUrl !== undefined\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '')\n\n if (req.requireExplicitBaseUrl && !baseUrlExplicit) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: requireExplicitBaseUrl set but opts.baseUrl is undefined; would fall back to ${DEFAULT_BASE_URL}.`,\n 'no_explicit_base_url',\n baseUrl,\n )\n }\n\n if (req.blockedBaseUrls?.some((p) => matchUrl(baseUrl, p))) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: baseUrl ${baseUrl} matches a blocked pattern.`,\n 'base_url_blocked',\n baseUrl,\n )\n }\n\n if (req.allowedBaseUrls && req.allowedBaseUrls.length > 0) {\n const ok = req.allowedBaseUrls.some((p) => matchUrl(baseUrl, p))\n if (!ok) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: baseUrl ${baseUrl} is not in the allowed list (${req.allowedBaseUrls.map(describePattern).join(', ')}).`,\n 'base_url_not_allowed',\n baseUrl,\n )\n }\n }\n\n if (req.requireAuth && !opts.apiKey && !opts.bearer && !opts.authHeader) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: requireAuth set but no apiKey, bearer, or authHeader was supplied.`,\n 'no_auth',\n baseUrl,\n )\n }\n\n if (req.expectedProvider) {\n const actual = opts.provider ?? providerFromBaseUrl(baseUrl)\n if (actual !== req.expectedProvider) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: expected provider ${req.expectedProvider} but baseUrl ${baseUrl} resolves to ${actual}.`,\n 'wrong_provider',\n baseUrl,\n )\n }\n }\n}\n\nfunction matchUrl(url: string, pattern: string | RegExp): boolean {\n if (pattern instanceof RegExp) return pattern.test(url)\n return url.toLowerCase().startsWith(pattern.toLowerCase())\n}\n\nfunction describePattern(p: string | RegExp): string {\n return p instanceof RegExp ? p.source : p\n}\n\n/**\n * Probe whether a model is reachable. Returns latency + null error on\n * success; `ok=false` + error message on any failure (HTTP, timeout,\n * network, parse). Designed for sweep preflights — fail loud at the\n * boundary before burning a 30-leaf run on a misconfigured router.\n *\n * Sends a tiny `ping` message with `maxTokens=64`. Reasoning models\n * (glm-5.1, deepseek-v4) can burn the entire budget on internal reasoning\n * for short prompts, so don't tighten this further. We don't validate\n * content; HTTP 200 means reachable.\n */\nexport async function probeLlm(\n model: string,\n opts: LlmClientOptions & { timeoutMs?: number } = {},\n): Promise<{ ok: boolean; latencyMs: number; error: string | null }> {\n const start = Date.now()\n try {\n await callLlm(\n {\n model,\n messages: [{ role: 'user', content: 'ping' }],\n maxTokens: 64,\n timeoutMs: opts.timeoutMs ?? 30_000,\n },\n opts,\n )\n return { ok: true, latencyMs: Date.now() - start, error: null }\n } catch (err) {\n return {\n ok: false,\n latencyMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n }\n }\n}\n\n/**\n * Stateful client — construct once with defaults, call many times.\n * Thin wrapper around the free functions; exists for callers that want\n * to inject a single configured instance into multiple primitives.\n */\nexport class LlmClient {\n constructor(private readonly opts: LlmClientOptions = {}) {}\n\n call(req: LlmCallRequest, per?: LlmClientOptions): Promise<LlmCallResult> {\n return callLlm(req, { ...this.opts, ...per })\n }\n\n callJson<T = unknown>(\n req: LlmCallRequest,\n per?: LlmClientOptions,\n ): Promise<{ value: T; result: LlmCallResult }> {\n return callLlmJson<T>(req, { ...this.opts, ...per })\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_TRACE_ANALYST_KINDS,
|
|
4
4
|
createTraceAnalystKind,
|
|
5
5
|
makeFinding
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5S5NJ63F.js";
|
|
7
7
|
import {
|
|
8
8
|
LLM_INPUT_TOKEN_ATTR_KEYS,
|
|
9
9
|
LLM_OUTPUT_TOKEN_ATTR_KEYS,
|
|
@@ -202,4 +202,4 @@ export {
|
|
|
202
202
|
behavioralAnalyst,
|
|
203
203
|
buildDefaultAnalystRegistry
|
|
204
204
|
};
|
|
205
|
-
//# sourceMappingURL=chunk-
|
|
205
|
+
//# sourceMappingURL=chunk-I6LVHOV3.js.map
|