@agent-inspect/viewer 6.31.8 → 6.31.10
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 +187 -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 +187 -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
|
};
|
|
@@ -1706,6 +1717,17 @@ var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
|
|
|
1706
1717
|
summary: "Trace contains a parentId cycle.",
|
|
1707
1718
|
remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
|
|
1708
1719
|
relatedCodes: ["structure.cycle"]
|
|
1720
|
+
},
|
|
1721
|
+
AI_TRACE_CONTRACT_INPUT_INVALID: {
|
|
1722
|
+
code: "AI_TRACE_CONTRACT_INPUT_INVALID",
|
|
1723
|
+
summary: "evaluateTraceContract expects ({ read }, contract) or use evaluateTraceContractRead(read, contract).",
|
|
1724
|
+
remediation: "Pass TraceCheckInput as the first argument: evaluateTraceContract({ read }, contract).",
|
|
1725
|
+
relatedCodes: ["AI_CHECK_INVALID_ARGUMENTS"]
|
|
1726
|
+
},
|
|
1727
|
+
AI_INSPECT_RUN_UNSUPPORTED_OPTION: {
|
|
1728
|
+
code: "AI_INSPECT_RUN_UNSUPPORTED_OPTION",
|
|
1729
|
+
summary: 'inspectRun does not accept a "writer" option.',
|
|
1730
|
+
remediation: "Use createInspector({ writer }) then inspector.run(...). inspectRun persists via the global JSONL path (schema 0.1)."
|
|
1709
1731
|
}
|
|
1710
1732
|
});
|
|
1711
1733
|
function formatProgrammaticDiagnostic(code, detail) {
|
|
@@ -2261,6 +2283,13 @@ function metadataStringAttr(event, keys) {
|
|
|
2261
2283
|
}
|
|
2262
2284
|
return void 0;
|
|
2263
2285
|
}
|
|
2286
|
+
function numericAttr(event, keys) {
|
|
2287
|
+
for (const key of keys) {
|
|
2288
|
+
const value = event.attributes?.[key];
|
|
2289
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2290
|
+
}
|
|
2291
|
+
return void 0;
|
|
2292
|
+
}
|
|
2264
2293
|
function stripPrefix(name, prefixes) {
|
|
2265
2294
|
for (const prefix of prefixes) {
|
|
2266
2295
|
if (name.startsWith(prefix)) return name.slice(prefix.length);
|
|
@@ -2316,9 +2345,12 @@ function llmFinishReason(event) {
|
|
|
2316
2345
|
const keys = ["finishReason", "rawFinishReason", "finish_reason"];
|
|
2317
2346
|
return stringAttr(event, keys) ?? metadataStringAttr(event, keys);
|
|
2318
2347
|
}
|
|
2348
|
+
function retryCount(event) {
|
|
2349
|
+
return numericAttr(event, ["retryCount", "retryAttempt", "retry_attempt", "attempt"]);
|
|
2350
|
+
}
|
|
2319
2351
|
function finishedEvents(context, kind) {
|
|
2320
2352
|
return semanticEvents(context).filter(
|
|
2321
|
-
(event) => (event.kind === kind) && event.status !== "running"
|
|
2353
|
+
(event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
|
|
2322
2354
|
);
|
|
2323
2355
|
}
|
|
2324
2356
|
function toolInvocationEvents(context) {
|
|
@@ -2383,6 +2415,35 @@ function createRunDurationRule(options) {
|
|
|
2383
2415
|
}
|
|
2384
2416
|
};
|
|
2385
2417
|
}
|
|
2418
|
+
function createRunDepthRule(options) {
|
|
2419
|
+
return {
|
|
2420
|
+
id: "run.depth",
|
|
2421
|
+
category: "run",
|
|
2422
|
+
defaultSeverity: "error",
|
|
2423
|
+
evaluate(context) {
|
|
2424
|
+
const nodes = [...context.nodesByEventId.values()];
|
|
2425
|
+
const maxDepth = nodes.reduce((max, node) => Math.max(max, node.depth), 0);
|
|
2426
|
+
if (maxDepth <= options.maxDepth) return [];
|
|
2427
|
+
const deepest = nodes.filter((node) => node.depth === maxDepth);
|
|
2428
|
+
return [
|
|
2429
|
+
failFinding(
|
|
2430
|
+
"run.depth",
|
|
2431
|
+
`Run depth ${maxDepth} exceeded ${options.maxDepth}.`,
|
|
2432
|
+
deepest.map((node) => ({
|
|
2433
|
+
runId: node.event.runId,
|
|
2434
|
+
eventId: node.event.eventId,
|
|
2435
|
+
parentId: node.event.parentId,
|
|
2436
|
+
kind: node.event.kind,
|
|
2437
|
+
name: node.event.name,
|
|
2438
|
+
status: node.event.status
|
|
2439
|
+
})),
|
|
2440
|
+
{ maxDepth: options.maxDepth },
|
|
2441
|
+
maxDepth
|
|
2442
|
+
)
|
|
2443
|
+
];
|
|
2444
|
+
}
|
|
2445
|
+
};
|
|
2446
|
+
}
|
|
2386
2447
|
function createToolUsageRule(options) {
|
|
2387
2448
|
return {
|
|
2388
2449
|
id: "tool.usage",
|
|
@@ -2447,6 +2508,45 @@ function createToolUsageRule(options) {
|
|
|
2447
2508
|
}
|
|
2448
2509
|
};
|
|
2449
2510
|
}
|
|
2511
|
+
function createToolFailureRule(options) {
|
|
2512
|
+
return {
|
|
2513
|
+
id: "tool.failures",
|
|
2514
|
+
category: "tool",
|
|
2515
|
+
defaultSeverity: "error",
|
|
2516
|
+
evaluate(context) {
|
|
2517
|
+
const tools = finishedEvents(context, "TOOL");
|
|
2518
|
+
const failures = tools.filter((event) => event.status === "error");
|
|
2519
|
+
const retries = tools.map((event) => ({ event, count: retryCount(event) })).filter((item) => item.count !== void 0);
|
|
2520
|
+
const findings = [];
|
|
2521
|
+
if (options.maxFailures !== void 0 && failures.length > options.maxFailures) {
|
|
2522
|
+
findings.push(
|
|
2523
|
+
failFinding(
|
|
2524
|
+
"tool.failures",
|
|
2525
|
+
`Tool failure count ${failures.length} exceeded ${options.maxFailures}.`,
|
|
2526
|
+
failures.map((event) => eventEvidence(event)),
|
|
2527
|
+
{ maxFailures: options.maxFailures },
|
|
2528
|
+
failures.length
|
|
2529
|
+
)
|
|
2530
|
+
);
|
|
2531
|
+
}
|
|
2532
|
+
if (options.maxRetries !== void 0) {
|
|
2533
|
+
const excessiveRetries = retries.filter((item) => item.count > options.maxRetries);
|
|
2534
|
+
if (excessiveRetries.length > 0) {
|
|
2535
|
+
findings.push(
|
|
2536
|
+
failFinding(
|
|
2537
|
+
"tool.failures",
|
|
2538
|
+
`Tool retry count exceeded ${options.maxRetries}.`,
|
|
2539
|
+
excessiveRetries.map((item) => eventEvidence(item.event, "attributes.retryCount")),
|
|
2540
|
+
{ maxRetries: options.maxRetries },
|
|
2541
|
+
excessiveRetries.map((item) => ({ tool: toolName(item.event), retries: item.count }))
|
|
2542
|
+
)
|
|
2543
|
+
);
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
return findings;
|
|
2547
|
+
}
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2450
2550
|
function createLlmUsageRule(options) {
|
|
2451
2551
|
return {
|
|
2452
2552
|
id: "llm.usage",
|
|
@@ -5550,21 +5650,48 @@ function openTrace(input, options = {}) {
|
|
|
5550
5650
|
}
|
|
5551
5651
|
|
|
5552
5652
|
// packages/core/src/suite/run.ts
|
|
5653
|
+
var KNOWN_SUITE_SELECT_IDS = /* @__PURE__ */ new Set([
|
|
5654
|
+
"run.status",
|
|
5655
|
+
"run.duration",
|
|
5656
|
+
"run.depth",
|
|
5657
|
+
"outcome.status",
|
|
5658
|
+
"tool.usage",
|
|
5659
|
+
"tool.failures",
|
|
5660
|
+
"llm.usage"
|
|
5661
|
+
]);
|
|
5553
5662
|
function diagnostic4(code, message, severity = "error", caseId) {
|
|
5554
5663
|
return { code, message, severity, ...caseId !== void 0 ? { caseId } : {} };
|
|
5555
5664
|
}
|
|
5556
|
-
function
|
|
5665
|
+
function buildCaseAssertions(suiteCase, config) {
|
|
5557
5666
|
const rules = [];
|
|
5558
5667
|
const select = new Set(config.checks?.select ?? []);
|
|
5559
|
-
|
|
5668
|
+
const configDiagnostics = [];
|
|
5669
|
+
const evalConfig = config.eval;
|
|
5670
|
+
const declaredSelect = [...select];
|
|
5671
|
+
for (const id of declaredSelect) {
|
|
5672
|
+
if (!KNOWN_SUITE_SELECT_IDS.has(id)) {
|
|
5673
|
+
configDiagnostics.push(
|
|
5674
|
+
diagnostic4(
|
|
5675
|
+
"AI_SUITE_UNKNOWN_SELECTOR",
|
|
5676
|
+
`Unknown or unsupported suite check selector "${id}".`,
|
|
5677
|
+
"error",
|
|
5678
|
+
suiteCase.id
|
|
5679
|
+
)
|
|
5680
|
+
);
|
|
5681
|
+
}
|
|
5682
|
+
}
|
|
5683
|
+
if (select.has("run.status") || evalConfig?.requireSuccess === true) {
|
|
5560
5684
|
rules.push(createRunStatusRule());
|
|
5685
|
+
select.add("run.status");
|
|
5561
5686
|
}
|
|
5562
5687
|
const requiredTools = [
|
|
5563
5688
|
...config.checks?.tool?.required ?? [],
|
|
5689
|
+
...evalConfig?.requiredTools ?? [],
|
|
5564
5690
|
...suiteCase.requireTools ?? []
|
|
5565
5691
|
];
|
|
5566
5692
|
const forbiddenTools = [
|
|
5567
5693
|
...config.checks?.tool?.forbidden ?? [],
|
|
5694
|
+
...evalConfig?.forbiddenTools ?? [],
|
|
5568
5695
|
...suiteCase.forbidTools ?? []
|
|
5569
5696
|
];
|
|
5570
5697
|
if (requiredTools.length > 0 || forbiddenTools.length > 0) {
|
|
@@ -5576,20 +5703,51 @@ function buildCaseRules(suiteCase, config) {
|
|
|
5576
5703
|
);
|
|
5577
5704
|
select.add("tool.usage");
|
|
5578
5705
|
}
|
|
5579
|
-
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ??
|
|
5706
|
+
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ?? evalConfig?.maxDurationMs;
|
|
5580
5707
|
if (maxDurationMs !== void 0) {
|
|
5581
5708
|
rules.push(createRunDurationRule({ maxDurationMs }));
|
|
5582
5709
|
select.add("run.duration");
|
|
5583
5710
|
}
|
|
5584
|
-
const
|
|
5585
|
-
if (
|
|
5586
|
-
rules.push(
|
|
5711
|
+
const maxDepth = config.checks?.run?.maxDepth ?? evalConfig?.maxDepth;
|
|
5712
|
+
if (maxDepth !== void 0) {
|
|
5713
|
+
rules.push(createRunDepthRule({ maxDepth }));
|
|
5714
|
+
select.add("run.depth");
|
|
5715
|
+
}
|
|
5716
|
+
if (evalConfig?.maxRetries !== void 0) {
|
|
5717
|
+
rules.push(createToolFailureRule({ maxRetries: evalConfig.maxRetries }));
|
|
5718
|
+
select.add("tool.failures");
|
|
5719
|
+
}
|
|
5720
|
+
const allowedModels = config.checks?.llm?.allowedModels;
|
|
5721
|
+
const maxTotalTokens = config.checks?.llm?.maxTotalTokens ?? evalConfig?.maxTotalTokens;
|
|
5722
|
+
if (allowedModels !== void 0 || maxTotalTokens !== void 0) {
|
|
5723
|
+
rules.push(
|
|
5724
|
+
createLlmUsageRule({
|
|
5725
|
+
...allowedModels !== void 0 ? { allowedModels } : {},
|
|
5726
|
+
...maxTotalTokens !== void 0 ? { maxTotalTokens } : {}
|
|
5727
|
+
})
|
|
5728
|
+
);
|
|
5587
5729
|
select.add("llm.usage");
|
|
5588
5730
|
}
|
|
5589
5731
|
if (select.has("outcome.status")) {
|
|
5590
5732
|
rules.push(createObservedOutcomeRule({ failOn: ["failed"] }));
|
|
5591
5733
|
}
|
|
5592
|
-
|
|
5734
|
+
const observationCount = suiteCase.expectedObservations?.length ?? 0;
|
|
5735
|
+
if (rules.length === 0 && observationCount === 0 && configDiagnostics.length === 0) {
|
|
5736
|
+
configDiagnostics.push(
|
|
5737
|
+
diagnostic4(
|
|
5738
|
+
"AI_SUITE_NO_ASSERTIONS",
|
|
5739
|
+
`Suite case "${suiteCase.id}" declares no effective checks, eval controls, or expected observations.`,
|
|
5740
|
+
"error",
|
|
5741
|
+
suiteCase.id
|
|
5742
|
+
)
|
|
5743
|
+
);
|
|
5744
|
+
}
|
|
5745
|
+
return {
|
|
5746
|
+
rules,
|
|
5747
|
+
select: [...select],
|
|
5748
|
+
observationCount,
|
|
5749
|
+
configDiagnostics
|
|
5750
|
+
};
|
|
5593
5751
|
}
|
|
5594
5752
|
function outcomesFromRead(read) {
|
|
5595
5753
|
const persistedOutcomes = extractOutcomesFromPersistedEvents(
|
|
@@ -5670,8 +5828,20 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5670
5828
|
]
|
|
5671
5829
|
};
|
|
5672
5830
|
}
|
|
5673
|
-
const
|
|
5674
|
-
|
|
5831
|
+
const compiled = buildCaseAssertions(suiteCase, config);
|
|
5832
|
+
if (compiled.configDiagnostics.length > 0) {
|
|
5833
|
+
return {
|
|
5834
|
+
id: suiteCase.id,
|
|
5835
|
+
status: "error",
|
|
5836
|
+
tracePath: resolved.tracePath,
|
|
5837
|
+
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5838
|
+
checkOk: false,
|
|
5839
|
+
...config.eval?.requireSuccess === true ? { evalOk: false } : {},
|
|
5840
|
+
message: compiled.configDiagnostics.map((item) => item.message).join("; "),
|
|
5841
|
+
diagnostics: compiled.configDiagnostics
|
|
5842
|
+
};
|
|
5843
|
+
}
|
|
5844
|
+
const checkResult = compiled.rules.length > 0 ? runTraceChecks({ read }, { rules: compiled.rules, select: compiled.select }) : {
|
|
5675
5845
|
ok: true,
|
|
5676
5846
|
status: "pass",
|
|
5677
5847
|
format: read.format,
|
|
@@ -5699,6 +5869,9 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5699
5869
|
];
|
|
5700
5870
|
const checkOk = checkResult.ok;
|
|
5701
5871
|
const observationsOk = observationResult.ok;
|
|
5872
|
+
const evalOk = config.eval?.requireSuccess === true ? checkResult.findings.every(
|
|
5873
|
+
(finding) => finding.ruleId !== "run.status" || finding.status !== "fail"
|
|
5874
|
+
) && checkResult.diagnostics.every((item) => item.severity !== "error") : void 0;
|
|
5702
5875
|
const ok = checkOk && observationsOk;
|
|
5703
5876
|
const status = ok ? "pass" : checkResult.status === "error" ? "error" : "fail";
|
|
5704
5877
|
return {
|
|
@@ -5707,6 +5880,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5707
5880
|
tracePath: resolved.tracePath,
|
|
5708
5881
|
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5709
5882
|
checkOk,
|
|
5883
|
+
...evalOk !== void 0 ? { evalOk } : {},
|
|
5710
5884
|
observationsOk,
|
|
5711
5885
|
diagnostics,
|
|
5712
5886
|
...ok ? {} : {
|