@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.mjs
CHANGED
|
@@ -2622,10 +2622,11 @@ function emptySummary() {
|
|
|
2622
2622
|
passed: 0,
|
|
2623
2623
|
failed: 0,
|
|
2624
2624
|
warnings: 0,
|
|
2625
|
-
errors: 0
|
|
2625
|
+
errors: 0,
|
|
2626
|
+
rulesEvaluated: 0
|
|
2626
2627
|
};
|
|
2627
2628
|
}
|
|
2628
|
-
function errorResult(input, diagnostics, selectedRun) {
|
|
2629
|
+
function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
|
|
2629
2630
|
return {
|
|
2630
2631
|
ok: false,
|
|
2631
2632
|
status: "error",
|
|
@@ -2633,10 +2634,12 @@ function errorResult(input, diagnostics, selectedRun) {
|
|
|
2633
2634
|
...selectedRun ? { runId: selectedRun.runId } : {},
|
|
2634
2635
|
summary: {
|
|
2635
2636
|
...emptySummary(),
|
|
2636
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
2637
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
2638
|
+
rulesEvaluated: ruleExecutions.length
|
|
2637
2639
|
},
|
|
2638
2640
|
findings: [],
|
|
2639
|
-
diagnostics: [...diagnostics]
|
|
2641
|
+
diagnostics: [...diagnostics],
|
|
2642
|
+
ruleExecutions: [...ruleExecutions]
|
|
2640
2643
|
};
|
|
2641
2644
|
}
|
|
2642
2645
|
function flattenNodes(nodes) {
|
|
@@ -2792,7 +2795,7 @@ function normalizeFinding(rule, finding) {
|
|
|
2792
2795
|
...finding.action !== void 0 ? { action: finding.action } : {}
|
|
2793
2796
|
};
|
|
2794
2797
|
}
|
|
2795
|
-
function summarize(findings, diagnostics) {
|
|
2798
|
+
function summarize(findings, diagnostics, rulesEvaluated) {
|
|
2796
2799
|
return {
|
|
2797
2800
|
passed: findings.filter((finding) => finding.status === "pass").length,
|
|
2798
2801
|
failed: findings.filter(
|
|
@@ -2801,9 +2804,21 @@ function summarize(findings, diagnostics) {
|
|
|
2801
2804
|
warnings: findings.filter(
|
|
2802
2805
|
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
2803
2806
|
).length,
|
|
2804
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
2807
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
2808
|
+
rulesEvaluated
|
|
2805
2809
|
};
|
|
2806
2810
|
}
|
|
2811
|
+
function classifyRuleExecution(findings, threw) {
|
|
2812
|
+
if (findings.some((finding) => finding.status === "fail" && finding.severity === "error")) {
|
|
2813
|
+
return "fail";
|
|
2814
|
+
}
|
|
2815
|
+
if (findings.some(
|
|
2816
|
+
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
2817
|
+
)) {
|
|
2818
|
+
return "warning";
|
|
2819
|
+
}
|
|
2820
|
+
return "pass";
|
|
2821
|
+
}
|
|
2807
2822
|
function stringAttr(event, keys) {
|
|
2808
2823
|
for (const key of keys) {
|
|
2809
2824
|
const value = event.attributes?.[key];
|
|
@@ -2880,9 +2895,12 @@ function llmFinishReason(event) {
|
|
|
2880
2895
|
}
|
|
2881
2896
|
function finishedEvents(context, kind) {
|
|
2882
2897
|
return semanticEvents(context).filter(
|
|
2883
|
-
(event) => (
|
|
2898
|
+
(event) => (event.kind === kind) && event.status !== "running"
|
|
2884
2899
|
);
|
|
2885
2900
|
}
|
|
2901
|
+
function toolInvocationEvents(context) {
|
|
2902
|
+
return semanticEvents(context).filter((event) => event.kind === "TOOL");
|
|
2903
|
+
}
|
|
2886
2904
|
function createRunStatusRule(options = {}) {
|
|
2887
2905
|
const expected = options.expected ?? "ok";
|
|
2888
2906
|
const allowIncomplete = options.allowIncomplete === true;
|
|
@@ -2948,7 +2966,7 @@ function createToolUsageRule(options) {
|
|
|
2948
2966
|
category: "tool",
|
|
2949
2967
|
defaultSeverity: "error",
|
|
2950
2968
|
evaluate(context) {
|
|
2951
|
-
const tools =
|
|
2969
|
+
const tools = toolInvocationEvents(context);
|
|
2952
2970
|
const names = tools.map(toolName);
|
|
2953
2971
|
const nameSet = new Set(names);
|
|
2954
2972
|
const findings = [];
|
|
@@ -3064,12 +3082,24 @@ function createLlmUsageRule(options) {
|
|
|
3064
3082
|
}
|
|
3065
3083
|
function createObservedOutcomeRule(options = {}) {
|
|
3066
3084
|
const failOn = options.failOn ?? ["failed"];
|
|
3085
|
+
const requireAny = options.requireAny === true;
|
|
3067
3086
|
return {
|
|
3068
3087
|
id: "outcome.status",
|
|
3069
3088
|
category: "run",
|
|
3070
3089
|
defaultSeverity: "error",
|
|
3071
3090
|
evaluate(context) {
|
|
3072
3091
|
const outcomes = extractOutcomesFromPersistedEvents(context.events);
|
|
3092
|
+
if (requireAny && outcomes.length === 0) {
|
|
3093
|
+
return [
|
|
3094
|
+
failFinding(
|
|
3095
|
+
"outcome.status",
|
|
3096
|
+
"Expected at least one observed outcome.",
|
|
3097
|
+
runEvidence(context.selectedRun),
|
|
3098
|
+
{ requireAny: true, expected: "at least one observed outcome" },
|
|
3099
|
+
{ code: "outcome.missing", actual: 0 }
|
|
3100
|
+
)
|
|
3101
|
+
];
|
|
3102
|
+
}
|
|
3073
3103
|
const matching = outcomesMatchingStatus(outcomes, failOn);
|
|
3074
3104
|
if (matching.length === 0) return [];
|
|
3075
3105
|
return [
|
|
@@ -3105,6 +3135,18 @@ function runTraceChecks(input, options = {}) {
|
|
|
3105
3135
|
if (rules.diagnostics.length > 0) {
|
|
3106
3136
|
return errorResult(input, rules.diagnostics, selected.run);
|
|
3107
3137
|
}
|
|
3138
|
+
if (rules.rules.length === 0) {
|
|
3139
|
+
return errorResult(
|
|
3140
|
+
input,
|
|
3141
|
+
[
|
|
3142
|
+
diagnostic3(
|
|
3143
|
+
"AI_CHECK_NO_RULES_EVALUATED",
|
|
3144
|
+
"No trace check rules were evaluated. Configure at least one rule, contract, or CLI check option."
|
|
3145
|
+
)
|
|
3146
|
+
],
|
|
3147
|
+
selected.run
|
|
3148
|
+
);
|
|
3149
|
+
}
|
|
3108
3150
|
const facts = buildFacts(input, selected.run);
|
|
3109
3151
|
const context = {
|
|
3110
3152
|
...facts,
|
|
@@ -3113,22 +3155,38 @@ function runTraceChecks(input, options = {}) {
|
|
|
3113
3155
|
};
|
|
3114
3156
|
const diagnostics = [];
|
|
3115
3157
|
const findings = [];
|
|
3158
|
+
const ruleExecutions = [];
|
|
3116
3159
|
for (const rule of rules.rules) {
|
|
3117
3160
|
try {
|
|
3118
|
-
|
|
3161
|
+
const ruleFindings = rule.evaluate(context).map((finding) => normalizeFinding(rule, finding));
|
|
3162
|
+
findings.push(...ruleFindings);
|
|
3163
|
+
ruleExecutions.push({
|
|
3164
|
+
ruleId: rule.id,
|
|
3165
|
+
category: rule.category,
|
|
3166
|
+
status: classifyRuleExecution(ruleFindings, false),
|
|
3167
|
+
findingCount: ruleFindings.length,
|
|
3168
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
3169
|
+
});
|
|
3119
3170
|
} catch (error) {
|
|
3120
3171
|
const message = error instanceof Error ? error.message : String(error);
|
|
3121
3172
|
diagnostics.push(
|
|
3122
3173
|
diagnostic3("AI_CHECK_INTERNAL_ERROR", `Rule ${rule.id} failed: ${message}`, rule.id)
|
|
3123
3174
|
);
|
|
3175
|
+
ruleExecutions.push({
|
|
3176
|
+
ruleId: rule.id,
|
|
3177
|
+
category: rule.category,
|
|
3178
|
+
status: "error",
|
|
3179
|
+
findingCount: 0,
|
|
3180
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
3181
|
+
});
|
|
3124
3182
|
}
|
|
3125
3183
|
}
|
|
3126
3184
|
if (diagnostics.length > 0) {
|
|
3127
|
-
return errorResult(input, diagnostics, selected.run);
|
|
3185
|
+
return errorResult(input, diagnostics, selected.run, ruleExecutions);
|
|
3128
3186
|
}
|
|
3129
3187
|
const eventById = new Map(input.read.events.map((event) => [event.eventId, event]));
|
|
3130
3188
|
const sortedFindings = findings.sort(compareFindings(eventById));
|
|
3131
|
-
const summary = summarize(sortedFindings, diagnostics);
|
|
3189
|
+
const summary = summarize(sortedFindings, diagnostics, ruleExecutions.length);
|
|
3132
3190
|
const status = summary.failed > 0 ? "fail" : "pass";
|
|
3133
3191
|
return {
|
|
3134
3192
|
ok: status === "pass",
|
|
@@ -3137,7 +3195,8 @@ function runTraceChecks(input, options = {}) {
|
|
|
3137
3195
|
...selected.run ? { runId: selected.run.runId } : {},
|
|
3138
3196
|
summary,
|
|
3139
3197
|
findings: sortedFindings,
|
|
3140
|
-
diagnostics
|
|
3198
|
+
diagnostics,
|
|
3199
|
+
ruleExecutions
|
|
3141
3200
|
};
|
|
3142
3201
|
}
|
|
3143
3202
|
|
|
@@ -5464,8 +5523,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
5464
5523
|
status: "pass",
|
|
5465
5524
|
format: read.format,
|
|
5466
5525
|
findings: [],
|
|
5467
|
-
diagnostics: []
|
|
5468
|
-
};
|
|
5526
|
+
diagnostics: []};
|
|
5469
5527
|
const observationResult = validateExpectedObservations(suiteCase, read);
|
|
5470
5528
|
const diagnostics = [
|
|
5471
5529
|
...checkResult.diagnostics.map(
|