@agent-inspect/viewer 6.31.31 → 6.31.33
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 +76 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +76 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2226,6 +2226,11 @@ function compareFindings(eventById) {
|
|
|
2226
2226
|
if (STATUS_RANK[a.status] !== STATUS_RANK[b.status]) {
|
|
2227
2227
|
return STATUS_RANK[a.status] - STATUS_RANK[b.status];
|
|
2228
2228
|
}
|
|
2229
|
+
if (a.ruleId === "tool.usage") {
|
|
2230
|
+
const aHasEvent = a.evidence[0]?.eventId !== void 0;
|
|
2231
|
+
const bHasEvent = b.evidence[0]?.eventId !== void 0;
|
|
2232
|
+
if (aHasEvent !== bHasEvent) return aHasEvent ? -1 : 1;
|
|
2233
|
+
}
|
|
2229
2234
|
const byRun = compareStrings(a.evidence[0]?.runId, b.evidence[0]?.runId);
|
|
2230
2235
|
if (byRun !== 0) return byRun;
|
|
2231
2236
|
const byTime = eventTimestamp(a, eventById).localeCompare(eventTimestamp(b, eventById));
|
|
@@ -2344,6 +2349,43 @@ function failFinding(ruleId, message, evidence, expected, actual, meta) {
|
|
|
2344
2349
|
function toolName(event) {
|
|
2345
2350
|
return resolveCanonicalToolName(event);
|
|
2346
2351
|
}
|
|
2352
|
+
function formatToolNameForMessage(name) {
|
|
2353
|
+
const details = [];
|
|
2354
|
+
for (let index = 0; index < name.length; ) {
|
|
2355
|
+
const codePoint = name.codePointAt(index);
|
|
2356
|
+
const width = codePoint > 65535 ? 2 : 1;
|
|
2357
|
+
if (codePoint > 127) {
|
|
2358
|
+
details.push(
|
|
2359
|
+
`U+${codePoint.toString(16).toUpperCase().padStart(4, "0")} at index ${index}`
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
index += width;
|
|
2363
|
+
}
|
|
2364
|
+
if (details.length === 0) return name;
|
|
2365
|
+
return `"${name}" (contains ${details.join("; ")})`;
|
|
2366
|
+
}
|
|
2367
|
+
function describeRunningEvent(event) {
|
|
2368
|
+
if (event.kind === "TOOL") {
|
|
2369
|
+
return `tool ${formatToolNameForMessage(resolveCanonicalToolName(event))}`;
|
|
2370
|
+
}
|
|
2371
|
+
if (event.kind === "LLM") {
|
|
2372
|
+
return `llm ${stepEndpointName(event)}`;
|
|
2373
|
+
}
|
|
2374
|
+
return `${event.kind} ${event.name}`;
|
|
2375
|
+
}
|
|
2376
|
+
function incompleteRunningMessage(prefix, running) {
|
|
2377
|
+
const labels = running.map(describeRunningEvent);
|
|
2378
|
+
if (labels.length === 1) {
|
|
2379
|
+
return `${prefix}: ${labels[0]} never completed.`;
|
|
2380
|
+
}
|
|
2381
|
+
return `${prefix}: ${labels.join("; ")}.`;
|
|
2382
|
+
}
|
|
2383
|
+
function stepEndpointName(event, kind) {
|
|
2384
|
+
for (const prefix of ["llm:", "generation:", "transcription:", "speech:"]) {
|
|
2385
|
+
if (event.name.startsWith(prefix)) return event.name.slice(prefix.length);
|
|
2386
|
+
}
|
|
2387
|
+
return event.name;
|
|
2388
|
+
}
|
|
2347
2389
|
function semanticEvents(context) {
|
|
2348
2390
|
return context.logicalEvents ?? context.events;
|
|
2349
2391
|
}
|
|
@@ -2397,10 +2439,13 @@ function createRunStatusRule(options = {}) {
|
|
|
2397
2439
|
findings.push(
|
|
2398
2440
|
failFinding(
|
|
2399
2441
|
"run.status",
|
|
2400
|
-
"Run contains incomplete running events
|
|
2442
|
+
incompleteRunningMessage("Run contains incomplete running events", running),
|
|
2401
2443
|
running.map((event) => eventEvidence(event)),
|
|
2402
2444
|
"no running events",
|
|
2403
|
-
|
|
2445
|
+
{
|
|
2446
|
+
count: running.length,
|
|
2447
|
+
unfinished: running.map(describeRunningEvent)
|
|
2448
|
+
}
|
|
2404
2449
|
)
|
|
2405
2450
|
);
|
|
2406
2451
|
}
|
|
@@ -2468,6 +2513,34 @@ function createToolUsageRule(options) {
|
|
|
2468
2513
|
const names = tools.map(toolName);
|
|
2469
2514
|
const nameSet = new Set(names);
|
|
2470
2515
|
const findings = [];
|
|
2516
|
+
const forbidden = new Set(options.forbidden ?? []);
|
|
2517
|
+
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
2518
|
+
for (const event of tools) {
|
|
2519
|
+
const name = toolName(event);
|
|
2520
|
+
const display = formatToolNameForMessage(name);
|
|
2521
|
+
if (forbidden.has(name)) {
|
|
2522
|
+
findings.push(
|
|
2523
|
+
failFinding(
|
|
2524
|
+
"tool.usage",
|
|
2525
|
+
`Forbidden tool ${display} appeared.`,
|
|
2526
|
+
[eventEvidence(event)],
|
|
2527
|
+
"tool absent",
|
|
2528
|
+
name
|
|
2529
|
+
)
|
|
2530
|
+
);
|
|
2531
|
+
}
|
|
2532
|
+
if (allowed && !allowed.has(name)) {
|
|
2533
|
+
findings.push(
|
|
2534
|
+
failFinding(
|
|
2535
|
+
"tool.usage",
|
|
2536
|
+
`Tool ${display} is not in the allowed tool set.`,
|
|
2537
|
+
[eventEvidence(event)],
|
|
2538
|
+
[...allowed].sort(),
|
|
2539
|
+
name
|
|
2540
|
+
)
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2471
2544
|
for (const required of options.required ?? []) {
|
|
2472
2545
|
if (!nameSet.has(required)) {
|
|
2473
2546
|
const otherKinds = [
|
|
@@ -2485,7 +2558,7 @@ function createToolUsageRule(options) {
|
|
|
2485
2558
|
findings.push(
|
|
2486
2559
|
failFinding(
|
|
2487
2560
|
"tool.usage",
|
|
2488
|
-
`Required tool ${required} did not appear.${hint}`,
|
|
2561
|
+
`Required tool ${formatToolNameForMessage(required)} did not appear.${hint}`,
|
|
2489
2562
|
runEvidence(context.selectedRun),
|
|
2490
2563
|
required,
|
|
2491
2564
|
names
|
|
@@ -2493,21 +2566,6 @@ function createToolUsageRule(options) {
|
|
|
2493
2566
|
);
|
|
2494
2567
|
}
|
|
2495
2568
|
}
|
|
2496
|
-
const forbidden = new Set(options.forbidden ?? []);
|
|
2497
|
-
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
2498
|
-
for (const event of tools) {
|
|
2499
|
-
const name = toolName(event);
|
|
2500
|
-
if (forbidden.has(name)) {
|
|
2501
|
-
findings.push(
|
|
2502
|
-
failFinding("tool.usage", `Forbidden tool ${name} appeared.`, [eventEvidence(event)], "tool absent", name)
|
|
2503
|
-
);
|
|
2504
|
-
}
|
|
2505
|
-
if (allowed && !allowed.has(name)) {
|
|
2506
|
-
findings.push(
|
|
2507
|
-
failFinding("tool.usage", `Tool ${name} is not in the allowed tool set.`, [eventEvidence(event)], [...allowed].sort(), name)
|
|
2508
|
-
);
|
|
2509
|
-
}
|
|
2510
|
-
}
|
|
2511
2569
|
if (options.minCount !== void 0 && tools.length < options.minCount) {
|
|
2512
2570
|
findings.push(
|
|
2513
2571
|
failFinding("tool.usage", `Tool count ${tools.length} was below minimum ${options.minCount}.`, runEvidence(context.selectedRun), { minCount: options.minCount }, tools.length)
|