ag-ui-validate 0.2.0 → 0.4.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 +82 -23
- package/dist/{catalog-BglXBNbL.js → catalog-3e6INLCp.js} +122 -4
- package/dist/catalog-3e6INLCp.js.map +1 -0
- package/dist/{catalog-Ci9dqc1a.cjs → catalog-DH5gDIbo.cjs} +122 -4
- package/dist/catalog-DH5gDIbo.cjs.map +1 -0
- package/dist/cli.js +641 -63
- package/dist/cli.js.map +1 -1
- package/dist/{index-Hmqj3r_r.d.cts → index-Cydfs-rB.d.ts} +4 -4
- package/dist/{index-oNG1kOp9.d.ts → index-DsVmjcLO.d.cts} +4 -4
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/report.cjs +11 -2
- package/dist/report.cjs.map +1 -1
- package/dist/report.d.cts +21 -12
- package/dist/report.d.ts +21 -12
- package/dist/report.js +11 -2
- package/dist/report.js.map +1 -1
- package/dist/{src-rGZ2G4qA.js → src-CezZ73Mm.js} +494 -59
- package/dist/src-CezZ73Mm.js.map +1 -0
- package/dist/{src-HmI-kxef.cjs → src-CyugLoks.cjs} +494 -59
- package/dist/src-CyugLoks.cjs.map +1 -0
- package/dist/transport.cjs +1 -1
- package/dist/transport.cjs.map +1 -1
- package/dist/transport.d.cts +1 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +1 -1
- package/dist/transport.js.map +1 -1
- package/dist/{types-oH_QTnn2.d.ts → types-CUIgyj2N.d.cts} +3 -1
- package/dist/{types-oH_QTnn2.d.cts → types-CUIgyj2N.d.ts} +3 -1
- package/dist/vitest.js +616 -61
- package/dist/vitest.js.map +1 -1
- package/{src → js/src}/cli-args.ts +16 -0
- package/{src → js/src}/cli.ts +1 -1
- package/{src → js/src}/index.ts +5 -0
- package/{src → js/src}/protocol/event-table.ts +93 -2
- package/js/src/report/json.ts +31 -0
- package/{src → js/src}/report/sarif.ts +3 -6
- package/{src → js/src}/rules/catalog.ts +5 -1
- package/{src → js/src}/rules/checks/context.ts +48 -3
- package/{src → js/src}/rules/checks/lifecycle.ts +5 -2
- package/js/src/rules/checks/subagents.ts +78 -0
- package/{src → js/src}/rules/checks/text.ts +11 -3
- package/{src → js/src}/rules/checks/toolcalls.ts +8 -2
- package/{src → js/src}/transport/index.ts +1 -1
- package/package.json +15 -14
- package/{src/rules → spec}/catalog.json +109 -2
- package/spec/event-categories.json +60 -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/AGUI601-duplicate-subagent-started/expected.json +12 -0
- package/spec/fixtures/invalid/AGUI601-duplicate-subagent-started/stream.jsonl +5 -0
- package/spec/fixtures/invalid/AGUI602-finished-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI602-finished-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI603-error-without-start/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI603-error-without-start/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI604-subagent-unterminated/expected.json +10 -0
- package/spec/fixtures/invalid/AGUI604-subagent-unterminated/stream.jsonl +3 -0
- package/spec/fixtures/invalid/AGUI605-unknown-parent-subagent-run-id/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI605-unknown-parent-subagent-run-id/stream.jsonl +4 -0
- package/spec/fixtures/invalid/AGUI606-continuation-owner-mismatch/expected.json +11 -0
- package/spec/fixtures/invalid/AGUI606-continuation-owner-mismatch/stream.jsonl +6 -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/report/json.ts +0 -20
- /package/{src → js/src}/protocol/jsonpatch.ts +0 -0
- /package/{src → js/src}/report/index.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}/rules/checks/reasoning.ts +0 -0
- /package/{src → js/src}/rules/checks/state.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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { Severity } from "./types.js"
|
|
4
4
|
|
|
5
5
|
export type CliFormat = "pretty" | "json" | "sarif" | "junit"
|
|
6
|
+
export type FailOn = "error" | "warning" | "none"
|
|
6
7
|
|
|
7
8
|
export interface CliConfig {
|
|
8
9
|
/** URL, file path, or "-" for stdin. Empty only with --help/--version. */
|
|
@@ -11,6 +12,8 @@ export interface CliConfig {
|
|
|
11
12
|
/** true/false forced; null = auto-detect from TTY. */
|
|
12
13
|
color: boolean | null
|
|
13
14
|
maxWarnings?: number
|
|
15
|
+
/** Severity threshold for a nonzero exit. Unset behaves like "error", today's default. */
|
|
16
|
+
failOn?: FailOn
|
|
14
17
|
timeoutMs?: number
|
|
15
18
|
/** Header names lowercased. */
|
|
16
19
|
headers: Record<string, string>
|
|
@@ -50,6 +53,7 @@ Rules:
|
|
|
50
53
|
--off AGUI### shorthand for --rule AGUI###=off
|
|
51
54
|
--features <a,b,...> declare exercised features (enables e.g. AGUI305)
|
|
52
55
|
--max-warnings <n> exit 1 when warnings exceed n
|
|
56
|
+
--fail-on <error|warning|none> severity that triggers a nonzero exit (default: error)
|
|
53
57
|
|
|
54
58
|
Endpoint options:
|
|
55
59
|
--header "Name: value" extra request header (repeatable)
|
|
@@ -59,6 +63,7 @@ Exit codes: 0 clean, 1 findings at error level (or warnings over --max-warnings)
|
|
|
59
63
|
`
|
|
60
64
|
|
|
61
65
|
const SEVERITIES = new Set(["error", "warning", "info", "off"])
|
|
66
|
+
const FAIL_ON_VALUES = new Set<FailOn>(["error", "warning", "none"])
|
|
62
67
|
const RULE_ID = /^AGUI\d{3}$/
|
|
63
68
|
|
|
64
69
|
interface Flag {
|
|
@@ -106,6 +111,14 @@ const FLAGS: Record<string, Flag> = {
|
|
|
106
111
|
return null
|
|
107
112
|
},
|
|
108
113
|
},
|
|
114
|
+
"--fail-on": {
|
|
115
|
+
takesValue: true,
|
|
116
|
+
apply: (c, v) => {
|
|
117
|
+
if (!FAIL_ON_VALUES.has(v as FailOn)) return `--fail-on expects error, warning, or none, got '${v}'`
|
|
118
|
+
c.failOn = v as FailOn
|
|
119
|
+
return null
|
|
120
|
+
},
|
|
121
|
+
},
|
|
109
122
|
"--timeout": {
|
|
110
123
|
takesValue: true,
|
|
111
124
|
apply: (c, v) => {
|
|
@@ -206,8 +219,11 @@ export function parseCliArgs(argv: string[]): ParseResult {
|
|
|
206
219
|
export function decideExitCode(
|
|
207
220
|
summary: { errors: number; warnings: number; info: number },
|
|
208
221
|
maxWarnings?: number,
|
|
222
|
+
failOn: FailOn = "error",
|
|
209
223
|
): 0 | 1 {
|
|
224
|
+
if (failOn === "none") return 0
|
|
210
225
|
if (summary.errors > 0) return 1
|
|
226
|
+
if (failOn === "warning" && summary.warnings > 0) return 1
|
|
211
227
|
if (maxWarnings !== undefined && summary.warnings > maxWarnings) return 1
|
|
212
228
|
return 0
|
|
213
229
|
}
|
package/{src → js/src}/cli.ts
RENAMED
|
@@ -132,7 +132,7 @@ async function main(): Promise<number> {
|
|
|
132
132
|
process.stdout.write(toJUnit(report, { name: targetLabel }))
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
return decideExitCode(report.summary, config.maxWarnings)
|
|
135
|
+
return decideExitCode(report.summary, config.maxWarnings, config.failOn)
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
main().then(
|
package/{src → js/src}/index.ts
RENAMED
|
@@ -14,6 +14,7 @@ import { newRunState, str } from "./rules/checks/context.js"
|
|
|
14
14
|
import { checkRunIdStability, endOfRunSteps, handleStepEvent } from "./rules/checks/lifecycle.js"
|
|
15
15
|
import { closeReasoningChunk, endOfRunReasoning, handleReasoningEvent } from "./rules/checks/reasoning.js"
|
|
16
16
|
import { handleStateEvent } from "./rules/checks/state.js"
|
|
17
|
+
import { endOfRunSubagents, handleSubagentEvent } from "./rules/checks/subagents.js"
|
|
17
18
|
import { closeTextChunk, endOfRunText, handleTextEvent } from "./rules/checks/text.js"
|
|
18
19
|
import { closeToolChunk, endOfRunToolCalls, handleToolCallEvent } from "./rules/checks/toolcalls.js"
|
|
19
20
|
import { TRANSPORT_RULE_IDS, TRANSPORT_SKIP_REASON } from "./rules/checks/transport.js"
|
|
@@ -156,6 +157,7 @@ export function createValidator(opts: ValidatorOptions = {}): Validator {
|
|
|
156
157
|
endOfRunToolCalls(r, emit, atIndex)
|
|
157
158
|
endOfRunSteps(r, emit, atIndex)
|
|
158
159
|
endOfRunReasoning(r, emit, atIndex)
|
|
160
|
+
endOfRunSubagents(r, emit, atIndex)
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
/** Opens the implicit run scope for streams that never announced one. */
|
|
@@ -325,6 +327,9 @@ export function createValidator(opts: ValidatorOptions = {}): Validator {
|
|
|
325
327
|
case "activity":
|
|
326
328
|
// No activity rules in the catalog yet.
|
|
327
329
|
break
|
|
330
|
+
case "subagent":
|
|
331
|
+
handleSubagentEvent(a)
|
|
332
|
+
break
|
|
328
333
|
case "special":
|
|
329
334
|
if (type === "RAW") {
|
|
330
335
|
const wrapped = ev.event
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// AUTO-GENERATED from @ag-ui/core v0.0.
|
|
1
|
+
// AUTO-GENERATED from @ag-ui/core v0.0.59 — do not edit by hand.
|
|
2
2
|
// Regenerate with: node scripts/generate-event-table.mjs
|
|
3
3
|
// test/protocol-drift.test.ts fails if this file drifts from the installed SDK.
|
|
4
4
|
|
|
@@ -13,6 +13,7 @@ export type EventCategory =
|
|
|
13
13
|
| "reasoning"
|
|
14
14
|
| "thinking"
|
|
15
15
|
| "special"
|
|
16
|
+
| "subagent"
|
|
16
17
|
|
|
17
18
|
export interface FieldSpec {
|
|
18
19
|
kind: FieldKind
|
|
@@ -31,7 +32,7 @@ export interface EventSpec {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/** Version of @ag-ui/core this table was derived from. */
|
|
34
|
-
export const SDK_VERSION = "0.0.
|
|
35
|
+
export const SDK_VERSION = "0.0.59"
|
|
35
36
|
|
|
36
37
|
/** Canonical wire event types and their schemas, derived from @ag-ui/core. */
|
|
37
38
|
export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
@@ -39,78 +40,96 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
39
40
|
category: "text",
|
|
40
41
|
specUrl: "https://docs.ag-ui.com/concepts/events#textmessagestart",
|
|
41
42
|
fields: {
|
|
43
|
+
"metadata": { kind: "object", required: false },
|
|
42
44
|
"messageId": { kind: "string", required: true },
|
|
43
45
|
"role": { kind: "string", required: false, enum: ["developer","system","assistant","user"] },
|
|
44
46
|
"name": { kind: "string", required: false },
|
|
47
|
+
"subagentRunId": { kind: "string", required: false },
|
|
45
48
|
},
|
|
46
49
|
},
|
|
47
50
|
"TEXT_MESSAGE_CONTENT": {
|
|
48
51
|
category: "text",
|
|
49
52
|
specUrl: "https://docs.ag-ui.com/concepts/events#textmessagecontent",
|
|
50
53
|
fields: {
|
|
54
|
+
"metadata": { kind: "object", required: false },
|
|
51
55
|
"messageId": { kind: "string", required: true },
|
|
52
56
|
"delta": { kind: "string", required: true },
|
|
57
|
+
"subagentRunId": { kind: "string", required: false },
|
|
53
58
|
},
|
|
54
59
|
},
|
|
55
60
|
"TEXT_MESSAGE_END": {
|
|
56
61
|
category: "text",
|
|
57
62
|
specUrl: "https://docs.ag-ui.com/concepts/events#textmessageend",
|
|
58
63
|
fields: {
|
|
64
|
+
"metadata": { kind: "object", required: false },
|
|
59
65
|
"messageId": { kind: "string", required: true },
|
|
66
|
+
"subagentRunId": { kind: "string", required: false },
|
|
60
67
|
},
|
|
61
68
|
},
|
|
62
69
|
"TEXT_MESSAGE_CHUNK": {
|
|
63
70
|
category: "text",
|
|
64
71
|
specUrl: "https://docs.ag-ui.com/concepts/events#textmessagechunk",
|
|
65
72
|
fields: {
|
|
73
|
+
"metadata": { kind: "object", required: false },
|
|
66
74
|
"messageId": { kind: "string", required: false },
|
|
67
75
|
"role": { kind: "string", required: false, enum: ["developer","system","assistant","user"] },
|
|
68
76
|
"delta": { kind: "string", required: false },
|
|
69
77
|
"name": { kind: "string", required: false },
|
|
78
|
+
"subagentRunId": { kind: "string", required: false },
|
|
70
79
|
},
|
|
71
80
|
},
|
|
72
81
|
"TOOL_CALL_START": {
|
|
73
82
|
category: "toolcall",
|
|
74
83
|
specUrl: "https://docs.ag-ui.com/concepts/events#toolcallstart",
|
|
75
84
|
fields: {
|
|
85
|
+
"metadata": { kind: "object", required: false },
|
|
76
86
|
"toolCallId": { kind: "string", required: true },
|
|
77
87
|
"toolCallName": { kind: "string", required: true },
|
|
78
88
|
"parentMessageId": { kind: "string", required: false },
|
|
89
|
+
"subagentRunId": { kind: "string", required: false },
|
|
79
90
|
},
|
|
80
91
|
},
|
|
81
92
|
"TOOL_CALL_ARGS": {
|
|
82
93
|
category: "toolcall",
|
|
83
94
|
specUrl: "https://docs.ag-ui.com/concepts/events#toolcallargs",
|
|
84
95
|
fields: {
|
|
96
|
+
"metadata": { kind: "object", required: false },
|
|
85
97
|
"toolCallId": { kind: "string", required: true },
|
|
86
98
|
"delta": { kind: "string", required: true },
|
|
99
|
+
"subagentRunId": { kind: "string", required: false },
|
|
87
100
|
},
|
|
88
101
|
},
|
|
89
102
|
"TOOL_CALL_END": {
|
|
90
103
|
category: "toolcall",
|
|
91
104
|
specUrl: "https://docs.ag-ui.com/concepts/events#toolcallend",
|
|
92
105
|
fields: {
|
|
106
|
+
"metadata": { kind: "object", required: false },
|
|
93
107
|
"toolCallId": { kind: "string", required: true },
|
|
108
|
+
"subagentRunId": { kind: "string", required: false },
|
|
94
109
|
},
|
|
95
110
|
},
|
|
96
111
|
"TOOL_CALL_CHUNK": {
|
|
97
112
|
category: "toolcall",
|
|
98
113
|
specUrl: "https://docs.ag-ui.com/concepts/events#toolcallchunk",
|
|
99
114
|
fields: {
|
|
115
|
+
"metadata": { kind: "object", required: false },
|
|
100
116
|
"toolCallId": { kind: "string", required: false },
|
|
101
117
|
"toolCallName": { kind: "string", required: false },
|
|
102
118
|
"parentMessageId": { kind: "string", required: false },
|
|
103
119
|
"delta": { kind: "string", required: false },
|
|
120
|
+
"subagentRunId": { kind: "string", required: false },
|
|
104
121
|
},
|
|
105
122
|
},
|
|
106
123
|
"TOOL_CALL_RESULT": {
|
|
107
124
|
category: "toolcall",
|
|
108
125
|
specUrl: "https://docs.ag-ui.com/concepts/events#toolcallresult",
|
|
109
126
|
fields: {
|
|
127
|
+
"metadata": { kind: "object", required: false },
|
|
110
128
|
"messageId": { kind: "string", required: true },
|
|
111
129
|
"toolCallId": { kind: "string", required: true },
|
|
112
130
|
"content": { kind: "string", required: true },
|
|
113
131
|
"role": { kind: "string", required: false, enum: ["tool"] },
|
|
132
|
+
"subagentRunId": { kind: "string", required: false },
|
|
114
133
|
},
|
|
115
134
|
},
|
|
116
135
|
"THINKING_START": {
|
|
@@ -118,6 +137,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
118
137
|
deprecated: "REASONING_START",
|
|
119
138
|
specUrl: "https://docs.ag-ui.com/concepts/events#thinking-events-deprecated",
|
|
120
139
|
fields: {
|
|
140
|
+
"metadata": { kind: "object", required: false },
|
|
121
141
|
"title": { kind: "string", required: false },
|
|
122
142
|
},
|
|
123
143
|
},
|
|
@@ -126,6 +146,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
126
146
|
deprecated: "REASONING_END",
|
|
127
147
|
specUrl: "https://docs.ag-ui.com/concepts/events#thinking-events-deprecated",
|
|
128
148
|
fields: {
|
|
149
|
+
"metadata": { kind: "object", required: false },
|
|
129
150
|
},
|
|
130
151
|
},
|
|
131
152
|
"THINKING_TEXT_MESSAGE_START": {
|
|
@@ -133,6 +154,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
133
154
|
deprecated: "REASONING_MESSAGE_START",
|
|
134
155
|
specUrl: "https://docs.ag-ui.com/concepts/events#thinking-events-deprecated",
|
|
135
156
|
fields: {
|
|
157
|
+
"metadata": { kind: "object", required: false },
|
|
136
158
|
},
|
|
137
159
|
},
|
|
138
160
|
"THINKING_TEXT_MESSAGE_CONTENT": {
|
|
@@ -140,6 +162,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
140
162
|
deprecated: "REASONING_MESSAGE_CONTENT",
|
|
141
163
|
specUrl: "https://docs.ag-ui.com/concepts/events#thinking-events-deprecated",
|
|
142
164
|
fields: {
|
|
165
|
+
"metadata": { kind: "object", required: false },
|
|
143
166
|
"delta": { kind: "string", required: true },
|
|
144
167
|
},
|
|
145
168
|
},
|
|
@@ -148,26 +171,32 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
148
171
|
deprecated: "REASONING_MESSAGE_END",
|
|
149
172
|
specUrl: "https://docs.ag-ui.com/concepts/events#thinking-events-deprecated",
|
|
150
173
|
fields: {
|
|
174
|
+
"metadata": { kind: "object", required: false },
|
|
151
175
|
},
|
|
152
176
|
},
|
|
153
177
|
"STATE_SNAPSHOT": {
|
|
154
178
|
category: "state",
|
|
155
179
|
specUrl: "https://docs.ag-ui.com/concepts/events#statesnapshot",
|
|
156
180
|
fields: {
|
|
181
|
+
"metadata": { kind: "object", required: false },
|
|
157
182
|
"snapshot": { kind: "any", required: true },
|
|
183
|
+
"subagentRunId": { kind: "string", required: false },
|
|
158
184
|
},
|
|
159
185
|
},
|
|
160
186
|
"STATE_DELTA": {
|
|
161
187
|
category: "state",
|
|
162
188
|
specUrl: "https://docs.ag-ui.com/concepts/events#statedelta",
|
|
163
189
|
fields: {
|
|
190
|
+
"metadata": { kind: "object", required: false },
|
|
164
191
|
"delta": { kind: "array", required: true },
|
|
192
|
+
"subagentRunId": { kind: "string", required: false },
|
|
165
193
|
},
|
|
166
194
|
},
|
|
167
195
|
"MESSAGES_SNAPSHOT": {
|
|
168
196
|
category: "state",
|
|
169
197
|
specUrl: "https://docs.ag-ui.com/concepts/events#messagessnapshot",
|
|
170
198
|
fields: {
|
|
199
|
+
"metadata": { kind: "object", required: false },
|
|
171
200
|
"messages": { kind: "array", required: true },
|
|
172
201
|
},
|
|
173
202
|
},
|
|
@@ -175,41 +204,50 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
175
204
|
category: "activity",
|
|
176
205
|
specUrl: "https://docs.ag-ui.com/concepts/events#activitysnapshot",
|
|
177
206
|
fields: {
|
|
207
|
+
"metadata": { kind: "object", required: false },
|
|
178
208
|
"messageId": { kind: "string", required: true },
|
|
179
209
|
"activityType": { kind: "string", required: true },
|
|
180
210
|
"content": { kind: "object", required: true },
|
|
181
211
|
"replace": { kind: "boolean", required: false },
|
|
212
|
+
"subagentRunId": { kind: "string", required: false },
|
|
182
213
|
},
|
|
183
214
|
},
|
|
184
215
|
"ACTIVITY_DELTA": {
|
|
185
216
|
category: "activity",
|
|
186
217
|
specUrl: "https://docs.ag-ui.com/concepts/events#activitydelta",
|
|
187
218
|
fields: {
|
|
219
|
+
"metadata": { kind: "object", required: false },
|
|
188
220
|
"messageId": { kind: "string", required: true },
|
|
189
221
|
"activityType": { kind: "string", required: true },
|
|
190
222
|
"patch": { kind: "array", required: true },
|
|
223
|
+
"subagentRunId": { kind: "string", required: false },
|
|
191
224
|
},
|
|
192
225
|
},
|
|
193
226
|
"RAW": {
|
|
194
227
|
category: "special",
|
|
195
228
|
specUrl: "https://docs.ag-ui.com/concepts/events#raw",
|
|
196
229
|
fields: {
|
|
230
|
+
"metadata": { kind: "object", required: false },
|
|
197
231
|
"event": { kind: "any", required: true },
|
|
198
232
|
"source": { kind: "string", required: false },
|
|
233
|
+
"subagentRunId": { kind: "string", required: false },
|
|
199
234
|
},
|
|
200
235
|
},
|
|
201
236
|
"CUSTOM": {
|
|
202
237
|
category: "special",
|
|
203
238
|
specUrl: "https://docs.ag-ui.com/concepts/events#custom",
|
|
204
239
|
fields: {
|
|
240
|
+
"metadata": { kind: "object", required: false },
|
|
205
241
|
"name": { kind: "string", required: true },
|
|
206
242
|
"value": { kind: "any", required: true },
|
|
243
|
+
"subagentRunId": { kind: "string", required: false },
|
|
207
244
|
},
|
|
208
245
|
},
|
|
209
246
|
"RUN_STARTED": {
|
|
210
247
|
category: "lifecycle",
|
|
211
248
|
specUrl: "https://docs.ag-ui.com/concepts/events#runstarted",
|
|
212
249
|
fields: {
|
|
250
|
+
"metadata": { kind: "object", required: false },
|
|
213
251
|
"threadId": { kind: "string", required: true },
|
|
214
252
|
"runId": { kind: "string", required: true },
|
|
215
253
|
"parentRunId": { kind: "string", required: false },
|
|
@@ -220,6 +258,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
220
258
|
category: "lifecycle",
|
|
221
259
|
specUrl: "https://docs.ag-ui.com/concepts/events#runfinished",
|
|
222
260
|
fields: {
|
|
261
|
+
"metadata": { kind: "object", required: false },
|
|
223
262
|
"threadId": { kind: "string", required: true },
|
|
224
263
|
"runId": { kind: "string", required: true },
|
|
225
264
|
"result": { kind: "any", required: false },
|
|
@@ -231,6 +270,7 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
231
270
|
category: "lifecycle",
|
|
232
271
|
specUrl: "https://docs.ag-ui.com/concepts/events#runerror",
|
|
233
272
|
fields: {
|
|
273
|
+
"metadata": { kind: "object", required: false },
|
|
234
274
|
"message": { kind: "string", required: true },
|
|
235
275
|
"code": { kind: "string", required: false },
|
|
236
276
|
"usage": { kind: "array", required: false },
|
|
@@ -240,68 +280,119 @@ export const EVENT_TABLE: Readonly<Record<string, EventSpec>> = {
|
|
|
240
280
|
category: "lifecycle",
|
|
241
281
|
specUrl: "https://docs.ag-ui.com/concepts/events#stepstarted",
|
|
242
282
|
fields: {
|
|
283
|
+
"metadata": { kind: "object", required: false },
|
|
243
284
|
"stepName": { kind: "string", required: true },
|
|
285
|
+
"subagentRunId": { kind: "string", required: false },
|
|
244
286
|
},
|
|
245
287
|
},
|
|
246
288
|
"STEP_FINISHED": {
|
|
247
289
|
category: "lifecycle",
|
|
248
290
|
specUrl: "https://docs.ag-ui.com/concepts/events#stepfinished",
|
|
249
291
|
fields: {
|
|
292
|
+
"metadata": { kind: "object", required: false },
|
|
250
293
|
"stepName": { kind: "string", required: true },
|
|
294
|
+
"subagentRunId": { kind: "string", required: false },
|
|
251
295
|
},
|
|
252
296
|
},
|
|
253
297
|
"REASONING_START": {
|
|
254
298
|
category: "reasoning",
|
|
255
299
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningstart",
|
|
256
300
|
fields: {
|
|
301
|
+
"metadata": { kind: "object", required: false },
|
|
257
302
|
"messageId": { kind: "string", required: true },
|
|
303
|
+
"subagentRunId": { kind: "string", required: false },
|
|
258
304
|
},
|
|
259
305
|
},
|
|
260
306
|
"REASONING_MESSAGE_START": {
|
|
261
307
|
category: "reasoning",
|
|
262
308
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningmessagestart",
|
|
263
309
|
fields: {
|
|
310
|
+
"metadata": { kind: "object", required: false },
|
|
264
311
|
"messageId": { kind: "string", required: true },
|
|
265
312
|
"role": { kind: "string", required: true, enum: ["reasoning"] },
|
|
313
|
+
"subagentRunId": { kind: "string", required: false },
|
|
266
314
|
},
|
|
267
315
|
},
|
|
268
316
|
"REASONING_MESSAGE_CONTENT": {
|
|
269
317
|
category: "reasoning",
|
|
270
318
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningmessagecontent",
|
|
271
319
|
fields: {
|
|
320
|
+
"metadata": { kind: "object", required: false },
|
|
272
321
|
"messageId": { kind: "string", required: true },
|
|
273
322
|
"delta": { kind: "string", required: true },
|
|
323
|
+
"subagentRunId": { kind: "string", required: false },
|
|
274
324
|
},
|
|
275
325
|
},
|
|
276
326
|
"REASONING_MESSAGE_END": {
|
|
277
327
|
category: "reasoning",
|
|
278
328
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningmessageend",
|
|
279
329
|
fields: {
|
|
330
|
+
"metadata": { kind: "object", required: false },
|
|
280
331
|
"messageId": { kind: "string", required: true },
|
|
332
|
+
"subagentRunId": { kind: "string", required: false },
|
|
281
333
|
},
|
|
282
334
|
},
|
|
283
335
|
"REASONING_MESSAGE_CHUNK": {
|
|
284
336
|
category: "reasoning",
|
|
285
337
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningmessagechunk",
|
|
286
338
|
fields: {
|
|
339
|
+
"metadata": { kind: "object", required: false },
|
|
287
340
|
"messageId": { kind: "string", required: false },
|
|
288
341
|
"delta": { kind: "string", required: false },
|
|
342
|
+
"subagentRunId": { kind: "string", required: false },
|
|
289
343
|
},
|
|
290
344
|
},
|
|
291
345
|
"REASONING_END": {
|
|
292
346
|
category: "reasoning",
|
|
293
347
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningend",
|
|
294
348
|
fields: {
|
|
349
|
+
"metadata": { kind: "object", required: false },
|
|
295
350
|
"messageId": { kind: "string", required: true },
|
|
351
|
+
"subagentRunId": { kind: "string", required: false },
|
|
296
352
|
},
|
|
297
353
|
},
|
|
298
354
|
"REASONING_ENCRYPTED_VALUE": {
|
|
299
355
|
category: "reasoning",
|
|
300
356
|
specUrl: "https://docs.ag-ui.com/concepts/events#reasoningencryptedvalue",
|
|
301
357
|
fields: {
|
|
358
|
+
"metadata": { kind: "object", required: false },
|
|
302
359
|
"subtype": { kind: "string", required: true, enum: ["tool-call","message"] },
|
|
303
360
|
"entityId": { kind: "string", required: true },
|
|
304
361
|
"encryptedValue": { kind: "string", required: true },
|
|
362
|
+
"subagentRunId": { kind: "string", required: false },
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
"SUBAGENT_STARTED": {
|
|
366
|
+
category: "subagent",
|
|
367
|
+
specUrl: "https://docs.ag-ui.com/concepts/events#subagent-events",
|
|
368
|
+
fields: {
|
|
369
|
+
"metadata": { kind: "object", required: false },
|
|
370
|
+
"subagentRunId": { kind: "string", required: true },
|
|
371
|
+
"name": { kind: "string", required: true },
|
|
372
|
+
"description": { kind: "string", required: false },
|
|
373
|
+
"parentSubagentRunId": { kind: "string", required: false },
|
|
374
|
+
"parentToolCallId": { kind: "string", required: false },
|
|
375
|
+
"parentMessageId": { kind: "string", required: false },
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
"SUBAGENT_FINISHED": {
|
|
379
|
+
category: "subagent",
|
|
380
|
+
specUrl: "https://docs.ag-ui.com/concepts/events#subagent-events",
|
|
381
|
+
fields: {
|
|
382
|
+
"metadata": { kind: "object", required: false },
|
|
383
|
+
"subagentRunId": { kind: "string", required: true },
|
|
384
|
+
"result": { kind: "any", required: false },
|
|
385
|
+
"outcome": { kind: "object", required: false },
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
"SUBAGENT_ERROR": {
|
|
389
|
+
category: "subagent",
|
|
390
|
+
specUrl: "https://docs.ag-ui.com/concepts/events#subagent-events",
|
|
391
|
+
fields: {
|
|
392
|
+
"metadata": { kind: "object", required: false },
|
|
393
|
+
"subagentRunId": { kind: "string", required: true },
|
|
394
|
+
"message": { kind: "string", required: true },
|
|
395
|
+
"code": { kind: "string", required: false },
|
|
305
396
|
},
|
|
306
397
|
},
|
|
307
398
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Machine-readable report: the core Report plus tool identification, so a
|
|
2
|
+
// stored document is self-describing.
|
|
3
|
+
import { RULES } from "../rules/catalog.js"
|
|
4
|
+
import type { Diagnostic, Report } from "../types.js"
|
|
5
|
+
|
|
6
|
+
export interface JsonReportOptions {
|
|
7
|
+
tool: { name: string; version: string }
|
|
8
|
+
/** What was validated: URL, file path, or "stdin". */
|
|
9
|
+
target?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface JsonDiagnostic extends Diagnostic {
|
|
13
|
+
/** The rule's catalog category, e.g. "toolcall". Joined in from the catalog by rule id. */
|
|
14
|
+
category?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface JsonReportDocument extends Omit<Report, "diagnostics"> {
|
|
18
|
+
tool: { name: string; version: string }
|
|
19
|
+
target?: string
|
|
20
|
+
diagnostics: JsonDiagnostic[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function toJsonReport(report: Report, opts: JsonReportOptions): JsonReportDocument {
|
|
24
|
+
const diagnostics: JsonDiagnostic[] = report.diagnostics.map((d) => {
|
|
25
|
+
const category = RULES.get(d.rule)?.category
|
|
26
|
+
return category === undefined ? { ...d } : { ...d, category }
|
|
27
|
+
})
|
|
28
|
+
const doc: JsonReportDocument = { tool: opts.tool, ...report, diagnostics }
|
|
29
|
+
if (opts.target !== undefined) doc.target = opts.target
|
|
30
|
+
return doc
|
|
31
|
+
}
|
|
@@ -34,12 +34,7 @@ export interface SarifLog {
|
|
|
34
34
|
name: string
|
|
35
35
|
version: string
|
|
36
36
|
informationUri: string
|
|
37
|
-
rules:
|
|
38
|
-
id: string
|
|
39
|
-
helpUri: string
|
|
40
|
-
shortDescription?: { text: string }
|
|
41
|
-
defaultConfiguration?: { level: SarifLevel }
|
|
42
|
-
}>
|
|
37
|
+
rules: SarifRule[]
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
40
|
results: SarifResult[]
|
|
@@ -57,6 +52,7 @@ type SarifRule = {
|
|
|
57
52
|
helpUri: string
|
|
58
53
|
shortDescription?: { text: string }
|
|
59
54
|
defaultConfiguration?: { level: SarifLevel }
|
|
55
|
+
properties?: { tags: string[] }
|
|
60
56
|
}
|
|
61
57
|
|
|
62
58
|
export function toSarif(report: Report, opts: SarifOptions): SarifLog {
|
|
@@ -68,6 +64,7 @@ export function toSarif(report: Report, opts: SarifOptions): SarifLog {
|
|
|
68
64
|
if (catalog !== undefined) {
|
|
69
65
|
entry.shortDescription = { text: catalog.title }
|
|
70
66
|
entry.defaultConfiguration = { level: LEVEL[catalog.severity] }
|
|
67
|
+
entry.properties = { tags: [catalog.category] }
|
|
71
68
|
}
|
|
72
69
|
rules.set(d.rule, entry)
|
|
73
70
|
}
|
|
@@ -6,19 +6,22 @@
|
|
|
6
6
|
// malformed catalog is a programming error in this package, so the loader
|
|
7
7
|
// throws loudly at import time.
|
|
8
8
|
|
|
9
|
-
import catalogJson from "
|
|
9
|
+
import catalogJson from "../../../spec/catalog.json"
|
|
10
10
|
|
|
11
11
|
export type Severity = "error" | "warning" | "info"
|
|
12
12
|
export type SeverityOrOff = Severity | "off"
|
|
13
13
|
|
|
14
14
|
const SEVERITIES: readonly string[] = ["error", "warning", "info"]
|
|
15
15
|
const LAYERS: readonly string[] = ["core", "transport"]
|
|
16
|
+
export const CATEGORIES: readonly string[] = ["lifecycle", "text", "toolcall", "state", "reasoning", "transport", "hygiene", "subagent"]
|
|
16
17
|
|
|
17
18
|
export interface RuleDefinition {
|
|
18
19
|
/** e.g. "AGUI203" */
|
|
19
20
|
id: string
|
|
20
21
|
severity: Severity
|
|
21
22
|
title: string
|
|
23
|
+
/** Which part of the protocol this rule governs, e.g. "toolcall". */
|
|
24
|
+
category: string
|
|
22
25
|
/** Human template with {placeholder} slots filled per diagnostic. */
|
|
23
26
|
messageTemplate: string
|
|
24
27
|
/** Governing spec section. Mandatory: rules that cannot cite one don't ship. */
|
|
@@ -58,6 +61,7 @@ export function validateCatalog(data: unknown): Catalog {
|
|
|
58
61
|
seen.add(rule.id)
|
|
59
62
|
if (!SEVERITIES.includes(rule.severity)) problems.push(`${where}: bad severity '${rule.severity}'`)
|
|
60
63
|
if (!rule.title) problems.push(`${where}: missing title`)
|
|
64
|
+
if (!CATEGORIES.includes(rule.category)) problems.push(`${where}: bad category '${rule.category}'`)
|
|
61
65
|
if (!rule.messageTemplate) problems.push(`${where}: missing messageTemplate`)
|
|
62
66
|
if (!rule.specUrl?.startsWith("https://")) problems.push(`${where}: specUrl must be an https URL`)
|
|
63
67
|
if (!rule.since) problems.push(`${where}: missing since`)
|
|
@@ -24,6 +24,10 @@ export interface OpenToolCall {
|
|
|
24
24
|
startIndex: number
|
|
25
25
|
args: string
|
|
26
26
|
sawArgs: boolean
|
|
27
|
+
/** subagentRunId this call belongs to (explicit, or inherited from the
|
|
28
|
+
* parentMessageId's owner - AGUI606's "an untagged tool call inherits the
|
|
29
|
+
* parent message's owner"). undefined means it belongs to the run itself. */
|
|
30
|
+
owner: string | undefined
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export interface RunState {
|
|
@@ -34,19 +38,33 @@ export interface RunState {
|
|
|
34
38
|
implicit: boolean
|
|
35
39
|
terminal: { type: string; index: number } | null
|
|
36
40
|
|
|
37
|
-
openMessages: Map<string, { startIndex: number }>
|
|
41
|
+
openMessages: Map<string, { startIndex: number; owner: string | undefined }>
|
|
38
42
|
/** messageId -> index of the event that closed it. */
|
|
39
43
|
closedMessages: Map<string, number>
|
|
40
44
|
/** Every message id observed (starts, chunks, snapshots, tool results). */
|
|
41
45
|
knownMessageIds: Set<string>
|
|
46
|
+
/** messageId -> owning subagentRunId (undefined for the run), for AGUI606's
|
|
47
|
+
* tool-call-inherits-its-parent-message's-owner resolution. Persists past
|
|
48
|
+
* the message closing, unlike openMessages/closedMessages. */
|
|
49
|
+
messageOwner: Map<string, string | undefined>
|
|
42
50
|
|
|
43
51
|
openToolCalls: Map<string, OpenToolCall>
|
|
44
52
|
closedToolCalls: Map<string, number>
|
|
45
53
|
/** Ids also known from MESSAGES_SNAPSHOT history. */
|
|
46
54
|
knownToolCallIds: Set<string>
|
|
47
55
|
|
|
48
|
-
/** stepName -> re-entrant open count (SQ-10)
|
|
49
|
-
|
|
56
|
+
/** stepName -> re-entrant open count (SQ-10), first-open index, and the
|
|
57
|
+
* subagentRunId recorded from the first STEP_STARTED (AGUI606) - a
|
|
58
|
+
* re-entrant reopen does not change it. */
|
|
59
|
+
openSteps: Map<string, { count: number; firstIndex: number; owner: string | undefined }>
|
|
60
|
+
|
|
61
|
+
openSubagents: Map<string, { startIndex: number }>
|
|
62
|
+
/** Closed via SUBAGENT_FINISHED (resumable only when outcome.type ===
|
|
63
|
+
* "suspended" - the one case where a later SUBAGENT_STARTED reusing this
|
|
64
|
+
* id is a legitimate continuation, not a duplicate, AGUI601) or SUBAGENT_ERROR. */
|
|
65
|
+
closedSubagents: Map<string, { index: number; resumable: boolean }>
|
|
66
|
+
/** Every subagentRunId ever started (open or closed), for parentSubagentRunId checks. */
|
|
67
|
+
knownSubagentRunIds: Set<string>
|
|
50
68
|
|
|
51
69
|
openReasoningBlocks: Map<string, number>
|
|
52
70
|
openReasoningMessages: Map<string, number>
|
|
@@ -78,10 +96,14 @@ export function newRunState(init: {
|
|
|
78
96
|
openMessages: new Map(),
|
|
79
97
|
closedMessages: new Map(),
|
|
80
98
|
knownMessageIds: new Set(),
|
|
99
|
+
messageOwner: new Map(),
|
|
81
100
|
openToolCalls: new Map(),
|
|
82
101
|
closedToolCalls: new Map(),
|
|
83
102
|
knownToolCallIds: new Set(),
|
|
84
103
|
openSteps: new Map(),
|
|
104
|
+
openSubagents: new Map(),
|
|
105
|
+
closedSubagents: new Map(),
|
|
106
|
+
knownSubagentRunIds: new Set(),
|
|
85
107
|
openReasoningBlocks: new Map(),
|
|
86
108
|
openReasoningMessages: new Map(),
|
|
87
109
|
state: { known: false, value: undefined, deltasSinceSnapshot: 0, snapshotSeen: false, agui301Fired: false },
|
|
@@ -115,3 +137,26 @@ export function str(event: Record<string, unknown>, field: string): string | und
|
|
|
115
137
|
const v = event[field]
|
|
116
138
|
return typeof v === "string" ? v : undefined
|
|
117
139
|
}
|
|
140
|
+
|
|
141
|
+
/** AGUI606 — a continuation/close event's explicit subagentRunId must agree
|
|
142
|
+
* with the owner recorded when its entity opened. Only compared when the
|
|
143
|
+
* event explicitly tags itself; omitting the field is never flagged (SQ-15).
|
|
144
|
+
* Shared by text/toolcalls/lifecycle — not the *_CHUNK forms or
|
|
145
|
+
* TOOL_CALL_RESULT, which are independently attributed by spec. */
|
|
146
|
+
export function checkOwnerConsistency(
|
|
147
|
+
emit: EmitFn,
|
|
148
|
+
type: string,
|
|
149
|
+
entityType: string,
|
|
150
|
+
entityId: string,
|
|
151
|
+
event: Record<string, unknown>,
|
|
152
|
+
owner: string | undefined,
|
|
153
|
+
): void {
|
|
154
|
+
const actual = str(event, "subagentRunId")
|
|
155
|
+
if (actual !== undefined && actual !== owner) {
|
|
156
|
+
emit(
|
|
157
|
+
"AGUI606",
|
|
158
|
+
{ type, actual, entityType, entityId, expected: owner !== undefined ? `'${owner}'` : "the run" },
|
|
159
|
+
{ pointer: "/subagentRunId" },
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
}
|