ag-ui-validate 0.2.0 → 0.3.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/README.md +70 -10
- package/dist/{catalog-Ci9dqc1a.cjs → catalog-AB5vuZ8j.cjs} +3 -3
- package/dist/catalog-AB5vuZ8j.cjs.map +1 -0
- package/dist/{catalog-BglXBNbL.js → catalog-DqTI4VLt.js} +3 -3
- package/dist/catalog-DqTI4VLt.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +2 -2
- package/dist/report.cjs +1 -1
- package/dist/report.cjs.map +1 -1
- package/dist/report.js +1 -1
- package/dist/report.js.map +1 -1
- package/dist/{src-HmI-kxef.cjs → src-D04i3Vso.cjs} +2 -2
- package/dist/src-D04i3Vso.cjs.map +1 -0
- package/dist/{src-rGZ2G4qA.js → src-Dcuqz2QC.js} +2 -2
- package/dist/src-Dcuqz2QC.js.map +1 -0
- package/dist/transport.cjs +1 -1
- package/dist/transport.cjs.map +1 -1
- package/dist/transport.js +1 -1
- package/dist/transport.js.map +1 -1
- package/dist/vitest.js +2 -2
- package/dist/vitest.js.map +1 -1
- package/{src → js/src}/rules/catalog.ts +1 -1
- package/{src → js/src}/transport/index.ts +1 -1
- package/package.json +14 -13
- package/{src/rules → spec}/catalog.json +1 -1
- package/spec/event-categories.json +56 -0
- package/spec/fixtures/README.md +91 -0
- package/spec/fixtures/invalid/AGUI001-first-event-not-run-started/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI001-first-event-not-run-started/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI002-duplicate-run-started/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI002-duplicate-run-started/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI003-run-never-terminated/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI003-run-never-terminated/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI004-event-after-terminal/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI004-event-after-terminal/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI005-finished-and-error/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI005-finished-and-error/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI006-step-finished-unmatched/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI006-step-finished-unmatched/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI007-step-unterminated/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI007-step-unterminated/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI008-unstable-run-ids/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI008-unstable-run-ids/stream.jsonl +2 -0
- package/spec/fixtures/invalid/AGUI101-content-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI101-content-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI102-end-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI102-end-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI103-message-unterminated/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI103-message-unterminated/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI104-duplicate-message-id/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI104-duplicate-message-id/stream.jsonl +6 -0
- package/spec/fixtures/invalid/AGUI105-empty-content-delta/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI105-empty-content-delta/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI106-interleaved-same-message-id/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI106-interleaved-same-message-id/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI201-args-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI201-args-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI202-end-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI202-end-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI203-unterminated-tool-call/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI203-unterminated-tool-call/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI204-args-not-json/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI204-args-not-json/stream.jsonl +6 -0
- package/spec/fixtures/invalid/AGUI205-duplicate-tool-call-id/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI205-duplicate-tool-call-id/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI206-result-before-end/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI206-result-before-end/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI207-result-unknown-id/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI207-result-unknown-id/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI208-unknown-parent-message-id/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI208-unknown-parent-message-id/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI301-delta-before-snapshot/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI301-delta-before-snapshot/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI302-delta-failed-to-apply/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI302-delta-failed-to-apply/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI303-invalid-patch-document/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI303-invalid-patch-document/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI304-midrun-snapshot-discards-deltas/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI304-midrun-snapshot-discards-deltas/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI305-shared-state-never-established/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI305-shared-state-never-established/options.json +5 -0
- package/spec/fixtures/invalid/AGUI305-shared-state-never-established/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI401-reasoning-content-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI401-reasoning-content-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI402-reasoning-unterminated/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI402-reasoning-unterminated/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI501-missing-data-prefix/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI501-missing-data-prefix/scenario.json +17 -0
- package/spec/fixtures/invalid/AGUI502-payload-not-json/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI502-payload-not-json/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI503-unknown-event-type/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI503-unknown-event-type/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI504-schema-violation/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI504-schema-violation/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI505-unexpected-content-type/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI505-unexpected-content-type/scenario.json +25 -0
- package/spec/fixtures/invalid/AGUI506-keepalive-gap/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI506-keepalive-gap/scenario.json +25 -0
- package/spec/fixtures/invalid/AGUI507-buffered-response/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI507-buffered-response/scenario.json +9 -0
- package/spec/fixtures/invalid/AGUI508-connection-dropped/expected.json +17 -0
- package/spec/fixtures/invalid/AGUI508-connection-dropped/scenario.json +10 -0
- package/spec/fixtures/invalid/AGUI901-raw-wraps-typed-event/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI901-raw-wraps-typed-event/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI902-no-timestamps/expected.json +9 -0
- package/spec/fixtures/invalid/AGUI902-no-timestamps/stream.jsonl +2 -0
- package/spec/fixtures/invalid/AGUI903-custom-name-not-namespaced/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI903-custom-name-not-namespaced/stream.jsonl +3 -0
- package/spec/fixtures/valid/agentic-chat.jsonl +14 -0
- package/spec/fixtures/valid/agentic-generative-ui.jsonl +13 -0
- package/spec/fixtures/valid/backend-tool-rendering.jsonl +14 -0
- package/spec/fixtures/valid/human-in-the-loop.jsonl +13 -0
- package/spec/fixtures/valid/predictive-state-updates.expected.json +11 -0
- package/spec/fixtures/valid/predictive-state-updates.jsonl +11 -0
- package/spec/fixtures/valid/shared-state.jsonl +8 -0
- package/spec/fixtures/valid/tool-based-generative-ui.jsonl +5 -0
- package/dist/catalog-BglXBNbL.js.map +0 -1
- package/dist/catalog-Ci9dqc1a.cjs.map +0 -1
- package/dist/src-HmI-kxef.cjs.map +0 -1
- package/dist/src-rGZ2G4qA.js.map +0 -1
- /package/{src → js/src}/cli-args.ts +0 -0
- /package/{src → js/src}/cli.ts +0 -0
- /package/{src → js/src}/index.ts +0 -0
- /package/{src → js/src}/protocol/event-table.ts +0 -0
- /package/{src → js/src}/protocol/jsonpatch.ts +0 -0
- /package/{src → js/src}/report/index.ts +0 -0
- /package/{src → js/src}/report/json.ts +0 -0
- /package/{src → js/src}/report/junit.ts +0 -0
- /package/{src → js/src}/report/pretty.ts +0 -0
- /package/{src → js/src}/report/sarif.ts +0 -0
- /package/{src → js/src}/rules/checks/context.ts +0 -0
- /package/{src → js/src}/rules/checks/lifecycle.ts +0 -0
- /package/{src → js/src}/rules/checks/reasoning.ts +0 -0
- /package/{src → js/src}/rules/checks/state.ts +0 -0
- /package/{src → js/src}/rules/checks/text.ts +0 -0
- /package/{src → js/src}/rules/checks/toolcalls.ts +0 -0
- /package/{src → js/src}/rules/checks/transport.ts +0 -0
- /package/{src → js/src}/transport/ndjson.ts +0 -0
- /package/{src → js/src}/transport/sse.ts +0 -0
- /package/{src → js/src}/types.ts +0 -0
- /package/{src → js/src}/vitest/index.ts +0 -0
- /package/{src → js/src}/vitest/matcher.ts +0 -0
package/README.md
CHANGED
|
@@ -15,10 +15,11 @@ spec section.
|
|
|
15
15
|
2 errors, 0 warnings, 1 info — 3 of 7 AG-UI features exercised
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
> **Status
|
|
19
|
-
>
|
|
20
|
-
>
|
|
21
|
-
>
|
|
18
|
+
> **Status:** the TypeScript implementation is released to npm
|
|
19
|
+
> (`npm install ag-ui-validate`). A native Python port — same rule catalog,
|
|
20
|
+
> same fixture corpus, byte-identical CLI — is fully implemented and tested
|
|
21
|
+
> but not yet published to PyPI as a functional release; see
|
|
22
|
+
> [Python](#python) below.
|
|
22
23
|
|
|
23
24
|
## Why
|
|
24
25
|
|
|
@@ -124,7 +125,7 @@ const { diagnostics, summary, features, skipped } = v.report()
|
|
|
124
125
|
```
|
|
125
126
|
|
|
126
127
|
The core is a pure function over an event sequence: zero I/O, zero runtime
|
|
127
|
-
dependencies, isomorphic across Node
|
|
128
|
+
dependencies, isomorphic across Node 22+, browsers, Deno, and Workers.
|
|
128
129
|
|
|
129
130
|
### Validate a live endpoint
|
|
130
131
|
|
|
@@ -170,12 +171,71 @@ import { formatReportSummary, toSarif, toJUnit } from "ag-ui-validate/report"
|
|
|
170
171
|
}
|
|
171
172
|
```
|
|
172
173
|
|
|
174
|
+
## Python
|
|
175
|
+
|
|
176
|
+
A native Python port ships in [py/](py/) — the same rule catalog, the same
|
|
177
|
+
fixture corpus, and a CLI with byte-identical flags, error messages, and
|
|
178
|
+
JSON/SARIF/JUnit output to the TypeScript one above. It's fully implemented
|
|
179
|
+
and tested, and checked against the TypeScript implementation on every PR
|
|
180
|
+
by Parity CI (see [docs/TESTING.md](docs/TESTING.md) for how, and
|
|
181
|
+
[docs/PYTHON-PORT-PLAN.md](docs/PYTHON-PORT-PLAN.md) for the port's full
|
|
182
|
+
milestone history). **Not yet published to PyPI as a functional release**
|
|
183
|
+
— only a name-reservation placeholder (`0.0.1`) is live today.
|
|
184
|
+
Install from source until a real release ships:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
git clone https://github.com/langport-dev/ag-ui-validate
|
|
188
|
+
cd ag-ui-validate/py
|
|
189
|
+
pip install -e ".[dev]" # or ".[transport]" for just the endpoint-validating extras
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### CLI
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
ag-ui-validate http://localhost:8000/agui # live endpoint (POSTs a RunAgentInput)
|
|
196
|
+
ag-ui-validate run.jsonl # recorded stream (NDJSON/JSONL or SSE capture)
|
|
197
|
+
cat run.jsonl | ag-ui-validate - # stdin
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Same exit codes and the same flags as the [CLI](#cli) above (see
|
|
201
|
+
`ag-ui-validate --help`) — the Python argument parser is a direct,
|
|
202
|
+
hand-rolled port of the TypeScript one rather than `argparse`/`click`,
|
|
203
|
+
specifically to keep both CLIs' invocation and error messages
|
|
204
|
+
byte-for-byte identical.
|
|
205
|
+
|
|
206
|
+
### Test your agent in pytest
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from ag_ui_validate.pytest_plugin import assert_valid_agui
|
|
210
|
+
|
|
211
|
+
def test_my_agent_stream(captured_events):
|
|
212
|
+
assert_valid_agui(captured_events, features=["shared-state"], max_warnings=0)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`assert_valid_agui` accepts a list of events (dicts or JSON strings) or a
|
|
216
|
+
whole JSONL capture as one string, and raises `AssertionError` with every
|
|
217
|
+
finding's rule ID and spec link on failure. It registers automatically as a
|
|
218
|
+
pytest plugin on install — no `conftest.py` setup needed. An async
|
|
219
|
+
counterpart validates a live endpoint directly from a test:
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from ag_ui_validate.pytest_plugin import assert_valid_agui_endpoint
|
|
223
|
+
|
|
224
|
+
async def test_my_live_agent():
|
|
225
|
+
await assert_valid_agui_endpoint("http://localhost:8000/agui", max_warnings=0)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`assert_valid_agui` has zero runtime dependencies; only the
|
|
229
|
+
endpoint-validating helpers (`assert_valid_agui_endpoint`,
|
|
230
|
+
`validate_agui_endpoint`) pull in `httpx`
|
|
231
|
+
(`pip install ag-ui-validate[transport]`).
|
|
232
|
+
|
|
173
233
|
## The rule catalog
|
|
174
234
|
|
|
175
235
|
40 rules, maintained as **data** in
|
|
176
|
-
[
|
|
177
|
-
(
|
|
178
|
-
|
|
236
|
+
[spec/catalog.json](spec/catalog.json), shared by both implementations in
|
|
237
|
+
this repo ([TypeScript](.) and [Python](py/)) rather than duplicated.
|
|
238
|
+
Every rule has its own page — spec grounding,
|
|
179
239
|
**[rule index](docs/rules/README.md)** (generated from the catalog,
|
|
180
240
|
drift-checked in CI):
|
|
181
241
|
|
|
@@ -195,7 +255,7 @@ drift-tested against the installed SDK on every run.
|
|
|
195
255
|
|
|
196
256
|
## The fixture corpus
|
|
197
257
|
|
|
198
|
-
[fixtures/](fixtures/README.md) is a language-neutral conformance corpus:
|
|
258
|
+
[spec/fixtures/](spec/fixtures/README.md) is a language-neutral conformance corpus:
|
|
199
259
|
7 valid streams (one per canonical AG-UI feature — the false-positive guards)
|
|
200
260
|
and 40 invalid fixtures (one per rule) with exact expected diagnostics. Any
|
|
201
261
|
validator implementation that consumes the shared catalog can be tested
|
|
@@ -219,7 +279,7 @@ Component-by-component instructions live in
|
|
|
219
279
|
rules are tracked in [docs/spec-questions.md](docs/spec-questions.md).
|
|
220
280
|
|
|
221
281
|
Adding a rule: add the catalog entry (with its `specUrl`), add the fixture
|
|
222
|
-
stream + intended findings to `scripts/build-fixtures.mjs`, and run
|
|
282
|
+
stream + intended findings to `js/scripts/build-fixtures.mjs`, and run
|
|
223
283
|
`npm run fixtures:build` — the meta-tests fail until both exist. Rule
|
|
224
284
|
*proposals* belong upstream as issues on
|
|
225
285
|
[`ag-ui-protocol/ag-ui`](https://github.com/ag-ui-protocol/ag-ui) first; this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region
|
|
1
|
+
//#region ../spec/catalog.json
|
|
2
2
|
var catalog_default = {
|
|
3
3
|
$comment: "AG-UI conformance rule catalog. Data, not code: a Python/Go implementation shares these rules. Severities follow the working agreement that behaviour the spec does not clearly govern is at most 'info' — entries with 'specQuestion' were downgraded accordingly; see docs/spec-questions.md.",
|
|
4
4
|
catalogVersion: "0.1.0",
|
|
@@ -342,7 +342,7 @@ var catalog_default = {
|
|
|
342
342
|
"id": "AGUI503",
|
|
343
343
|
"severity": "error",
|
|
344
344
|
"title": "Unknown event type",
|
|
345
|
-
"messageTemplate": "Unknown event type '{type}' (not in
|
|
345
|
+
"messageTemplate": "Unknown event type '{type}' (not in the installed AG-UI SDK v{sdkVersion}, and not RAW or CUSTOM)",
|
|
346
346
|
"specUrl": "https://docs.ag-ui.com/concepts/events#event-types-overview",
|
|
347
347
|
"specQuote": "Events in the protocol are categorized by their purpose.",
|
|
348
348
|
"since": "0.x",
|
|
@@ -492,4 +492,4 @@ Object.defineProperty(exports, "validateCatalog", {
|
|
|
492
492
|
}
|
|
493
493
|
});
|
|
494
494
|
|
|
495
|
-
//# sourceMappingURL=catalog-
|
|
495
|
+
//# sourceMappingURL=catalog-AB5vuZ8j.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-AB5vuZ8j.cjs","names":["catalogJson"],"sources":["../spec/catalog.json","../js/src/rules/catalog.ts"],"sourcesContent":["","// Typed loader for the rule catalog. The catalog itself is data\n// (catalog.json) so other implementations can share it; this module gives it\n// types and validates its invariants once at load time.\n//\n// Note the asymmetry: the validator never throws on stream input, but a\n// malformed catalog is a programming error in this package, so the loader\n// throws loudly at import time.\n\nimport catalogJson from \"../../../spec/catalog.json\"\n\nexport type Severity = \"error\" | \"warning\" | \"info\"\nexport type SeverityOrOff = Severity | \"off\"\n\nconst SEVERITIES: readonly string[] = [\"error\", \"warning\", \"info\"]\nconst LAYERS: readonly string[] = [\"core\", \"transport\"]\n\nexport interface RuleDefinition {\n /** e.g. \"AGUI203\" */\n id: string\n severity: Severity\n title: string\n /** Human template with {placeholder} slots filled per diagnostic. */\n messageTemplate: string\n /** Governing spec section. Mandatory: rules that cannot cite one don't ship. */\n specUrl: string\n /** Exact sentence from the spec section, where one exists. */\n specQuote?: string\n since: string\n /** Canonical AG-UI feature this rule relates to, if any. */\n feature?: string\n /** True when the rule only fires if opts.features declares `feature`. */\n requiresFeature?: boolean\n /** Cross-reference into docs/spec-questions.md for downgraded/ambiguous rules. */\n specQuestion?: string\n /** Where the rule is evaluated. Transport rules are skipped (and the skip\n * reported) when validating recorded input with no transport in play. */\n checkedIn: \"core\" | \"transport\"\n}\n\nexport interface Catalog {\n catalogVersion: string\n spec: string\n rules: readonly RuleDefinition[]\n}\n\n/** Validates catalog data and returns it typed. Throws on structural problems. */\nexport function validateCatalog(data: unknown): Catalog {\n const problems: string[] = []\n const cat = data as Catalog\n if (typeof cat !== \"object\" || cat === null || !Array.isArray(cat.rules)) {\n throw new Error(\"rule catalog: expected an object with a rules array\")\n }\n const seen = new Set<string>()\n for (const rule of cat.rules) {\n const where = rule?.id ?? \"<missing id>\"\n if (!/^AGUI\\d{3}$/.test(rule.id ?? \"\")) problems.push(`${where}: id must match AGUI###`)\n if (seen.has(rule.id)) problems.push(`${where}: duplicate id`)\n seen.add(rule.id)\n if (!SEVERITIES.includes(rule.severity)) problems.push(`${where}: bad severity '${rule.severity}'`)\n if (!rule.title) problems.push(`${where}: missing title`)\n if (!rule.messageTemplate) problems.push(`${where}: missing messageTemplate`)\n if (!rule.specUrl?.startsWith(\"https://\")) problems.push(`${where}: specUrl must be an https URL`)\n if (!rule.since) problems.push(`${where}: missing since`)\n if (!LAYERS.includes(rule.checkedIn)) problems.push(`${where}: bad checkedIn '${rule.checkedIn}'`)\n if (rule.requiresFeature && !rule.feature) problems.push(`${where}: requiresFeature without feature`)\n }\n if (problems.length > 0) {\n throw new Error(`rule catalog is invalid:\\n ${problems.join(\"\\n \")}`)\n }\n return cat\n}\n\nexport const CATALOG: Catalog = validateCatalog(catalogJson)\n\nexport const RULES: ReadonlyMap<string, RuleDefinition> = new Map(\n CATALOG.rules.map((r) => [r.id, r]),\n)\n\n/** Fills a rule's messageTemplate. Unknown placeholders are left intact. */\nexport function formatMessage(rule: RuleDefinition, params: Record<string, unknown>): string {\n return rule.messageTemplate.replace(/\\{(\\w+)\\}/g, (whole, key: string) =>\n key in params ? String(params[key]) : whole,\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACaA,MAAM,aAAgC;CAAC;CAAS;CAAW;AAAM;AACjE,MAAM,SAA4B,CAAC,QAAQ,WAAW;;AAgCtD,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,WAAqB,CAAC;CAC5B,MAAM,MAAM;CACZ,IAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,IAAI,KAAK,GACrE,MAAM,IAAI,MAAM,qDAAqD;CAEvE,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,QAAQ,IAAI,OAAO;EAC5B,MAAM,QAAQ,MAAM,MAAM;EAC1B,IAAI,CAAC,cAAc,KAAK,KAAK,MAAM,EAAE,GAAG,SAAS,KAAK,GAAG,MAAM,wBAAwB;EACvF,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,SAAS,KAAK,GAAG,MAAM,eAAe;EAC7D,KAAK,IAAI,KAAK,EAAE;EAChB,IAAI,CAAC,WAAW,SAAS,KAAK,QAAQ,GAAG,SAAS,KAAK,GAAG,MAAM,kBAAkB,KAAK,SAAS,EAAE;EAClG,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,GAAG,MAAM,gBAAgB;EACxD,IAAI,CAAC,KAAK,iBAAiB,SAAS,KAAK,GAAG,MAAM,0BAA0B;EAC5E,IAAI,CAAC,KAAK,SAAS,WAAW,UAAU,GAAG,SAAS,KAAK,GAAG,MAAM,+BAA+B;EACjG,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,GAAG,MAAM,gBAAgB;EACxD,IAAI,CAAC,OAAO,SAAS,KAAK,SAAS,GAAG,SAAS,KAAK,GAAG,MAAM,mBAAmB,KAAK,UAAU,EAAE;EACjG,IAAI,KAAK,mBAAmB,CAAC,KAAK,SAAS,SAAS,KAAK,GAAG,MAAM,kCAAkC;CACtG;CACA,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,MAAM,+BAA+B,SAAS,KAAK,MAAM,GAAG;CAExE,OAAO;AACT;AAEA,MAAa,UAAmB,gBAAgBA,eAAW;AAE3D,MAAa,QAA6C,IAAI,IAC5D,QAAQ,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CACpC;;AAGA,SAAgB,cAAc,MAAsB,QAAyC;CAC3F,OAAO,KAAK,gBAAgB,QAAQ,eAAe,OAAO,QACxD,OAAO,SAAS,OAAO,OAAO,IAAI,IAAI,KACxC;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region
|
|
1
|
+
//#region ../spec/catalog.json
|
|
2
2
|
var catalog_default = {
|
|
3
3
|
$comment: "AG-UI conformance rule catalog. Data, not code: a Python/Go implementation shares these rules. Severities follow the working agreement that behaviour the spec does not clearly govern is at most 'info' — entries with 'specQuestion' were downgraded accordingly; see docs/spec-questions.md.",
|
|
4
4
|
catalogVersion: "0.1.0",
|
|
@@ -342,7 +342,7 @@ var catalog_default = {
|
|
|
342
342
|
"id": "AGUI503",
|
|
343
343
|
"severity": "error",
|
|
344
344
|
"title": "Unknown event type",
|
|
345
|
-
"messageTemplate": "Unknown event type '{type}' (not in
|
|
345
|
+
"messageTemplate": "Unknown event type '{type}' (not in the installed AG-UI SDK v{sdkVersion}, and not RAW or CUSTOM)",
|
|
346
346
|
"specUrl": "https://docs.ag-ui.com/concepts/events#event-types-overview",
|
|
347
347
|
"specQuote": "Events in the protocol are categorized by their purpose.",
|
|
348
348
|
"since": "0.x",
|
|
@@ -469,4 +469,4 @@ function formatMessage(rule, params) {
|
|
|
469
469
|
//#endregion
|
|
470
470
|
export { validateCatalog as i, RULES as n, formatMessage as r, CATALOG as t };
|
|
471
471
|
|
|
472
|
-
//# sourceMappingURL=catalog-
|
|
472
|
+
//# sourceMappingURL=catalog-DqTI4VLt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-DqTI4VLt.js","names":["catalogJson"],"sources":["../spec/catalog.json","../js/src/rules/catalog.ts"],"sourcesContent":["","// Typed loader for the rule catalog. The catalog itself is data\n// (catalog.json) so other implementations can share it; this module gives it\n// types and validates its invariants once at load time.\n//\n// Note the asymmetry: the validator never throws on stream input, but a\n// malformed catalog is a programming error in this package, so the loader\n// throws loudly at import time.\n\nimport catalogJson from \"../../../spec/catalog.json\"\n\nexport type Severity = \"error\" | \"warning\" | \"info\"\nexport type SeverityOrOff = Severity | \"off\"\n\nconst SEVERITIES: readonly string[] = [\"error\", \"warning\", \"info\"]\nconst LAYERS: readonly string[] = [\"core\", \"transport\"]\n\nexport interface RuleDefinition {\n /** e.g. \"AGUI203\" */\n id: string\n severity: Severity\n title: string\n /** Human template with {placeholder} slots filled per diagnostic. */\n messageTemplate: string\n /** Governing spec section. Mandatory: rules that cannot cite one don't ship. */\n specUrl: string\n /** Exact sentence from the spec section, where one exists. */\n specQuote?: string\n since: string\n /** Canonical AG-UI feature this rule relates to, if any. */\n feature?: string\n /** True when the rule only fires if opts.features declares `feature`. */\n requiresFeature?: boolean\n /** Cross-reference into docs/spec-questions.md for downgraded/ambiguous rules. */\n specQuestion?: string\n /** Where the rule is evaluated. Transport rules are skipped (and the skip\n * reported) when validating recorded input with no transport in play. */\n checkedIn: \"core\" | \"transport\"\n}\n\nexport interface Catalog {\n catalogVersion: string\n spec: string\n rules: readonly RuleDefinition[]\n}\n\n/** Validates catalog data and returns it typed. Throws on structural problems. */\nexport function validateCatalog(data: unknown): Catalog {\n const problems: string[] = []\n const cat = data as Catalog\n if (typeof cat !== \"object\" || cat === null || !Array.isArray(cat.rules)) {\n throw new Error(\"rule catalog: expected an object with a rules array\")\n }\n const seen = new Set<string>()\n for (const rule of cat.rules) {\n const where = rule?.id ?? \"<missing id>\"\n if (!/^AGUI\\d{3}$/.test(rule.id ?? \"\")) problems.push(`${where}: id must match AGUI###`)\n if (seen.has(rule.id)) problems.push(`${where}: duplicate id`)\n seen.add(rule.id)\n if (!SEVERITIES.includes(rule.severity)) problems.push(`${where}: bad severity '${rule.severity}'`)\n if (!rule.title) problems.push(`${where}: missing title`)\n if (!rule.messageTemplate) problems.push(`${where}: missing messageTemplate`)\n if (!rule.specUrl?.startsWith(\"https://\")) problems.push(`${where}: specUrl must be an https URL`)\n if (!rule.since) problems.push(`${where}: missing since`)\n if (!LAYERS.includes(rule.checkedIn)) problems.push(`${where}: bad checkedIn '${rule.checkedIn}'`)\n if (rule.requiresFeature && !rule.feature) problems.push(`${where}: requiresFeature without feature`)\n }\n if (problems.length > 0) {\n throw new Error(`rule catalog is invalid:\\n ${problems.join(\"\\n \")}`)\n }\n return cat\n}\n\nexport const CATALOG: Catalog = validateCatalog(catalogJson)\n\nexport const RULES: ReadonlyMap<string, RuleDefinition> = new Map(\n CATALOG.rules.map((r) => [r.id, r]),\n)\n\n/** Fills a rule's messageTemplate. Unknown placeholders are left intact. */\nexport function formatMessage(rule: RuleDefinition, params: Record<string, unknown>): string {\n return rule.messageTemplate.replace(/\\{(\\w+)\\}/g, (whole, key: string) =>\n key in params ? String(params[key]) : whole,\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACaA,MAAM,aAAgC;CAAC;CAAS;CAAW;AAAM;AACjE,MAAM,SAA4B,CAAC,QAAQ,WAAW;;AAgCtD,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,WAAqB,CAAC;CAC5B,MAAM,MAAM;CACZ,IAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,IAAI,KAAK,GACrE,MAAM,IAAI,MAAM,qDAAqD;CAEvE,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,QAAQ,IAAI,OAAO;EAC5B,MAAM,QAAQ,MAAM,MAAM;EAC1B,IAAI,CAAC,cAAc,KAAK,KAAK,MAAM,EAAE,GAAG,SAAS,KAAK,GAAG,MAAM,wBAAwB;EACvF,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,SAAS,KAAK,GAAG,MAAM,eAAe;EAC7D,KAAK,IAAI,KAAK,EAAE;EAChB,IAAI,CAAC,WAAW,SAAS,KAAK,QAAQ,GAAG,SAAS,KAAK,GAAG,MAAM,kBAAkB,KAAK,SAAS,EAAE;EAClG,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,GAAG,MAAM,gBAAgB;EACxD,IAAI,CAAC,KAAK,iBAAiB,SAAS,KAAK,GAAG,MAAM,0BAA0B;EAC5E,IAAI,CAAC,KAAK,SAAS,WAAW,UAAU,GAAG,SAAS,KAAK,GAAG,MAAM,+BAA+B;EACjG,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,GAAG,MAAM,gBAAgB;EACxD,IAAI,CAAC,OAAO,SAAS,KAAK,SAAS,GAAG,SAAS,KAAK,GAAG,MAAM,mBAAmB,KAAK,UAAU,EAAE;EACjG,IAAI,KAAK,mBAAmB,CAAC,KAAK,SAAS,SAAS,KAAK,GAAG,MAAM,kCAAkC;CACtG;CACA,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,MAAM,+BAA+B,SAAS,KAAK,MAAM,GAAG;CAExE,OAAO;AACT;AAEA,MAAa,UAAmB,gBAAgBA,eAAW;AAE3D,MAAa,QAA6C,IAAI,IAC5D,QAAQ,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CACpC;;AAGA,SAAgB,cAAc,MAAsB,QAAyC;CAC3F,OAAO,KAAK,gBAAgB,QAAQ,eAAe,OAAO,QACxD,OAAO,SAAS,OAAO,OAAO,IAAI,IAAI,KACxC;AACF"}
|
package/dist/cli.js
CHANGED
|
@@ -212,7 +212,7 @@ function decideExitCode(summary, maxWarnings) {
|
|
|
212
212
|
return 0;
|
|
213
213
|
}
|
|
214
214
|
//#endregion
|
|
215
|
-
//#region
|
|
215
|
+
//#region ../spec/catalog.json
|
|
216
216
|
var catalog_default = {
|
|
217
217
|
$comment: "AG-UI conformance rule catalog. Data, not code: a Python/Go implementation shares these rules. Severities follow the working agreement that behaviour the spec does not clearly govern is at most 'info' — entries with 'specQuestion' were downgraded accordingly; see docs/spec-questions.md.",
|
|
218
218
|
catalogVersion: "0.1.0",
|
|
@@ -556,7 +556,7 @@ var catalog_default = {
|
|
|
556
556
|
"id": "AGUI503",
|
|
557
557
|
"severity": "error",
|
|
558
558
|
"title": "Unknown event type",
|
|
559
|
-
"messageTemplate": "Unknown event type '{type}' (not in
|
|
559
|
+
"messageTemplate": "Unknown event type '{type}' (not in the installed AG-UI SDK v{sdkVersion}, and not RAW or CUSTOM)",
|
|
560
560
|
"specUrl": "https://docs.ag-ui.com/concepts/events#event-types-overview",
|
|
561
561
|
"specQuote": "Events in the protocol are categorized by their purpose.",
|
|
562
562
|
"since": "0.x",
|