@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.d.cts
CHANGED
|
@@ -186,7 +186,7 @@ interface TimelineOptions {
|
|
|
186
186
|
declare function buildRunTimeline(events: readonly TraceEvent[], options?: TimelineOptions): RunTimeline;
|
|
187
187
|
|
|
188
188
|
type SuiteCaseStatus = "pass" | "fail" | "error" | "skipped";
|
|
189
|
-
type SuiteDiagnosticCode = "AI_SUITE_CONFIG_INVALID" | "AI_SUITE_CONFIG_LOAD_FAILED" | "AI_SUITE_CASE_TRACE_MISSING" | "AI_SUITE_CASE_CHECK_FAILED" | "AI_SUITE_CASE_EVAL_FAILED" | "AI_SUITE_CASE_OBSERVATION_FAILED" | "AI_SUITE_TRACE_UNREADABLE";
|
|
189
|
+
type SuiteDiagnosticCode = "AI_SUITE_CONFIG_INVALID" | "AI_SUITE_CONFIG_LOAD_FAILED" | "AI_SUITE_CASE_TRACE_MISSING" | "AI_SUITE_CASE_CHECK_FAILED" | "AI_SUITE_CASE_EVAL_FAILED" | "AI_SUITE_CASE_OBSERVATION_FAILED" | "AI_SUITE_NO_ASSERTIONS" | "AI_SUITE_UNKNOWN_SELECTOR" | "AI_SUITE_TRACE_UNREADABLE";
|
|
190
190
|
interface SuiteDiagnostic {
|
|
191
191
|
code: SuiteDiagnosticCode;
|
|
192
192
|
severity: "error" | "warning" | "info";
|
package/dist/index.d.ts
CHANGED
|
@@ -186,7 +186,7 @@ interface TimelineOptions {
|
|
|
186
186
|
declare function buildRunTimeline(events: readonly TraceEvent[], options?: TimelineOptions): RunTimeline;
|
|
187
187
|
|
|
188
188
|
type SuiteCaseStatus = "pass" | "fail" | "error" | "skipped";
|
|
189
|
-
type SuiteDiagnosticCode = "AI_SUITE_CONFIG_INVALID" | "AI_SUITE_CONFIG_LOAD_FAILED" | "AI_SUITE_CASE_TRACE_MISSING" | "AI_SUITE_CASE_CHECK_FAILED" | "AI_SUITE_CASE_EVAL_FAILED" | "AI_SUITE_CASE_OBSERVATION_FAILED" | "AI_SUITE_TRACE_UNREADABLE";
|
|
189
|
+
type SuiteDiagnosticCode = "AI_SUITE_CONFIG_INVALID" | "AI_SUITE_CONFIG_LOAD_FAILED" | "AI_SUITE_CASE_TRACE_MISSING" | "AI_SUITE_CASE_CHECK_FAILED" | "AI_SUITE_CASE_EVAL_FAILED" | "AI_SUITE_CASE_OBSERVATION_FAILED" | "AI_SUITE_NO_ASSERTIONS" | "AI_SUITE_UNKNOWN_SELECTOR" | "AI_SUITE_TRACE_UNREADABLE";
|
|
190
190
|
interface SuiteDiagnostic {
|
|
191
191
|
code: SuiteDiagnosticCode;
|
|
192
192
|
severity: "error" | "warning" | "info";
|
package/dist/index.mjs
CHANGED
|
@@ -764,7 +764,18 @@ async function readTraceEventsFromFile(filePath) {
|
|
|
764
764
|
}
|
|
765
765
|
|
|
766
766
|
// packages/core/src/context.ts
|
|
767
|
-
|
|
767
|
+
var GLOBAL_CONTEXT_ALS_KEY = "agent-inspect:execution-context-als:v1";
|
|
768
|
+
function getSharedContextStorage() {
|
|
769
|
+
const host = globalThis;
|
|
770
|
+
const existing = host[GLOBAL_CONTEXT_ALS_KEY];
|
|
771
|
+
if (existing instanceof AsyncLocalStorage) {
|
|
772
|
+
return existing;
|
|
773
|
+
}
|
|
774
|
+
const created = new AsyncLocalStorage();
|
|
775
|
+
host[GLOBAL_CONTEXT_ALS_KEY] = created;
|
|
776
|
+
return created;
|
|
777
|
+
}
|
|
778
|
+
getSharedContextStorage();
|
|
768
779
|
|
|
769
780
|
// packages/core/src/outcomes/types.ts
|
|
770
781
|
var OBSERVED_OUTCOME_METHODS = [
|
|
@@ -1367,7 +1378,7 @@ function enrichSessionSummary(summary, runs, options = {}) {
|
|
|
1367
1378
|
}
|
|
1368
1379
|
const lastMs = latestActivityMs(sessionRuns);
|
|
1369
1380
|
const lastActivity = lastMs > 0 ? new Date(lastMs).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
1370
|
-
const
|
|
1381
|
+
const retryCount2 = summary.retries.filter(
|
|
1371
1382
|
(retry) => retry.retryOf !== void 0 || (retry.attempt ?? 0) > 1
|
|
1372
1383
|
).length;
|
|
1373
1384
|
return {
|
|
@@ -1381,7 +1392,7 @@ function enrichSessionSummary(summary, runs, options = {}) {
|
|
|
1381
1392
|
workflowId,
|
|
1382
1393
|
lastError: deriveLastError(sessionRuns),
|
|
1383
1394
|
lastActivity,
|
|
1384
|
-
retryCount,
|
|
1395
|
+
retryCount: retryCount2,
|
|
1385
1396
|
observationSummary: deriveObservationSummary(sessionRuns),
|
|
1386
1397
|
checkSummary: deriveCheckSummary(sessionRuns)
|
|
1387
1398
|
};
|
|
@@ -2254,6 +2265,13 @@ function metadataStringAttr(event, keys) {
|
|
|
2254
2265
|
}
|
|
2255
2266
|
return void 0;
|
|
2256
2267
|
}
|
|
2268
|
+
function numericAttr(event, keys) {
|
|
2269
|
+
for (const key of keys) {
|
|
2270
|
+
const value = event.attributes?.[key];
|
|
2271
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2272
|
+
}
|
|
2273
|
+
return void 0;
|
|
2274
|
+
}
|
|
2257
2275
|
function stripPrefix(name, prefixes) {
|
|
2258
2276
|
for (const prefix of prefixes) {
|
|
2259
2277
|
if (name.startsWith(prefix)) return name.slice(prefix.length);
|
|
@@ -2309,9 +2327,12 @@ function llmFinishReason(event) {
|
|
|
2309
2327
|
const keys = ["finishReason", "rawFinishReason", "finish_reason"];
|
|
2310
2328
|
return stringAttr(event, keys) ?? metadataStringAttr(event, keys);
|
|
2311
2329
|
}
|
|
2330
|
+
function retryCount(event) {
|
|
2331
|
+
return numericAttr(event, ["retryCount", "retryAttempt", "retry_attempt", "attempt"]);
|
|
2332
|
+
}
|
|
2312
2333
|
function finishedEvents(context, kind) {
|
|
2313
2334
|
return semanticEvents(context).filter(
|
|
2314
|
-
(event) => (event.kind === kind) && event.status !== "running"
|
|
2335
|
+
(event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
|
|
2315
2336
|
);
|
|
2316
2337
|
}
|
|
2317
2338
|
function toolInvocationEvents(context) {
|
|
@@ -2376,6 +2397,35 @@ function createRunDurationRule(options) {
|
|
|
2376
2397
|
}
|
|
2377
2398
|
};
|
|
2378
2399
|
}
|
|
2400
|
+
function createRunDepthRule(options) {
|
|
2401
|
+
return {
|
|
2402
|
+
id: "run.depth",
|
|
2403
|
+
category: "run",
|
|
2404
|
+
defaultSeverity: "error",
|
|
2405
|
+
evaluate(context) {
|
|
2406
|
+
const nodes = [...context.nodesByEventId.values()];
|
|
2407
|
+
const maxDepth = nodes.reduce((max, node) => Math.max(max, node.depth), 0);
|
|
2408
|
+
if (maxDepth <= options.maxDepth) return [];
|
|
2409
|
+
const deepest = nodes.filter((node) => node.depth === maxDepth);
|
|
2410
|
+
return [
|
|
2411
|
+
failFinding(
|
|
2412
|
+
"run.depth",
|
|
2413
|
+
`Run depth ${maxDepth} exceeded ${options.maxDepth}.`,
|
|
2414
|
+
deepest.map((node) => ({
|
|
2415
|
+
runId: node.event.runId,
|
|
2416
|
+
eventId: node.event.eventId,
|
|
2417
|
+
parentId: node.event.parentId,
|
|
2418
|
+
kind: node.event.kind,
|
|
2419
|
+
name: node.event.name,
|
|
2420
|
+
status: node.event.status
|
|
2421
|
+
})),
|
|
2422
|
+
{ maxDepth: options.maxDepth },
|
|
2423
|
+
maxDepth
|
|
2424
|
+
)
|
|
2425
|
+
];
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2379
2429
|
function createToolUsageRule(options) {
|
|
2380
2430
|
return {
|
|
2381
2431
|
id: "tool.usage",
|
|
@@ -2440,6 +2490,45 @@ function createToolUsageRule(options) {
|
|
|
2440
2490
|
}
|
|
2441
2491
|
};
|
|
2442
2492
|
}
|
|
2493
|
+
function createToolFailureRule(options) {
|
|
2494
|
+
return {
|
|
2495
|
+
id: "tool.failures",
|
|
2496
|
+
category: "tool",
|
|
2497
|
+
defaultSeverity: "error",
|
|
2498
|
+
evaluate(context) {
|
|
2499
|
+
const tools = finishedEvents(context, "TOOL");
|
|
2500
|
+
const failures = tools.filter((event) => event.status === "error");
|
|
2501
|
+
const retries = tools.map((event) => ({ event, count: retryCount(event) })).filter((item) => item.count !== void 0);
|
|
2502
|
+
const findings = [];
|
|
2503
|
+
if (options.maxFailures !== void 0 && failures.length > options.maxFailures) {
|
|
2504
|
+
findings.push(
|
|
2505
|
+
failFinding(
|
|
2506
|
+
"tool.failures",
|
|
2507
|
+
`Tool failure count ${failures.length} exceeded ${options.maxFailures}.`,
|
|
2508
|
+
failures.map((event) => eventEvidence(event)),
|
|
2509
|
+
{ maxFailures: options.maxFailures },
|
|
2510
|
+
failures.length
|
|
2511
|
+
)
|
|
2512
|
+
);
|
|
2513
|
+
}
|
|
2514
|
+
if (options.maxRetries !== void 0) {
|
|
2515
|
+
const excessiveRetries = retries.filter((item) => item.count > options.maxRetries);
|
|
2516
|
+
if (excessiveRetries.length > 0) {
|
|
2517
|
+
findings.push(
|
|
2518
|
+
failFinding(
|
|
2519
|
+
"tool.failures",
|
|
2520
|
+
`Tool retry count exceeded ${options.maxRetries}.`,
|
|
2521
|
+
excessiveRetries.map((item) => eventEvidence(item.event, "attributes.retryCount")),
|
|
2522
|
+
{ maxRetries: options.maxRetries },
|
|
2523
|
+
excessiveRetries.map((item) => ({ tool: toolName(item.event), retries: item.count }))
|
|
2524
|
+
)
|
|
2525
|
+
);
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
return findings;
|
|
2529
|
+
}
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2443
2532
|
function createLlmUsageRule(options) {
|
|
2444
2533
|
return {
|
|
2445
2534
|
id: "llm.usage",
|
|
@@ -5543,21 +5632,48 @@ function openTrace(input, options = {}) {
|
|
|
5543
5632
|
}
|
|
5544
5633
|
|
|
5545
5634
|
// packages/core/src/suite/run.ts
|
|
5635
|
+
var KNOWN_SUITE_SELECT_IDS = /* @__PURE__ */ new Set([
|
|
5636
|
+
"run.status",
|
|
5637
|
+
"run.duration",
|
|
5638
|
+
"run.depth",
|
|
5639
|
+
"outcome.status",
|
|
5640
|
+
"tool.usage",
|
|
5641
|
+
"tool.failures",
|
|
5642
|
+
"llm.usage"
|
|
5643
|
+
]);
|
|
5546
5644
|
function diagnostic4(code, message, severity = "error", caseId) {
|
|
5547
5645
|
return { code, message, severity, ...caseId !== void 0 ? { caseId } : {} };
|
|
5548
5646
|
}
|
|
5549
|
-
function
|
|
5647
|
+
function buildCaseAssertions(suiteCase, config) {
|
|
5550
5648
|
const rules = [];
|
|
5551
5649
|
const select = new Set(config.checks?.select ?? []);
|
|
5552
|
-
|
|
5650
|
+
const configDiagnostics = [];
|
|
5651
|
+
const evalConfig = config.eval;
|
|
5652
|
+
const declaredSelect = [...select];
|
|
5653
|
+
for (const id of declaredSelect) {
|
|
5654
|
+
if (!KNOWN_SUITE_SELECT_IDS.has(id)) {
|
|
5655
|
+
configDiagnostics.push(
|
|
5656
|
+
diagnostic4(
|
|
5657
|
+
"AI_SUITE_UNKNOWN_SELECTOR",
|
|
5658
|
+
`Unknown or unsupported suite check selector "${id}".`,
|
|
5659
|
+
"error",
|
|
5660
|
+
suiteCase.id
|
|
5661
|
+
)
|
|
5662
|
+
);
|
|
5663
|
+
}
|
|
5664
|
+
}
|
|
5665
|
+
if (select.has("run.status") || evalConfig?.requireSuccess === true) {
|
|
5553
5666
|
rules.push(createRunStatusRule());
|
|
5667
|
+
select.add("run.status");
|
|
5554
5668
|
}
|
|
5555
5669
|
const requiredTools = [
|
|
5556
5670
|
...config.checks?.tool?.required ?? [],
|
|
5671
|
+
...evalConfig?.requiredTools ?? [],
|
|
5557
5672
|
...suiteCase.requireTools ?? []
|
|
5558
5673
|
];
|
|
5559
5674
|
const forbiddenTools = [
|
|
5560
5675
|
...config.checks?.tool?.forbidden ?? [],
|
|
5676
|
+
...evalConfig?.forbiddenTools ?? [],
|
|
5561
5677
|
...suiteCase.forbidTools ?? []
|
|
5562
5678
|
];
|
|
5563
5679
|
if (requiredTools.length > 0 || forbiddenTools.length > 0) {
|
|
@@ -5569,20 +5685,51 @@ function buildCaseRules(suiteCase, config) {
|
|
|
5569
5685
|
);
|
|
5570
5686
|
select.add("tool.usage");
|
|
5571
5687
|
}
|
|
5572
|
-
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ??
|
|
5688
|
+
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ?? evalConfig?.maxDurationMs;
|
|
5573
5689
|
if (maxDurationMs !== void 0) {
|
|
5574
5690
|
rules.push(createRunDurationRule({ maxDurationMs }));
|
|
5575
5691
|
select.add("run.duration");
|
|
5576
5692
|
}
|
|
5577
|
-
const
|
|
5578
|
-
if (
|
|
5579
|
-
rules.push(
|
|
5693
|
+
const maxDepth = config.checks?.run?.maxDepth ?? evalConfig?.maxDepth;
|
|
5694
|
+
if (maxDepth !== void 0) {
|
|
5695
|
+
rules.push(createRunDepthRule({ maxDepth }));
|
|
5696
|
+
select.add("run.depth");
|
|
5697
|
+
}
|
|
5698
|
+
if (evalConfig?.maxRetries !== void 0) {
|
|
5699
|
+
rules.push(createToolFailureRule({ maxRetries: evalConfig.maxRetries }));
|
|
5700
|
+
select.add("tool.failures");
|
|
5701
|
+
}
|
|
5702
|
+
const allowedModels = config.checks?.llm?.allowedModels;
|
|
5703
|
+
const maxTotalTokens = config.checks?.llm?.maxTotalTokens ?? evalConfig?.maxTotalTokens;
|
|
5704
|
+
if (allowedModels !== void 0 || maxTotalTokens !== void 0) {
|
|
5705
|
+
rules.push(
|
|
5706
|
+
createLlmUsageRule({
|
|
5707
|
+
...allowedModels !== void 0 ? { allowedModels } : {},
|
|
5708
|
+
...maxTotalTokens !== void 0 ? { maxTotalTokens } : {}
|
|
5709
|
+
})
|
|
5710
|
+
);
|
|
5580
5711
|
select.add("llm.usage");
|
|
5581
5712
|
}
|
|
5582
5713
|
if (select.has("outcome.status")) {
|
|
5583
5714
|
rules.push(createObservedOutcomeRule({ failOn: ["failed"] }));
|
|
5584
5715
|
}
|
|
5585
|
-
|
|
5716
|
+
const observationCount = suiteCase.expectedObservations?.length ?? 0;
|
|
5717
|
+
if (rules.length === 0 && observationCount === 0 && configDiagnostics.length === 0) {
|
|
5718
|
+
configDiagnostics.push(
|
|
5719
|
+
diagnostic4(
|
|
5720
|
+
"AI_SUITE_NO_ASSERTIONS",
|
|
5721
|
+
`Suite case "${suiteCase.id}" declares no effective checks, eval controls, or expected observations.`,
|
|
5722
|
+
"error",
|
|
5723
|
+
suiteCase.id
|
|
5724
|
+
)
|
|
5725
|
+
);
|
|
5726
|
+
}
|
|
5727
|
+
return {
|
|
5728
|
+
rules,
|
|
5729
|
+
select: [...select],
|
|
5730
|
+
observationCount,
|
|
5731
|
+
configDiagnostics
|
|
5732
|
+
};
|
|
5586
5733
|
}
|
|
5587
5734
|
function outcomesFromRead(read) {
|
|
5588
5735
|
const persistedOutcomes = extractOutcomesFromPersistedEvents(
|
|
@@ -5663,8 +5810,20 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5663
5810
|
]
|
|
5664
5811
|
};
|
|
5665
5812
|
}
|
|
5666
|
-
const
|
|
5667
|
-
|
|
5813
|
+
const compiled = buildCaseAssertions(suiteCase, config);
|
|
5814
|
+
if (compiled.configDiagnostics.length > 0) {
|
|
5815
|
+
return {
|
|
5816
|
+
id: suiteCase.id,
|
|
5817
|
+
status: "error",
|
|
5818
|
+
tracePath: resolved.tracePath,
|
|
5819
|
+
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5820
|
+
checkOk: false,
|
|
5821
|
+
...config.eval?.requireSuccess === true ? { evalOk: false } : {},
|
|
5822
|
+
message: compiled.configDiagnostics.map((item) => item.message).join("; "),
|
|
5823
|
+
diagnostics: compiled.configDiagnostics
|
|
5824
|
+
};
|
|
5825
|
+
}
|
|
5826
|
+
const checkResult = compiled.rules.length > 0 ? runTraceChecks({ read }, { rules: compiled.rules, select: compiled.select }) : {
|
|
5668
5827
|
ok: true,
|
|
5669
5828
|
status: "pass",
|
|
5670
5829
|
format: read.format,
|
|
@@ -5692,6 +5851,9 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5692
5851
|
];
|
|
5693
5852
|
const checkOk = checkResult.ok;
|
|
5694
5853
|
const observationsOk = observationResult.ok;
|
|
5854
|
+
const evalOk = config.eval?.requireSuccess === true ? checkResult.findings.every(
|
|
5855
|
+
(finding) => finding.ruleId !== "run.status" || finding.status !== "fail"
|
|
5856
|
+
) && checkResult.diagnostics.every((item) => item.severity !== "error") : void 0;
|
|
5695
5857
|
const ok = checkOk && observationsOk;
|
|
5696
5858
|
const status = ok ? "pass" : checkResult.status === "error" ? "error" : "fail";
|
|
5697
5859
|
return {
|
|
@@ -5700,6 +5862,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5700
5862
|
tracePath: resolved.tracePath,
|
|
5701
5863
|
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5702
5864
|
checkOk,
|
|
5865
|
+
...evalOk !== void 0 ? { evalOk } : {},
|
|
5703
5866
|
observationsOk,
|
|
5704
5867
|
diagnostics,
|
|
5705
5868
|
...ok ? {} : {
|