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.
Files changed (144) hide show
  1. package/README.md +70 -10
  2. package/dist/{catalog-Ci9dqc1a.cjs → catalog-AB5vuZ8j.cjs} +3 -3
  3. package/dist/catalog-AB5vuZ8j.cjs.map +1 -0
  4. package/dist/{catalog-BglXBNbL.js → catalog-DqTI4VLt.js} +3 -3
  5. package/dist/catalog-DqTI4VLt.js.map +1 -0
  6. package/dist/cli.js +2 -2
  7. package/dist/cli.js.map +1 -1
  8. package/dist/index.cjs +2 -2
  9. package/dist/index.js +2 -2
  10. package/dist/report.cjs +1 -1
  11. package/dist/report.cjs.map +1 -1
  12. package/dist/report.js +1 -1
  13. package/dist/report.js.map +1 -1
  14. package/dist/{src-HmI-kxef.cjs → src-D04i3Vso.cjs} +2 -2
  15. package/dist/src-D04i3Vso.cjs.map +1 -0
  16. package/dist/{src-rGZ2G4qA.js → src-Dcuqz2QC.js} +2 -2
  17. package/dist/src-Dcuqz2QC.js.map +1 -0
  18. package/dist/transport.cjs +1 -1
  19. package/dist/transport.cjs.map +1 -1
  20. package/dist/transport.js +1 -1
  21. package/dist/transport.js.map +1 -1
  22. package/dist/vitest.js +2 -2
  23. package/dist/vitest.js.map +1 -1
  24. package/{src → js/src}/rules/catalog.ts +1 -1
  25. package/{src → js/src}/transport/index.ts +1 -1
  26. package/package.json +14 -13
  27. package/{src/rules → spec}/catalog.json +1 -1
  28. package/spec/event-categories.json +56 -0
  29. package/spec/fixtures/README.md +91 -0
  30. package/spec/fixtures/invalid/AGUI001-first-event-not-run-started/expected.json +10 -0
  31. package/spec/fixtures/invalid/AGUI001-first-event-not-run-started/stream.jsonl +4 -0
  32. package/spec/fixtures/invalid/AGUI002-duplicate-run-started/expected.json +11 -0
  33. package/spec/fixtures/invalid/AGUI002-duplicate-run-started/stream.jsonl +3 -0
  34. package/spec/fixtures/invalid/AGUI003-run-never-terminated/expected.json +10 -0
  35. package/spec/fixtures/invalid/AGUI003-run-never-terminated/stream.jsonl +4 -0
  36. package/spec/fixtures/invalid/AGUI004-event-after-terminal/expected.json +11 -0
  37. package/spec/fixtures/invalid/AGUI004-event-after-terminal/stream.jsonl +3 -0
  38. package/spec/fixtures/invalid/AGUI005-finished-and-error/expected.json +11 -0
  39. package/spec/fixtures/invalid/AGUI005-finished-and-error/stream.jsonl +3 -0
  40. package/spec/fixtures/invalid/AGUI006-step-finished-unmatched/expected.json +11 -0
  41. package/spec/fixtures/invalid/AGUI006-step-finished-unmatched/stream.jsonl +3 -0
  42. package/spec/fixtures/invalid/AGUI007-step-unterminated/expected.json +10 -0
  43. package/spec/fixtures/invalid/AGUI007-step-unterminated/stream.jsonl +3 -0
  44. package/spec/fixtures/invalid/AGUI008-unstable-run-ids/expected.json +12 -0
  45. package/spec/fixtures/invalid/AGUI008-unstable-run-ids/stream.jsonl +2 -0
  46. package/spec/fixtures/invalid/AGUI101-content-without-start/expected.json +11 -0
  47. package/spec/fixtures/invalid/AGUI101-content-without-start/stream.jsonl +3 -0
  48. package/spec/fixtures/invalid/AGUI102-end-without-start/expected.json +11 -0
  49. package/spec/fixtures/invalid/AGUI102-end-without-start/stream.jsonl +3 -0
  50. package/spec/fixtures/invalid/AGUI103-message-unterminated/expected.json +10 -0
  51. package/spec/fixtures/invalid/AGUI103-message-unterminated/stream.jsonl +4 -0
  52. package/spec/fixtures/invalid/AGUI104-duplicate-message-id/expected.json +12 -0
  53. package/spec/fixtures/invalid/AGUI104-duplicate-message-id/stream.jsonl +6 -0
  54. package/spec/fixtures/invalid/AGUI105-empty-content-delta/expected.json +12 -0
  55. package/spec/fixtures/invalid/AGUI105-empty-content-delta/stream.jsonl +5 -0
  56. package/spec/fixtures/invalid/AGUI106-interleaved-same-message-id/expected.json +12 -0
  57. package/spec/fixtures/invalid/AGUI106-interleaved-same-message-id/stream.jsonl +5 -0
  58. package/spec/fixtures/invalid/AGUI201-args-without-start/expected.json +11 -0
  59. package/spec/fixtures/invalid/AGUI201-args-without-start/stream.jsonl +3 -0
  60. package/spec/fixtures/invalid/AGUI202-end-without-start/expected.json +11 -0
  61. package/spec/fixtures/invalid/AGUI202-end-without-start/stream.jsonl +3 -0
  62. package/spec/fixtures/invalid/AGUI203-unterminated-tool-call/expected.json +10 -0
  63. package/spec/fixtures/invalid/AGUI203-unterminated-tool-call/stream.jsonl +4 -0
  64. package/spec/fixtures/invalid/AGUI204-args-not-json/expected.json +10 -0
  65. package/spec/fixtures/invalid/AGUI204-args-not-json/stream.jsonl +6 -0
  66. package/spec/fixtures/invalid/AGUI205-duplicate-tool-call-id/expected.json +12 -0
  67. package/spec/fixtures/invalid/AGUI205-duplicate-tool-call-id/stream.jsonl +5 -0
  68. package/spec/fixtures/invalid/AGUI206-result-before-end/expected.json +12 -0
  69. package/spec/fixtures/invalid/AGUI206-result-before-end/stream.jsonl +5 -0
  70. package/spec/fixtures/invalid/AGUI207-result-unknown-id/expected.json +11 -0
  71. package/spec/fixtures/invalid/AGUI207-result-unknown-id/stream.jsonl +3 -0
  72. package/spec/fixtures/invalid/AGUI208-unknown-parent-message-id/expected.json +11 -0
  73. package/spec/fixtures/invalid/AGUI208-unknown-parent-message-id/stream.jsonl +4 -0
  74. package/spec/fixtures/invalid/AGUI301-delta-before-snapshot/expected.json +10 -0
  75. package/spec/fixtures/invalid/AGUI301-delta-before-snapshot/stream.jsonl +3 -0
  76. package/spec/fixtures/invalid/AGUI302-delta-failed-to-apply/expected.json +11 -0
  77. package/spec/fixtures/invalid/AGUI302-delta-failed-to-apply/stream.jsonl +4 -0
  78. package/spec/fixtures/invalid/AGUI303-invalid-patch-document/expected.json +11 -0
  79. package/spec/fixtures/invalid/AGUI303-invalid-patch-document/stream.jsonl +4 -0
  80. package/spec/fixtures/invalid/AGUI304-midrun-snapshot-discards-deltas/expected.json +10 -0
  81. package/spec/fixtures/invalid/AGUI304-midrun-snapshot-discards-deltas/stream.jsonl +5 -0
  82. package/spec/fixtures/invalid/AGUI305-shared-state-never-established/expected.json +9 -0
  83. package/spec/fixtures/invalid/AGUI305-shared-state-never-established/options.json +5 -0
  84. package/spec/fixtures/invalid/AGUI305-shared-state-never-established/stream.jsonl +5 -0
  85. package/spec/fixtures/invalid/AGUI401-reasoning-content-without-start/expected.json +11 -0
  86. package/spec/fixtures/invalid/AGUI401-reasoning-content-without-start/stream.jsonl +3 -0
  87. package/spec/fixtures/invalid/AGUI402-reasoning-unterminated/expected.json +10 -0
  88. package/spec/fixtures/invalid/AGUI402-reasoning-unterminated/stream.jsonl +3 -0
  89. package/spec/fixtures/invalid/AGUI501-missing-data-prefix/expected.json +9 -0
  90. package/spec/fixtures/invalid/AGUI501-missing-data-prefix/scenario.json +17 -0
  91. package/spec/fixtures/invalid/AGUI502-payload-not-json/expected.json +10 -0
  92. package/spec/fixtures/invalid/AGUI502-payload-not-json/stream.jsonl +3 -0
  93. package/spec/fixtures/invalid/AGUI503-unknown-event-type/expected.json +10 -0
  94. package/spec/fixtures/invalid/AGUI503-unknown-event-type/stream.jsonl +3 -0
  95. package/spec/fixtures/invalid/AGUI504-schema-violation/expected.json +11 -0
  96. package/spec/fixtures/invalid/AGUI504-schema-violation/stream.jsonl +4 -0
  97. package/spec/fixtures/invalid/AGUI505-unexpected-content-type/expected.json +9 -0
  98. package/spec/fixtures/invalid/AGUI505-unexpected-content-type/scenario.json +25 -0
  99. package/spec/fixtures/invalid/AGUI506-keepalive-gap/expected.json +9 -0
  100. package/spec/fixtures/invalid/AGUI506-keepalive-gap/scenario.json +25 -0
  101. package/spec/fixtures/invalid/AGUI507-buffered-response/expected.json +9 -0
  102. package/spec/fixtures/invalid/AGUI507-buffered-response/scenario.json +9 -0
  103. package/spec/fixtures/invalid/AGUI508-connection-dropped/expected.json +17 -0
  104. package/spec/fixtures/invalid/AGUI508-connection-dropped/scenario.json +10 -0
  105. package/spec/fixtures/invalid/AGUI901-raw-wraps-typed-event/expected.json +11 -0
  106. package/spec/fixtures/invalid/AGUI901-raw-wraps-typed-event/stream.jsonl +3 -0
  107. package/spec/fixtures/invalid/AGUI902-no-timestamps/expected.json +9 -0
  108. package/spec/fixtures/invalid/AGUI902-no-timestamps/stream.jsonl +2 -0
  109. package/spec/fixtures/invalid/AGUI903-custom-name-not-namespaced/expected.json +11 -0
  110. package/spec/fixtures/invalid/AGUI903-custom-name-not-namespaced/stream.jsonl +3 -0
  111. package/spec/fixtures/valid/agentic-chat.jsonl +14 -0
  112. package/spec/fixtures/valid/agentic-generative-ui.jsonl +13 -0
  113. package/spec/fixtures/valid/backend-tool-rendering.jsonl +14 -0
  114. package/spec/fixtures/valid/human-in-the-loop.jsonl +13 -0
  115. package/spec/fixtures/valid/predictive-state-updates.expected.json +11 -0
  116. package/spec/fixtures/valid/predictive-state-updates.jsonl +11 -0
  117. package/spec/fixtures/valid/shared-state.jsonl +8 -0
  118. package/spec/fixtures/valid/tool-based-generative-ui.jsonl +5 -0
  119. package/dist/catalog-BglXBNbL.js.map +0 -1
  120. package/dist/catalog-Ci9dqc1a.cjs.map +0 -1
  121. package/dist/src-HmI-kxef.cjs.map +0 -1
  122. package/dist/src-rGZ2G4qA.js.map +0 -1
  123. /package/{src → js/src}/cli-args.ts +0 -0
  124. /package/{src → js/src}/cli.ts +0 -0
  125. /package/{src → js/src}/index.ts +0 -0
  126. /package/{src → js/src}/protocol/event-table.ts +0 -0
  127. /package/{src → js/src}/protocol/jsonpatch.ts +0 -0
  128. /package/{src → js/src}/report/index.ts +0 -0
  129. /package/{src → js/src}/report/json.ts +0 -0
  130. /package/{src → js/src}/report/junit.ts +0 -0
  131. /package/{src → js/src}/report/pretty.ts +0 -0
  132. /package/{src → js/src}/report/sarif.ts +0 -0
  133. /package/{src → js/src}/rules/checks/context.ts +0 -0
  134. /package/{src → js/src}/rules/checks/lifecycle.ts +0 -0
  135. /package/{src → js/src}/rules/checks/reasoning.ts +0 -0
  136. /package/{src → js/src}/rules/checks/state.ts +0 -0
  137. /package/{src → js/src}/rules/checks/text.ts +0 -0
  138. /package/{src → js/src}/rules/checks/toolcalls.ts +0 -0
  139. /package/{src → js/src}/rules/checks/transport.ts +0 -0
  140. /package/{src → js/src}/transport/ndjson.ts +0 -0
  141. /package/{src → js/src}/transport/sse.ts +0 -0
  142. /package/{src → js/src}/types.ts +0 -0
  143. /package/{src → js/src}/vitest/index.ts +0 -0
  144. /package/{src → js/src}/vitest/matcher.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  // ag-ui-validate/transport: SSE + NDJSON clients over the pure core.
