@assistant-ui/react-ag-ui 0.0.71 → 0.1.1

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 (70) hide show
  1. package/README.md +1 -1
  2. package/dist/agUiExtras.js +1 -2
  3. package/dist/hooks.js +1 -2
  4. package/dist/runtime/{AgUiThreadRuntimeCore.d.ts → AgUiThreadController.d.ts} +6 -12
  5. package/dist/runtime/AgUiThreadController.d.ts.map +1 -0
  6. package/dist/runtime/{AgUiThreadRuntimeCore.js → AgUiThreadController.js} +567 -194
  7. package/dist/runtime/AgUiThreadController.js.map +1 -0
  8. package/dist/runtime/adapter/conversions.d.ts +4 -4
  9. package/dist/runtime/adapter/conversions.d.ts.map +1 -1
  10. package/dist/runtime/adapter/conversions.js +120 -35
  11. package/dist/runtime/adapter/conversions.js.map +1 -1
  12. package/dist/runtime/adapter/replay-content.d.ts +9 -0
  13. package/dist/runtime/adapter/replay-content.d.ts.map +1 -0
  14. package/dist/runtime/adapter/replay-content.js +185 -0
  15. package/dist/runtime/adapter/replay-content.js.map +1 -0
  16. package/dist/runtime/adapter/run-aggregator.d.ts +3 -5
  17. package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
  18. package/dist/runtime/adapter/run-aggregator.js +48 -63
  19. package/dist/runtime/adapter/run-aggregator.js.map +1 -1
  20. package/dist/runtime/adapter/subscriber.d.ts +0 -24
  21. package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
  22. package/dist/runtime/adapter/subscriber.js +2 -24
  23. package/dist/runtime/adapter/subscriber.js.map +1 -1
  24. package/dist/runtime/adapter/tool-approval.d.ts +2 -0
  25. package/dist/runtime/adapter/tool-approval.d.ts.map +1 -1
  26. package/dist/runtime/adapter/tool-approval.js +23 -6
  27. package/dist/runtime/adapter/tool-approval.js.map +1 -1
  28. package/dist/runtime/agUiThreadState.d.ts +60 -0
  29. package/dist/runtime/agUiThreadState.d.ts.map +1 -0
  30. package/dist/runtime/agUiThreadState.js +94 -0
  31. package/dist/runtime/agUiThreadState.js.map +1 -0
  32. package/dist/runtime/event-parser.d.ts.map +1 -1
  33. package/dist/runtime/event-parser.js +46 -50
  34. package/dist/runtime/event-parser.js.map +1 -1
  35. package/dist/runtime/interrupt-internals.js +1 -2
  36. package/dist/runtime/logger.js +1 -2
  37. package/dist/runtime/mcp-tool-result.d.ts +3 -1
  38. package/dist/runtime/mcp-tool-result.d.ts.map +1 -1
  39. package/dist/runtime/mcp-tool-result.js +7 -5
  40. package/dist/runtime/mcp-tool-result.js.map +1 -1
  41. package/dist/runtime/types.d.ts +11 -35
  42. package/dist/runtime/types.d.ts.map +1 -1
  43. package/dist/runtime/types.js +1 -2
  44. package/dist/runtime/types.js.map +1 -1
  45. package/dist/useAgUiRuntime.js +3 -4
  46. package/dist/useAgUiRuntime.js.map +1 -1
  47. package/package.json +12 -11
  48. package/src/runtime/AgUiThreadController.deferred-results.test.ts +548 -0
  49. package/src/runtime/{AgUiThreadRuntimeCore.interrupt-cancel.test.ts → AgUiThreadController.interrupt-cancel.test.ts} +4 -4
  50. package/src/runtime/AgUiThreadController.replay.test.ts +3932 -0
  51. package/src/runtime/{AgUiThreadRuntimeCore.test.ts → AgUiThreadController.test.ts} +114 -6
  52. package/src/runtime/{AgUiThreadRuntimeCore.ts → AgUiThreadController.ts} +1037 -236
  53. package/src/runtime/adapter/conversions.content.test.ts +149 -5
  54. package/src/runtime/adapter/conversions.tools.test.ts +2 -1
  55. package/src/runtime/adapter/conversions.ts +249 -62
  56. package/src/runtime/adapter/replay-content.test.ts +235 -0
  57. package/src/runtime/adapter/replay-content.ts +306 -0
  58. package/src/runtime/adapter/run-aggregator.ts +79 -114
  59. package/src/runtime/adapter/subscriber.ts +1 -44
  60. package/src/runtime/adapter/tool-approval.ts +41 -3
  61. package/src/runtime/agUiThreadState.test.ts +224 -0
  62. package/src/runtime/agUiThreadState.ts +139 -0
  63. package/src/runtime/event-parser.ts +40 -58
  64. package/src/runtime/mcp-tool-result.ts +16 -2
  65. package/src/runtime/types.ts +16 -28
  66. package/src/useAgUiRuntime.fast-refresh.test.tsx +3 -3
  67. package/src/useAgUiRuntime.thread-switch.test.tsx +4 -4
  68. package/src/useAgUiRuntime.ts +3 -3
  69. package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +0 -1
  70. package/dist/runtime/AgUiThreadRuntimeCore.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { readRawResponseSchema, withoutRawResponseSchema } from "../interrupt-internals.js";
2
2
  import { iterateToolCallParts, mapToolCallPartsDeep } from "@assistant-ui/core/internal";
3
3
  import { buildResumeArray } from "@ag-ui/client";
4
- //#region src/runtime/adapter/tool-approval.ts
4
+ // src/runtime/adapter/tool-approval.ts
5
5
  const EMPTY_APPROVALS = /* @__PURE__ */ new Map();
6
6
  const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7
7
  const isString = (value) => typeof value === "string";
@@ -136,6 +136,23 @@ const projectAgUiToolApprovals = (interrupts, boundToolCallIds) => {
136
136
  ...interrupt.message !== void 0 && { prompt: interrupt.message }
137
137
  }]));
138
138
  };
139
+ /** A recorded decision authorizes one exact call and gate, not a reused id. */
140
+ const preserveToolApprovalDecision = (previous, next) => {
141
+ const prior = previous?.approval;
142
+ let approval = next.approval;
143
+ if (!approval && prior) {
144
+ const { approved: _approved, reason: _reason, resolution: _resolution, ...pending } = prior;
145
+ approval = pending;
146
+ }
147
+ if (!approval) return void 0;
148
+ if (!previous || prior?.id !== approval.id || previous.toolCallId !== next.toolCallId || previous.toolName !== next.toolName || (previous.argsText || "{}") !== (next.argsText || "{}")) return approval;
149
+ return {
150
+ ...approval,
151
+ ...prior.approved !== void 0 ? { approved: prior.approved } : {},
152
+ ...prior.reason !== void 0 ? { reason: prior.reason } : {},
153
+ ...prior.resolution !== void 0 ? { resolution: prior.resolution } : {}
154
+ };
155
+ };
139
156
  /**
140
157
  * Records a decision on the gated tool call. The decision is held on the part
141
158
  * until every gate in the batch is answered, because AG-UI resumes a run with
@@ -167,12 +184,13 @@ const withToolApprovalDecision = (content, { approvalId, approved, reason }) =>
167
184
  * drop the denial reason on the wire.
168
185
  */
