@agent-inspect/viewer 6.31.32 → 6.31.34
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.mjs
CHANGED
|
@@ -2219,6 +2219,11 @@ function compareFindings(eventById) {
|
|
|
2219
2219
|
if (STATUS_RANK[a.status] !== STATUS_RANK[b.status]) {
|
|
2220
2220
|
return STATUS_RANK[a.status] - STATUS_RANK[b.status];
|
|
2221
2221
|
}
|
|
2222
|
+
if (a.ruleId === "tool.usage") {
|
|
2223
|
+
const aHasEvent = a.evidence[0]?.eventId !== void 0;
|
|
2224
|
+
const bHasEvent = b.evidence[0]?.eventId !== void 0;
|
|
2225
|
+
if (aHasEvent !== bHasEvent) return aHasEvent ? -1 : 1;
|
|
2226
|
+
}
|
|
2222
2227
|
const byRun = compareStrings(a.evidence[0]?.runId, b.evidence[0]?.runId);
|
|
2223
2228
|
if (byRun !== 0) return byRun;
|
|
2224
2229
|
const byTime = eventTimestamp(a, eventById).localeCompare(eventTimestamp(b, eventById));
|
|
@@ -2337,6 +2342,43 @@ function failFinding(ruleId, message, evidence, expected, actual, meta) {
|
|
|
2337
2342
|
function toolName(event) {
|
|
2338
2343
|
return resolveCanonicalToolName(event);
|
|
2339
2344
|
}
|
|
2345
|
+
function formatToolNameForMessage(name) {
|
|
2346
|
+
const details = [];
|
|
2347
|
+
for (let index = 0; index < name.length; ) {
|
|
2348
|
+
const codePoint = name.codePointAt(index);
|
|
2349
|
+
const width = codePoint > 65535 ? 2 : 1;
|
|
2350
|
+
if (codePoint > 127) {
|
|
2351
|
+
details.push(
|
|
2352
|
+
`U+${codePoint.toString(16).toUpperCase().padStart(4, "0")} at index ${index}`
|
|
2353
|
+
);
|
|
2354
|
+
}
|
|
2355
|
+
index += width;
|
|
2356
|
+
}
|
|
2357
|
+
if (details.length === 0) return name;
|
|
2358
|
+
return `"${name}" (contains ${details.join("; ")})`;
|
|
2359
|
+
}
|
|
2360
|
+
function describeRunningEvent(event) {
|
|
2361
|
+
if (event.kind === "TOOL") {
|
|
2362
|
+
return `tool ${formatToolNameForMessage(resolveCanonicalToolName(event))}`;
|
|
2363
|
+
}
|
|
2364
|
+
if (event.kind === "LLM") {
|
|
2365
|
+
return `llm ${stepEndpointName(event)}`;
|
|
2366
|
+
}
|
|
2367
|
+
return `${event.kind} ${event.name}`;
|
|
2368
|
+
}
|
|
2369
|
+
function incompleteRunningMessage(prefix, running) {
|
|
2370
|
+
const labels = running.map(describeRunningEvent);
|
|
2371
|
+
if (labels.length === 1) {
|
|
2372
|
+
return `${prefix}: ${labels[0]} never completed.`;
|
|
2373
|
+
}
|
|
2374
|
+
return `${prefix}: ${labels.join("; ")}.`;
|
|
2375
|
+
}
|
|
2376
|
+
function stepEndpointName(event, kind) {
|
|
2377
|
+
for (const prefix of ["llm:", "generation:", "transcription:", "speech:"]) {
|
|
2378
|
+
if (event.name.startsWith(prefix)) return event.name.slice(prefix.length);
|
|
2379
|
+
}
|
|
2380
|
+
return event.name;
|
|
2381
|
+
}
|
|
2340
2382
|
function semanticEvents(context) {
|
|
2341
2383
|
return context.logicalEvents ?? context.events;
|
|
2342
2384
|
}
|
|
@@ -2390,10 +2432,13 @@ function createRunStatusRule(options = {}) {
|
|
|
2390
2432
|
findings.push(
|
|
2391
2433
|
failFinding(
|
|
2392
2434
|
"run.status",
|
|
2393
|
-
"Run contains incomplete running events
|
|
2435
|
+
incompleteRunningMessage("Run contains incomplete running events", running),
|
|
2394
2436
|
running.map((event) => eventEvidence(event)),
|
|
2395
2437
|
"no running events",
|
|
2396
|
-
|
|
2438
|
+
{
|
|
2439
|
+
count: running.length,
|
|
2440
|
+
unfinished: running.map(describeRunningEvent)
|
|
2441
|
+
}
|
|
2397
2442
|
)
|
|
2398
2443
|
);
|
|
2399
2444
|
}
|
|
@@ -2461,6 +2506,34 @@ function createToolUsageRule(options) {
|
|
|
2461
2506
|
const names = tools.map(toolName);
|
|
2462
2507
|
const nameSet = new Set(names);
|
|
2463
2508
|
const findings = [];
|
|
2509
|
+
const forbidden = new Set(options.forbidden ?? []);
|
|
2510
|
+
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
2511
|
+
for (const event of tools) {
|
|
2512
|
+
const name = toolName(event);
|
|
2513
|
+
const display = formatToolNameForMessage(name);
|
|
2514
|
+
if (forbidden.has(name)) {
|
|
2515
|
+
findings.push(
|
|
2516
|
+
failFinding(
|
|
2517
|
+
"tool.usage",
|
|
2518
|
+
`Forbidden tool ${display} appeared.`,
|
|
2519
|
+
[eventEvidence(event)],
|
|
2520
|
+
"tool absent",
|
|
2521
|
+
name
|
|
2522
|
+
)
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
if (allowed && !allowed.has(name)) {
|
|
2526
|
+
findings.push(
|
|
2527
|
+
failFinding(
|
|
2528
|
+
"tool.usage",
|
|
2529
|
+
`Tool ${display} is not in the allowed tool set.`,
|
|
2530
|
+
[eventEvidence(event)],
|
|
2531
|
+
[...allowed].sort(),
|
|
2532
|
+
name
|
|
2533
|
+
)
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2464
2537
|
for (const required of options.required ?? []) {
|
|
2465
2538
|
if (!nameSet.has(required)) {
|
|
2466
2539
|
const otherKinds = [
|
|
@@ -2478,7 +2551,7 @@ function createToolUsageRule(options) {
|
|
|
2478
2551
|
findings.push(
|
|
2479
2552
|
failFinding(
|
|
2480
2553
|
"tool.usage",
|
|
2481
|
-
`Required tool ${required} did not appear.${hint}`,
|
|
2554
|
+
`Required tool ${formatToolNameForMessage(required)} did not appear.${hint}`,
|
|
2482
2555
|
runEvidence(context.selectedRun),
|
|
2483
2556
|
required,
|
|
2484
2557
|
names
|
|
@@ -2486,21 +2559,6 @@ function createToolUsageRule(options) {
|
|
|
2486
2559
|
);
|
|
2487
2560
|
}
|
|
2488
2561
|
}
|
|
2489
|
-
const forbidden = new Set(options.forbidden ?? []);
|
|
2490
|
-
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
2491
|
-
for (const event of tools) {
|
|
2492
|
-
const name = toolName(event);
|
|
2493
|
-
if (forbidden.has(name)) {
|
|
2494
|
-
findings.push(
|
|
2495
|
-
failFinding("tool.usage", `Forbidden tool ${name} appeared.`, [eventEvidence(event)], "tool absent", name)
|
|
2496
|
-
);
|
|
2497
|
-
}
|
|
2498
|
-
if (allowed && !allowed.has(name)) {
|
|
2499
|
-
findings.push(
|
|
2500
|
-
failFinding("tool.usage", `Tool ${name} is not in the allowed tool set.`, [eventEvidence(event)], [...allowed].sort(), name)
|
|
2501
|
-
);
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
2562
|
if (options.minCount !== void 0 && tools.length < options.minCount) {
|
|
2505
2563
|
findings.push(
|
|
2506
2564
|
failFinding("tool.usage", `Tool count ${tools.length} was below minimum ${options.minCount}.`, runEvidence(context.selectedRun), { minCount: options.minCount }, tools.length)
|