@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.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
|
};
|
|
@@ -1699,6 +1710,17 @@ var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
|
|
|
1699
1710
|
summary: "Trace contains a parentId cycle.",
|
|
1700
1711
|
remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
|
|
1701
1712
|
relatedCodes: ["structure.cycle"]
|
|
1713
|
+
},
|
|
1714
|
+
AI_TRACE_CONTRACT_INPUT_INVALID: {
|
|
1715
|
+
code: "AI_TRACE_CONTRACT_INPUT_INVALID",
|
|
1716
|
+
summary: "evaluateTraceContract expects ({ read }, contract) or use evaluateTraceContractRead(read, contract).",
|
|
1717
|
+
remediation: "Pass TraceCheckInput as the first argument: evaluateTraceContract({ read }, contract).",
|
|
1718
|
+
relatedCodes: ["AI_CHECK_INVALID_ARGUMENTS"]
|
|
1719
|
+
},
|
|
1720
|
+
AI_INSPECT_RUN_UNSUPPORTED_OPTION: {
|
|
1721
|
+
code: "AI_INSPECT_RUN_UNSUPPORTED_OPTION",
|
|
1722
|
+
summary: 'inspectRun does not accept a "writer" option.',
|
|
1723
|
+
remediation: "Use createInspector({ writer }) then inspector.run(...). inspectRun persists via the global JSONL path (schema 0.1)."
|
|
1702
1724
|
}
|
|
1703
1725
|
});
|
|
1704
1726
|
function formatProgrammaticDiagnostic(code, detail) {
|
|
@@ -2254,6 +2276,13 @@ function metadataStringAttr(event, keys) {
|
|
|
2254
2276
|
}
|
|
2255
2277
|
return void 0;
|
|
2256
2278
|
}
|
|
2279
|
+
function numericAttr(event, keys) {
|
|
2280
|
+
for (const key of keys) {
|
|
2281
|
+
const value = event.attributes?.[key];
|
|
2282
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2283
|
+
}
|
|
2284
|
+
return void 0;
|
|
2285
|
+
}
|
|
2257
2286
|
function stripPrefix(name, prefixes) {
|
|
2258
2287
|
for (const prefix of prefixes) {
|
|
2259
2288
|
if (name.startsWith(prefix)) return name.slice(prefix.length);
|
|
@@ -2309,9 +2338,12 @@ function llmFinishReason(event) {
|
|
|
2309
2338
|
const keys = ["finishReason", "rawFinishReason", "finish_reason"];
|
|
2310
2339
|
return stringAttr(event, keys) ?? metadataStringAttr(event, keys);
|
|
2311
2340
|
}
|
|
2341
|
+
function retryCount(event) {
|
|
2342
|
+
return numericAttr(event, ["retryCount", "retryAttempt", "retry_attempt", "attempt"]);
|
|
2343
|
+
}
|
|
2312
2344
|
function finishedEvents(context, kind) {
|
|
2313
2345
|
return semanticEvents(context).filter(
|
|
2314
|
-
(event) => (event.kind === kind) && event.status !== "running"
|
|
2346
|
+
(event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
|
|
2315
2347
|
);
|
|
2316
2348
|
}
|
|
2317
2349
|
function toolInvocationEvents(context) {
|
|
@@ -2376,6 +2408,35 @@ function createRunDurationRule(options) {
|
|
|
2376
2408
|
}
|
|
2377
2409
|
};
|
|
2378
2410
|
}
|
|
2411
|
+
function createRunDepthRule(options) {
|
|
2412
|
+
return {
|
|
2413
|
+
id: "run.depth",
|
|
2414
|
+
category: "run",
|
|
2415
|
+
defaultSeverity: "error",
|
|
2416
|
+
evaluate(context) {
|
|
2417
|
+
const nodes = [...context.nodesByEventId.values()];
|
|
2418
|
+
const maxDepth = nodes.reduce((max, node) => Math.max(max, node.depth), 0);
|
|
2419
|
+
if (maxDepth <= options.maxDepth) return [];
|
|
2420
|
+
const deepest = nodes.filter((node) => node.depth === maxDepth);
|
|
2421
|
+
return [
|
|
2422
|
+
failFinding(
|
|
2423
|
+
"run.depth",
|
|
2424
|
+
`Run depth ${maxDepth} exceeded ${options.maxDepth}.`,
|
|
2425
|
+
deepest.map((node) => ({
|
|
2426
|
+
runId: node.event.runId,
|
|
2427
|
+
eventId: node.event.eventId,
|
|
2428
|
+
parentId: node.event.parentId,
|
|
2429
|
+
kind: node.event.kind,
|
|
2430
|
+
name: node.event.name,
|
|
2431
|
+
status: node.event.status
|
|
2432
|
+
})),
|
|
2433
|
+
{ maxDepth: options.maxDepth },
|
|
2434
|
+
maxDepth
|
|
2435
|
+
)
|
|
2436
|
+
];
|
|
2437
|
+
}
|
|
2438
|
+
};
|
|
2439
|
+
}
|
|
2379
2440
|
function createToolUsageRule(options) {
|
|
2380
2441
|
return {
|
|
2381
2442
|
id: "tool.usage",
|
|
@@ -2440,6 +2501,45 @@ function createToolUsageRule(options) {
|
|
|
2440
2501
|
}
|
|
2441
2502
|
};
|
|
2442
2503
|
}
|
|
2504
|
+
function createToolFailureRule(options) {
|
|
2505
|
+
return {
|
|
2506
|
+
id: "tool.failures",
|
|
2507
|
+
category: "tool",
|
|
2508
|
+
defaultSeverity: "error",
|
|
2509
|
+
evaluate(context) {
|
|
2510
|
+
const tools = finishedEvents(context, "TOOL");
|
|
2511
|
+
const failures = tools.filter((event) => event.status === "error");
|
|
2512
|
+
const retries = tools.map((event) => ({ event, count: retryCount(event) })).filter((item) => item.count !== void 0);
|
|
2513
|
+
const findings = [];
|
|
2514
|
+
if (options.maxFailures !== void 0 && failures.length > options.maxFailures) {
|
|
2515
|
+
findings.push(
|
|
2516
|
+
failFinding(
|
|
2517
|
+
"tool.failures",
|
|
2518
|
+
`Tool failure count ${failures.length} exceeded ${options.maxFailures}.`,
|
|
2519
|
+
failures.map((event) => eventEvidence(event)),
|
|
2520
|
+
{ maxFailures: options.maxFailures },
|
|
2521
|
+
failures.length
|
|
2522
|
+
)
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
if (options.maxRetries !== void 0) {
|
|
2526
|
+
const excessiveRetries = retries.filter((item) => item.count > options.maxRetries);
|
|
2527
|
+
if (excessiveRetries.length > 0) {
|
|
2528
|
+
findings.push(
|
|
2529
|
+
failFinding(
|
|
2530
|
+
"tool.failures",
|
|
2531
|
+
`Tool retry count exceeded ${options.maxRetries}.`,
|
|
2532
|
+
excessiveRetries.map((item) => eventEvidence(item.event, "attributes.retryCount")),
|
|
2533
|
+
{ maxRetries: options.maxRetries },
|
|
2534
|
+
excessiveRetries.map((item) => ({ tool: toolName(item.event), retries: item.count }))
|
|
2535
|
+
)
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
return findings;
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2443
2543
|
function createLlmUsageRule(options) {
|
|
2444
2544
|
return {
|
|
2445
2545
|
id: "llm.usage",
|
|
@@ -5543,21 +5643,48 @@ function openTrace(input, options = {}) {
|
|
|
5543
5643
|
}
|
|
5544
5644
|
|
|
5545
5645
|
// packages/core/src/suite/run.ts
|
|
5646
|
+
var KNOWN_SUITE_SELECT_IDS = /* @__PURE__ */ new Set([
|
|
5647
|
+
"run.status",
|
|
5648
|
+
"run.duration",
|
|
5649
|
+
"run.depth",
|
|
5650
|
+
"outcome.status",
|
|
5651
|
+
"tool.usage",
|
|
5652
|
+
"tool.failures",
|
|
5653
|
+
"llm.usage"
|
|
5654
|
+
]);
|
|
5546
5655
|
function diagnostic4(code, message, severity = "error", caseId) {
|
|
5547
5656
|
return { code, message, severity, ...caseId !== void 0 ? { caseId } : {} };
|
|
5548
5657
|
}
|
|
5549
|
-
function
|
|
5658
|
+
function buildCaseAssertions(suiteCase, config) {
|
|
5550
5659
|
const rules = [];
|
|
5551
5660
|
const select = new Set(config.checks?.select ?? []);
|
|
5552
|
-
|
|
5661
|
+
const configDiagnostics = [];
|
|
5662
|
+
const evalConfig = config.eval;
|
|
5663
|
+
const declaredSelect = [...select];
|
|
5664
|
+
for (const id of declaredSelect) {
|
|
5665
|
+
if (!KNOWN_SUITE_SELECT_IDS.has(id)) {
|
|
5666
|
+
configDiagnostics.push(
|
|
5667
|
+
diagnostic4(
|
|
5668
|
+
"AI_SUITE_UNKNOWN_SELECTOR",
|
|
5669
|
+
`Unknown or unsupported suite check selector "${id}".`,
|
|
5670
|
+
"error",
|
|
5671
|
+
suiteCase.id
|
|
5672
|
+
)
|
|
5673
|
+
);
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
if (select.has("run.status") || evalConfig?.requireSuccess === true) {
|
|
5553
5677
|
rules.push(createRunStatusRule());
|
|
5678
|
+
select.add("run.status");
|
|
5554
5679
|
}
|
|
5555
5680
|
const requiredTools = [
|
|
5556
5681
|
...config.checks?.tool?.required ?? [],
|
|
5682
|
+
...evalConfig?.requiredTools ?? [],
|
|
5557
5683
|
...suiteCase.requireTools ?? []
|
|
5558
5684
|
];
|
|
5559
5685
|
const forbiddenTools = [
|
|
5560
5686
|
...config.checks?.tool?.forbidden ?? [],
|
|
5687
|
+
...evalConfig?.forbiddenTools ?? [],
|
|
5561
5688
|
...suiteCase.forbidTools ?? []
|
|
5562
5689
|
];
|
|
5563
5690
|
if (requiredTools.length > 0 || forbiddenTools.length > 0) {
|
|
@@ -5569,20 +5696,51 @@ function buildCaseRules(suiteCase, config) {
|
|
|
5569
5696
|
);
|
|
5570
5697
|
select.add("tool.usage");
|
|
5571
5698
|
}
|
|
5572
|
-
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ??
|
|
5699
|
+
const maxDurationMs = suiteCase.maxDurationMs ?? config.checks?.run?.maxDurationMs ?? evalConfig?.maxDurationMs;
|
|
5573
5700
|
if (maxDurationMs !== void 0) {
|
|
5574
5701
|
rules.push(createRunDurationRule({ maxDurationMs }));
|
|
5575
5702
|
select.add("run.duration");
|
|
5576
5703
|
}
|
|
5577
|
-
const
|
|
5578
|
-
if (
|
|
5579
|
-
rules.push(
|
|
5704
|
+
const maxDepth = config.checks?.run?.maxDepth ?? evalConfig?.maxDepth;
|
|
5705
|
+
if (maxDepth !== void 0) {
|
|
5706
|
+
rules.push(createRunDepthRule({ maxDepth }));
|
|
5707
|
+
select.add("run.depth");
|
|
5708
|
+
}
|
|
5709
|
+
if (evalConfig?.maxRetries !== void 0) {
|
|
5710
|
+
rules.push(createToolFailureRule({ maxRetries: evalConfig.maxRetries }));
|
|
5711
|
+
select.add("tool.failures");
|
|
5712
|
+
}
|
|
5713
|
+
const allowedModels = config.checks?.llm?.allowedModels;
|
|
5714
|
+
const maxTotalTokens = config.checks?.llm?.maxTotalTokens ?? evalConfig?.maxTotalTokens;
|
|
5715
|
+
if (allowedModels !== void 0 || maxTotalTokens !== void 0) {
|
|
5716
|
+
rules.push(
|
|
5717
|
+
createLlmUsageRule({
|
|
5718
|
+
...allowedModels !== void 0 ? { allowedModels } : {},
|
|
5719
|
+
...maxTotalTokens !== void 0 ? { maxTotalTokens } : {}
|
|
5720
|
+
})
|
|
5721
|
+
);
|
|
5580
5722
|
select.add("llm.usage");
|
|
5581
5723
|
}
|
|
5582
5724
|
if (select.has("outcome.status")) {
|
|
5583
5725
|
rules.push(createObservedOutcomeRule({ failOn: ["failed"] }));
|
|
5584
5726
|
}
|
|
5585
|
-
|
|
5727
|
+
const observationCount = suiteCase.expectedObservations?.length ?? 0;
|
|
5728
|
+
if (rules.length === 0 && observationCount === 0 && configDiagnostics.length === 0) {
|
|
5729
|
+
configDiagnostics.push(
|
|
5730
|
+
diagnostic4(
|
|
5731
|
+
"AI_SUITE_NO_ASSERTIONS",
|
|
5732
|
+
`Suite case "${suiteCase.id}" declares no effective checks, eval controls, or expected observations.`,
|
|
5733
|
+
"error",
|
|
5734
|
+
suiteCase.id
|
|
5735
|
+
)
|
|
5736
|
+
);
|
|
5737
|
+
}
|
|
5738
|
+
return {
|
|
5739
|
+
rules,
|
|
5740
|
+
select: [...select],
|
|
5741
|
+
observationCount,
|
|
5742
|
+
configDiagnostics
|
|
5743
|
+
};
|
|
5586
5744
|
}
|
|
5587
5745
|
function outcomesFromRead(read) {
|
|
5588
5746
|
const persistedOutcomes = extractOutcomesFromPersistedEvents(
|
|
@@ -5663,8 +5821,20 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5663
5821
|
]
|
|
5664
5822
|
};
|
|
5665
5823
|
}
|
|
5666
|
-
const
|
|
5667
|
-
|
|
5824
|
+
const compiled = buildCaseAssertions(suiteCase, config);
|
|
5825
|
+
if (compiled.configDiagnostics.length > 0) {
|
|
5826
|
+
return {
|
|
5827
|
+
id: suiteCase.id,
|
|
5828
|
+
status: "error",
|
|
5829
|
+
tracePath: resolved.tracePath,
|
|
5830
|
+
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5831
|
+
checkOk: false,
|
|
5832
|
+
...config.eval?.requireSuccess === true ? { evalOk: false } : {},
|
|
5833
|
+
message: compiled.configDiagnostics.map((item) => item.message).join("; "),
|
|
5834
|
+
diagnostics: compiled.configDiagnostics
|
|
5835
|
+
};
|
|
5836
|
+
}
|
|
5837
|
+
const checkResult = compiled.rules.length > 0 ? runTraceChecks({ read }, { rules: compiled.rules, select: compiled.select }) : {
|
|
5668
5838
|
ok: true,
|
|
5669
5839
|
status: "pass",
|
|
5670
5840
|
format: read.format,
|
|
@@ -5692,6 +5862,9 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5692
5862
|
];
|
|
5693
5863
|
const checkOk = checkResult.ok;
|
|
5694
5864
|
const observationsOk = observationResult.ok;
|
|
5865
|
+
const evalOk = config.eval?.requireSuccess === true ? checkResult.findings.every(
|
|
5866
|
+
(finding) => finding.ruleId !== "run.status" || finding.status !== "fail"
|
|
5867
|
+
) && checkResult.diagnostics.every((item) => item.severity !== "error") : void 0;
|
|
5695
5868
|
const ok = checkOk && observationsOk;
|
|
5696
5869
|
const status = ok ? "pass" : checkResult.status === "error" ? "error" : "fail";
|
|
5697
5870
|
return {
|
|
@@ -5700,6 +5873,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5700
5873
|
tracePath: resolved.tracePath,
|
|
5701
5874
|
...resolved.runId !== void 0 ? { runId: resolved.runId } : {},
|
|
5702
5875
|
checkOk,
|
|
5876
|
+
...evalOk !== void 0 ? { evalOk } : {},
|
|
5703
5877
|
observationsOk,
|
|
5704
5878
|
diagnostics,
|
|
5705
5879
|
...ok ? {} : {
|