169
186
  const buildToolApprovalResume = (content, interrupts) => {
170
- const open = new Set(interrupts.map((interrupt) => interrupt.id));
187
+ const calls = Array.from(iterateToolCallParts(content));
188
+ const gates = projectAgUiToolApprovals(interrupts, new Set(calls.map((part) => part.toolCallId)));
171
189
  const responses = /* @__PURE__ */ new Map();
172
- for (const part of iterateToolCallParts(content)) {
190
+ for (const part of calls) {
173
191
  const approval = part.approval;
174
192
  if (!approval || approval.approved === void 0) continue;
175
- if (!open.has(approval.id)) continue;
193
+ if (gates.get(part.toolCallId)?.id !== approval.id) continue;
176
194
  responses.set(approval.id, {
177
195
  status: "resolved",
178
196
  payload: {
@@ -237,7 +255,6 @@ const withSettledToolApprovals = (content, resume) => {
237
255
  });
238
256
  return changed ? next : content;
239
257
  };
240
- //#endregion
241
- export { buildToolApprovalResume, projectAgUiToolApprovals, withSettledToolApprovals, withToolApprovalDecision };
258
+ export { buildToolApprovalResume, preserveToolApprovalDecision, projectAgUiToolApprovals, withSettledToolApprovals, withToolApprovalDecision };
242
259
 
243
260
  //# sourceMappingURL=tool-approval.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-approval.js","names":[],"sources":["../../../src/runtime/adapter/tool-approval.ts"],"sourcesContent":["import {\n iterateToolCallParts,\n mapToolCallPartsDeep,\n} from \"@assistant-ui/core/internal\";\nimport { buildResumeArray } from \"@ag-ui/client\";\nimport type {\n RespondToToolApprovalOptions,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { AgUiInterrupt, AgUiResumeEntry } from \"../types\";\nimport {\n readRawResponseSchema,\n withoutRawResponseSchema,\n} from \"../interrupt-internals\";\n\ntype ToolApproval = NonNullable<ToolCallMessagePart[\"approval\"]>;\n\nconst EMPTY_APPROVALS: ReadonlyMap<string, ToolApproval> = new Map();\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isString = (value: unknown) => typeof value === \"string\";\n\nconst JSON_SCHEMA_TYPES = new Set([\n \"null\",\n \"boolean\",\n \"object\",\n \"array\",\n \"number\",\n \"integer\",\n \"string\",\n]);\n\nconst isUniqueStrings = (value: unknown) =>\n Array.isArray(value) &&\n value.every(isString) &&\n new Set(value).size === value.length;\n\nconst isSchemaType = (type: unknown) =>\n (isString(type) && JSON_SCHEMA_TYPES.has(type as string)) ||\n (Array.isArray(type) &&\n type.length > 0 &&\n isUniqueStrings(type) &&\n type.every((entry) => JSON_SCHEMA_TYPES.has(entry as string)));\n\nconst acceptsType = (type: unknown, primitive: string) =>\n type === primitive ||\n (Array.isArray(type) && isSchemaType(type) && type.includes(primitive));\n\nconst acceptsObject = (type: unknown) => acceptsType(type, \"object\");\n\nconst SUB_SCHEMA_ANNOTATIONS = new Set([\n \"$schema\",\n \"$id\",\n \"title\",\n \"description\",\n]);\n\n/**\n * A field schema accepts a value of `primitive` only where nothing in it can\n * narrow past the type: an annotation carries no constraint, and an absent\n * `type` constrains nothing. Any other keyword — `const`, `enum`, `anyOf`,\n * `format` — can reject the value this seam sends, so it is not interpreted.\n */\nconst acceptsOnly = (schema: unknown, primitive: string) =>\n isPlainObject(schema) &&\n Object.entries(schema).every(([keyword, value]) =>\n keyword === \"type\"\n ? acceptsType(value, primitive)\n : SUB_SCHEMA_ANNOTATIONS.has(keyword) && isString(value),\n );\n\n/**\n * Keywords of a sub-schema whose value shape a validator reads, each paired\n * with that shape: the same shapes the top-level schema is held to, plus\n * `properties` and `items`, which carry schemas, so a malformed one nested\n * under them is as uncompilable as a malformed one at the top. A keyword this\n * seam cannot judge is left alone: unlike the top-level schema, a field the\n * seam never sends needs only to be compilable, not permissive.\n */\nconst SUB_SCHEMA_SHAPES = new Map<string, (value: unknown) => boolean>([\n [\"type\", isSchemaType],\n [\"required\", isUniqueStrings],\n ...[...SUB_SCHEMA_ANNOTATIONS].map(\n (annotation) =>\n [annotation, isString] as [string, (value: unknown) => boolean],\n ),\n [\n \"properties\",\n (value) =>\n isPlainObject(value) &&\n Object.values(value).every((schema) => isWellFormedSubSchema(schema)),\n ],\n [\"items\", (value) => isWellFormedSubSchema(value)],\n]);\n\n/**\n * A schema the server cannot compile fails the run whatever payload follows, so\n * a field this seam never sends is still checked for the shape a validator\n * reads it as. A boolean is a schema in its own right.\n */\nconst isWellFormedSubSchema = (schema: unknown): boolean =>\n typeof schema === \"boolean\" ||\n (isPlainObject(schema) &&\n Object.entries(schema).every(([keyword, value]) => {\n const holds = SUB_SCHEMA_SHAPES.get(keyword);\n return holds === undefined || holds(value);\n }));\n\n/**\n * AG-UI's own tool-approval schema declares the fields it expects under\n * `properties`, so a declaration is read where it cannot reject what the seam\n * sends: `approved` must accept a boolean and `reason` a string. A field the\n * seam never sends is unconstrained by `required` (which admits only\n * `approved`), so only its well-formedness as a sub-schema is checked — the\n * `editedArgs` of the spec's approve-with-edits shape is such a field.\n */\nconst acceptsSeamProperties = (properties: unknown) =>\n isPlainObject(properties) &&\n Object.entries(properties).every(([field, schema]) => {\n if (field === \"approved\") return acceptsOnly(schema, \"boolean\");\n if (field === \"reason\") return acceptsOnly(schema, \"string\");\n return isWellFormedSubSchema(schema);\n });\n\nconst acceptsSeamPayload = (required: unknown) =>\n Array.isArray(required) &&\n required.every((field) => field === \"approved\") &&\n new Set(required).size === required.length;\n\n/**\n * Keywords that cannot reject a payload this seam emits, each paired with the\n * check that its value is the well-formed shape the keyword is read as. A\n * keyword whose value a validator would reject as an invalid schema is not\n * decided here, because a server that compiles the schema fails the run. An\n * unlisted keyword — `additionalProperties`, `allOf`, `$ref` — makes the gate\n * bespoke rather than being interpreted. The map is keyed by\n * `Map` rather than by object property, because a schema key of `constructor`\n * or `toString` would otherwise read an `Object.prototype` member as its\n * validator and `__proto__` would read the prototype itself.\n */\nconst SEAM_SAFE_KEYWORDS = new Map<string, (value: unknown) => boolean>([\n [\"$schema\", isString],\n [\"$id\", isString],\n [\"title\", isString],\n [\"description\", isString],\n [\"type\", acceptsObject],\n [\"required\", acceptsSeamPayload],\n [\"properties\", acceptsSeamProperties],\n]);\n\n/**\n * The seam sends `{ approved }` and may add `reason`, so it may answer a\n * `responseSchema` only where acceptance of those exact payloads is established\n * by construction. AG-UI answers a resume payload its schema rejects with\n * `RunError`, and the host can always build the exact payload through the\n * bespoke interrupt hooks, so an undecidable schema is left to them. Only an\n * absent schema and a plain object of well-formed allowed keywords establish\n * that: a boolean schema (`false` rejects every payload), a malformed one, and\n * a keyword whose value is not the shape it interprets are all left bespoke.\n */\nconst isSeamAnswerable = (schema: unknown) => {\n if (schema === undefined) return true;\n if (!isPlainObject(schema)) return false;\n return Object.entries(schema).every(([keyword, value]) => {\n const accepts = SEAM_SAFE_KEYWORDS.get(keyword);\n return accepts !== undefined && accepts(value);\n });\n};\n\nconst isGate = (\n interrupt: AgUiInterrupt,\n): interrupt is AgUiInterrupt & { toolCallId: string } =>\n interrupt.reason === \"tool_call\" &&\n !!interrupt.id &&\n !!interrupt.toolCallId &&\n // A restored interrupt is untyped, so `responseSchema` may hold any persisted\n // shape; a non-object schema received live arrives on the internal carrier.\n readRawResponseSchema(interrupt) === undefined &&\n isSeamAnswerable(interrupt.responseSchema);\n\nconst isPending = (approval: ToolCallMessagePart[\"approval\"]) =>\n !!approval && approval.approved === undefined && !approval.resolution;\n\n/**\n * AG-UI binds a decision to a tool call with `reason: \"tool_call\"`;\n * `confirmation` is a free-standing yes/no and `input_required` wants structured\n * input, so both stay on the bespoke interrupt hooks, as does a `tool_call`\n * whose `responseSchema` asks for more than this seam can send. A batch mixing a\n * gate with any other interrupt projects nothing: AG-UI resumes with one\n * response per open interrupt, so a half-owned batch cannot be completed from\n * either side alone.\n *\n * The same rule covers binding. A gate naming a tool call the message does not\n * render can never be decided through this seam, so the batch it belongs to\n * could never be completed either: the decisions taken on its visible siblings\n * would sit on the message while the run waited for a response that no click\n * can produce. `boundToolCallIds` spans every call the run produced — root or\n * nested on ToolCallMessagePart.messages — so only a gate naming a call the\n * message renders nowhere leaves the batch bespoke.\n */\nexport const projectAgUiToolApprovals = (\n interrupts: readonly AgUiInterrupt[] | undefined,\n boundToolCallIds?: ReadonlySet<string>,\n): ReadonlyMap<string, ToolApproval> => {\n if (!interrupts?.length || !interrupts.every(isGate)) return EMPTY_APPROVALS;\n if (\n boundToolCallIds &&\n !interrupts.every((interrupt) => boundToolCallIds.has(interrupt.toolCallId))\n ) {\n return EMPTY_APPROVALS;\n }\n // Two gates naming one tool call would collapse into a single approval, so\n // the batch could never be completed: the surviving gate takes one decision\n // while the resume array still waits on the id that no part carries.\n const toolCallIds = interrupts.map((interrupt) => interrupt.toolCallId);\n if (new Set(toolCallIds).size !== toolCallIds.length) return EMPTY_APPROVALS;\n return new Map(\n interrupts.map((interrupt) => [\n interrupt.toolCallId,\n {\n id: interrupt.id,\n ...(interrupt.message !== undefined && { prompt: interrupt.message }),\n },\n ]),\n );\n};\n\n/**\n * Records a decision on the gated tool call. The decision is held on the part\n * until every gate in the batch is answered, because AG-UI resumes a run with\n * one response per open interrupt rather than one response per gate. A chosen\n * `optionId` is not recorded: the projection exposes an approval without\n * options, and core rejects an `optionId` absent from them, so no option can\n * reach this seam.\n */\nexport const withToolApprovalDecision = (\n content: readonly ThreadAssistantMessagePart[],\n { approvalId, approved, reason }: RespondToToolApprovalOptions,\n): readonly ThreadAssistantMessagePart[] => {\n const { content: next, changed } = mapToolCallPartsDeep(content, (part) => {\n const approval = part.approval;\n if (approval?.id !== approvalId || !isPending(approval)) return part;\n return {\n ...part,\n approval: {\n ...approval,\n approved,\n ...(reason !== undefined && { reason }),\n },\n };\n });\n return changed ? next : content;\n};\n\n/**\n * Maps the recorded decisions onto AG-UI resume entries, or `null` while the\n * batch is incomplete. A denial is a resolved response carrying\n * `approved: false`, not a cancellation: `cancelled` means the user abandoned\n * the interrupt without meaningful input and carries no payload, which would\n * drop the denial reason on the wire.\n */\nexport const buildToolApprovalResume = (\n content: readonly ThreadAssistantMessagePart[],\n interrupts: readonly AgUiInterrupt[],\n): AgUiResumeEntry[] | null => {\n const open = new Set(interrupts.map((interrupt) => interrupt.id));\n // Decisions accumulate in a `Map` rather than in an object literal, because an\n // interrupt id of `__proto__` would otherwise write to the prototype chain\n // instead of recording a response, and `constructor` or `toString` would\n // report themselves as answered while undecided.\n const responses = new Map<string, { status: \"resolved\"; payload: unknown }>();\n for (const part of iterateToolCallParts(content)) {\n const approval = part.approval;\n if (!approval || approval.approved === undefined) continue;\n if (!open.has(approval.id)) continue;\n responses.set(approval.id, {\n status: \"resolved\",\n payload: {\n approved: approval.approved,\n ...(approval.reason !== undefined && { reason: approval.reason }),\n },\n });\n }\n if (interrupts.some((interrupt) => !responses.has(interrupt.id))) return null;\n // The schema is dropped rather than cast: AG-UI's own interrupt type cannot\n // express a boolean schema, and `buildResumeArray` reads only the ids.\n return buildResumeArray(\n interrupts.map((interrupt) => {\n const { responseSchema: _schema, ...rest } =\n withoutRawResponseSchema(interrupt);\n return rest;\n }),\n Object.fromEntries(responses),\n );\n};\n\nconst settle = (\n approval: ToolApproval,\n entry: AgUiResumeEntry,\n): ToolApproval | undefined => {\n // A decision this gate recorded locally but never sent is dropped rather than\n // displayed beside the settlement it contradicts: a submitted entry carries\n // the whole outcome, so no field of an earlier one may survive it.\n const {\n approved: _approved,\n reason: _reason,\n resolution: _resolution,\n ...rest\n } = approval;\n if (entry.status === \"cancelled\") {\n return { ...rest, resolution: \"cancelled\" };\n }\n const payload = entry.payload;\n if (\n typeof payload !== \"object\" ||\n payload === null ||\n typeof (payload as { approved?: unknown }).approved !== \"boolean\"\n ) {\n // The entry settles the gate with no decision. Nothing is fabricated, and a\n // decision recorded locally is dropped: the payload that went out carried\n // none, so displaying one would show what was never sent. The gate is still\n // marked terminal, because the interrupt it belonged to is closed and a\n // click on it afterwards would find nothing pending.\n return { ...rest, resolution: \"cancelled\" };\n }\n const { approved, reason } = payload as {\n approved: boolean;\n reason?: unknown;\n };\n return {\n ...rest,\n approved,\n ...(typeof reason === \"string\" && { reason }),\n };\n};\n\n/**\n * Settles every gate the submitted resume array names, so the displayed outcome\n * cannot contradict the wire. A decision recorded locally is not exempt: a gate\n * approved while the batch waited on its sibling is still cancelled when\n * `steerAway` submits a cancellation for it. A gate is shown as cancelled only\n * where its own entry is cancelled; a resolved entry supplies the decision it\n * carries, and one that carries none settles the gate with no decision rather\n * than fabricating one or keeping an unsent local decision beside it.\n *\n * A settlement always overrides an earlier one, in either direction. A resolved\n * settlement leaves no state a locally recorded decision does not also leave —\n * core's `resolution` covers only `cancelled` and `expired` — so honoring the\n * first settlement instead would mean treating an unsent local decision as\n * terminal, which is exactly what the cancellation case must override.\n */\nexport const withSettledToolApprovals = (\n content: readonly ThreadAssistantMessagePart[],\n resume: readonly AgUiResumeEntry[],\n): readonly ThreadAssistantMessagePart[] => {\n if (resume.length === 0) return content;\n const byId = new Map(resume.map((entry) => [entry.interruptId, entry]));\n const { content: next, changed } = mapToolCallPartsDeep(content, (part) => {\n const approval = part.approval;\n if (!approval) return part;\n const entry = byId.get(approval.id);\n if (!entry) return part;\n const settled = settle(approval, entry);\n if (!settled) return part;\n return { ...part, approval: settled };\n });\n return changed ? next : content;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-approval.js","names":[],"sources":["../../../src/runtime/adapter/tool-approval.ts"],"sourcesContent":["import {\n iterateToolCallParts,\n mapToolCallPartsDeep,\n} from \"@assistant-ui/core/internal\";\nimport { buildResumeArray } from \"@ag-ui/client\";\nimport type {\n RespondToToolApprovalOptions,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { AgUiInterrupt, AgUiResumeEntry } from \"../types\";\nimport {\n readRawResponseSchema,\n withoutRawResponseSchema,\n} from \"../interrupt-internals\";\n\ntype ToolApproval = NonNullable<ToolCallMessagePart[\"approval\"]>;\n\nconst EMPTY_APPROVALS: ReadonlyMap<string, ToolApproval> = new Map();\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isString = (value: unknown) => typeof value === \"string\";\n\nconst JSON_SCHEMA_TYPES = new Set([\n \"null\",\n \"boolean\",\n \"object\",\n \"array\",\n \"number\",\n \"integer\",\n \"string\",\n]);\n\nconst isUniqueStrings = (value: unknown) =>\n Array.isArray(value) &&\n value.every(isString) &&\n new Set(value).size === value.length;\n\nconst isSchemaType = (type: unknown) =>\n (isString(type) && JSON_SCHEMA_TYPES.has(type as string)) ||\n (Array.isArray(type) &&\n type.length > 0 &&\n isUniqueStrings(type) &&\n type.every((entry) => JSON_SCHEMA_TYPES.has(entry as string)));\n\nconst acceptsType = (type: unknown, primitive: string) =>\n type === primitive ||\n (Array.isArray(type) && isSchemaType(type) && type.includes(primitive));\n\nconst acceptsObject = (type: unknown) => acceptsType(type, \"object\");\n\nconst SUB_SCHEMA_ANNOTATIONS = new Set([\n \"$schema\",\n \"$id\",\n \"title\",\n \"description\",\n]);\n\n/**\n * A field schema accepts a value of `primitive` only where nothing in it can\n * narrow past the type: an annotation carries no constraint, and an absent\n * `type` constrains nothing. Any other keyword — `const`, `enum`, `anyOf`,\n * `format` — can reject the value this seam sends, so it is not interpreted.\n */\nconst acceptsOnly = (schema: unknown, primitive: string) =>\n isPlainObject(schema) &&\n Object.entries(schema).every(([keyword, value]) =>\n keyword === \"type\"\n ? acceptsType(value, primitive)\n : SUB_SCHEMA_ANNOTATIONS.has(keyword) && isString(value),\n );\n\n/**\n * Keywords of a sub-schema whose value shape a validator reads, each paired\n * with that shape: the same shapes the top-level schema is held to, plus\n * `properties` and `items`, which carry schemas, so a malformed one nested\n * under them is as uncompilable as a malformed one at the top. A keyword this\n * seam cannot judge is left alone: unlike the top-level schema, a field the\n * seam never sends needs only to be compilable, not permissive.\n */\nconst SUB_SCHEMA_SHAPES = new Map<string, (value: unknown) => boolean>([\n [\"type\", isSchemaType],\n [\"required\", isUniqueStrings],\n ...[...SUB_SCHEMA_ANNOTATIONS].map(\n (annotation) =>\n [annotation, isString] as [string, (value: unknown) => boolean],\n ),\n [\n \"properties\",\n (value) =>\n isPlainObject(value) &&\n Object.values(value).every((schema) => isWellFormedSubSchema(schema)),\n ],\n [\"items\", (value) => isWellFormedSubSchema(value)],\n]);\n\n/**\n * A schema the server cannot compile fails the run whatever payload follows, so\n * a field this seam never sends is still checked for the shape a validator\n * reads it as. A boolean is a schema in its own right.\n */\nconst isWellFormedSubSchema = (schema: unknown): boolean =>\n typeof schema === \"boolean\" ||\n (isPlainObject(schema) &&\n Object.entries(schema).every(([keyword, value]) => {\n const holds = SUB_SCHEMA_SHAPES.get(keyword);\n return holds === undefined || holds(value);\n }));\n\n/**\n * AG-UI's own tool-approval schema declares the fields it expects under\n * `properties`, so a declaration is read where it cannot reject what the seam\n * sends: `approved` must accept a boolean and `reason` a string. A field the\n * seam never sends is unconstrained by `required` (which admits only\n * `approved`), so only its well-formedness as a sub-schema is checked — the\n * `editedArgs` of the spec's approve-with-edits shape is such a field.\n */\nconst acceptsSeamProperties = (properties: unknown) =>\n isPlainObject(properties) &&\n Object.entries(properties).every(([field, schema]) => {\n if (field === \"approved\") return acceptsOnly(schema, \"boolean\");\n if (field === \"reason\") return acceptsOnly(schema, \"string\");\n return isWellFormedSubSchema(schema);\n });\n\nconst acceptsSeamPayload = (required: unknown) =>\n Array.isArray(required) &&\n required.every((field) => field === \"approved\") &&\n new Set(required).size === required.length;\n\n/**\n * Keywords that cannot reject a payload this seam emits, each paired with the\n * check that its value is the well-formed shape the keyword is read as. A\n * keyword whose value a validator would reject as an invalid schema is not\n * decided here, because a server that compiles the schema fails the run. An\n * unlisted keyword — `additionalProperties`, `allOf`, `$ref` — makes the gate\n * bespoke rather than being interpreted. The map is keyed by\n * `Map` rather than by object property, because a schema key of `constructor`\n * or `toString` would otherwise read an `Object.prototype` member as its\n * validator and `__proto__` would read the prototype itself.\n */\nconst SEAM_SAFE_KEYWORDS = new Map<string, (value: unknown) => boolean>([\n [\"$schema\", isString],\n [\"$id\", isString],\n [\"title\", isString],\n [\"description\", isString],\n [\"type\", acceptsObject],\n [\"required\", acceptsSeamPayload],\n [\"properties\", acceptsSeamProperties],\n]);\n\n/**\n * The seam sends `{ approved }` and may add `reason`, so it may answer a\n * `responseSchema` only where acceptance of those exact payloads is established\n * by construction. AG-UI answers a resume payload its schema rejects with\n * `RunError`, and the host can always build the exact payload through the\n * bespoke interrupt hooks, so an undecidable schema is left to them. Only an\n * absent schema and a plain object of well-formed allowed keywords establish\n * that: a boolean schema (`false` rejects every payload), a malformed one, and\n * a keyword whose value is not the shape it interprets are all left bespoke.\n */\nconst isSeamAnswerable = (schema: unknown) => {\n if (schema === undefined) return true;\n if (!isPlainObject(schema)) return false;\n return Object.entries(schema).every(([keyword, value]) => {\n const accepts = SEAM_SAFE_KEYWORDS.get(keyword);\n return accepts !== undefined && accepts(value);\n });\n};\n\nconst isGate = (\n interrupt: AgUiInterrupt,\n): interrupt is AgUiInterrupt & { toolCallId: string } =>\n interrupt.reason === \"tool_call\" &&\n !!interrupt.id &&\n !!interrupt.toolCallId &&\n // A restored interrupt is untyped, so `responseSchema` may hold any persisted\n // shape; a non-object schema received live arrives on the internal carrier.\n readRawResponseSchema(interrupt) === undefined &&\n isSeamAnswerable(interrupt.responseSchema);\n\nconst isPending = (approval: ToolCallMessagePart[\"approval\"]) =>\n !!approval && approval.approved === undefined && !approval.resolution;\n\n/**\n * AG-UI binds a decision to a tool call with `reason: \"tool_call\"`;\n * `confirmation` is a free-standing yes/no and `input_required` wants structured\n * input, so both stay on the bespoke interrupt hooks, as does a `tool_call`\n * whose `responseSchema` asks for more than this seam can send. A batch mixing a\n * gate with any other interrupt projects nothing: AG-UI resumes with one\n * response per open interrupt, so a half-owned batch cannot be completed from\n * either side alone.\n *\n * The same rule covers binding. A gate naming a tool call the message does not\n * render can never be decided through this seam, so the batch it belongs to\n * could never be completed either: the decisions taken on its visible siblings\n * would sit on the message while the run waited for a response that no click\n * can produce. `boundToolCallIds` spans every call the run produced — root or\n * nested on ToolCallMessagePart.messages — so only a gate naming a call the\n * message renders nowhere leaves the batch bespoke.\n */\nexport const projectAgUiToolApprovals = (\n interrupts: readonly AgUiInterrupt[] | undefined,\n boundToolCallIds?: ReadonlySet<string>,\n): ReadonlyMap<string, ToolApproval> => {\n if (!interrupts?.length || !interrupts.every(isGate)) return EMPTY_APPROVALS;\n if (\n boundToolCallIds &&\n !interrupts.every((interrupt) => boundToolCallIds.has(interrupt.toolCallId))\n ) {\n return EMPTY_APPROVALS;\n }\n // Two gates naming one tool call would collapse into a single approval, so\n // the batch could never be completed: the surviving gate takes one decision\n // while the resume array still waits on the id that no part carries.\n const toolCallIds = interrupts.map((interrupt) => interrupt.toolCallId);\n if (new Set(toolCallIds).size !== toolCallIds.length) return EMPTY_APPROVALS;\n return new Map(\n interrupts.map((interrupt) => [\n interrupt.toolCallId,\n {\n id: interrupt.id,\n ...(interrupt.message !== undefined && { prompt: interrupt.message }),\n },\n ]),\n );\n};\n\n/** A recorded decision authorizes one exact call and gate, not a reused id. */\nexport const preserveToolApprovalDecision = (\n previous: ToolCallMessagePart | undefined,\n next: ToolCallMessagePart,\n): ToolApproval | undefined => {\n const prior = previous?.approval;\n let approval = next.approval;\n if (!approval && prior) {\n const {\n approved: _approved,\n reason: _reason,\n resolution: _resolution,\n ...pending\n } = prior;\n approval = pending;\n }\n if (!approval) return undefined;\n // AG-UI may omit argument events for a no-argument call; both forms mean {}.\n if (\n !previous ||\n prior?.id !== approval.id ||\n previous.toolCallId !== next.toolCallId ||\n previous.toolName !== next.toolName ||\n (previous.argsText || \"{}\") !== (next.argsText || \"{}\")\n )\n return approval;\n return {\n ...approval,\n ...(prior.approved !== undefined ? { approved: prior.approved } : {}),\n ...(prior.reason !== undefined ? { reason: prior.reason } : {}),\n ...(prior.resolution !== undefined ? { resolution: prior.resolution } : {}),\n };\n};\n\n/**\n * Records a decision on the gated tool call. The decision is held on the part\n * until every gate in the batch is answered, because AG-UI resumes a run with\n * one response per open interrupt rather than one response per gate. A chosen\n * `optionId` is not recorded: the projection exposes an approval without\n * options, and core rejects an `optionId` absent from them, so no option can\n * reach this seam.\n */\nexport const withToolApprovalDecision = (\n content: readonly ThreadAssistantMessagePart[],\n { approvalId, approved, reason }: RespondToToolApprovalOptions,\n): readonly ThreadAssistantMessagePart[] => {\n const { content: next, changed } = mapToolCallPartsDeep(content, (part) => {\n const approval = part.approval;\n if (approval?.id !== approvalId || !isPending(approval)) return part;\n return {\n ...part,\n approval: {\n ...approval,\n approved,\n ...(reason !== undefined && { reason }),\n },\n };\n });\n return changed ? next : content;\n};\n\n/**\n * Maps the recorded decisions onto AG-UI resume entries, or `null` while the\n * batch is incomplete. A denial is a resolved response carrying\n * `approved: false`, not a cancellation: `cancelled` means the user abandoned\n * the interrupt without meaningful input and carries no payload, which would\n * drop the denial reason on the wire.\n */\nexport const buildToolApprovalResume = (\n content: readonly ThreadAssistantMessagePart[],\n interrupts: readonly AgUiInterrupt[],\n): AgUiResumeEntry[] | null => {\n const calls = Array.from(iterateToolCallParts(content));\n const gates = projectAgUiToolApprovals(\n interrupts,\n new Set(calls.map((part) => part.toolCallId)),\n );\n // Decisions accumulate in a `Map` rather than in an object literal, because an\n // interrupt id of `__proto__` would otherwise write to the prototype chain\n // instead of recording a response, and `constructor` or `toString` would\n // report themselves as answered while undecided.\n const responses = new Map<string, { status: \"resolved\"; payload: unknown }>();\n for (const part of calls) {\n const approval = part.approval;\n if (!approval || approval.approved === undefined) continue;\n if (gates.get(part.toolCallId)?.id !== approval.id) continue;\n responses.set(approval.id, {\n status: \"resolved\",\n payload: {\n approved: approval.approved,\n ...(approval.reason !== undefined && { reason: approval.reason }),\n },\n });\n }\n if (interrupts.some((interrupt) => !responses.has(interrupt.id))) return null;\n // The schema is dropped rather than cast: AG-UI's own interrupt type cannot\n // express a boolean schema, and `buildResumeArray` reads only the ids.\n return buildResumeArray(\n interrupts.map((interrupt) => {\n const { responseSchema: _schema, ...rest } =\n withoutRawResponseSchema(interrupt);\n return rest;\n }),\n Object.fromEntries(responses),\n );\n};\n\nconst settle = (\n approval: ToolApproval,\n entry: AgUiResumeEntry,\n): ToolApproval | undefined => {\n // A decision this gate recorded locally but never sent is dropped rather than\n // displayed beside the settlement it contradicts: a submitted entry carries\n // the whole outcome, so no field of an earlier one may survive it.\n const {\n approved: _approved,\n reason: _reason,\n resolution: _resolution,\n ...rest\n } = approval;\n if (entry.status === \"cancelled\") {\n return { ...rest, resolution: \"cancelled\" };\n }\n const payload = entry.payload;\n if (\n typeof payload !== \"object\" ||\n payload === null ||\n typeof (payload as { approved?: unknown }).approved !== \"boolean\"\n ) {\n // The entry settles the gate with no decision. Nothing is fabricated, and a\n // decision recorded locally is dropped: the payload that went out carried\n // none, so displaying one would show what was never sent. The gate is still\n // marked terminal, because the interrupt it belonged to is closed and a\n // click on it afterwards would find nothing pending.\n return { ...rest, resolution: \"cancelled\" };\n }\n const { approved, reason } = payload as {\n approved: boolean;\n reason?: unknown;\n };\n return {\n ...rest,\n approved,\n ...(typeof reason === \"string\" && { reason }),\n };\n};\n\n/**\n * Settles every gate the submitted resume array names, so the displayed outcome\n * cannot contradict the wire. A decision recorded locally is not exempt: a gate\n * approved while the batch waited on its sibling is still cancelled when\n * `steerAway` submits a cancellation for it. A gate is shown as cancelled only\n * where its own entry is cancelled; a resolved entry supplies the decision it\n * carries, and one that carries none settles the gate with no decision rather\n * than fabricating one or keeping an unsent local decision beside it.\n *\n * A settlement always overrides an earlier one, in either direction. A resolved\n * settlement leaves no state a locally recorded decision does not also leave —\n * core's `resolution` covers only `cancelled` and `expired` — so honoring the\n * first settlement instead would mean treating an unsent local decision as\n * terminal, which is exactly what the cancellation case must override.\n */\nexport const withSettledToolApprovals = (\n content: readonly ThreadAssistantMessagePart[],\n resume: readonly AgUiResumeEntry[],\n): readonly ThreadAssistantMessagePart[] => {\n if (resume.length === 0) return content;\n const byId = new Map(resume.map((entry) => [entry.interruptId, entry]));\n const { content: next, changed } = mapToolCallPartsDeep(content, (part) => {\n const approval = part.approval;\n if (!approval) return part;\n const entry = byId.get(approval.id);\n if (!entry) return part;\n const settled = settle(approval, entry);\n if (!settled) return part;\n return { ...part, approval: settled };\n });\n return changed ? next : content;\n};\n"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { RunConfig } from "@assistant-ui/core";
2
+ import type { ReadonlyJSONValue } from "assistant-stream/utils";
3
+ export type AgUiThreadState = {
4
+ isRunning: boolean;
5
+ isLoading: boolean;
6
+ loadRequested: boolean;
7
+ historyMutationGeneration: number;
8
+ stateSnapshot: ReadonlyJSONValue | undefined;
9
+ lastRunConfig: RunConfig | undefined;
10
+ pendingResume: {
11
+ owner: AbortController;
12
+ messageIds: readonly string[];
13
+ } | null;
14
+ pendingA2uiResumeOwner: AbortController | null;
15
+ pendingA2uiAction: Record<string, unknown> | undefined;
16
+ };
17
+ export type AgUiThreadAction = {
18
+ type: "runStarted";
19
+ } | {
20
+ type: "runFinished";
21
+ } | {
22
+ type: "loadRequested";
23
+ } | {
24
+ type: "loadStarted";
25
+ } | {
26
+ type: "loadFinished";
27
+ } | {
28
+ type: "historyMutationAdvanced";
29
+ } | {
30
+ type: "stateSnapshot";
31
+ snapshot: ReadonlyJSONValue;
32
+ } | {
33
+ type: "resetState";
34
+ } | {
35
+ type: "runConfigRecorded";
36
+ runConfig: RunConfig;
37
+ } | {
38
+ type: "resumeDeferred";
39
+ owner: AbortController;
40
+ messageId: string;
41
+ } | {
42
+ type: "resumeCleared";
43
+ } | {
44
+ type: "a2uiResumeDeferred";
45
+ owner: AbortController;
46
+ } | {
47
+ type: "a2uiResumeCleared";
48
+ } | {
49
+ type: "a2uiActionDeferred";
50
+ action: Record<string, unknown>;
51
+ } | {
52
+ type: "a2uiActionCleared";
53
+ } | {
54
+ type: "a2uiContinuationsCleared";
55
+ } | {
56
+ type: "resetThread";
57
+ };
58
+ export declare const createAgUiThreadState: () => AgUiThreadState;
59
+ export declare const reduceAgUiThreadState: (state: AgUiThreadState, action: AgUiThreadAction) => AgUiThreadState;
60
+ //# sourceMappingURL=agUiThreadState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agUiThreadState.d.ts","sourceRoot":"","sources":["../../src/runtime/agUiThreadState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,yBAAyB,EAAE,MAAM,CAAC;IAClC,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,aAAa,EAAE;QACb,KAAK,EAAE,eAAe,CAAC;QACvB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;KAC/B,GAAG,IAAI,CAAC;IACT,sBAAsB,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,yBAAyB,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,0BAA0B,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5B,eAAO,MAAM,qBAAqB,QAAO,eAUvC,CAAC;AAEH,eAAO,MAAM,qBAAqB,GAChC,OAAO,eAAe,EACtB,QAAQ,gBAAgB,KACvB,eAsFF,CAAC"}
@@ -0,0 +1,94 @@
1
+ // src/runtime/agUiThreadState.ts
2
+ const createAgUiThreadState = () => ({
3
+ isRunning: false,
4
+ isLoading: false,
5
+ loadRequested: false,
6
+ historyMutationGeneration: 0,
7
+ stateSnapshot: void 0,
8
+ lastRunConfig: void 0,
9
+ pendingResume: null,
10
+ pendingA2uiResumeOwner: null,
11
+ pendingA2uiAction: void 0
12
+ });
13
+ const reduceAgUiThreadState = (state, action) => {
14
+ switch (action.type) {
15
+ case "runStarted": return state.isRunning ? state : {
16
+ ...state,
17
+ isRunning: true
18
+ };
19
+ case "runFinished": return !state.isRunning ? state : {
20
+ ...state,
21
+ isRunning: false
22
+ };
23
+ case "loadRequested": return state.loadRequested ? state : {
24
+ ...state,
25
+ loadRequested: true
26
+ };
27
+ case "loadStarted": return state.isLoading ? state : {
28
+ ...state,
29
+ isLoading: true
30
+ };
31
+ case "loadFinished": return !state.isLoading ? state : {
32
+ ...state,
33
+ isLoading: false
34
+ };
35
+ case "historyMutationAdvanced": return {
36
+ ...state,
37
+ historyMutationGeneration: state.historyMutationGeneration + 1
38
+ };
39
+ case "stateSnapshot": return state.stateSnapshot === action.snapshot ? state : {
40
+ ...state,
41
+ stateSnapshot: action.snapshot
42
+ };
43
+ case "resetState": return state.stateSnapshot === void 0 ? state : {
44
+ ...state,
45
+ stateSnapshot: void 0
46
+ };
47
+ case "runConfigRecorded": return state.lastRunConfig === action.runConfig ? state : {
48
+ ...state,
49
+ lastRunConfig: action.runConfig
50
+ };
51
+ case "resumeDeferred": return state.pendingResume?.owner === action.owner && state.pendingResume.messageIds.includes(action.messageId) ? state : {
52
+ ...state,
53
+ pendingResume: {
54
+ owner: action.owner,
55
+ messageIds: state.pendingResume?.owner === action.owner ? [...state.pendingResume.messageIds, action.messageId] : [action.messageId]
56
+ }
57
+ };
58
+ case "resumeCleared": return state.pendingResume === null ? state : {
59
+ ...state,
60
+ pendingResume: null
61
+ };
62
+ case "a2uiResumeDeferred": return state.pendingA2uiResumeOwner === action.owner ? state : {
63
+ ...state,
64
+ pendingA2uiResumeOwner: action.owner
65
+ };
66
+ case "a2uiResumeCleared": return state.pendingA2uiResumeOwner === null ? state : {
67
+ ...state,
68
+ pendingA2uiResumeOwner: null
69
+ };
70
+ case "a2uiActionDeferred": return state.pendingA2uiAction === action.action ? state : {
71
+ ...state,
72
+ pendingA2uiAction: action.action
73
+ };
74
+ case "a2uiActionCleared": return state.pendingA2uiAction === void 0 ? state : {
75
+ ...state,
76
+ pendingA2uiAction: void 0
77
+ };
78
+ case "a2uiContinuationsCleared": return state.pendingA2uiResumeOwner === null && state.pendingA2uiAction === void 0 ? state : {
79
+ ...state,
80
+ pendingA2uiResumeOwner: null,
81
+ pendingA2uiAction: void 0
82
+ };
83
+ case "resetThread": return state.stateSnapshot === void 0 && state.pendingResume === null && state.pendingA2uiResumeOwner === null && state.pendingA2uiAction === void 0 ? state : {
84
+ ...state,
85
+ stateSnapshot: void 0,
86
+ pendingResume: null,
87
+ pendingA2uiResumeOwner: null,
88
+ pendingA2uiAction: void 0
89
+ };
90
+ }
91
+ };
92
+ export { createAgUiThreadState, reduceAgUiThreadState };
93
+
94
+ //# sourceMappingURL=agUiThreadState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agUiThreadState.js","names":[],"sources":["../../src/runtime/agUiThreadState.ts"],"sourcesContent":["import type { RunConfig } from \"@assistant-ui/core\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\n\nexport type AgUiThreadState = {\n isRunning: boolean;\n isLoading: boolean;\n loadRequested: boolean;\n historyMutationGeneration: number;\n stateSnapshot: ReadonlyJSONValue | undefined;\n lastRunConfig: RunConfig | undefined;\n pendingResume: {\n owner: AbortController;\n messageIds: readonly string[];\n } | null;\n pendingA2uiResumeOwner: AbortController | null;\n pendingA2uiAction: Record<string, unknown> | undefined;\n};\n\nexport type AgUiThreadAction =\n | { type: \"runStarted\" }\n | { type: \"runFinished\" }\n | { type: \"loadRequested\" }\n | { type: \"loadStarted\" }\n | { type: \"loadFinished\" }\n | { type: \"historyMutationAdvanced\" }\n | { type: \"stateSnapshot\"; snapshot: ReadonlyJSONValue }\n | { type: \"resetState\" }\n | { type: \"runConfigRecorded\"; runConfig: RunConfig }\n | { type: \"resumeDeferred\"; owner: AbortController; messageId: string }\n | { type: \"resumeCleared\" }\n | { type: \"a2uiResumeDeferred\"; owner: AbortController }\n | { type: \"a2uiResumeCleared\" }\n | { type: \"a2uiActionDeferred\"; action: Record<string, unknown> }\n | { type: \"a2uiActionCleared\" }\n | { type: \"a2uiContinuationsCleared\" }\n | { type: \"resetThread\" };\n\nexport const createAgUiThreadState = (): AgUiThreadState => ({\n isRunning: false,\n isLoading: false,\n loadRequested: false,\n historyMutationGeneration: 0,\n stateSnapshot: undefined,\n lastRunConfig: undefined,\n pendingResume: null,\n pendingA2uiResumeOwner: null,\n pendingA2uiAction: undefined,\n});\n\nexport const reduceAgUiThreadState = (\n state: AgUiThreadState,\n action: AgUiThreadAction,\n): AgUiThreadState => {\n switch (action.type) {\n case \"runStarted\":\n return state.isRunning ? state : { ...state, isRunning: true };\n case \"runFinished\":\n return !state.isRunning ? state : { ...state, isRunning: false };\n case \"loadRequested\":\n return state.loadRequested ? state : { ...state, loadRequested: true };\n case \"loadStarted\":\n return state.isLoading ? state : { ...state, isLoading: true };\n case \"loadFinished\":\n return !state.isLoading ? state : { ...state, isLoading: false };\n case \"historyMutationAdvanced\":\n return {\n ...state,\n historyMutationGeneration: state.historyMutationGeneration + 1,\n };\n case \"stateSnapshot\":\n return state.stateSnapshot === action.snapshot\n ? state\n : { ...state, stateSnapshot: action.snapshot };\n case \"resetState\":\n return state.stateSnapshot === undefined\n ? state\n : { ...state, stateSnapshot: undefined };\n case \"runConfigRecorded\":\n return state.lastRunConfig === action.runConfig\n ? state\n : { ...state, lastRunConfig: action.runConfig };\n case \"resumeDeferred\":\n return state.pendingResume?.owner === action.owner &&\n state.pendingResume.messageIds.includes(action.messageId)\n ? state\n : {\n ...state,\n pendingResume: {\n owner: action.owner,\n messageIds:\n state.pendingResume?.owner === action.owner\n ? [...state.pendingResume.messageIds, action.messageId]\n : [action.messageId],\n },\n };\n case \"resumeCleared\":\n return state.pendingResume === null\n ? state\n : { ...state, pendingResume: null };\n case \"a2uiResumeDeferred\":\n return state.pendingA2uiResumeOwner === action.owner\n ? state\n : { ...state, pendingA2uiResumeOwner: action.owner };\n case \"a2uiResumeCleared\":\n return state.pendingA2uiResumeOwner === null\n ? state\n : { ...state, pendingA2uiResumeOwner: null };\n case \"a2uiActionDeferred\":\n return state.pendingA2uiAction === action.action\n ? state\n : { ...state, pendingA2uiAction: action.action };\n case \"a2uiActionCleared\":\n return state.pendingA2uiAction === undefined\n ? state\n : { ...state, pendingA2uiAction: undefined };\n case \"a2uiContinuationsCleared\":\n return state.pendingA2uiResumeOwner === null &&\n state.pendingA2uiAction === undefined\n ? state\n : {\n ...state,\n pendingA2uiResumeOwner: null,\n pendingA2uiAction: undefined,\n };\n case \"resetThread\":\n return state.stateSnapshot === undefined &&\n state.pendingResume === null &&\n state.pendingA2uiResumeOwner === null &&\n state.pendingA2uiAction === undefined\n ? state\n : {\n ...state,\n stateSnapshot: undefined,\n pendingResume: null,\n pendingA2uiResumeOwner: null,\n pendingA2uiAction: undefined,\n };\n }\n};\n"],"mappings":";AAqCA,MAAa,+BAAgD;CAC3D,WAAW;CACX,WAAW;CACX,eAAe;CACf,2BAA2B;CAC3B,eAAe,KAAA;CACf,eAAe,KAAA;CACf,eAAe;CACf,wBAAwB;CACxB,mBAAmB,KAAA;AACrB;AAEA,MAAa,yBACX,OACA,WACoB;CACpB,QAAQ,OAAO,MAAf;EACE,KAAK,cACH,OAAO,MAAM,YAAY,QAAQ;GAAE,GAAG;GAAO,WAAW;EAAK;EAC/D,KAAK,eACH,OAAO,CAAC,MAAM,YAAY,QAAQ;GAAE,GAAG;GAAO,WAAW;EAAM;EACjE,KAAK,iBACH,OAAO,MAAM,gBAAgB,QAAQ;GAAE,GAAG;GAAO,eAAe;EAAK;EACvE,KAAK,eACH,OAAO,MAAM,YAAY,QAAQ;GAAE,GAAG;GAAO,WAAW;EAAK;EAC/D,KAAK,gBACH,OAAO,CAAC,MAAM,YAAY,QAAQ;GAAE,GAAG;GAAO,WAAW;EAAM;EACjE,KAAK,2BACH,OAAO;GACL,GAAG;GACH,2BAA2B,MAAM,4BAA4B;EAC/D;EACF,KAAK,iBACH,OAAO,MAAM,kBAAkB,OAAO,WAClC,QACA;GAAE,GAAG;GAAO,eAAe,OAAO;EAAS;EACjD,KAAK,cACH,OAAO,MAAM,kBAAkB,KAAA,IAC3B,QACA;GAAE,GAAG;GAAO,eAAe,KAAA;EAAU;EAC3C,KAAK,qBACH,OAAO,MAAM,kBAAkB,OAAO,YAClC,QACA;GAAE,GAAG;GAAO,eAAe,OAAO;EAAU;EAClD,KAAK,kBACH,OAAO,MAAM,eAAe,UAAU,OAAO,SAC3C,MAAM,cAAc,WAAW,SAAS,OAAO,SAAS,IACtD,QACA;GACE,GAAG;GACH,eAAe;IACb,OAAO,OAAO;IACd,YACE,MAAM,eAAe,UAAU,OAAO,QAClC,CAAC,GAAG,MAAM,cAAc,YAAY,OAAO,SAAS,IACpD,CAAC,OAAO,SAAS;GACzB;EACF;EACN,KAAK,iBACH,OAAO,MAAM,kBAAkB,OAC3B,QACA;GAAE,GAAG;GAAO,eAAe;EAAK;EACtC,KAAK,sBACH,OAAO,MAAM,2BAA2B,OAAO,QAC3C,QACA;GAAE,GAAG;GAAO,wBAAwB,OAAO;EAAM;EACvD,KAAK,qBACH,OAAO,MAAM,2BAA2B,OACpC,QACA;GAAE,GAAG;GAAO,wBAAwB;EAAK;EAC/C,KAAK,sBACH,OAAO,MAAM,sBAAsB,OAAO,SACtC,QACA;GAAE,GAAG;GAAO,mBAAmB,OAAO;EAAO;EACnD,KAAK,qBACH,OAAO,MAAM,sBAAsB,KAAA,IAC/B,QACA;GAAE,GAAG;GAAO,mBAAmB,KAAA;EAAU;EAC/C,KAAK,4BACH,OAAO,MAAM,2BAA2B,QACtC,MAAM,sBAAsB,KAAA,IAC1B,QACA;GACE,GAAG;GACH,wBAAwB;GACxB,mBAAmB,KAAA;EACrB;EACN,KAAK,eACH,OAAO,MAAM,kBAAkB,KAAA,KAC7B,MAAM,kBAAkB,QACxB,MAAM,2BAA2B,QACjC,MAAM,sBAAsB,KAAA,IAC1B,QACA;GACE,GAAG;GACH,eAAe,KAAA;GACf,eAAe;GACf,wBAAwB;GACxB,mBAAmB,KAAA;EACrB;CACR;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"event-parser.d.ts","sourceRoot":"","sources":["../../src/runtime/event-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAIV,mBAAgB;AACjB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAIvC,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAkHF,eAAO,MAAM,cAAc,GACzB,OAAO,OAAO,EACd,UAAU,qBAAqB,KAC9B,SAAS,GAAG,IAyXd,CAAC"}
1
+ {"version":3,"file":"event-parser.d.ts","sourceRoot":"","sources":["../../src/runtime/event-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAIV,mBAAgB;AACjB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAKvC,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AA8HF,eAAO,MAAM,cAAc,GACzB,OAAO,OAAO,EACd,UAAU,qBAAqB,KAC9B,SAAS,GAAG,IA0Vd,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { parseMcpToolCallResult } from "./mcp-tool-result.js";
2
2
  import { withRawResponseSchema } from "./interrupt-internals.js";
3
- //#region src/runtime/event-parser.ts
3
+ // src/runtime/event-parser.ts
4
4
  const isString = (value) => typeof value === "string";
5
5
  const isNonEmptyString = (value) => isString(value) && value.length > 0;
6
6
  const withOptional = (base, optionals) => {
@@ -40,7 +40,8 @@ const parseRunFinishedOutcome = (raw, runId, logger) => {
40
40
  }, "has invalid outcome");
41
41
  return;
42
42
  }
43
- if (raw.type === "success") return { type: "success" };
43
+ if (raw.type === "success") return withOptional({ type: "success" }, { pendingToolCallIds: Array.isArray(raw.pendingToolCallIds) && raw.pendingToolCallIds.every(isString) ? raw.pendingToolCallIds : void 0 });
44
+ if (raw.type === "cancelled") return { type: "cancelled" };
44
45
  if (raw.type === "interrupt") {
45
46
  if (!Array.isArray(raw.interrupts)) {
46
47
  logRejectedEvent(logger, "RUN_FINISHED", {
@@ -134,52 +135,49 @@ const parseAgUiEvent = (event, options) => {
134
135
  messageId: getString("messageId"),
135
136
  subagentRunId: getString("subagentRunId")
136
137
  });
137
- case "TEXT_MESSAGE_CHUNK": {
138
- const delta = getString("delta") ?? "";
138
+ case "REASONING_START": {
139
+ const messageId = getString("messageId");
140
+ if (!messageId) return reject("missing messageId");
139
141
  return withOptional({
140
- type: "TEXT_MESSAGE_CHUNK",
141
- delta
142
+ type: "REASONING_START",
143
+ messageId
142
144
  }, {
143
- messageId: getString("messageId"),
144
- subagentRunId: getString("subagentRunId")
145
+ subagentRunId: getString("subagentRunId"),
146
+ timestamp
147
+ });
148
+ }
149
+ case "REASONING_MESSAGE_START": {
150
+ const messageId = getString("messageId");
151
+ if (!messageId) return reject("missing messageId");
152
+ return withOptional({
153
+ type: "REASONING_MESSAGE_START",
154
+ messageId
155
+ }, {
156
+ subagentRunId: getString("subagentRunId"),
157
+ timestamp
145
158
  });
146
159
  }
147
- case "THINKING_START": return withOptional({ type: "THINKING_START" }, {
148
- title: getString("title"),
149
- timestamp
150
- });
151
- case "THINKING_TEXT_MESSAGE_START": return withOptional({ type: "THINKING_TEXT_MESSAGE_START" }, { timestamp });
152
- case "THINKING_TEXT_MESSAGE_CONTENT": return {
153
- type: "THINKING_TEXT_MESSAGE_CONTENT",
154
- delta: getString("delta") ?? ""
155
- };
156
- case "THINKING_TEXT_MESSAGE_END": return withOptional({ type: "THINKING_TEXT_MESSAGE_END" }, { timestamp });
157
- case "THINKING_END": return withOptional({ type: "THINKING_END" }, { timestamp });
158
- case "REASONING_START": return withOptional({ type: "REASONING_START" }, {
159
- messageId: getString("messageId"),
160
- subagentRunId: getString("subagentRunId"),
161
- timestamp
162
- });
163
- case "REASONING_MESSAGE_START": return withOptional({ type: "REASONING_MESSAGE_START" }, {
164
- messageId: getString("messageId"),
165
- subagentRunId: getString("subagentRunId"),
166
- timestamp
167
- });
168
160
  case "REASONING_MESSAGE_CONTENT": {
161
+ const messageId = getString("messageId");
162
+ if (!messageId) return reject("missing messageId");
169
163
  const delta = getString("delta") ?? "";
170
164
  return withOptional({
171
165
  type: "REASONING_MESSAGE_CONTENT",
166
+ messageId,
172
167
  delta
168
+ }, { subagentRunId: getString("subagentRunId") });
169
+ }
170
+ case "REASONING_MESSAGE_END": {
171
+ const messageId = getString("messageId");
172
+ if (!messageId) return reject("missing messageId");
173
+ return withOptional({
174
+ type: "REASONING_MESSAGE_END",
175
+ messageId
173
176
  }, {
174
- messageId: getString("messageId"),
175
- subagentRunId: getString("subagentRunId")
177
+ subagentRunId: getString("subagentRunId"),
178
+ timestamp
176
179
  });
177
180
  }
178
- case "REASONING_MESSAGE_END": return withOptional({ type: "REASONING_MESSAGE_END" }, {
179
- messageId: getString("messageId"),
180
- subagentRunId: getString("subagentRunId"),
181
- timestamp
182
- });
183
181
  case "REASONING_ENCRYPTED_VALUE": {
184
182
  const entityId = getString("entityId");
185
183
  const encryptedValue = getString("encryptedValue");
@@ -195,11 +193,17 @@ const parseAgUiEvent = (event, options) => {
195
193
  ...subagentRunId !== void 0 ? { subagentRunId } : {}
196
194
  };
197
195
  }
198
- case "REASONING_END": return withOptional({ type: "REASONING_END" }, {
199
- messageId: getString("messageId"),
200
- subagentRunId: getString("subagentRunId"),
201
- timestamp
202
- });
196
+ case "REASONING_END": {
197
+ const messageId = getString("messageId");
198
+ if (!messageId) return reject("missing messageId");
199
+ return withOptional({
200
+ type: "REASONING_END",
201
+ messageId
202
+ }, {
203
+ subagentRunId: getString("subagentRunId"),
204
+ timestamp
205
+ });
206
+ }
203
207
  case "TOOL_CALL_START": {
204
208
  const toolCallId = getString("toolCallId");
205
209
  if (!toolCallId) return reject("missing toolCallId");
@@ -230,17 +234,10 @@ const parseAgUiEvent = (event, options) => {
230
234
  toolCallId
231
235
  }, { subagentRunId: getString("subagentRunId") });
232
236
  }
233
- case "TOOL_CALL_CHUNK": return withOptional({ type: "TOOL_CALL_CHUNK" }, {
234
- toolCallId: getString("toolCallId"),
235
- toolCallName: getString("toolCallName"),
236
- parentMessageId: getString("parentMessageId"),
237
- delta: getString("delta"),
238
- subagentRunId: getString("subagentRunId")
239
- });
240
237
  case "TOOL_CALL_RESULT": {
241
238
  const toolCallId = getString("toolCallId");
242
239
  if (!toolCallId) return reject("missing toolCallId");
243
- const content = getString("content") ?? "";
240
+ const content = Array.isArray(payload.content) ? payload.content : getString("content") ?? "";
244
241
  return withOptional({
245
242
  type: "TOOL_CALL_RESULT",
246
243
  toolCallId,
@@ -365,7 +362,6 @@ const parseAgUiEvent = (event, options) => {
365
362
  }, { source: isString(payload.type) ? payload.type : void 0 });
366
363
  }
367
364
  };
368
- //#endregion
369
365
  export { parseAgUiEvent };
370
366
 
371
367
  //# sourceMappingURL=event-parser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-parser.js","names":[],"sources":["../../src/runtime/event-parser.ts"],"sourcesContent":["import type {\n AgUiEvent,\n AgUiInterrupt,\n AgUiRunFinishedOutcome,\n AgUiSubagentFinishedOutcome,\n} from \"./types\";\nimport type { Logger } from \"./logger\";\nimport { parseMcpToolCallResult } from \"./mcp-tool-result\";\nimport { withRawResponseSchema } from \"./interrupt-internals\";\n\nexport type ParseAgUiEventOptions = {\n logger?: Logger;\n};\n\nconst isString = (value: unknown): value is string => typeof value === \"string\";\nconst isNonEmptyString = (value: unknown): value is string =>\n isString(value) && value.length > 0;\n\nconst withOptional = <T extends object>(\n base: T,\n optionals: Record<string, unknown>,\n) => {\n const definedEntries = Object.entries(optionals).filter(\n ([, value]) => value !== undefined,\n );\n return definedEntries.length === 0\n ? base\n : ({ ...base, ...Object.fromEntries(definedEntries) } as T);\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\nconst logRejectedEvent = (\n logger: Logger | undefined,\n type: unknown,\n payload: unknown,\n reason: string,\n) => {\n const typeLabel = isString(type) ? type : \"unknown\";\n logger?.debug?.(`[agui] ${typeLabel} ${reason}`, payload);\n};\n\nconst parseInterrupt = (raw: unknown): AgUiInterrupt | null => {\n if (!isPlainObject(raw)) return null;\n const id = raw.id;\n const reason = raw.reason;\n if (typeof id !== \"string\" || typeof reason !== \"string\") return null;\n const interrupt: AgUiInterrupt = { id, reason };\n if (typeof raw.message === \"string\") interrupt.message = raw.message;\n if (typeof raw.toolCallId === \"string\") interrupt.toolCallId = raw.toolCallId;\n if (typeof raw.expiresAt === \"string\") interrupt.expiresAt = raw.expiresAt;\n if (isPlainObject(raw.responseSchema))\n interrupt.responseSchema = raw.responseSchema;\n if (isPlainObject(raw.metadata)) interrupt.metadata = raw.metadata;\n // A present schema is kept whatever its shape: `false` is a JSON Schema that\n // rejects every payload, so normalizing it to absent would claim a gate no\n // decision can answer. Only an object schema fits `responseSchema`; every\n // other shape travels on the internal carrier. `null` is not a JSON Schema at\n // all, and it is what a server serializing an unset optional field sends, so\n // it reads as absent rather than as a schema nothing can satisfy.\n return raw.responseSchema == null || isPlainObject(raw.responseSchema)\n ? interrupt\n : withRawResponseSchema(interrupt, raw.responseSchema);\n};\n\nconst parseRunFinishedOutcome = (\n raw: unknown,\n runId: string,\n logger: Logger | undefined,\n): AgUiRunFinishedOutcome | undefined => {\n if (raw == null) return undefined;\n if (!isPlainObject(raw)) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has invalid outcome\",\n );\n return undefined;\n }\n if (raw.type === \"success\") return { type: \"success\" };\n if (raw.type === \"interrupt\") {\n if (!Array.isArray(raw.interrupts)) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has an interrupt outcome missing interrupts array\",\n );\n return undefined;\n }\n const parsed = raw.interrupts\n .map((entry) => {\n const interrupt = parseInterrupt(entry);\n if (interrupt === null) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, interrupt: entry },\n \"has malformed interrupt\",\n );\n }\n return interrupt;\n })\n .filter((entry): entry is AgUiInterrupt => entry !== null);\n if (parsed.length === 0) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, interrupts: raw.interrupts },\n \"has an interrupt outcome with no valid interrupts\",\n );\n return undefined;\n }\n return { type: \"interrupt\", interrupts: parsed };\n }\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has unsupported outcome type\",\n );\n return undefined;\n};\n\nexport const parseAgUiEvent = (\n event: unknown,\n options?: ParseAgUiEventOptions,\n): AgUiEvent | null => {\n if (!event || typeof event !== \"object\") {\n logRejectedEvent(options?.logger, undefined, event, \"is not an object\");\n return null;\n }\n const payload = event as Record<string, unknown>;\n const typeValue = payload.type;\n if (!isString(typeValue)) {\n logRejectedEvent(options?.logger, typeValue, payload, \"has no string type\");\n return null;\n }\n\n const reject = (reason: string): null => {\n logRejectedEvent(options?.logger, typeValue, payload, reason);\n return null;\n };\n\n const getString = (key: string) =>\n isString(payload[key]) ? (payload[key] as string) : undefined;\n const timestamp =\n typeof payload.timestamp === \"number\" && Number.isFinite(payload.timestamp)\n ? payload.timestamp\n : undefined;\n\n switch (typeValue) {\n case \"RUN_STARTED\": {\n const runId = getString(\"runId\");\n return runId ? { type: \"RUN_STARTED\", runId } : reject(\"missing runId\");\n }\n case \"RUN_FINISHED\": {\n const runId = getString(\"runId\");\n if (!runId) return reject(\"missing runId\");\n return withOptional(\n { type: \"RUN_FINISHED\" as const, runId },\n {\n outcome: parseRunFinishedOutcome(\n payload.outcome,\n runId,\n options?.logger,\n ),\n },\n );\n }\n case \"RUN_CANCELLED\": {\n const runId = getString(\"runId\");\n return withOptional({ type: \"RUN_CANCELLED\" as const }, { runId });\n }\n case \"RUN_ERROR\": {\n return withOptional(\n { type: \"RUN_ERROR\" as const },\n {\n message: getString(\"message\"),\n code: getString(\"code\"),\n },\n );\n }\n case \"TEXT_MESSAGE_START\":\n return withOptional(\n { type: \"TEXT_MESSAGE_START\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n case \"TEXT_MESSAGE_CONTENT\": {\n const delta = getString(\"delta\");\n if (!isNonEmptyString(delta)) return reject(\"missing non-empty delta\");\n return withOptional(\n { type: \"TEXT_MESSAGE_CONTENT\" as const, delta },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"TEXT_MESSAGE_END\":\n return withOptional(\n { type: \"TEXT_MESSAGE_END\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n case \"TEXT_MESSAGE_CHUNK\": {\n const delta = getString(\"delta\") ?? \"\";\n return withOptional(\n { type: \"TEXT_MESSAGE_CHUNK\" as const, delta },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"THINKING_START\":\n return withOptional(\n { type: \"THINKING_START\" as const },\n { title: getString(\"title\"), timestamp },\n );\n case \"THINKING_TEXT_MESSAGE_START\":\n return withOptional(\n { type: \"THINKING_TEXT_MESSAGE_START\" as const },\n { timestamp },\n );\n case \"THINKING_TEXT_MESSAGE_CONTENT\": {\n const delta = getString(\"delta\") ?? \"\";\n return { type: \"THINKING_TEXT_MESSAGE_CONTENT\", delta };\n }\n case \"THINKING_TEXT_MESSAGE_END\":\n return withOptional(\n { type: \"THINKING_TEXT_MESSAGE_END\" as const },\n { timestamp },\n );\n case \"THINKING_END\":\n return withOptional({ type: \"THINKING_END\" as const }, { timestamp });\n case \"REASONING_START\":\n return withOptional(\n { type: \"REASONING_START\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n case \"REASONING_MESSAGE_START\":\n return withOptional(\n { type: \"REASONING_MESSAGE_START\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n case \"REASONING_MESSAGE_CONTENT\": {\n const delta = getString(\"delta\") ?? \"\";\n return withOptional(\n { type: \"REASONING_MESSAGE_CONTENT\" as const, delta },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"REASONING_MESSAGE_END\":\n return withOptional(\n { type: \"REASONING_MESSAGE_END\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n case \"REASONING_ENCRYPTED_VALUE\": {\n const entityId = getString(\"entityId\");\n const encryptedValue = getString(\"encryptedValue\");\n const subtype = getString(\"subtype\");\n if (!entityId || !encryptedValue) {\n return reject(\"missing entityId or encryptedValue\");\n }\n if (subtype !== \"message\" && subtype !== \"tool-call\") {\n return reject(\"has an invalid subtype\");\n }\n // Spread rather than withOptional: routing the narrowed `subtype` through\n // a generic helper widens it back to string.\n const subagentRunId = getString(\"subagentRunId\");\n return {\n type: \"REASONING_ENCRYPTED_VALUE\" as const,\n subtype,\n entityId,\n encryptedValue,\n ...(subagentRunId !== undefined ? { subagentRunId } : {}),\n };\n }\n case \"REASONING_END\":\n return withOptional(\n { type: \"REASONING_END\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n case \"TOOL_CALL_START\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n return withOptional(\n { type: \"TOOL_CALL_START\" as const, toolCallId },\n {\n toolCallName: getString(\"toolCallName\"),\n parentMessageId: getString(\"parentMessageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"TOOL_CALL_ARGS\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n const delta = getString(\"delta\") ?? \"\";\n return withOptional(\n { type: \"TOOL_CALL_ARGS\" as const, toolCallId, delta },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"TOOL_CALL_END\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n return withOptional(\n { type: \"TOOL_CALL_END\" as const, toolCallId },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"TOOL_CALL_CHUNK\":\n return withOptional(\n { type: \"TOOL_CALL_CHUNK\" as const },\n {\n toolCallId: getString(\"toolCallId\"),\n toolCallName: getString(\"toolCallName\"),\n parentMessageId: getString(\"parentMessageId\"),\n delta: getString(\"delta\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n case \"TOOL_CALL_RESULT\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n const content = getString(\"content\") ?? \"\";\n return withOptional(\n {\n type: \"TOOL_CALL_RESULT\" as const,\n toolCallId,\n content,\n },\n {\n messageId: getString(\"messageId\"),\n role: payload.role === \"tool\" ? \"tool\" : undefined,\n mcpResult: parseMcpToolCallResult(payload, content),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"STATE_SNAPSHOT\":\n if (payload.snapshot === undefined) {\n return reject(\"missing snapshot\");\n }\n return { type: \"STATE_SNAPSHOT\", snapshot: payload.snapshot };\n case \"STATE_DELTA\":\n return {\n type: \"STATE_DELTA\",\n delta: Array.isArray(payload.delta) ? (payload.delta as any[]) : [],\n };\n case \"MESSAGES_SNAPSHOT\":\n if (!Array.isArray(payload.messages)) {\n return reject(\"missing messages array\");\n }\n return {\n type: \"MESSAGES_SNAPSHOT\",\n messages: payload.messages as any[],\n };\n case \"ACTIVITY_SNAPSHOT\": {\n const activityType = getString(\"activityType\");\n if (!activityType || !isPlainObject(payload.content)) {\n return reject(\"missing activityType or object content\");\n }\n return withOptional(\n {\n type: \"ACTIVITY_SNAPSHOT\" as const,\n activityType,\n content: payload.content,\n },\n {\n messageId: getString(\"messageId\"),\n replace:\n typeof payload.replace === \"boolean\" ? payload.replace : undefined,\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"ACTIVITY_DELTA\": {\n const messageId = getString(\"messageId\");\n const activityType = getString(\"activityType\");\n if (!messageId || !activityType || !Array.isArray(payload.patch)) {\n return reject(\"missing messageId, activityType or patch array\");\n }\n return withOptional(\n {\n type: \"ACTIVITY_DELTA\" as const,\n messageId,\n activityType,\n patch: payload.patch as any[],\n },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"RAW\":\n return withOptional(\n { type: \"RAW\" as const, event: payload.event },\n { source: getString(\"source\") },\n );\n case \"CUSTOM\": {\n const name = getString(\"name\");\n if (!name) return reject(\"missing name\");\n return { type: \"CUSTOM\", name, value: payload.value };\n }\n case \"SUBAGENT_STARTED\": {\n const subagentRunId = getString(\"subagentRunId\");\n const name = getString(\"name\");\n if (!subagentRunId || !name) {\n return reject(\"missing subagentRunId or name\");\n }\n return withOptional(\n { type: \"SUBAGENT_STARTED\" as const, subagentRunId, name },\n {\n description: getString(\"description\"),\n parentSubagentRunId: getString(\"parentSubagentRunId\"),\n parentToolCallId: getString(\"parentToolCallId\"),\n parentMessageId: getString(\"parentMessageId\"),\n },\n );\n }\n case \"SUBAGENT_FINISHED\": {\n const subagentRunId = getString(\"subagentRunId\");\n if (!subagentRunId) return reject(\"missing subagentRunId\");\n const rawOutcome = payload.outcome;\n let outcome: AgUiSubagentFinishedOutcome | undefined;\n if (rawOutcome == null) {\n outcome = undefined;\n } else if (!isPlainObject(rawOutcome)) {\n logRejectedEvent(\n options?.logger,\n \"SUBAGENT_FINISHED\",\n { subagentRunId, outcome: rawOutcome },\n \"has invalid outcome\",\n );\n outcome = undefined;\n } else if (rawOutcome.type === \"success\") {\n outcome = { type: \"success\" as const };\n } else if (rawOutcome.type === \"suspended\") {\n outcome = withOptional(\n { type: \"suspended\" as const },\n {\n interruptIds: Array.isArray(rawOutcome.interruptIds)\n ? (rawOutcome.interruptIds as unknown[]).filter(isString)\n : undefined,\n },\n );\n } else {\n logRejectedEvent(\n options?.logger,\n \"SUBAGENT_FINISHED\",\n { subagentRunId, outcome: rawOutcome },\n \"has unsupported outcome type\",\n );\n outcome = undefined;\n }\n return withOptional(\n { type: \"SUBAGENT_FINISHED\" as const, subagentRunId },\n { result: payload.result, outcome },\n );\n }\n case \"SUBAGENT_ERROR\": {\n const subagentRunId = getString(\"subagentRunId\");\n const message = getString(\"message\");\n if (!subagentRunId || !message) {\n return reject(\"missing subagentRunId or message\");\n }\n return withOptional(\n { type: \"SUBAGENT_ERROR\" as const, subagentRunId, message },\n { code: getString(\"code\") },\n );\n }\n default:\n return withOptional(\n { type: \"RAW\" as const, event: payload },\n {\n source: isString(payload.type) ? (payload.type as string) : undefined,\n },\n );\n }\n};\n"],"mappings":";;;AAcA,MAAM,YAAY,UAAoC,OAAO,UAAU;AACvE,MAAM,oBAAoB,UACxB,SAAS,KAAK,KAAK,MAAM,SAAS;AAEpC,MAAM,gBACJ,MACA,cACG;CACH,MAAM,iBAAiB,OAAO,QAAQ,SAAS,CAAC,CAAC,QAC9C,GAAG,WAAW,UAAU,KAAA,CAC3B;CACA,OAAO,eAAe,WAAW,IAC7B,OACC;EAAE,GAAG;EAAM,GAAG,OAAO,YAAY,cAAc;CAAE;AACxD;AAEA,MAAM,iBAAiB,UACrB,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAE9D,MAAM,oBACJ,QACA,MACA,SACA,WACG;CACH,MAAM,YAAY,SAAS,IAAI,IAAI,OAAO;CAC1C,QAAQ,QAAQ,UAAU,UAAU,GAAG,UAAU,OAAO;AAC1D;AAEA,MAAM,kBAAkB,QAAuC;CAC7D,IAAI,CAAC,cAAc,GAAG,GAAG,OAAO;CAChC,MAAM,KAAK,IAAI;CACf,MAAM,SAAS,IAAI;CACnB,IAAI,OAAO,OAAO,YAAY,OAAO,WAAW,UAAU,OAAO;CACjE,MAAM,YAA2B;EAAE;EAAI;CAAO;CAC9C,IAAI,OAAO,IAAI,YAAY,UAAU,UAAU,UAAU,IAAI;CAC7D,IAAI,OAAO,IAAI,eAAe,UAAU,UAAU,aAAa,IAAI;CACnE,IAAI,OAAO,IAAI,cAAc,UAAU,UAAU,YAAY,IAAI;CACjE,IAAI,cAAc,IAAI,cAAc,GAClC,UAAU,iBAAiB,IAAI;CACjC,IAAI,cAAc,IAAI,QAAQ,GAAG,UAAU,WAAW,IAAI;CAO1D,OAAO,IAAI,kBAAkB,QAAQ,cAAc,IAAI,cAAc,IACjE,YACA,sBAAsB,WAAW,IAAI,cAAc;AACzD;AAEA,MAAM,2BACJ,KACA,OACA,WACuC;CACvC,IAAI,OAAO,MAAM,OAAO,KAAA;CACxB,IAAI,CAAC,cAAc,GAAG,GAAG;EACvB,iBACE,QACA,gBACA;GAAE;GAAO,SAAS;EAAI,GACtB,qBACF;EACA;CACF;CACA,IAAI,IAAI,SAAS,WAAW,OAAO,EAAE,MAAM,UAAU;CACrD,IAAI,IAAI,SAAS,aAAa;EAC5B,IAAI,CAAC,MAAM,QAAQ,IAAI,UAAU,GAAG;GAClC,iBACE,QACA,gBACA;IAAE;IAAO,SAAS;GAAI,GACtB,mDACF;GACA;EACF;EACA,MAAM,SAAS,IAAI,WAChB,KAAK,UAAU;GACd,MAAM,YAAY,eAAe,KAAK;GACtC,IAAI,cAAc,MAChB,iBACE,QACA,gBACA;IAAE;IAAO,WAAW;GAAM,GAC1B,yBACF;GAEF,OAAO;EACT,CAAC,CAAC,CACD,QAAQ,UAAkC,UAAU,IAAI;EAC3D,IAAI,OAAO,WAAW,GAAG;GACvB,iBACE,QACA,gBACA;IAAE;IAAO,YAAY,IAAI;GAAW,GACpC,mDACF;GACA;EACF;EACA,OAAO;GAAE,MAAM;GAAa,YAAY;EAAO;CACjD;CACA,iBACE,QACA,gBACA;EAAE;EAAO,SAAS;CAAI,GACtB,8BACF;AAEF;AAEA,MAAa,kBACX,OACA,YACqB;CACrB,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU;EACvC,iBAAiB,SAAS,QAAQ,KAAA,GAAW,OAAO,kBAAkB;EACtE,OAAO;CACT;CACA,MAAM,UAAU;CAChB,MAAM,YAAY,QAAQ;CAC1B,IAAI,CAAC,SAAS,SAAS,GAAG;EACxB,iBAAiB,SAAS,QAAQ,WAAW,SAAS,oBAAoB;EAC1E,OAAO;CACT;CAEA,MAAM,UAAU,WAAyB;EACvC,iBAAiB,SAAS,QAAQ,WAAW,SAAS,MAAM;EAC5D,OAAO;CACT;CAEA,MAAM,aAAa,QACjB,SAAS,QAAQ,IAAI,IAAK,QAAQ,OAAkB,KAAA;CACtD,MAAM,YACJ,OAAO,QAAQ,cAAc,YAAY,OAAO,SAAS,QAAQ,SAAS,IACtE,QAAQ,YACR,KAAA;CAEN,QAAQ,WAAR;EACE,KAAK,eAAe;GAClB,MAAM,QAAQ,UAAU,OAAO;GAC/B,OAAO,QAAQ;IAAE,MAAM;IAAe;GAAM,IAAI,OAAO,eAAe;EACxE;EACA,KAAK,gBAAgB;GACnB,MAAM,QAAQ,UAAU,OAAO;GAC/B,IAAI,CAAC,OAAO,OAAO,OAAO,eAAe;GACzC,OAAO,aACL;IAAE,MAAM;IAAyB;GAAM,GACvC,EACE,SAAS,wBACP,QAAQ,SACR,OACA,SAAS,MACX,EACF,CACF;EACF;EACA,KAAK,iBAAiB;GACpB,MAAM,QAAQ,UAAU,OAAO;GAC/B,OAAO,aAAa,EAAE,MAAM,gBAAyB,GAAG,EAAE,MAAM,CAAC;EACnE;EACA,KAAK,aACH,OAAO,aACL,EAAE,MAAM,YAAqB,GAC7B;GACE,SAAS,UAAU,SAAS;GAC5B,MAAM,UAAU,MAAM;EACxB,CACF;EAEF,KAAK,sBACH,OAAO,aACL,EAAE,MAAM,qBAA8B,GACtC;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;EAC1C,CACF;EACF,KAAK,wBAAwB;GAC3B,MAAM,QAAQ,UAAU,OAAO;GAC/B,IAAI,CAAC,iBAAiB,KAAK,GAAG,OAAO,OAAO,yBAAyB;GACrE,OAAO,aACL;IAAE,MAAM;IAAiC;GAAM,GAC/C;IACE,WAAW,UAAU,WAAW;IAChC,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK,oBACH,OAAO,aACL,EAAE,MAAM,mBAA4B,GACpC;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;EAC1C,CACF;EACF,KAAK,sBAAsB;GACzB,MAAM,QAAQ,UAAU,OAAO,KAAK;GACpC,OAAO,aACL;IAAE,MAAM;IAA+B;GAAM,GAC7C;IACE,WAAW,UAAU,WAAW;IAChC,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK,kBACH,OAAO,aACL,EAAE,MAAM,iBAA0B,GAClC;GAAE,OAAO,UAAU,OAAO;GAAG;EAAU,CACzC;EACF,KAAK,+BACH,OAAO,aACL,EAAE,MAAM,8BAAuC,GAC/C,EAAE,UAAU,CACd;EACF,KAAK,iCAEH,OAAO;GAAE,MAAM;GAAiC,OADlC,UAAU,OAAO,KAAK;EACkB;EAExD,KAAK,6BACH,OAAO,aACL,EAAE,MAAM,4BAAqC,GAC7C,EAAE,UAAU,CACd;EACF,KAAK,gBACH,OAAO,aAAa,EAAE,MAAM,eAAwB,GAAG,EAAE,UAAU,CAAC;EACtE,KAAK,mBACH,OAAO,aACL,EAAE,MAAM,kBAA2B,GACnC;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;GACxC;EACF,CACF;EACF,KAAK,2BACH,OAAO,aACL,EAAE,MAAM,0BAAmC,GAC3C;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;GACxC;EACF,CACF;EACF,KAAK,6BAA6B;GAChC,MAAM,QAAQ,UAAU,OAAO,KAAK;GACpC,OAAO,aACL;IAAE,MAAM;IAAsC;GAAM,GACpD;IACE,WAAW,UAAU,WAAW;IAChC,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK,yBACH,OAAO,aACL,EAAE,MAAM,wBAAiC,GACzC;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;GACxC;EACF,CACF;EACF,KAAK,6BAA6B;GAChC,MAAM,WAAW,UAAU,UAAU;GACrC,MAAM,iBAAiB,UAAU,gBAAgB;GACjD,MAAM,UAAU,UAAU,SAAS;GACnC,IAAI,CAAC,YAAY,CAAC,gBAChB,OAAO,OAAO,oCAAoC;GAEpD,IAAI,YAAY,aAAa,YAAY,aACvC,OAAO,OAAO,wBAAwB;GAIxC,MAAM,gBAAgB,UAAU,eAAe;GAC/C,OAAO;IACL,MAAM;IACN;IACA;IACA;IACA,GAAI,kBAAkB,KAAA,IAAY,EAAE,cAAc,IAAI,CAAC;GACzD;EACF;EACA,KAAK,iBACH,OAAO,aACL,EAAE,MAAM,gBAAyB,GACjC;GACE,WAAW,UAAU,WAAW;GAChC,eAAe,UAAU,eAAe;GACxC;EACF,CACF;EACF,KAAK,mBAAmB;GACtB,MAAM,aAAa,UAAU,YAAY;GACzC,IAAI,CAAC,YAAY,OAAO,OAAO,oBAAoB;GACnD,OAAO,aACL;IAAE,MAAM;IAA4B;GAAW,GAC/C;IACE,cAAc,UAAU,cAAc;IACtC,iBAAiB,UAAU,iBAAiB;IAC5C,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK,kBAAkB;GACrB,MAAM,aAAa,UAAU,YAAY;GACzC,IAAI,CAAC,YAAY,OAAO,OAAO,oBAAoB;GACnD,MAAM,QAAQ,UAAU,OAAO,KAAK;GACpC,OAAO,aACL;IAAE,MAAM;IAA2B;IAAY;GAAM,GACrD,EAAE,eAAe,UAAU,eAAe,EAAE,CAC9C;EACF;EACA,KAAK,iBAAiB;GACpB,MAAM,aAAa,UAAU,YAAY;GACzC,IAAI,CAAC,YAAY,OAAO,OAAO,oBAAoB;GACnD,OAAO,aACL;IAAE,MAAM;IAA0B;GAAW,GAC7C,EAAE,eAAe,UAAU,eAAe,EAAE,CAC9C;EACF;EACA,KAAK,mBACH,OAAO,aACL,EAAE,MAAM,kBAA2B,GACnC;GACE,YAAY,UAAU,YAAY;GAClC,cAAc,UAAU,cAAc;GACtC,iBAAiB,UAAU,iBAAiB;GAC5C,OAAO,UAAU,OAAO;GACxB,eAAe,UAAU,eAAe;EAC1C,CACF;EACF,KAAK,oBAAoB;GACvB,MAAM,aAAa,UAAU,YAAY;GACzC,IAAI,CAAC,YAAY,OAAO,OAAO,oBAAoB;GACnD,MAAM,UAAU,UAAU,SAAS,KAAK;GACxC,OAAO,aACL;IACE,MAAM;IACN;IACA;GACF,GACA;IACE,WAAW,UAAU,WAAW;IAChC,MAAM,QAAQ,SAAS,SAAS,SAAS,KAAA;IACzC,WAAW,uBAAuB,SAAS,OAAO;IAClD,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK;GACH,IAAI,QAAQ,aAAa,KAAA,GACvB,OAAO,OAAO,kBAAkB;GAElC,OAAO;IAAE,MAAM;IAAkB,UAAU,QAAQ;GAAS;EAC9D,KAAK,eACH,OAAO;GACL,MAAM;GACN,OAAO,MAAM,QAAQ,QAAQ,KAAK,IAAK,QAAQ,QAAkB,CAAC;EACpE;EACF,KAAK;GACH,IAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GACjC,OAAO,OAAO,wBAAwB;GAExC,OAAO;IACL,MAAM;IACN,UAAU,QAAQ;GACpB;EACF,KAAK,qBAAqB;GACxB,MAAM,eAAe,UAAU,cAAc;GAC7C,IAAI,CAAC,gBAAgB,CAAC,cAAc,QAAQ,OAAO,GACjD,OAAO,OAAO,wCAAwC;GAExD,OAAO,aACL;IACE,MAAM;IACN;IACA,SAAS,QAAQ;GACnB,GACA;IACE,WAAW,UAAU,WAAW;IAChC,SACE,OAAO,QAAQ,YAAY,YAAY,QAAQ,UAAU,KAAA;IAC3D,eAAe,UAAU,eAAe;GAC1C,CACF;EACF;EACA,KAAK,kBAAkB;GACrB,MAAM,YAAY,UAAU,WAAW;GACvC,MAAM,eAAe,UAAU,cAAc;GAC7C,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,MAAM,QAAQ,QAAQ,KAAK,GAC7D,OAAO,OAAO,gDAAgD;GAEhE,OAAO,aACL;IACE,MAAM;IACN;IACA;IACA,OAAO,QAAQ;GACjB,GACA,EAAE,eAAe,UAAU,eAAe,EAAE,CAC9C;EACF;EACA,KAAK,OACH,OAAO,aACL;GAAE,MAAM;GAAgB,OAAO,QAAQ;EAAM,GAC7C,EAAE,QAAQ,UAAU,QAAQ,EAAE,CAChC;EACF,KAAK,UAAU;GACb,MAAM,OAAO,UAAU,MAAM;GAC7B,IAAI,CAAC,MAAM,OAAO,OAAO,cAAc;GACvC,OAAO;IAAE,MAAM;IAAU;IAAM,OAAO,QAAQ;GAAM;EACtD;EACA,KAAK,oBAAoB;GACvB,MAAM,gBAAgB,UAAU,eAAe;GAC/C,MAAM,OAAO,UAAU,MAAM;GAC7B,IAAI,CAAC,iBAAiB,CAAC,MACrB,OAAO,OAAO,+BAA+B;GAE/C,OAAO,aACL;IAAE,MAAM;IAA6B;IAAe;GAAK,GACzD;IACE,aAAa,UAAU,aAAa;IACpC,qBAAqB,UAAU,qBAAqB;IACpD,kBAAkB,UAAU,kBAAkB;IAC9C,iBAAiB,UAAU,iBAAiB;GAC9C,CACF;EACF;EACA,KAAK,qBAAqB;GACxB,MAAM,gBAAgB,UAAU,eAAe;GAC/C,IAAI,CAAC,eAAe,OAAO,OAAO,uBAAuB;GACzD,MAAM,aAAa,QAAQ;GAC3B,IAAI;GACJ,IAAI,cAAc,MAChB,UAAU,KAAA;QACL,IAAI,CAAC,cAAc,UAAU,GAAG;IACrC,iBACE,SAAS,QACT,qBACA;KAAE;KAAe,SAAS;IAAW,GACrC,qBACF;IACA,UAAU,KAAA;GACZ,OAAO,IAAI,WAAW,SAAS,WAC7B,UAAU,EAAE,MAAM,UAAmB;QAChC,IAAI,WAAW,SAAS,aAC7B,UAAU,aACR,EAAE,MAAM,YAAqB,GAC7B,EACE,cAAc,MAAM,QAAQ,WAAW,YAAY,IAC9C,WAAW,aAA2B,OAAO,QAAQ,IACtD,KAAA,EACN,CACF;QACK;IACL,iBACE,SAAS,QACT,qBACA;KAAE;KAAe,SAAS;IAAW,GACrC,8BACF;IACA,UAAU,KAAA;GACZ;GACA,OAAO,aACL;IAAE,MAAM;IAA8B;GAAc,GACpD;IAAE,QAAQ,QAAQ;IAAQ;GAAQ,CACpC;EACF;EACA,KAAK,kBAAkB;GACrB,MAAM,gBAAgB,UAAU,eAAe;GAC/C,MAAM,UAAU,UAAU,SAAS;GACnC,IAAI,CAAC,iBAAiB,CAAC,SACrB,OAAO,OAAO,kCAAkC;GAElD,OAAO,aACL;IAAE,MAAM;IAA2B;IAAe;GAAQ,GAC1D,EAAE,MAAM,UAAU,MAAM,EAAE,CAC5B;EACF;EACA,SACE,OAAO,aACL;GAAE,MAAM;GAAgB,OAAO;EAAQ,GACvC,EACE,QAAQ,SAAS,QAAQ,IAAI,IAAK,QAAQ,OAAkB,KAAA,EAC9D,CACF;CACJ;AACF"}
1
+ {"version":3,"file":"event-parser.js","names":[],"sources":["../../src/runtime/event-parser.ts"],"sourcesContent":["import type {\n AgUiEvent,\n AgUiInterrupt,\n AgUiRunFinishedOutcome,\n AgUiSubagentFinishedOutcome,\n} from \"./types\";\nimport type { Logger } from \"./logger\";\nimport { parseMcpToolCallResult } from \"./mcp-tool-result\";\nimport { withRawResponseSchema } from \"./interrupt-internals\";\nimport type { ContentPart } from \"@ag-ui/client\";\n\nexport type ParseAgUiEventOptions = {\n logger?: Logger;\n};\n\nconst isString = (value: unknown): value is string => typeof value === \"string\";\nconst isNonEmptyString = (value: unknown): value is string =>\n isString(value) && value.length > 0;\n\nconst withOptional = <T extends object>(\n base: T,\n optionals: Record<string, unknown>,\n) => {\n const definedEntries = Object.entries(optionals).filter(\n ([, value]) => value !== undefined,\n );\n return definedEntries.length === 0\n ? base\n : ({ ...base, ...Object.fromEntries(definedEntries) } as T);\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\nconst logRejectedEvent = (\n logger: Logger | undefined,\n type: unknown,\n payload: unknown,\n reason: string,\n) => {\n const typeLabel = isString(type) ? type : \"unknown\";\n logger?.debug?.(`[agui] ${typeLabel} ${reason}`, payload);\n};\n\nconst parseInterrupt = (raw: unknown): AgUiInterrupt | null => {\n if (!isPlainObject(raw)) return null;\n const id = raw.id;\n const reason = raw.reason;\n if (typeof id !== \"string\" || typeof reason !== \"string\") return null;\n const interrupt: AgUiInterrupt = { id, reason };\n if (typeof raw.message === \"string\") interrupt.message = raw.message;\n if (typeof raw.toolCallId === \"string\") interrupt.toolCallId = raw.toolCallId;\n if (typeof raw.expiresAt === \"string\") interrupt.expiresAt = raw.expiresAt;\n if (isPlainObject(raw.responseSchema))\n interrupt.responseSchema = raw.responseSchema;\n if (isPlainObject(raw.metadata)) interrupt.metadata = raw.metadata;\n // A present schema is kept whatever its shape: `false` is a JSON Schema that\n // rejects every payload, so normalizing it to absent would claim a gate no\n // decision can answer. Only an object schema fits `responseSchema`; every\n // other shape travels on the internal carrier. `null` is not a JSON Schema at\n // all, and it is what a server serializing an unset optional field sends, so\n // it reads as absent rather than as a schema nothing can satisfy.\n return raw.responseSchema == null || isPlainObject(raw.responseSchema)\n ? interrupt\n : withRawResponseSchema(interrupt, raw.responseSchema);\n};\n\nconst parseRunFinishedOutcome = (\n raw: unknown,\n runId: string,\n logger: Logger | undefined,\n): AgUiRunFinishedOutcome | undefined => {\n if (raw == null) return undefined;\n if (!isPlainObject(raw)) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has invalid outcome\",\n );\n return undefined;\n }\n if (raw.type === \"success\") {\n return withOptional(\n { type: \"success\" as const },\n {\n pendingToolCallIds:\n Array.isArray(raw.pendingToolCallIds) &&\n raw.pendingToolCallIds.every(isString)\n ? raw.pendingToolCallIds\n : undefined,\n },\n );\n }\n if (raw.type === \"cancelled\") return { type: \"cancelled\" };\n if (raw.type === \"interrupt\") {\n if (!Array.isArray(raw.interrupts)) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has an interrupt outcome missing interrupts array\",\n );\n return undefined;\n }\n const parsed = raw.interrupts\n .map((entry) => {\n const interrupt = parseInterrupt(entry);\n if (interrupt === null) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, interrupt: entry },\n \"has malformed interrupt\",\n );\n }\n return interrupt;\n })\n .filter((entry): entry is AgUiInterrupt => entry !== null);\n if (parsed.length === 0) {\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, interrupts: raw.interrupts },\n \"has an interrupt outcome with no valid interrupts\",\n );\n return undefined;\n }\n return { type: \"interrupt\", interrupts: parsed };\n }\n logRejectedEvent(\n logger,\n \"RUN_FINISHED\",\n { runId, outcome: raw },\n \"has unsupported outcome type\",\n );\n return undefined;\n};\n\nexport const parseAgUiEvent = (\n event: unknown,\n options?: ParseAgUiEventOptions,\n): AgUiEvent | null => {\n if (!event || typeof event !== \"object\") {\n logRejectedEvent(options?.logger, undefined, event, \"is not an object\");\n return null;\n }\n const payload = event as Record<string, unknown>;\n const typeValue = payload.type;\n if (!isString(typeValue)) {\n logRejectedEvent(options?.logger, typeValue, payload, \"has no string type\");\n return null;\n }\n\n const reject = (reason: string): null => {\n logRejectedEvent(options?.logger, typeValue, payload, reason);\n return null;\n };\n\n const getString = (key: string) =>\n isString(payload[key]) ? (payload[key] as string) : undefined;\n const timestamp =\n typeof payload.timestamp === \"number\" && Number.isFinite(payload.timestamp)\n ? payload.timestamp\n : undefined;\n\n switch (typeValue) {\n case \"RUN_STARTED\": {\n const runId = getString(\"runId\");\n return runId ? { type: \"RUN_STARTED\", runId } : reject(\"missing runId\");\n }\n case \"RUN_FINISHED\": {\n const runId = getString(\"runId\");\n if (!runId) return reject(\"missing runId\");\n return withOptional(\n { type: \"RUN_FINISHED\" as const, runId },\n {\n outcome: parseRunFinishedOutcome(\n payload.outcome,\n runId,\n options?.logger,\n ),\n },\n );\n }\n case \"RUN_CANCELLED\": {\n const runId = getString(\"runId\");\n return withOptional({ type: \"RUN_CANCELLED\" as const }, { runId });\n }\n case \"RUN_ERROR\": {\n return withOptional(\n { type: \"RUN_ERROR\" as const },\n {\n message: getString(\"message\"),\n code: getString(\"code\"),\n },\n );\n }\n case \"TEXT_MESSAGE_START\":\n return withOptional(\n { type: \"TEXT_MESSAGE_START\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n case \"TEXT_MESSAGE_CONTENT\": {\n const delta = getString(\"delta\");\n if (!isNonEmptyString(delta)) return reject(\"missing non-empty delta\");\n return withOptional(\n { type: \"TEXT_MESSAGE_CONTENT\" as const, delta },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"TEXT_MESSAGE_END\":\n return withOptional(\n { type: \"TEXT_MESSAGE_END\" as const },\n {\n messageId: getString(\"messageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n case \"REASONING_START\": {\n const messageId = getString(\"messageId\");\n if (!messageId) return reject(\"missing messageId\");\n return withOptional(\n { type: \"REASONING_START\" as const, messageId },\n {\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n }\n case \"REASONING_MESSAGE_START\": {\n const messageId = getString(\"messageId\");\n if (!messageId) return reject(\"missing messageId\");\n return withOptional(\n { type: \"REASONING_MESSAGE_START\" as const, messageId },\n {\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n }\n case \"REASONING_MESSAGE_CONTENT\": {\n const messageId = getString(\"messageId\");\n if (!messageId) return reject(\"missing messageId\");\n const delta = getString(\"delta\") ?? \"\";\n return withOptional(\n { type: \"REASONING_MESSAGE_CONTENT\" as const, messageId, delta },\n {\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"REASONING_MESSAGE_END\": {\n const messageId = getString(\"messageId\");\n if (!messageId) return reject(\"missing messageId\");\n return withOptional(\n { type: \"REASONING_MESSAGE_END\" as const, messageId },\n {\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n }\n case \"REASONING_ENCRYPTED_VALUE\": {\n const entityId = getString(\"entityId\");\n const encryptedValue = getString(\"encryptedValue\");\n const subtype = getString(\"subtype\");\n if (!entityId || !encryptedValue) {\n return reject(\"missing entityId or encryptedValue\");\n }\n if (subtype !== \"message\" && subtype !== \"tool-call\") {\n return reject(\"has an invalid subtype\");\n }\n // Spread rather than withOptional: routing the narrowed `subtype` through\n // a generic helper widens it back to string.\n const subagentRunId = getString(\"subagentRunId\");\n return {\n type: \"REASONING_ENCRYPTED_VALUE\" as const,\n subtype,\n entityId,\n encryptedValue,\n ...(subagentRunId !== undefined ? { subagentRunId } : {}),\n };\n }\n case \"REASONING_END\": {\n const messageId = getString(\"messageId\");\n if (!messageId) return reject(\"missing messageId\");\n return withOptional(\n { type: \"REASONING_END\" as const, messageId },\n {\n subagentRunId: getString(\"subagentRunId\"),\n timestamp,\n },\n );\n }\n case \"TOOL_CALL_START\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n return withOptional(\n { type: \"TOOL_CALL_START\" as const, toolCallId },\n {\n toolCallName: getString(\"toolCallName\"),\n parentMessageId: getString(\"parentMessageId\"),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"TOOL_CALL_ARGS\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n const delta = getString(\"delta\") ?? \"\";\n return withOptional(\n { type: \"TOOL_CALL_ARGS\" as const, toolCallId, delta },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"TOOL_CALL_END\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n return withOptional(\n { type: \"TOOL_CALL_END\" as const, toolCallId },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"TOOL_CALL_RESULT\": {\n const toolCallId = getString(\"toolCallId\");\n if (!toolCallId) return reject(\"missing toolCallId\");\n const content = Array.isArray(payload.content)\n ? (payload.content as ContentPart[])\n : (getString(\"content\") ?? \"\");\n return withOptional(\n {\n type: \"TOOL_CALL_RESULT\" as const,\n toolCallId,\n content,\n },\n {\n messageId: getString(\"messageId\"),\n role: payload.role === \"tool\" ? \"tool\" : undefined,\n mcpResult: parseMcpToolCallResult(payload, content),\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"STATE_SNAPSHOT\":\n if (payload.snapshot === undefined) {\n return reject(\"missing snapshot\");\n }\n return { type: \"STATE_SNAPSHOT\", snapshot: payload.snapshot };\n case \"STATE_DELTA\":\n return {\n type: \"STATE_DELTA\",\n delta: Array.isArray(payload.delta) ? (payload.delta as any[]) : [],\n };\n case \"MESSAGES_SNAPSHOT\":\n if (!Array.isArray(payload.messages)) {\n return reject(\"missing messages array\");\n }\n return {\n type: \"MESSAGES_SNAPSHOT\",\n messages: payload.messages as any[],\n };\n case \"ACTIVITY_SNAPSHOT\": {\n const activityType = getString(\"activityType\");\n if (!activityType || !isPlainObject(payload.content)) {\n return reject(\"missing activityType or object content\");\n }\n return withOptional(\n {\n type: \"ACTIVITY_SNAPSHOT\" as const,\n activityType,\n content: payload.content,\n },\n {\n messageId: getString(\"messageId\"),\n replace:\n typeof payload.replace === \"boolean\" ? payload.replace : undefined,\n subagentRunId: getString(\"subagentRunId\"),\n },\n );\n }\n case \"ACTIVITY_DELTA\": {\n const messageId = getString(\"messageId\");\n const activityType = getString(\"activityType\");\n if (!messageId || !activityType || !Array.isArray(payload.patch)) {\n return reject(\"missing messageId, activityType or patch array\");\n }\n return withOptional(\n {\n type: \"ACTIVITY_DELTA\" as const,\n messageId,\n activityType,\n patch: payload.patch as any[],\n },\n { subagentRunId: getString(\"subagentRunId\") },\n );\n }\n case \"RAW\":\n return withOptional(\n { type: \"RAW\" as const, event: payload.event },\n { source: getString(\"source\") },\n );\n case \"CUSTOM\": {\n const name = getString(\"name\");\n if (!name) return reject(\"missing name\");\n return { type: \"CUSTOM\", name, value: payload.value };\n }\n case \"SUBAGENT_STARTED\": {\n const subagentRunId = getString(\"subagentRunId\");\n const name = getString(\"name\");\n if (!subagentRunId || !name) {\n return reject(\"missing subagentRunId or name\");\n }\n return withOptional(\n { type: \"SUBAGENT_STARTED\" as const, subagentRunId, name },\n {\n description: getString(\"description\"),\n parentSubagentRunId: getString(\"parentSubagentRunId\"),\n parentToolCallId: getString(\"parentToolCallId\"),\n parentMessageId: getString(\"parentMessageId\"),\n },\n );\n }\n case \"SUBAGENT_FINISHED\": {\n const subagentRunId = getString(\"subagentRunId\");\n if (!subagentRunId) return reject(\"missing subagentRunId\");\n const rawOutcome = payload.outcome;\n let outcome: AgUiSubagentFinishedOutcome | undefined;\n if (rawOutcome == null) {\n outcome = undefined;\n } else if (!isPlainObject(rawOutcome)) {\n logRejectedEvent(\n options?.logger,\n \"SUBAGENT_FINISHED\",\n { subagentRunId, outcome: rawOutcome },\n \"has invalid outcome\",\n );\n outcome = undefined;\n } else if (rawOutcome.type === \"success\") {\n outcome = { type: \"success\" as const };\n } else if (rawOutcome.type === \"suspended\") {\n outcome = withOptional(\n { type: \"suspended\" as const },\n {\n interruptIds: Array.isArray(rawOutcome.interruptIds)\n ? (rawOutcome.interruptIds as unknown[]).filter(isString)\n : undefined,\n },\n );\n } else {\n logRejectedEvent(\n options?.logger,\n \"SUBAGENT_FINISHED\",\n { subagentRunId, outcome: rawOutcome },\n \"has unsupported outcome type\",\n );\n outcome = undefined;\n }\n return withOptional(\n { type: \"SUBAGENT_FINISHED\" as const, subagentRunId },\n { result: payload.result, outcome },\n );\n }\n case \"SUBAGENT_ERROR\": {\n const subagentRunId = getString(\"subagentRunId\");\n const message = getString(\"message\");\n if (!subagentRunId || !message) {\n return reject(\"missing subagentRunId or message\");\n }\n return withOptional(\n { type: \"SUBAGENT_ERROR\" as const, subagentRunId, message },\n { code: getString(\"code\") },\n );\n }\n default:\n return withOptional(\n { type: \"RAW\" as const, event: payload },\n {\n source: isString(payload.type) ? (payload.type as string) : undefined,\n },\n );\n }\n};\n"],"mappings":"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"}