@agent-inspect/viewer 6.17.4 → 6.17.6
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 +72 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +72 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2629,10 +2629,11 @@ function emptySummary() {
|
|
|
2629
2629
|
passed: 0,
|
|
2630
2630
|
failed: 0,
|
|
2631
2631
|
warnings: 0,
|
|
2632
|
-
errors: 0
|
|
2632
|
+
errors: 0,
|
|
2633
|
+
rulesEvaluated: 0
|
|
2633
2634
|
};
|
|
2634
2635
|
}
|
|
2635
|
-
function errorResult(input, diagnostics, selectedRun) {
|
|
2636
|
+
function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
|
|
2636
2637
|
return {
|
|
2637
2638
|
ok: false,
|
|
2638
2639
|
status: "error",
|
|
@@ -2640,10 +2641,12 @@ function errorResult(input, diagnostics, selectedRun) {
|
|
|
2640
2641
|
...selectedRun ? { runId: selectedRun.runId } : {},
|
|
2641
2642
|
summary: {
|
|
2642
2643
|
...emptySummary(),
|
|
2643
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
2644
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
2645
|
+
rulesEvaluated: ruleExecutions.length
|
|
2644
2646
|
},
|
|
2645
2647
|
findings: [],
|
|
2646
|
-
diagnostics: [...diagnostics]
|
|
2648
|
+
diagnostics: [...diagnostics],
|
|
2649
|
+
ruleExecutions: [...ruleExecutions]
|
|
2647
2650
|
};
|
|
2648
2651
|
}
|
|
2649
2652
|
function flattenNodes(nodes) {
|
|
@@ -2799,7 +2802,7 @@ function normalizeFinding(rule, finding) {
|
|
|
2799
2802
|
...finding.action !== void 0 ? { action: finding.action } : {}
|
|
2800
2803
|
};
|
|
2801
2804
|
}
|
|
2802
|
-
function summarize(findings, diagnostics) {
|
|
2805
|
+
function summarize(findings, diagnostics, rulesEvaluated) {
|
|
2803
2806
|
return {
|
|
2804
2807
|
passed: findings.filter((finding) => finding.status === "pass").length,
|
|
2805
2808
|
failed: findings.filter(
|
|
@@ -2808,9 +2811,21 @@ function summarize(findings, diagnostics) {
|
|
|
2808
2811
|
warnings: findings.filter(
|
|
2809
2812
|
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
2810
2813
|
).length,
|
|
2811
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
2814
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
2815
|
+
rulesEvaluated
|
|
2812
2816
|
};
|
|
2813
2817
|
}
|
|
2818
|
+
function classifyRuleExecution(findings, threw) {
|
|
2819
|
+
if (findings.some((finding) => finding.status === "fail" && finding.severity === "error")) {
|
|
2820
|
+
return "fail";
|
|
2821
|
+
}
|
|
2822
|
+
if (findings.some(
|
|
2823
|
+
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
2824
|
+
)) {
|
|
2825
|
+
return "warning";
|
|
2826
|
+
}
|
|
2827
|
+
return "pass";
|
|
2828
|
+
}
|
|
2814
2829
|
function stringAttr(event, keys) {
|
|
2815
2830
|
for (const key of keys) {
|
|
2816
2831
|
const value = event.attributes?.[key];
|
|
@@ -2887,9 +2902,12 @@ function llmFinishReason(event) {
|
|
|
2887
2902
|
}
|
|
2888
2903
|
function finishedEvents(context, kind) {
|
|
2889
2904
|
return semanticEvents(context).filter(
|
|
2890
|
-
(event) => (
|
|
2905
|
+
(event) => (event.kind === kind) && event.status !== "running"
|
|
2891
2906
|
);
|
|
2892
2907
|
}
|
|
2908
|
+
function toolInvocationEvents(context) {
|
|
2909
|
+
return semanticEvents(context).filter((event) => event.kind === "TOOL");
|
|
2910
|
+
}
|
|
2893
2911
|
function createRunStatusRule(options = {}) {
|
|
2894
2912
|
const expected = options.expected ?? "ok";
|
|
2895
2913
|
const allowIncomplete = options.allowIncomplete === true;
|
|
@@ -2955,7 +2973,7 @@ function createToolUsageRule(options) {
|
|
|
2955
2973
|
category: "tool",
|
|
2956
2974
|
defaultSeverity: "error",
|
|
2957
2975
|
evaluate(context) {
|
|
2958
|
-
const tools =
|
|
2976
|
+
const tools = toolInvocationEvents(context);
|
|
2959
2977
|
const names = tools.map(toolName);
|
|
2960
2978
|
const nameSet = new Set(names);
|
|
2961
2979
|
const findings = [];
|
|
@@ -3071,12 +3089,24 @@ function createLlmUsageRule(options) {
|
|
|
3071
3089
|
}
|
|
3072
3090
|
function createObservedOutcomeRule(options = {}) {
|
|
3073
3091
|
const failOn = options.failOn ?? ["failed"];
|
|
3092
|
+
const requireAny = options.requireAny === true;
|
|
3074
3093
|
return {
|
|
3075
3094
|
id: "outcome.status",
|
|
3076
3095
|
category: "run",
|
|
3077
3096
|
defaultSeverity: "error",
|
|
3078
3097
|
evaluate(context) {
|
|
3079
3098
|
const outcomes = extractOutcomesFromPersistedEvents(context.events);
|
|
3099
|
+
if (requireAny && outcomes.length === 0) {
|
|
3100
|
+
return [
|
|
3101
|
+
failFinding(
|
|
3102
|
+
"outcome.status",
|
|
3103
|
+
"Expected at least one observed outcome.",
|
|
3104
|
+
runEvidence(context.selectedRun),
|
|
3105
|
+
{ requireAny: true, expected: "at least one observed outcome" },
|
|
3106
|
+
{ code: "outcome.missing", actual: 0 }
|
|
3107
|
+
)
|
|
3108
|
+
];
|
|
3109
|
+
}
|
|
3080
3110
|
const matching = outcomesMatchingStatus(outcomes, failOn);
|
|
3081
3111
|
if (matching.length === 0) return [];
|
|
3082
3112
|
return [
|
|
@@ -3112,6 +3142,18 @@ function runTraceChecks(input, options = {}) {
|
|
|
3112
3142
|
if (rules.diagnostics.length > 0) {
|
|
3113
3143
|
return errorResult(input, rules.diagnostics, selected.run);
|
|
3114
3144
|
}
|
|
3145
|
+
if (rules.rules.length === 0) {
|
|
3146
|
+
return errorResult(
|
|
3147
|
+
input,
|
|
3148
|
+
[
|
|
3149
|
+
diagnostic3(
|
|
3150
|
+
"AI_CHECK_NO_RULES_EVALUATED",
|
|
3151
|
+
"No trace check rules were evaluated. Configure at least one rule, contract, or CLI check option."
|
|
3152
|
+
)
|
|
3153
|
+
],
|
|
3154
|
+
selected.run
|
|
3155
|
+
);
|
|
3156
|
+
}
|
|
3115
3157
|
const facts = buildFacts(input, selected.run);
|
|
3116
3158
|
const context = {
|
|
3117
3159
|
...facts,
|
|
@@ -3120,22 +3162,38 @@ function runTraceChecks(input, options = {}) {
|
|
|
3120
3162
|
};
|
|
3121
3163
|
const diagnostics = [];
|
|
3122
3164
|
const findings = [];
|
|
3165
|
+
const ruleExecutions = [];
|
|
3123
3166
|
for (const rule of rules.rules) {
|
|
3124
3167
|
try {
|
|
3125
|
-
|
|
3168
|
+
const ruleFindings = rule.evaluate(context).map((finding) => normalizeFinding(rule, finding));
|
|
3169
|
+
findings.push(...ruleFindings);
|
|
3170
|
+
ruleExecutions.push({
|
|
3171
|
+
ruleId: rule.id,
|
|
3172
|
+
category: rule.category,
|
|
3173
|
+
status: classifyRuleExecution(ruleFindings, false),
|
|
3174
|
+
findingCount: ruleFindings.length,
|
|
3175
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
3176
|
+
});
|
|
3126
3177
|
} catch (error) {
|
|
3127
3178
|
const message = error instanceof Error ? error.message : String(error);
|
|
3128
3179
|
diagnostics.push(
|
|
3129
3180
|
diagnostic3("AI_CHECK_INTERNAL_ERROR", `Rule ${rule.id} failed: ${message}`, rule.id)
|
|
3130
3181
|
);
|
|
3182
|
+
ruleExecutions.push({
|
|
3183
|
+
ruleId: rule.id,
|
|
3184
|
+
category: rule.category,
|
|
3185
|
+
status: "error",
|
|
3186
|
+
findingCount: 0,
|
|
3187
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
3188
|
+
});
|
|
3131
3189
|
}
|
|
3132
3190
|
}
|
|
3133
3191
|
if (diagnostics.length > 0) {
|
|
3134
|
-
return errorResult(input, diagnostics, selected.run);
|
|
3192
|
+
return errorResult(input, diagnostics, selected.run, ruleExecutions);
|
|
3135
3193
|
}
|
|
3136
3194
|
const eventById = new Map(input.read.events.map((event) => [event.eventId, event]));
|
|
3137
3195
|
const sortedFindings = findings.sort(compareFindings(eventById));
|
|
3138
|
-
const summary = summarize(sortedFindings, diagnostics);
|
|
3196
|
+
const summary = summarize(sortedFindings, diagnostics, ruleExecutions.length);
|
|
3139
3197
|
const status = summary.failed > 0 ? "fail" : "pass";
|
|
3140
3198
|
return {
|
|
3141
3199
|
ok: status === "pass",
|
|
@@ -3144,7 +3202,8 @@ function runTraceChecks(input, options = {}) {
|
|
|
3144
3202
|
...selected.run ? { runId: selected.run.runId } : {},
|
|
3145
3203
|
summary,
|
|
3146
3204
|
findings: sortedFindings,
|
|
3147
|
-
diagnostics
|
|
3205
|
+
diagnostics,
|
|
3206
|
+
ruleExecutions
|
|
3148
3207
|
};
|
|
3149
3208
|
}
|
|
3150
3209
|
|
|
@@ -5471,8 +5530,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5471
5530
|
status: "pass",
|
|
5472
5531
|
format: read.format,
|
|
5473
5532
|
findings: [],
|
|
5474
|
-
diagnostics: []
|
|
5475
|
-
};
|
|
5533
|
+
diagnostics: []};
|
|
5476
5534
|
const observationResult = validateExpectedObservations(suiteCase, read);
|
|
5477
5535
|
const diagnostics = [
|
|
5478
5536
|
...checkResult.diagnostics.map(
|