@agent-inspect/viewer 6.31.8 → 6.31.9
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/dist/index.cjs +176 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +176 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -771,7 +771,18 @@ async function readTraceEventsFromFile(filePath) {
|
|
|
771
771
|
}
|
|
772
772
|
|
|
773
773
|
// packages/core/src/context.ts
|
|
774
|
-
|
|
774
|
+
var GLOBAL_CONTEXT_ALS_KEY = "agent-inspect:execution-context-als:v1";
|
|
775
|
+
function getSharedContextStorage() {
|
|
776
|
+
const host = globalThis;
|
|
777
|
+
const existing = host[GLOBAL_CONTEXT_ALS_KEY];
|
|
778
|
+
if (existing instanceof async_hooks.AsyncLocalStorage) {
|
|
779
|
+
return existing;
|
|
780
|
+
}
|
|
781
|
+
const created = new async_hooks.AsyncLocalStorage();
|
|
782
|
+
host[GLOBAL_CONTEXT_ALS_KEY] = created;
|
|
783
|
+
return created;
|
|
784
|
+
}
|
|
785
|
+
getSharedContextStorage();
|
|
775
786
|
|
|
776
787
|
// packages/core/src/outcomes/types.ts
|
|
777
788
|
var OBSERVED_OUTCOME_METHODS = [
|
|
@@ -1374,7 +1385,7 @@ function enrichSessionSummary(summary, runs, options = {}) {
|
|
|
1374
1385
|
}
|
|
1375
1386
|
const lastMs = latestActivityMs(sessionRuns);
|
|
1376
1387
|
const lastActivity = lastMs > 0 ? new Date(lastMs).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
1377
|
-
const
|
|
1388
|
+
const retryCount2 = summary.retries.filter(
|
|
1378
1389
|
(retry) => retry.retryOf !== void 0 || (retry.attempt ?? 0) > 1
|
|
1379
1390
|
).length;
|
|
1380
1391
|
return {
|
|
@@ -1388,7 +1399,7 @@ function enrichSessionSummary(summary, runs, options = {}) {
|
|
|
1388
1399
|
workflowId,
|
|
1389
1400
|
lastError: deriveLastError(sessionRuns),
|
|
1390
1401
|
lastActivity,
|
|
1391
|
-
retryCount,
|
|
1402
|
+
retryCount: retryCount2,
|
|
1392
1403
|
observationSummary: deriveObservationSummary(sessionRuns),
|
|
1393
1404
|
checkSummary: deriveCheckSummary(sessionRuns)
|
|
1394
1405
|
};
|
|
@@ -2261,6 +2272,13 @@ function metadataStringAttr(event, keys) {
|
|
|
2261
2272
|
}
|
|
2262
2273
|
return void 0;
|
|
2263
2274
|
}
|
|
2275
|
+
function numericAttr(event, keys) {
|
|
2276
|
+
for (const key of keys) {
|
|
2277
|
+
const value = event.attributes?.[key];
|
|
2278
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2279
|
+
}
|
|
2280
|
+
return void 0;
|
|
2281
|
+
}
|
|
2264
2282
|
function stripPrefix(name, prefixes) {
|
|
2265
2283
|
for (const prefix of prefixes) {
|
|
2266
2284
|
if (name.startsWith(prefix)) return name.slice(prefix.length);
|
|
@@ -2316,9 +2334,12 @@ function llmFinishReason(event) {
|
|
|
2316
2334
|
const keys = ["finishReason", "rawFinishReason", "finish_reason"];
|
|
2317
2335
|
return stringAttr(event, keys) ?? metadataStringAttr(event, keys);
|
|
2318
2336
|
}
|
|
2337
|
+
function retryCount(event) {
|
|
2338
|
+
return numericAttr(event, ["retryCount", "retryAttempt", "retry_attempt", "attempt"]);
|
|
2339
|
+
}
|
|
2319
2340
|
function finishedEvents(context, kind) {
|
|
2320
2341
|
return semanticEvents(context).filter(
|
|
2321
|
-
(event) => (event.kind === kind) && event.status !== "running"
|
|
2342
|
+
(event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
|
|
2322
2343
|
);
|
|
2323
2344
|
}
|
|
2324
2345
|
function toolInvocationEvents(context) {
|
|
@@ -2383,6 +2404,35 @@ function createRunDurationRule(options) {
|
|
|
2383
2404
|
}
|
|
2384
2405
|
};
|
|
2385
2406
|
}
|
|
2407
|
+
function createRunDepthRule(options) {
|
|
2408
|
+
return {
|
|
2409
|
+
id: "run.depth",
|
|
2410
|
+
category: "run",
|
|
2411
|
+
defaultSeverity: "error",
|
|
2412
|
+
evaluate(context) {
|
|
2413
|
+
const nodes = [...context.nodesByEventId.values()];
|
|
2414
|
+
const maxDepth = nodes.reduce((max, node) => Math.max(max, node.depth), 0);
|
|
2415
|
+
if (maxDepth <= options.maxDepth) return [];
|
|
2416
|
+
const deepest = nodes.filter((node) => node.depth === maxDepth);
|
|
2417
|
+
return [
|
|
2418
|
+
failFinding(
|
|
2419
|
+
"run.depth",
|
|
2420
|
+
`Run depth ${maxDepth} exceeded ${options.maxDepth}.`,
|
|
2421
|
+
deepest.map((node) => ({
|
|
2422
|
+
runId: node.event.runId,
|
|
2423
|
+
eventId: node.event.eventId,
|
|
2424
|
+
parentId: node.event.parentId,
|
|
2425
|
+
kind: node.event.kind,
|
|
2426
|
+
name: node.event.name,
|
|
2427
|
+
status: node.event.status
|
|
2428
|
+
})),
|
|
2429
|
+
{ maxDepth: options.maxDepth },
|
|
2430
|
+
maxDepth
|
|
2431
|
+
)
|
|
2432
|
+
];
|
|
2433
|
+
}
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2386
2436
|
function createToolUsageRule(options) {
|
|
2387
2437
|
return {
|
|
2388
2438
|
id: "tool.usage",
|
|
@@ -2447,6 +2497,45 @@ function createToolUsageRule(options) {
|
|
|
2447
2497
|
}
|
|
2448
2498
|
};
|
|
2449
2499
|
}
|
|
2500
|
+
function createToolFailureRule(options) {
|
|
2501
|
+
return {
|
|
2502
|
+
id: "tool.failures",
|
|
2503
|
+
category: "tool",
|
|
2504
|
+
defaultSeverity: "error",
|
|
2505
|
+
evaluate(context) {
|
|
2506
|
+
const tools = finishedEvents(context, "TOOL");
|
|
2507
|
+
const failures = tools.filter((event) => event.status === "error");
|
|
2508
|
+
const retries = tools.map((event) => ({ event, count: retryCount(event) })).filter((item) => item.count !== void 0);
|
|
2509
|
+
const findings = [];
|
|
2510
|
+
if (options.maxFailures !== void 0 && failures.length > options.maxFailures) {
|
|
2511
|
+
findings.push(
|
|
2512
|
+
failFinding(
|
|
2513
|
+
"tool.failures",
|
|
2514
|
+
`Tool failure count ${failures.length} exceeded ${options.maxFailures}.`,
|
|
2515
|
+
failures.map((event) => eventEvidence(event)),
|
|
2516
|
+
{ maxFailures: options.maxFailures },
|
|
2517
|
+
failures.length
|
|
2518
|
+
)
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
if (options.maxRetries !== void 0) {
|
|
2522
|
+
const excessiveRetries = retries.filter((item) => item.count > options.maxRetries);
|
|
2523
|
+
if (excessiveRetries.length > 0) {
|
|
2524
|
+
findings.push(
|
|
2525
|
+
failFinding(
|
|
2526
|
+
"tool.failures",
|
|
2527
|
+
`Tool retry count exceeded ${options.maxRetries}.`,
|
|
2528
|
+
excessiveRetries.map((item) => eventEvidence(item.event, "attributes.retryCount")),
|
|
2529
|
+
{ maxRetries: options.maxRetries },
|
|
2530
|
+
excessiveRetries.map((item) => ({ tool: toolName(item.event), retries: item.count }))
|
|
2531
|
+
)
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return findings;
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2450
2539
|
function createLlmUsageRule(options) {
|
|
2451
2540
|
return {
|
|
2452
2541
|
id: "llm.usage",
|
|
@@ -5550,21 +5639,48 @@ function openTrace(input, options = {}) {
|
|
|
5550
5639
|
}
|
|
5551
5640
|
|
|
5552
5641
|
// packages/core/src/suite/run.ts
|
|
5642
|
+
var KNOWN_SUITE_SELECT_IDS = /* @__PURE__ */ new Set([
|
|
5643
|
+
"run.status",
|
|
5644
|
+
"run.duration",
|
|
5645
|
+
"run.depth",
|
|
5646
|
+
"outcome.status",
|
|
5647
|
+
"tool.usage",
|
|
5648
|
+
"tool.failures",
|
|
5649
|
+
"llm.usage"
|
|
5650
|
+
]);
|
|
5553
5651
|
function diagnostic4(code, message, severity = "error", caseId) {
|
|
5554
5652
|
return { code, message, severity, ...caseId !== void 0 ? { caseId } : {} };
|
|
5555
5653
|
}
|
|
5556
|
-
function
|
|
5654
|
+
function buildCaseAssertions(suiteCase, config) {
|
|
5557
5655
|
const rules = [];
|
|
5558
5656
|
const select = new Set(config.checks?.select ?? []);
|
|
5559
|
-
|
|
5657
|
+
const configDiagnostics = [];
|
|
5658
|
+
const evalConfig = config.eval;
|
|
5659
|
+
const declaredSelect = [...select];
|
|
5660
|
+
for (const id of declaredSelect) {
|
|
5661
|
+
if (!KNOWN_SUITE_SELECT_IDS.has(id)) {
|
|
5662
|
+
configDiagnostics.push(
|
|
5663
|
+
diagnostic4(
|
|
5664
|
+
"AI_SUITE_UNKNOWN_SELECTOR",
|
|
5665
|
+
`Unknown or unsupported suite check selector "${id}".`,
|
|
5666
|
+
"error",
|
|
5667
|
+
suiteCase.id
|
|
5668
|
+
)
|
|
5669
|
+
);
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
if (select.has("run.status") || evalConfig?.requireSuccess === true) {
|
|
5560
5673
|
rules.push(createRunStatusRule());
|
|
5674
|
+
select.add("run.status");
|
|
5561
5675
|
}
|
|
5562
5676
|
const requiredTools = [
|
|
5563
5677
|
...config.checks?.tool?.required ?? [],
|
|
5678
|
+
...evalConfig?.requiredTools ?? [],
|
|
5564
5679
|
...suiteCase.requireTools ?? []
|
|
5565
5680
|
];
|
|
5566
5681
|
const forbiddenTools = [
|
|
5567
5682
|
...config.checks?.tool?.forbidden ?? [],
|
|
5683
|
+
...evalConfig?.forbiddenTools ?? [],
|
|
5568
5684
|
...suiteCase.forbidTools ?? []
|
|
5569
5685
|
];
|
|
5570
5686
|
if (requiredTools.length > 0 || forbiddenTools.length > 0) {
|
|
@@ -5576,20 +5692,51 @@ function buildCaseRules(suiteCase, config) {
|
|
|
5576
5692
|
);
|
|
5577
5693
|
select.add("tool.usage");
|
|
5578
5694
|
}
|
|
5579
|
-
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ??
|
|
5695
|
+
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ?? evalConfig?.maxDurationMs;
|
|
5580
5696
|
if (maxDurationMs !== void 0) {
|
|
5581
5697
|
rules.push(createRunDurationRule({ maxDurationMs }));
|
|
5582
5698
|
select.add("run.duration");
|
|
5583
5699
|
}
|
|
5584
|
-
const
|
|
5585
|
-
if (
|
|
5586
|
-
rules.push(
|
|
5700
|
+
const maxDepth = config.checks?.run?.maxDepth ?? evalConfig?.maxDepth;
|
|
5701
|
+
if (maxDepth !== void 0) {
|
|
5702
|
+
rules.push(createRunDepthRule({ maxDepth }));
|
|
5703
|
+
select.add("run.depth");
|
|
5704
|
+
}
|
|
5705
|
+
if (evalConfig?.maxRetries !== void 0) {
|
|
5706
|
+
rules.push(createToolFailureRule({ maxRetries: evalConfig.maxRetries }));
|
|
5707
|
+
select.add("tool.failures");
|
|
5708
|
+
}
|
|
5709
|
+
const allowedModels = config.checks?.llm?.allowedModels;
|
|
5710
|
+
const maxTotalTokens = config.checks?.llm?.maxTotalTokens ?? evalConfig?.maxTotalTokens;
|
|
5711
|
+
if (allowedModels !== void 0 || maxTotalTokens !== void 0) {
|
|
5712
|
+
rules.push(
|
|
5713
|
+
createLlmUsageRule({
|
|
5714
|
+
...allowedModels !== void 0 ? { allowedModels } : {},
|
|
5715
|
+
...maxTotalTokens !== void 0 ? { maxTotalTokens } : {}
|
|
5716
|
+
})
|
|
5717
|
+
);
|
|
5587
5718
|
select.add("llm.usage");
|
|
5588
5719
|
}
|
|
5589
5720
|
if (select.has("outcome.status")) {
|
|
5590
5721
|
rules.push(createObservedOutcomeRule({ failOn: ["failed"] }));
|
|
5591
5722
|
}
|
|
5592
|
-
|
|
5723
|
+
const observationCount = suiteCase.expectedObservations?.length ?? 0;
|
|
5724
|
+
if (rules.length === 0 && observationCount === 0 && configDiagnostics.length === 0) {
|
|
5725
|
+
configDiagnostics.push(
|
|
5726
|
+
diagnostic4(
|
|
5727
|
+
"AI_SUITE_NO_ASSERTIONS",
|
|
5728
|
+
`Suite case "${suiteCase.id}" declares no effective checks, eval controls, or expected observations.`,
|
|
5729
|
+
"error",
|
|
5730
|
+
suiteCase.id
|
|
5731
|
+
)
|
|
5732
|
+
);
|
|
5733
|
+
}
|
|
5734
|
+
return {
|
|
5735
|
+
rules,
|
|
5736
|
+
select: [...select],
|
|
5737
|
+
observationCount,
|
|
5738
|
+
configDiagnostics
|
|
5739
|
+
};
|
|
5593
5740
|
}
|
|
5594
5741
|
function outcomesFromRead(read) {
|
|
5595
5742
|
const persistedOutcomes = extractOutcomesFromPersistedEvents(
|
|
@@ -5670,8 +5817,20 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5670
5817
|
]
|
|
5671
5818
|
};
|
|
5672
5819
|
}
|
|
5673
|
-
const
|
|
5674
|
-
|
|
5820
|
+
const compiled = buildCaseAssertions(suiteCase, config);
|
|
5821
|
+
if (compiled.configDiagnostics.length > 0) {
|
|
5822
|
+
return {
|
|
5823
|
+
id: suiteCase.id,
|
|
5824
|
+
status: "error",
|
|
5825
|
+
tracePath: resolved.tracePath,
|
|
5826
|
+
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5827
|
+
checkOk: false,
|
|
5828
|
+
...config.eval?.requireSuccess === true ? { evalOk: false } : {},
|
|
5829
|
+
message: compiled.configDiagnostics.map((item) => item.message).join("; "),
|
|
5830
|
+
diagnostics: compiled.configDiagnostics
|
|
5831
|
+
};
|
|
5832
|
+
}
|
|
5833
|
+
const checkResult = compiled.rules.length > 0 ? runTraceChecks({ read }, { rules: compiled.rules, select: compiled.select }) : {
|
|
5675
5834
|
ok: true,
|
|
5676
5835
|
status: "pass",
|
|
5677
5836
|
format: read.format,
|
|
@@ -5699,6 +5858,9 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5699
5858
|
];
|
|
5700
5859
|
const checkOk = checkResult.ok;
|
|
5701
5860
|
const observationsOk = observationResult.ok;
|
|
5861
|
+
const evalOk = config.eval?.requireSuccess === true ? checkResult.findings.every(
|
|
5862
|
+
(finding) => finding.ruleId !== "run.status" || finding.status !== "fail"
|
|
5863
|
+
) && checkResult.diagnostics.every((item) => item.severity !== "error") : void 0;
|
|
5702
5864
|
const ok = checkOk && observationsOk;
|
|
5703
5865
|
const status = ok ? "pass" : checkResult.status === "error" ? "error" : "fail";
|
|
5704
5866
|
return {
|
|
@@ -5707,6 +5869,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5707
5869
|
tracePath: resolved.tracePath,
|
|
5708
5870
|
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5709
5871
|
checkOk,
|
|
5872
|
+
...evalOk !== void 0 ? { evalOk } : {},
|
|
5710
5873
|
observationsOk,
|
|
5711
5874
|
diagnostics,
|
|
5712
5875
|
...ok ? {} : {
|