ag-ui-validate 0.1.0
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/LICENSE +21 -0
- package/README.md +229 -0
- package/dist/catalog-BglXBNbL.js +472 -0
- package/dist/catalog-BglXBNbL.js.map +1 -0
- package/dist/catalog-Ci9dqc1a.cjs +495 -0
- package/dist/catalog-Ci9dqc1a.cjs.map +1 -0
- package/dist/cli.js +2783 -0
- package/dist/cli.js.map +1 -0
- package/dist/index-Hmqj3r_r.d.cts +52 -0
- package/dist/index-oNG1kOp9.d.ts +52 -0
- package/dist/index.cjs +14 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/report.cjs +139 -0
- package/dist/report.cjs.map +1 -0
- package/dist/report.d.cts +85 -0
- package/dist/report.d.ts +85 -0
- package/dist/report.js +134 -0
- package/dist/report.js.map +1 -0
- package/dist/src-HmI-kxef.cjs +1596 -0
- package/dist/src-HmI-kxef.cjs.map +1 -0
- package/dist/src-rGZ2G4qA.js +1555 -0
- package/dist/src-rGZ2G4qA.js.map +1 -0
- package/dist/transport.cjs +329 -0
- package/dist/transport.cjs.map +1 -0
- package/dist/transport.d.cts +89 -0
- package/dist/transport.d.ts +89 -0
- package/dist/transport.js +323 -0
- package/dist/transport.js.map +1 -0
- package/dist/types-oH_QTnn2.d.cts +148 -0
- package/dist/types-oH_QTnn2.d.ts +148 -0
- package/dist/vitest.d.ts +28 -0
- package/dist/vitest.js +2089 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +127 -0
- package/src/cli-args.ts +202 -0
- package/src/cli.ts +147 -0
- package/src/index.ts +465 -0
- package/src/protocol/event-table.ts +316 -0
- package/src/protocol/jsonpatch.ts +220 -0
- package/src/report/index.ts +10 -0
- package/src/report/json.ts +20 -0
- package/src/report/junit.ts +56 -0
- package/src/report/pretty.ts +59 -0
- package/src/report/sarif.ts +109 -0
- package/src/rules/catalog.json +431 -0
- package/src/rules/catalog.ts +84 -0
- package/src/rules/checks/context.ts +117 -0
- package/src/rules/checks/lifecycle.ts +59 -0
- package/src/rules/checks/reasoning.ts +97 -0
- package/src/rules/checks/state.ts +72 -0
- package/src/rules/checks/text.ts +109 -0
- package/src/rules/checks/toolcalls.ts +167 -0
- package/src/rules/checks/transport.ts +17 -0
- package/src/transport/index.ts +331 -0
- package/src/transport/ndjson.ts +25 -0
- package/src/transport/sse.ts +126 -0
- package/src/types.ts +136 -0
- package/src/vitest/index.ts +19 -0
- package/src/vitest/matcher.ts +77 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// The matcher itself is framework-agnostic and pure: it takes the received
|
|
2
|
+
// value and options, runs the core validator, and returns {pass, message}.
|
|
3
|
+
// vitest/index.ts registers it with expect.extend; Jest users can do the same.
|
|
4
|
+
import { decideExitCode } from "../cli-args.js"
|
|
5
|
+
import { createValidator } from "../index.js"
|
|
6
|
+
import { formatDiagnosticLine } from "../report/pretty.js"
|
|
7
|
+
import type { SeverityOrOff, ValidatorOptions } from "../types.js"
|
|
8
|
+
|
|
9
|
+
export interface ToBeValidAGUIOptions {
|
|
10
|
+
/** Declared features (enables feature-conditional rules, e.g. AGUI305). */
|
|
11
|
+
features?: string[]
|
|
12
|
+
/** Per-rule severity overrides; "off" disables a rule. */
|
|
13
|
+
severityOverrides?: Record<string, SeverityOrOff>
|
|
14
|
+
/** Fail when warning-severity findings exceed this budget. */
|
|
15
|
+
maxWarnings?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MatcherResult {
|
|
19
|
+
pass: boolean
|
|
20
|
+
message: () => string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function toBeValidAGUI(
|
|
24
|
+
received: unknown,
|
|
25
|
+
options: ToBeValidAGUIOptions = {},
|
|
26
|
+
): MatcherResult {
|
|
27
|
+
let events: unknown[]
|
|
28
|
+
if (typeof received === "string") {
|
|
29
|
+
// A JSONL/NDJSON capture: one event per non-empty line.
|
|
30
|
+
events = received.split(/\r?\n/).filter((line) => line.trim() !== "")
|
|
31
|
+
} else if (Array.isArray(received)) {
|
|
32
|
+
events = received
|
|
33
|
+
} else {
|
|
34
|
+
throw new TypeError(
|
|
35
|
+
`toBeValidAGUI expects an array of events (objects or JSON strings) or a JSONL string; ` +
|
|
36
|
+
`received ${received === null ? "null" : typeof received}. Wrap a single event in an array.`,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const validatorOptions: ValidatorOptions = {}
|
|
41
|
+
if (options.features !== undefined) validatorOptions.features = options.features
|
|
42
|
+
if (options.severityOverrides !== undefined) {
|
|
43
|
+
validatorOptions.severityOverrides = options.severityOverrides
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const v = createValidator(validatorOptions)
|
|
47
|
+
for (const e of events) v.feed(e)
|
|
48
|
+
v.finalize()
|
|
49
|
+
const report = v.report()
|
|
50
|
+
const { errors, warnings, info } = report.summary
|
|
51
|
+
const pass = decideExitCode(report.summary, options.maxWarnings) === 0
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
pass,
|
|
55
|
+
message: (): string => {
|
|
56
|
+
if (pass) {
|
|
57
|
+
return (
|
|
58
|
+
`expected the stream to violate AG-UI conformance, but it is valid: ` +
|
|
59
|
+
`${report.eventCount} events, ${errors} errors, ${warnings} warnings, ${info} info`
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
const lines: string[] = []
|
|
63
|
+
if (errors > 0) {
|
|
64
|
+
lines.push(`expected a valid AG-UI stream, but found ${errors} error-severity finding${errors === 1 ? "" : "s"}:`)
|
|
65
|
+
} else {
|
|
66
|
+
lines.push(
|
|
67
|
+
`expected a valid AG-UI stream, but ${warnings} warning${warnings === 1 ? "" : "s"} exceed maxWarnings: ${options.maxWarnings}:`,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
for (const d of report.diagnostics) {
|
|
71
|
+
if (d.severity === "info") continue
|
|
72
|
+
lines.push(formatDiagnosticLine(d, { color: false }))
|
|
73
|
+
}
|
|
74
|
+
return lines.join("\n")
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|