2
2
  // This is the I/O layer — fetch, streams, and clocks live here, never in the
3
3
  // core. Uses only web-platform APIs (fetch, TextDecoder, AbortController) so
4
- // it stays isomorphic: Node 20+, browsers, Deno, Workers.
4
+ // it stays isomorphic: Node 22+, browsers, Deno, Workers.
5
5
 
6
6
  import { createValidator } from "../index.js"
7
7
  import type { Diagnostic, Report, ValidationLayer, ValidatorOptions } from "../index.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ag-ui-validate",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Conformance validator for the AG-UI protocol. Feed it an event stream, get every violation with a rule ID, a severity, and a link to the governing spec section.",
5
5
  "keywords": [
6
6
  "ag-ui",
@@ -23,10 +23,10 @@
23
23
  "type": "module",
24
24
  "sideEffects": [
25
25
  "./dist/vitest.js",
26
- "./src/vitest/index.ts"
26
+ "./js/src/vitest/index.ts"
27
27
  ],
28
28
  "engines": {
29
- "node": ">=20"
29
+ "node": ">=22"
30
30
  },
31
31
  "bin": {
32
32
  "ag-ui-validate": "./dist/cli.js"
@@ -88,20 +88,21 @@
88
88
  },
89
89
  "files": [
90
90
  "dist",
91
- "src"
91
+ "js/src",
92
+ "spec"
92
93
  ],
93
94
  "scripts": {
94
- "build": "tsdown",
95
- "typecheck": "tsc --noEmit -p tsconfig.src.json && tsc --noEmit",
96
- "test": "vitest run",
97
- "test:watch": "vitest",
98
- "fixtures:build": "npm run build && node scripts/build-fixtures.mjs",
99
- "protocol:derive": "node scripts/generate-event-table.mjs",
95
+ "build": "tsdown --config js/tsdown.config.mjs",
96
+ "typecheck": "tsc --noEmit -p js/tsconfig.src.json && tsc --noEmit -p js/tsconfig.json",
97
+ "test": "vitest run --config js/vitest.config.ts",
98
+ "test:watch": "vitest --config js/vitest.config.ts",
99
+ "fixtures:build": "npm run build && node js/scripts/build-fixtures.mjs",
100
+ "protocol:derive": "node js/scripts/generate-event-table.mjs",
100
101
  "docs:generate": "node scripts/generate-rule-docs.mjs",
101
102
  "docs:check": "node scripts/generate-rule-docs.mjs --check",
102
- "demo": "node scripts/demo.mjs",
103
- "fuzz": "node scripts/fuzz.mjs",
104
- "e2e": "node scripts/e2e-live-server.mjs",
103
+ "demo": "node js/scripts/demo.mjs",
104
+ "fuzz": "node js/scripts/fuzz.mjs",
105
+ "e2e": "node js/scripts/e2e-live-server.mjs",
105
106
  "links:check": "node scripts/check-spec-links.mjs",
106
107
  "changeset": "changeset",
107
108
  "version": "changeset version",
@@ -341,7 +341,7 @@
341
341
  "id": "AGUI503",
342
342
  "severity": "error",
343
343
  "title": "Unknown event type",
344
- "messageTemplate": "Unknown event type '{type}' (not in @ag-ui/core v{sdkVersion}, and not RAW or CUSTOM)",
344
+ "messageTemplate": "Unknown event type '{type}' (not in the installed AG-UI SDK v{sdkVersion}, and not RAW or CUSTOM)",
345
345
  "specUrl": "https://docs.ag-ui.com/concepts/events#event-types-overview",
346
346
  "specQuote": "Events in the protocol are categorized by their purpose.",
347
347
  "since": "0.x",
@@ -0,0 +1,56 @@
1
+ {
2
+ "$comment": "Wire-type -> category/deprecation data for the canonical event table. Hand-maintained (not derivable from the SDK schemas themselves); shared by every language's event-table derivation tool so this classification is written once. Categories are display/grouping metadata only, not conformance rules — those live in catalog.json.",
3
+ "categories": [
4
+ "lifecycle",
5
+ "text",
6
+ "toolcall",
7
+ "state",
8
+ "activity",
9
+ "reasoning",
10
+ "thinking",
11
+ "special"
12
+ ],
13
+ "eventCategory": {
14
+ "RUN_STARTED": "lifecycle",
15
+ "RUN_FINISHED": "lifecycle",
16
+ "RUN_ERROR": "lifecycle",
17
+ "STEP_STARTED": "lifecycle",
18
+ "STEP_FINISHED": "lifecycle",
19
+ "TEXT_MESSAGE_START": "text",
20
+ "TEXT_MESSAGE_CONTENT": "text",
21
+ "TEXT_MESSAGE_END": "text",
22
+ "TEXT_MESSAGE_CHUNK": "text",
23
+ "TOOL_CALL_START": "toolcall",
24
+ "TOOL_CALL_ARGS": "toolcall",
25
+ "TOOL_CALL_END": "toolcall",
26
+ "TOOL_CALL_CHUNK": "toolcall",
27
+ "TOOL_CALL_RESULT": "toolcall",
28
+ "STATE_SNAPSHOT": "state",
29
+ "STATE_DELTA": "state",
30
+ "MESSAGES_SNAPSHOT": "state",
31
+ "ACTIVITY_SNAPSHOT": "activity",
32
+ "ACTIVITY_DELTA": "activity",
33
+ "REASONING_START": "reasoning",
34
+ "REASONING_MESSAGE_START": "reasoning",
35
+ "REASONING_MESSAGE_CONTENT": "reasoning",
36
+ "REASONING_MESSAGE_END": "reasoning",
37
+ "REASONING_MESSAGE_CHUNK": "reasoning",
38
+ "REASONING_END": "reasoning",
39
+ "REASONING_ENCRYPTED_VALUE": "reasoning",
40
+ "THINKING_START": "thinking",
41
+ "THINKING_END": "thinking",
42
+ "THINKING_TEXT_MESSAGE_START": "thinking",
43
+ "THINKING_TEXT_MESSAGE_CONTENT": "thinking",
44
+ "THINKING_TEXT_MESSAGE_END": "thinking",
45
+ "RAW": "special",
46
+ "CUSTOM": "special"
47
+ },
48
+ "$deprecatedComment": "@deprecated markers in @ag-ui/core's type definitions, 'Will be removed in 1.0.0'. Maps a deprecated wire type to its replacement.",
49
+ "deprecated": {
50
+ "THINKING_START": "REASONING_START",
51
+ "THINKING_END": "REASONING_END",
52
+ "THINKING_TEXT_MESSAGE_START": "REASONING_MESSAGE_START",
53
+ "THINKING_TEXT_MESSAGE_CONTENT": "REASONING_MESSAGE_CONTENT",
54
+ "THINKING_TEXT_MESSAGE_END": "REASONING_MESSAGE_END"
55
+ }
56
+ }
@@ -0,0 +1,91 @@
1
+ # AG-UI conformance fixture corpus
2
+
3
+ A language-neutral corpus for testing AG-UI protocol validators. Any
4
+ implementation — TypeScript, Python, Go — that consumes the shared rule
5
+ catalog ([`catalog.json`](../catalog.json)) can be tested
6
+ against these files. The corpus, not per-rule test code, is the suite: adding
7
+ a rule to the catalog means adding a fixture directory here.
8
+
9
+ ## Layout
10
+
11
+ ```
12
+ fixtures/
13
+ ├── valid/ one stream per canonical AG-UI feature
14
+ │ ├── agentic-chat.jsonl
15
+ │ ├── agentic-chat.expected.json (optional; assumed [] when absent)
16
+ │ └── …
17
+ └── invalid/ one directory per rule
18
+ ├── AGUI203-unterminated-tool-call/
19
+ │ ├── stream.jsonl the event stream
20
+ │ ├── expected.json the exact expected Diagnostic[]
21
+ │ └── options.json (optional) validator options for this run
22
+ └── AGUI506-keepalive-gap/ transport rules use a scenario instead
23
+ ├── scenario.json an HTTP response body as timed byte chunks
24
+ └── expected.json
25
+ ```
26
+
27
+ ## Running the corpus against an implementation
28
+
29
+ For every event-stream fixture (`stream.jsonl`):
30
+
31
+ 1. Read the `.jsonl` file and split it into lines; drop empty lines.
32
+ 2. Feed each remaining line to the validator **as a raw string** — do not
33
+ pre-parse. Malformed lines are intentional (they exercise AGUI502); a
34
+ conforming validator treats them as diagnostics, never exceptions.
35
+ 3. If `options.json` exists, construct the validator with those options
36
+ (e.g. `{"features": ["shared-state"]}` for AGUI305).
37
+ 4. After the last line, finalize (end-of-stream checks).
38
+ 5. Deep-compare the accumulated diagnostics with `expected.json`. Order
39
+ matters: diagnostics are emitted in stream order, and end-of-stream
40
+ diagnostics use `eventIndex: -1`.
41
+
42
+ For every transport fixture (`scenario.json`) — these exercise the rules that
43
+ need a live connection (AGUI501, AGUI505–AGUI508):
44
+
45
+ 1. The scenario describes an HTTP response: `contentType` and `chunks`, each
46
+ chunk being `{ "gapMs": n, "text": "…" }` — the raw bytes as they arrived,
47
+ with `gapMs` of simulated silence before the chunk.
48
+ 2. Feed the chunk bytes through your transport layer (SSE or NDJSON per the
49
+ content type, sniffing when unknown) with a simulated clock that advances
50
+ by each `gapMs`; the keepalive window is the default 30 000 ms.
51
+ 3. `"abnormalEof": true` means the connection errored after the last chunk
52
+ (as opposed to closing cleanly) — the AGUI508 condition.
53
+ 4. Finalize and deep-compare diagnostics with `expected.json` as above.
54
+
55
+ Every `invalid/` fixture must fire its directory's namesake rule; every
56
+ `valid/` fixture must produce exactly its `*.expected.json` (usually nothing —
57
+ they are the false-positive guards). `valid/predictive-state-updates` expects
58
+ one `info` finding: the Dojo's real `PredictState` custom event name is
59
+ un-namespaced (AGUI903, see `docs/spec-questions.md` SQ-14).
60
+
61
+ ## Diagnostic shape
62
+
63
+ ```json
64
+ {
65
+ "rule": "AGUI203",
66
+ "severity": "error",
67
+ "message": "TOOL_CALL_START id 'call_7' never terminated",
68
+ "eventIndex": 3,
69
+ "eventType": "RUN_FINISHED",
70
+ "pointer": "/toolCallId",
71
+ "relatedEventIndex": 1,
72
+ "specUrl": "https://docs.ag-ui.com/concepts/events#tool-call-events"
73
+ }
74
+ ```
75
+
76
+ `eventType`, `pointer`, and `relatedEventIndex` are optional and omitted when
77
+ absent. Messages come from the catalog's `messageTemplate`s, so independent
78
+ implementations produce identical output.
79
+
80
+ ## Maintenance
81
+
82
+ Fixtures are generated by [`scripts/build-fixtures.mjs`](../../js/scripts/build-fixtures.mjs),
83
+ which declares each stream's *intended* rule hits independently of the
84
+ validator and refuses to write anything on mismatch — regeneration can never
85
+ silently bake an implementation bug into `expected.json`.
86
+
87
+ ## Not yet covered
88
+
89
+ - **`valid/real-world/`** — captures from real frameworks (LangGraph, CrewAI,
90
+ Pydantic AI, Agno, Langflow `stream_protocol=agui`). Contributions welcome;
91
+ sanitise credentials before submitting.
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI001",
4
+ "severity": "error",
5
+ "message": "First event of the run is TEXT_MESSAGE_START; expected RUN_STARTED",
6
+ "eventIndex": 0,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#runstarted",
8
+ "eventType": "TEXT_MESSAGE_START"
9
+ }
10
+ ]
@@ -0,0 +1,4 @@
1
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300007900}
2
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_001","delta":"Hello without a run.","timestamp":1755300008000}
3
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_001","timestamp":1755300008100}
4
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","timestamp":1755300008200}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI002",
4
+ "severity": "error",
5
+ "message": "Duplicate RUN_STARTED (runId 'run_002') before the active run terminated",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#lifecycle-events",
8
+ "eventType": "RUN_STARTED",
9
+ "relatedEventIndex": 0
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300008300}
2
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_002","timestamp":1755300008400}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300008500}
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI003",
4
+ "severity": "error",
5
+ "message": "Run 'run_001' ended without RUN_FINISHED or RUN_ERROR",
6
+ "eventIndex": -1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#runfinished",
8
+ "relatedEventIndex": 0
9
+ }
10
+ ]
@@ -0,0 +1,4 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300008600}
2
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300008700}
3
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_001","delta":"This run just stops.","timestamp":1755300008800}
4
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_001","timestamp":1755300008900}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI004",
4
+ "severity": "error",
5
+ "message": "TEXT_MESSAGE_START follows the run's terminal RUN_FINISHED",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#lifecycle-events",
8
+ "eventType": "TEXT_MESSAGE_START",
9
+ "relatedEventIndex": 1
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300009000}
2
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300009100}
3
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300009200}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI005",
4
+ "severity": "error",
5
+ "message": "RUN_ERROR emitted after the run already terminated with RUN_FINISHED",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#runfinished",
8
+ "eventType": "RUN_ERROR",
9
+ "relatedEventIndex": 1
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300009300}
2
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300009400}
3
+ {"type":"RUN_ERROR","message":"boom","timestamp":1755300009500}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI006",
4
+ "severity": "error",
5
+ "message": "STEP_FINISHED 'plan' has no open STEP_STARTED",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#stepfinished",
8
+ "eventType": "STEP_FINISHED",
9
+ "pointer": "/stepName"
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300009600}
2
+ {"type":"STEP_FINISHED","stepName":"plan","timestamp":1755300009700}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300009800}
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI007",
4
+ "severity": "error",
5
+ "message": "STEP_STARTED 'plan' never finished",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#stepstarted",
8
+ "relatedEventIndex": 1
9
+ }
10
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300009900}
2
+ {"type":"STEP_STARTED","stepName":"plan","timestamp":1755300010000}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300010100}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI008",
4
+ "severity": "warning",
5
+ "message": "RUN_FINISHED runId 'run_999' does not match RUN_STARTED runId 'run_001'",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#runstarted",
8
+ "eventType": "RUN_FINISHED",
9
+ "pointer": "/runId",
10
+ "relatedEventIndex": 0
11
+ }
12
+ ]
@@ -0,0 +1,2 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300010200}
2
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_999","outcome":{"type":"success"},"timestamp":1755300010300}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI101",
4
+ "severity": "error",
5
+ "message": "TEXT_MESSAGE_CONTENT for messageId 'msg_ghost' with no open TEXT_MESSAGE_START",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#text-message-events",
8
+ "eventType": "TEXT_MESSAGE_CONTENT",
9
+ "pointer": "/messageId"
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300010400}
2
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_ghost","delta":"orphan","timestamp":1755300010500}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300010600}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI102",
4
+ "severity": "error",
5
+ "message": "TEXT_MESSAGE_END for messageId 'msg_ghost' with no open TEXT_MESSAGE_START",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#textmessageend",
8
+ "eventType": "TEXT_MESSAGE_END",
9
+ "pointer": "/messageId"
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300010700}
2
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_ghost","timestamp":1755300010800}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300010900}
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI103",
4
+ "severity": "error",
5
+ "message": "TEXT_MESSAGE_START messageId 'msg_001' never ended",
6
+ "eventIndex": 3,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#text-message-events",
8
+ "relatedEventIndex": 1
9
+ }
10
+ ]
@@ -0,0 +1,4 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300011000}
2
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300011100}
3
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_001","delta":"never ends","timestamp":1755300011200}
4
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300011300}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI104",
4
+ "severity": "error",
5
+ "message": "messageId 'msg_001' was already used by a completed message",
6
+ "eventIndex": 4,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#textmessagestart",
8
+ "eventType": "TEXT_MESSAGE_START",
9
+ "pointer": "/messageId",
10
+ "relatedEventIndex": 3
11
+ }
12
+ ]
@@ -0,0 +1,6 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300011400}
2
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300011500}
3
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_001","delta":"first use","timestamp":1755300011600}
4
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_001","timestamp":1755300011700}
5
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300011800}
6
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300011900}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI105",
4
+ "severity": "warning",
5
+ "message": "TEXT_MESSAGE_CONTENT for messageId 'msg_001' has an empty delta",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#textmessagecontent",
8
+ "eventType": "TEXT_MESSAGE_CONTENT",
9
+ "pointer": "/delta",
10
+ "relatedEventIndex": 1
11
+ }
12
+ ]
@@ -0,0 +1,5 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300012000}
2
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300012100}
3
+ {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_001","delta":"","timestamp":1755300012200}
4
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_001","timestamp":1755300012300}
5
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300012400}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI106",
4
+ "severity": "error",
5
+ "message": "TEXT_MESSAGE_START for messageId 'msg_001', which is already open",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#implementation-considerations",
8
+ "eventType": "TEXT_MESSAGE_START",
9
+ "pointer": "/messageId",
10
+ "relatedEventIndex": 1
11
+ }
12
+ ]
@@ -0,0 +1,5 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300012500}
2
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300012600}
3
+ {"type":"TEXT_MESSAGE_START","messageId":"msg_001","role":"assistant","timestamp":1755300012700}
4
+ {"type":"TEXT_MESSAGE_END","messageId":"msg_001","timestamp":1755300012800}
5
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300012900}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI201",
4
+ "severity": "error",
5
+ "message": "TOOL_CALL_ARGS for toolCallId 'call_ghost' with no open TOOL_CALL_START",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#tool-call-events",
8
+ "eventType": "TOOL_CALL_ARGS",
9
+ "pointer": "/toolCallId"
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300013000}
2
+ {"type":"TOOL_CALL_ARGS","toolCallId":"call_ghost","delta":"{}","timestamp":1755300013100}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300013200}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI202",
4
+ "severity": "error",
5
+ "message": "TOOL_CALL_END for toolCallId 'call_ghost' with no open TOOL_CALL_START",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#toolcallend",
8
+ "eventType": "TOOL_CALL_END",
9
+ "pointer": "/toolCallId"
10
+ }
11
+ ]
@@ -0,0 +1,3 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300013300}
2
+ {"type":"TOOL_CALL_END","toolCallId":"call_ghost","timestamp":1755300013400}
3
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300013500}
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI203",
4
+ "severity": "error",
5
+ "message": "TOOL_CALL_START id 'call_7' never terminated",
6
+ "eventIndex": 3,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#tool-call-events",
8
+ "relatedEventIndex": 1
9
+ }
10
+ ]
@@ -0,0 +1,4 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300013600}
2
+ {"type":"TOOL_CALL_START","toolCallId":"call_7","toolCallName":"get_weather","timestamp":1755300013700}
3
+ {"type":"TOOL_CALL_ARGS","toolCallId":"call_7","delta":"{\"city\":\"Berlin\"}","timestamp":1755300013800}
4
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300013900}
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "rule": "AGUI204",
4
+ "severity": "error",
5
+ "message": "Concatenated TOOL_CALL_ARGS for toolCallId 'call_001' do not parse as JSON: Unexpected token 'o', \"{\"city\":oops}\" is not valid JSON",
6
+ "eventIndex": 4,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#toolcallargs",
8
+ "relatedEventIndex": 1
9
+ }
10
+ ]
@@ -0,0 +1,6 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300014000}
2
+ {"type":"TOOL_CALL_START","toolCallId":"call_001","toolCallName":"get_weather","timestamp":1755300014100}
3
+ {"type":"TOOL_CALL_ARGS","toolCallId":"call_001","delta":"{\"city\":","timestamp":1755300014200}
4
+ {"type":"TOOL_CALL_ARGS","toolCallId":"call_001","delta":"oops}","timestamp":1755300014300}
5
+ {"type":"TOOL_CALL_END","toolCallId":"call_001","timestamp":1755300014400}
6
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300014500}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI205",
4
+ "severity": "error",
5
+ "message": "toolCallId 'call_001' was already used by a completed tool call",
6
+ "eventIndex": 3,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#toolcallstart",
8
+ "eventType": "TOOL_CALL_START",
9
+ "pointer": "/toolCallId",
10
+ "relatedEventIndex": 2
11
+ }
12
+ ]
@@ -0,0 +1,5 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300014600}
2
+ {"type":"TOOL_CALL_START","toolCallId":"call_001","toolCallName":"get_weather","timestamp":1755300014700}
3
+ {"type":"TOOL_CALL_END","toolCallId":"call_001","timestamp":1755300014800}
4
+ {"type":"TOOL_CALL_START","toolCallId":"call_001","toolCallName":"get_weather","timestamp":1755300014900}
5
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300015000}
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "rule": "AGUI206",
4
+ "severity": "warning",
5
+ "message": "TOOL_CALL_RESULT for toolCallId 'call_001' arrived while the call is still open",
6
+ "eventIndex": 2,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#toolcallresult",
8
+ "eventType": "TOOL_CALL_RESULT",
9
+ "pointer": "/toolCallId",
10
+ "relatedEventIndex": 1
11
+ }
12
+ ]
@@ -0,0 +1,5 @@
1
+ {"type":"RUN_STARTED","threadId":"thread_001","runId":"run_001","timestamp":1755300015100}
2
+ {"type":"TOOL_CALL_START","toolCallId":"call_001","toolCallName":"get_weather","timestamp":1755300015200}
3
+ {"type":"TOOL_CALL_RESULT","messageId":"msg_001","toolCallId":"call_001","content":"early","timestamp":1755300015300}
4
+ {"type":"TOOL_CALL_END","toolCallId":"call_001","timestamp":1755300015400}
5
+ {"type":"RUN_FINISHED","threadId":"thread_001","runId":"run_001","outcome":{"type":"success"},"timestamp":1755300015500}
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "rule": "AGUI207",
4
+ "severity": "error",
5
+ "message": "TOOL_CALL_RESULT references toolCallId 'call_ghost', which was never started",
6
+ "eventIndex": 1,
7
+ "specUrl": "https://docs.ag-ui.com/concepts/events#toolcallresult",
8
+ "eventType": "TOOL_CALL_RESULT",
9
+ "pointer": "/toolCallId"
10
+ }
11
+ ]