@tanstack/ai 0.42.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/README.md +15 -1
  2. package/dist/esm/activities/chat/adapter.js +23 -16
  3. package/dist/esm/activities/chat/adapter.js.map +1 -1
  4. package/dist/esm/activities/chat/agent-loop-strategies.d.ts +5 -36
  5. package/dist/esm/activities/chat/agent-loop-strategies.js +75 -21
  6. package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
  7. package/dist/esm/activities/chat/cancel.d.ts +40 -0
  8. package/dist/esm/activities/chat/cancel.js +54 -0
  9. package/dist/esm/activities/chat/cancel.js.map +1 -0
  10. package/dist/esm/activities/chat/index.d.ts +28 -21
  11. package/dist/esm/activities/chat/index.js +2100 -1813
  12. package/dist/esm/activities/chat/index.js.map +1 -1
  13. package/dist/esm/activities/chat/mcp/manager.d.ts +2 -2
  14. package/dist/esm/activities/chat/mcp/manager.js +90 -77
  15. package/dist/esm/activities/chat/mcp/manager.js.map +1 -1
  16. package/dist/esm/activities/chat/mcp/types.d.ts +2 -2
  17. package/dist/esm/activities/chat/messages.js +397 -346
  18. package/dist/esm/activities/chat/messages.js.map +1 -1
  19. package/dist/esm/activities/chat/middleware/builder.js +17 -15
  20. package/dist/esm/activities/chat/middleware/builder.js.map +1 -1
  21. package/dist/esm/activities/chat/middleware/capabilities.js +78 -43
  22. package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -1
  23. package/dist/esm/activities/chat/middleware/compose.d.ts +94 -1
  24. package/dist/esm/activities/chat/middleware/compose.js +623 -531
  25. package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
  26. package/dist/esm/activities/chat/middleware/define.js +12 -5
  27. package/dist/esm/activities/chat/middleware/define.js.map +1 -1
  28. package/dist/esm/activities/chat/middleware/index.d.ts +5 -1
  29. package/dist/esm/activities/chat/middleware/locks.d.ts +50 -0
  30. package/dist/esm/activities/chat/middleware/locks.js +71 -0
  31. package/dist/esm/activities/chat/middleware/locks.js.map +1 -0
  32. package/dist/esm/activities/chat/middleware/pending-turn.d.ts +15 -0
  33. package/dist/esm/activities/chat/middleware/pending-turn.js +35 -0
  34. package/dist/esm/activities/chat/middleware/pending-turn.js.map +1 -0
  35. package/dist/esm/activities/chat/middleware/run-disconnect.d.ts +23 -0
  36. package/dist/esm/activities/chat/middleware/run-disconnect.js +42 -0
  37. package/dist/esm/activities/chat/middleware/run-disconnect.js.map +1 -0
  38. package/dist/esm/activities/chat/middleware/run-store.d.ts +283 -0
  39. package/dist/esm/activities/chat/middleware/run-store.js +176 -0
  40. package/dist/esm/activities/chat/middleware/run-store.js.map +1 -0
  41. package/dist/esm/activities/chat/middleware/sandbox-runtime.js +14 -8
  42. package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
  43. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +79 -70
  44. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -1
  45. package/dist/esm/activities/chat/middleware/types.d.ts +59 -2
  46. package/dist/esm/activities/chat/middleware/validate.js +23 -28
  47. package/dist/esm/activities/chat/middleware/validate.js.map +1 -1
  48. package/dist/esm/activities/chat/stream/json-parser.js +39 -25
  49. package/dist/esm/activities/chat/stream/json-parser.js.map +1 -1
  50. package/dist/esm/activities/chat/stream/message-updaters.js +275 -234
  51. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  52. package/dist/esm/activities/chat/stream/processor.d.ts +24 -4
  53. package/dist/esm/activities/chat/stream/processor.js +1341 -1542
  54. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  55. package/dist/esm/activities/chat/stream/strategies.js +69 -53
  56. package/dist/esm/activities/chat/stream/strategies.js.map +1 -1
  57. package/dist/esm/activities/chat/tools/approval-schema.d.ts +19 -0
  58. package/dist/esm/activities/chat/tools/approval-schema.js +117 -0
  59. package/dist/esm/activities/chat/tools/approval-schema.js.map +1 -0
  60. package/dist/esm/activities/chat/tools/lazy-tool-manager.js +164 -191
  61. package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
  62. package/dist/esm/activities/chat/tools/lazy-tools.js +24 -12
  63. package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -1
  64. package/dist/esm/activities/chat/tools/schema-converter.js +293 -146
  65. package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
  66. package/dist/esm/activities/chat/tools/tool-calls.d.ts +18 -2
  67. package/dist/esm/activities/chat/tools/tool-calls.js +522 -531
  68. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  69. package/dist/esm/activities/chat/tools/tool-definition.d.ts +75 -16
  70. package/dist/esm/activities/chat/tools/tool-definition.js +95 -23
  71. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
  72. package/dist/esm/activities/error-payload.js +85 -47
  73. package/dist/esm/activities/error-payload.js.map +1 -1
  74. package/dist/esm/activities/generateAudio/adapter.js +22 -15
  75. package/dist/esm/activities/generateAudio/adapter.js.map +1 -1
  76. package/dist/esm/activities/generateAudio/index.d.ts +4 -0
  77. package/dist/esm/activities/generateAudio/index.js +141 -105
  78. package/dist/esm/activities/generateAudio/index.js.map +1 -1
  79. package/dist/esm/activities/generateImage/adapter.js +22 -15
  80. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  81. package/dist/esm/activities/generateImage/index.d.ts +4 -0
  82. package/dist/esm/activities/generateImage/index.js +155 -111
  83. package/dist/esm/activities/generateImage/index.js.map +1 -1
  84. package/dist/esm/activities/generateSpeech/adapter.js +22 -15
  85. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
  86. package/dist/esm/activities/generateSpeech/index.d.ts +4 -0
  87. package/dist/esm/activities/generateSpeech/index.js +159 -110
  88. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  89. package/dist/esm/activities/generateTranscription/adapter.js +22 -15
  90. package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
  91. package/dist/esm/activities/generateTranscription/index.d.ts +4 -0
  92. package/dist/esm/activities/generateTranscription/index.js +159 -100
  93. package/dist/esm/activities/generateTranscription/index.js.map +1 -1
  94. package/dist/esm/activities/generateVideo/adapter.js +36 -29
  95. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  96. package/dist/esm/activities/generateVideo/index.d.ts +143 -19
  97. package/dist/esm/activities/generateVideo/index.js +456 -279
  98. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  99. package/dist/esm/activities/generateVideo/snap.js +60 -48
  100. package/dist/esm/activities/generateVideo/snap.js.map +1 -1
  101. package/dist/esm/activities/index.js +8 -34
  102. package/dist/esm/activities/middleware/index.d.ts +1 -1
  103. package/dist/esm/activities/middleware/run.d.ts +10 -0
  104. package/dist/esm/activities/middleware/run.js +53 -29
  105. package/dist/esm/activities/middleware/run.js.map +1 -1
  106. package/dist/esm/activities/middleware/types.d.ts +44 -6
  107. package/dist/esm/activities/stream-generation-result.d.ts +4 -1
  108. package/dist/esm/activities/stream-generation-result.js +79 -44
  109. package/dist/esm/activities/stream-generation-result.js.map +1 -1
  110. package/dist/esm/activities/summarize/adapter.js +22 -15
  111. package/dist/esm/activities/summarize/adapter.js.map +1 -1
  112. package/dist/esm/activities/summarize/chat-stream-summarize.js +252 -202
  113. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
  114. package/dist/esm/activities/summarize/index.d.ts +27 -0
  115. package/dist/esm/activities/summarize/index.js +268 -102
  116. package/dist/esm/activities/summarize/index.js.map +1 -1
  117. package/dist/esm/adapter-internals.d.ts +2 -1
  118. package/dist/esm/adapter-internals.js +4 -11
  119. package/dist/esm/client.d.ts +25 -3
  120. package/dist/esm/client.js +131 -64
  121. package/dist/esm/client.js.map +1 -1
  122. package/dist/esm/custom-events.d.ts +76 -0
  123. package/dist/esm/custom-events.js +37 -0
  124. package/dist/esm/custom-events.js.map +1 -0
  125. package/dist/esm/delivery-detach.d.ts +50 -0
  126. package/dist/esm/delivery-detach.js +71 -0
  127. package/dist/esm/delivery-detach.js.map +1 -0
  128. package/dist/esm/delivery-disconnect.d.ts +62 -0
  129. package/dist/esm/delivery-disconnect.js +81 -0
  130. package/dist/esm/delivery-disconnect.js.map +1 -0
  131. package/dist/esm/extend-adapter.js +19 -17
  132. package/dist/esm/extend-adapter.js.map +1 -1
  133. package/dist/esm/index.d.ts +24 -6
  134. package/dist/esm/index.js +30 -98
  135. package/dist/esm/interrupt-resume.d.ts +71 -0
  136. package/dist/esm/interrupt-resume.js +438 -0
  137. package/dist/esm/interrupt-resume.js.map +1 -0
  138. package/dist/esm/interrupt-serialization.d.ts +12 -0
  139. package/dist/esm/interrupt-serialization.js +178 -0
  140. package/dist/esm/interrupt-serialization.js.map +1 -0
  141. package/dist/esm/interrupts.d.ts +84 -0
  142. package/dist/esm/interrupts.js +31 -0
  143. package/dist/esm/interrupts.js.map +1 -0
  144. package/dist/esm/locks.d.ts +10 -0
  145. package/dist/esm/locks.js +2 -0
  146. package/dist/esm/logger/console-logger.js +101 -78
  147. package/dist/esm/logger/console-logger.js.map +1 -1
  148. package/dist/esm/logger/internal-logger.js +104 -89
  149. package/dist/esm/logger/internal-logger.js.map +1 -1
  150. package/dist/esm/logger/resolve.js +54 -49
  151. package/dist/esm/logger/resolve.js.map +1 -1
  152. package/dist/esm/logger/types.d.ts +1 -1
  153. package/dist/esm/middlewares/content-guard.js +142 -148
  154. package/dist/esm/middlewares/content-guard.js.map +1 -1
  155. package/dist/esm/middlewares/index.js +2 -6
  156. package/dist/esm/middlewares/otel.js +598 -732
  157. package/dist/esm/middlewares/otel.js.map +1 -1
  158. package/dist/esm/middlewares/usage-attributes.js +47 -40
  159. package/dist/esm/middlewares/usage-attributes.js.map +1 -1
  160. package/dist/esm/realtime/event-emitter.js +24 -25
  161. package/dist/esm/realtime/event-emitter.js.map +1 -1
  162. package/dist/esm/realtime/index.d.ts +5 -9
  163. package/dist/esm/realtime/index.js +29 -6
  164. package/dist/esm/realtime/index.js.map +1 -1
  165. package/dist/esm/scope.d.ts +47 -0
  166. package/dist/esm/stream-durability.d.ts +171 -0
  167. package/dist/esm/stream-durability.js +295 -0
  168. package/dist/esm/stream-durability.js.map +1 -0
  169. package/dist/esm/stream-to-response.d.ts +178 -13
  170. package/dist/esm/stream-to-response.js +663 -115
  171. package/dist/esm/stream-to-response.js.map +1 -1
  172. package/dist/esm/strip-to-spec-middleware.js +30 -16
  173. package/dist/esm/strip-to-spec-middleware.js.map +1 -1
  174. package/dist/esm/system-prompts.js +27 -21
  175. package/dist/esm/system-prompts.js.map +1 -1
  176. package/dist/esm/tool-registry.js +72 -45
  177. package/dist/esm/tool-registry.js.map +1 -1
  178. package/dist/esm/tools/provider-tool.js +14 -5
  179. package/dist/esm/tools/provider-tool.js.map +1 -1
  180. package/dist/esm/types.d.ts +321 -42
  181. package/dist/esm/types.js +2 -0
  182. package/dist/esm/utilities/ag-ui-wire.js +79 -93
  183. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  184. package/dist/esm/utilities/chat-params.d.ts +26 -4
  185. package/dist/esm/utilities/chat-params.js +218 -92
  186. package/dist/esm/utilities/chat-params.js.map +1 -1
  187. package/dist/esm/utilities/errors.js +28 -18
  188. package/dist/esm/utilities/errors.js.map +1 -1
  189. package/dist/esm/utilities/media-prompt.js +46 -41
  190. package/dist/esm/utilities/media-prompt.js.map +1 -1
  191. package/dist/esm/utilities/numbers.js +13 -10
  192. package/dist/esm/utilities/numbers.js.map +1 -1
  193. package/dist/esm/utilities/provider-executed.js +20 -11
  194. package/dist/esm/utilities/provider-executed.js.map +1 -1
  195. package/dist/esm/utilities/sampling-keys.js +31 -19
  196. package/dist/esm/utilities/sampling-keys.js.map +1 -1
  197. package/dist/esm/utilities/tool-result.js +42 -30
  198. package/dist/esm/utilities/tool-result.js.map +1 -1
  199. package/dist/esm/utilities/usage.js +27 -9
  200. package/dist/esm/utilities/usage.js.map +1 -1
  201. package/dist/esm/utils.js +26 -18
  202. package/dist/esm/utils.js.map +1 -1
  203. package/package.json +10 -6
  204. package/skills/ai-core/SKILL.md +69 -18
  205. package/skills/ai-core/adapter-configuration/SKILL.md +44 -21
  206. package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +1 -3
  207. package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +148 -0
  208. package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -6
  209. package/skills/ai-core/adapter-configuration/references/groq-adapter.md +2 -6
  210. package/skills/ai-core/adapter-configuration/references/openai-adapter.md +1 -3
  211. package/skills/ai-core/ag-ui-protocol/SKILL.md +1 -1
  212. package/skills/ai-core/chat-experience/SKILL.md +98 -11
  213. package/skills/ai-core/client-persistence/SKILL.md +277 -0
  214. package/skills/ai-core/custom-backend-integration/SKILL.md +1 -1
  215. package/skills/ai-core/debug-logging/SKILL.md +1 -1
  216. package/skills/ai-core/locks/SKILL.md +143 -0
  217. package/skills/ai-core/media-generation/SKILL.md +144 -12
  218. package/skills/ai-core/middleware/SKILL.md +258 -33
  219. package/skills/ai-core/structured-outputs/SKILL.md +1 -1
  220. package/skills/ai-core/tool-calling/SKILL.md +54 -61
  221. package/src/activities/chat/agent-loop-strategies.ts +5 -39
  222. package/src/activities/chat/cancel.ts +81 -0
  223. package/src/activities/chat/index.ts +1091 -200
  224. package/src/activities/chat/mcp/manager.ts +4 -4
  225. package/src/activities/chat/mcp/types.ts +2 -2
  226. package/src/activities/chat/messages.ts +5 -3
  227. package/src/activities/chat/middleware/builder.ts +1 -1
  228. package/src/activities/chat/middleware/compose.ts +186 -9
  229. package/src/activities/chat/middleware/index.ts +26 -0
  230. package/src/activities/chat/middleware/locks.ts +102 -0
  231. package/src/activities/chat/middleware/pending-turn.ts +47 -0
  232. package/src/activities/chat/middleware/run-disconnect.ts +62 -0
  233. package/src/activities/chat/middleware/run-store.ts +412 -0
  234. package/src/activities/chat/middleware/types.ts +62 -1
  235. package/src/activities/chat/stream/processor.ts +189 -5
  236. package/src/activities/chat/tools/approval-schema.ts +205 -0
  237. package/src/activities/chat/tools/tool-calls.ts +106 -13
  238. package/src/activities/chat/tools/tool-definition.ts +210 -39
  239. package/src/activities/generateAudio/index.ts +20 -3
  240. package/src/activities/generateImage/index.ts +20 -3
  241. package/src/activities/generateSpeech/index.ts +25 -3
  242. package/src/activities/generateTranscription/index.ts +26 -3
  243. package/src/activities/generateVideo/index.ts +345 -82
  244. package/src/activities/middleware/index.ts +2 -0
  245. package/src/activities/middleware/run.ts +31 -0
  246. package/src/activities/middleware/types.ts +49 -5
  247. package/src/activities/stream-generation-result.ts +30 -2
  248. package/src/activities/summarize/chat-stream-summarize.ts +5 -0
  249. package/src/activities/summarize/index.ts +200 -10
  250. package/src/adapter-internals.ts +10 -1
  251. package/src/client.ts +244 -0
  252. package/src/custom-events.ts +107 -0
  253. package/src/delivery-detach.ts +72 -0
  254. package/src/delivery-disconnect.ts +84 -0
  255. package/src/index.ts +138 -1
  256. package/src/interrupt-resume.ts +824 -0
  257. package/src/interrupt-serialization.ts +183 -0
  258. package/src/interrupts.ts +146 -0
  259. package/src/locks.ts +17 -0
  260. package/src/logger/types.ts +1 -1
  261. package/src/middlewares/otel.ts +1 -0
  262. package/src/realtime/index.ts +5 -9
  263. package/src/scope.ts +47 -0
  264. package/src/stream-durability.ts +598 -0
  265. package/src/stream-to-response.ts +1051 -95
  266. package/src/strip-to-spec-middleware.ts +3 -3
  267. package/src/types.ts +405 -45
  268. package/src/utilities/chat-params.ts +245 -55
  269. package/dist/esm/activities/index.js.map +0 -1
  270. package/dist/esm/adapter-internals.js.map +0 -1
  271. package/dist/esm/index.js.map +0 -1
  272. package/dist/esm/middlewares/index.js.map +0 -1
@@ -1,255 +1,296 @@
1
1
  import { parsePartialJSON } from "./json-parser.js";
2
+ //#region src/activities/chat/stream/message-updaters.ts
3
+ /**
4
+ * Message Updaters (Internal)
5
+ *
6
+ * Internal helper functions for updating UIMessage parts.
7
+ * These are used by StreamProcessor to manage the message array.
8
+ */
9
+ /**
10
+ * Update or add a text part to a message.
11
+ *
12
+ * If the last part is a text part, update it (continuing the same text segment).
13
+ * Otherwise, create a new text part (starting a new text segment after tool calls).
14
+ */
2
15
  function updateTextPart(messages, messageId, content) {
3
- return messages.map((msg) => {
4
- if (msg.id !== messageId) {
5
- return msg;
6
- }
7
- const parts = [...msg.parts];
8
- const lastPart = parts.length > 0 ? parts[parts.length - 1] : null;
9
- if (lastPart && lastPart.type === "text") {
10
- parts[parts.length - 1] = { type: "text", content };
11
- } else {
12
- parts.push({ type: "text", content });
13
- }
14
- return { ...msg, parts };
15
- });
16
+ return messages.map((msg) => {
17
+ if (msg.id !== messageId) return msg;
18
+ const parts = [...msg.parts];
19
+ const lastPart = parts.length > 0 ? parts[parts.length - 1] : null;
20
+ if (lastPart && lastPart.type === "text") parts[parts.length - 1] = {
21
+ type: "text",
22
+ content
23
+ };
24
+ else parts.push({
25
+ type: "text",
26
+ content
27
+ });
28
+ return {
29
+ ...msg,
30
+ parts
31
+ };
32
+ });
16
33
  }
34
+ /**
35
+ * Update or add a tool call part to a message.
36
+ */
17
37
  function updateToolCallPart(messages, messageId, toolCall) {
18
- return messages.map((msg) => {
19
- if (msg.id !== messageId) {
20
- return msg;
21
- }
22
- const parts = [...msg.parts];
23
- const existing = parts.find(
24
- (p) => p.type === "tool-call" && p.id === toolCall.id
25
- );
26
- const metadata = toolCall.metadata ?? existing?.metadata;
27
- const input = toolCall.input ?? existing?.input;
28
- const toolCallPart = {
29
- type: "tool-call",
30
- id: toolCall.id,
31
- name: toolCall.name,
32
- arguments: toolCall.arguments,
33
- state: toolCall.state,
34
- // Carry forward approval, output and parsed input from the existing part
35
- ...existing?.approval && { approval: { ...existing.approval } },
36
- ...existing?.output !== void 0 && { output: existing.output },
37
- ...input !== void 0 && { input },
38
- ...metadata !== void 0 && { metadata }
39
- };
40
- if (existing) {
41
- parts[parts.indexOf(existing)] = toolCallPart;
42
- } else {
43
- parts.push(toolCallPart);
44
- }
45
- return { ...msg, parts };
46
- });
38
+ return messages.map((msg) => {
39
+ if (msg.id !== messageId) return msg;
40
+ const parts = [...msg.parts];
41
+ const existing = parts.find((p) => p.type === "tool-call" && p.id === toolCall.id);
42
+ const metadata = toolCall.metadata ?? existing?.metadata;
43
+ const input = toolCall.input ?? existing?.input;
44
+ const toolCallPart = {
45
+ type: "tool-call",
46
+ id: toolCall.id,
47
+ name: toolCall.name,
48
+ arguments: toolCall.arguments,
49
+ state: toolCall.state,
50
+ ...existing?.approval && { approval: { ...existing.approval } },
51
+ ...existing?.output !== void 0 && { output: existing.output },
52
+ ...input !== void 0 && { input },
53
+ ...metadata !== void 0 && { metadata }
54
+ };
55
+ if (existing) parts[parts.indexOf(existing)] = toolCallPart;
56
+ else parts.push(toolCallPart);
57
+ return {
58
+ ...msg,
59
+ parts
60
+ };
61
+ });
47
62
  }
63
+ /**
64
+ * Update or add a tool result part to a message.
65
+ */
48
66
  function updateToolResultPart(messages, messageId, toolCallId, content, state, error) {
49
- return messages.map((msg) => {
50
- if (msg.id !== messageId) {
51
- return msg;
52
- }
53
- const parts = [...msg.parts];
54
- const resultPartIndex = parts.findIndex(
55
- (p) => p.type === "tool-result" && p.toolCallId === toolCallId
56
- );
57
- const toolResultPart = {
58
- type: "tool-result",
59
- toolCallId,
60
- content,
61
- state,
62
- ...error && { error }
63
- };
64
- if (resultPartIndex >= 0) {
65
- parts[resultPartIndex] = toolResultPart;
66
- } else {
67
- parts.push(toolResultPart);
68
- }
69
- return { ...msg, parts };
70
- });
67
+ return messages.map((msg) => {
68
+ if (msg.id !== messageId) return msg;
69
+ const parts = [...msg.parts];
70
+ const resultPartIndex = parts.findIndex((p) => p.type === "tool-result" && p.toolCallId === toolCallId);
71
+ const toolResultPart = {
72
+ type: "tool-result",
73
+ toolCallId,
74
+ content,
75
+ state,
76
+ ...error && { error }
77
+ };
78
+ if (resultPartIndex >= 0) parts[resultPartIndex] = toolResultPart;
79
+ else parts.push(toolResultPart);
80
+ return {
81
+ ...msg,
82
+ parts
83
+ };
84
+ });
71
85
  }
86
+ /**
87
+ * Update a tool call part with approval request metadata.
88
+ */
72
89
  function updateToolCallApproval(messages, messageId, toolCallId, approvalId) {
73
- return messages.map((msg) => {
74
- if (msg.id !== messageId) {
75
- return msg;
76
- }
77
- const parts = [...msg.parts];
78
- const toolCallPart = parts.find(
79
- (p) => p.type === "tool-call" && p.id === toolCallId
80
- );
81
- if (toolCallPart) {
82
- const index = parts.indexOf(toolCallPart);
83
- parts[index] = {
84
- ...toolCallPart,
85
- state: "approval-requested",
86
- approval: {
87
- id: approvalId,
88
- needsApproval: true
89
- }
90
- };
91
- }
92
- return { ...msg, parts };
93
- });
90
+ return messages.map((msg) => {
91
+ if (msg.id !== messageId) return msg;
92
+ const parts = [...msg.parts];
93
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
94
+ if (toolCallPart) {
95
+ const index = parts.indexOf(toolCallPart);
96
+ parts[index] = {
97
+ ...toolCallPart,
98
+ state: "approval-requested",
99
+ approval: {
100
+ id: approvalId,
101
+ needsApproval: true
102
+ }
103
+ };
104
+ }
105
+ return {
106
+ ...msg,
107
+ parts
108
+ };
109
+ });
94
110
  }
111
+ /**
112
+ * Update a tool call part with output.
113
+ * Searches all messages to find the tool call by ID.
114
+ */
95
115
  function updateToolCallWithOutput(messages, toolCallId, output, state, errorText) {
96
- return messages.map((msg) => {
97
- const parts = [...msg.parts];
98
- const toolCallPart = parts.find(
99
- (p) => p.type === "tool-call" && p.id === toolCallId
100
- );
101
- if (toolCallPart) {
102
- const index = parts.indexOf(toolCallPart);
103
- parts[index] = {
104
- ...toolCallPart,
105
- output: errorText ? { error: errorText } : output,
106
- state: state ?? (errorText ? "error" : "complete")
107
- };
108
- }
109
- return { ...msg, parts };
110
- });
116
+ return messages.map((msg) => {
117
+ const parts = [...msg.parts];
118
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
119
+ if (toolCallPart) {
120
+ const index = parts.indexOf(toolCallPart);
121
+ parts[index] = {
122
+ ...toolCallPart,
123
+ output: errorText ? { error: errorText } : output,
124
+ state: state ?? (errorText ? "error" : "complete")
125
+ };
126
+ }
127
+ return {
128
+ ...msg,
129
+ parts
130
+ };
131
+ });
111
132
  }
133
+ /**
134
+ * Update a tool call part with approval response.
135
+ * Searches all messages to find the tool call by approval ID.
136
+ */
112
137
  function updateToolCallApprovalResponse(messages, approvalId, approved) {
113
- return messages.map((msg) => {
114
- const parts = [...msg.parts];
115
- const toolCallPart = parts.find(
116
- (p) => p.type === "tool-call" && p.approval?.id === approvalId
117
- );
118
- if (toolCallPart && toolCallPart.approval) {
119
- const index = parts.indexOf(toolCallPart);
120
- parts[index] = {
121
- ...toolCallPart,
122
- approval: { ...toolCallPart.approval, approved },
123
- state: "approval-responded"
124
- };
125
- }
126
- return { ...msg, parts };
127
- });
138
+ return messages.map((msg) => {
139
+ const parts = [...msg.parts];
140
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.approval?.id === approvalId);
141
+ if (toolCallPart && toolCallPart.approval) {
142
+ const index = parts.indexOf(toolCallPart);
143
+ parts[index] = {
144
+ ...toolCallPart,
145
+ approval: {
146
+ ...toolCallPart.approval,
147
+ approved
148
+ },
149
+ state: "approval-responded"
150
+ };
151
+ }
152
+ return {
153
+ ...msg,
154
+ parts
155
+ };
156
+ });
128
157
  }
158
+ /**
159
+ * Append a delta to the structured-output part on `messageId`, or create one
160
+ * if absent. Progressive parse of the accumulated buffer fills `partial`.
161
+ *
162
+ * Callers must only invoke this while the part is still in flight — the
163
+ * helper unconditionally writes `status: 'streaming'`, so feeding it a delta
164
+ * after a `complete`/`error` terminal would regress the part. In practice the
165
+ * processor gates calls via `structuredMessageIds`, which is dropped on
166
+ * terminal events.
167
+ *
168
+ * If the progressive parse returns null/undefined (the buffer is not yet a
169
+ * parseable JSON prefix), the previously-good `partial` is preserved so the
170
+ * UI doesn't flicker back to empty for a single render.
171
+ */
129
172
  function appendStructuredOutputDelta(messages, messageId, delta) {
130
- return messages.map((msg) => {
131
- if (msg.id !== messageId) {
132
- return msg;
133
- }
134
- const parts = [...msg.parts];
135
- const existingIndex = parts.findIndex(
136
- (p) => p.type === "structured-output"
137
- );
138
- const existing = existingIndex >= 0 ? parts[existingIndex] : null;
139
- const nextRaw = (existing?.raw ?? "") + delta;
140
- const progressive = parsePartialJSON(nextRaw);
141
- const nextPartial = progressive !== void 0 && progressive !== null ? progressive : existing?.partial;
142
- const nextPart = {
143
- type: "structured-output",
144
- status: "streaming",
145
- raw: nextRaw,
146
- ...nextPartial !== void 0 ? { partial: nextPartial } : {},
147
- ...existing?.reasoning !== void 0 ? { reasoning: existing.reasoning } : {}
148
- };
149
- if (existingIndex >= 0) {
150
- parts[existingIndex] = nextPart;
151
- } else {
152
- parts.push(nextPart);
153
- }
154
- return { ...msg, parts };
155
- });
173
+ return messages.map((msg) => {
174
+ if (msg.id !== messageId) return msg;
175
+ const parts = [...msg.parts];
176
+ const existingIndex = parts.findIndex((p) => p.type === "structured-output");
177
+ const existing = existingIndex >= 0 ? parts[existingIndex] : null;
178
+ const nextRaw = (existing?.raw ?? "") + delta;
179
+ const progressive = parsePartialJSON(nextRaw);
180
+ const nextPartial = progressive !== void 0 && progressive !== null ? progressive : existing?.partial;
181
+ const nextPart = {
182
+ type: "structured-output",
183
+ status: "streaming",
184
+ raw: nextRaw,
185
+ ...nextPartial !== void 0 ? { partial: nextPartial } : {},
186
+ ...existing?.reasoning !== void 0 ? { reasoning: existing.reasoning } : {}
187
+ };
188
+ if (existingIndex >= 0) parts[existingIndex] = nextPart;
189
+ else parts.push(nextPart);
190
+ return {
191
+ ...msg,
192
+ parts
193
+ };
194
+ });
156
195
  }
196
+ /**
197
+ * Snap the structured-output part on `messageId` to `complete` with the
198
+ * validated `data`. Picks the freshest available `raw` so the wire
199
+ * round-trip stays internally consistent:
200
+ *
201
+ * 1. Caller-supplied `raw` (the original streamed bytes from the model).
202
+ * 2. The existing part's `raw` (deltas accumulated before this terminal).
203
+ * 3. `JSON.stringify(data)` as a defensive fallback for terminal-only
204
+ * completes that never shipped raw — keeps the part self-consistent
205
+ * so downstream consumers never see a complete part with empty raw.
206
+ */
157
207
  function completeStructuredOutputPart(messages, messageId, data, raw, reasoning) {
158
- return messages.map((msg) => {
159
- if (msg.id !== messageId) {
160
- return msg;
161
- }
162
- const parts = [...msg.parts];
163
- const existingIndex = parts.findIndex(
164
- (p) => p.type === "structured-output"
165
- );
166
- const existingRaw = existingIndex >= 0 ? parts[existingIndex].raw : "";
167
- let resolvedRaw = raw || existingRaw;
168
- if (resolvedRaw === "" && data !== void 0) {
169
- try {
170
- resolvedRaw = JSON.stringify(data);
171
- } catch {
172
- }
173
- }
174
- const nextPart = {
175
- type: "structured-output",
176
- status: "complete",
177
- data,
178
- partial: data,
179
- raw: resolvedRaw,
180
- ...reasoning !== void 0 ? { reasoning } : {}
181
- };
182
- if (existingIndex >= 0) {
183
- parts[existingIndex] = nextPart;
184
- } else {
185
- parts.push(nextPart);
186
- }
187
- return { ...msg, parts };
188
- });
208
+ return messages.map((msg) => {
209
+ if (msg.id !== messageId) return msg;
210
+ const parts = [...msg.parts];
211
+ const existingIndex = parts.findIndex((p) => p.type === "structured-output");
212
+ const existingRaw = existingIndex >= 0 ? parts[existingIndex].raw : "";
213
+ let resolvedRaw = raw || existingRaw;
214
+ if (resolvedRaw === "" && data !== void 0) try {
215
+ resolvedRaw = JSON.stringify(data);
216
+ } catch {}
217
+ const nextPart = {
218
+ type: "structured-output",
219
+ status: "complete",
220
+ data,
221
+ partial: data,
222
+ raw: resolvedRaw,
223
+ ...reasoning !== void 0 ? { reasoning } : {}
224
+ };
225
+ if (existingIndex >= 0) parts[existingIndex] = nextPart;
226
+ else parts.push(nextPart);
227
+ return {
228
+ ...msg,
229
+ parts
230
+ };
231
+ });
189
232
  }
233
+ /**
234
+ * Mark the structured-output part on `messageId` as errored. If no part
235
+ * exists yet — RUN_ERROR fired after `structured-output.start` but before
236
+ * any delta — create an empty errored placeholder so consumers have
237
+ * something renderable. Existing complete parts are left alone (an error
238
+ * after a successful complete should not retroactively un-complete it).
239
+ */
190
240
  function errorStructuredOutputPart(messages, messageId, errorMessage) {
191
- return messages.map((msg) => {
192
- if (msg.id !== messageId) {
193
- return msg;
194
- }
195
- const parts = [...msg.parts];
196
- const existingIndex = parts.findIndex(
197
- (p) => p.type === "structured-output"
198
- );
199
- if (existingIndex < 0) {
200
- parts.push({
201
- type: "structured-output",
202
- status: "error",
203
- raw: "",
204
- errorMessage
205
- });
206
- return { ...msg, parts };
207
- }
208
- const existing = parts[existingIndex];
209
- if (existing.status === "complete") {
210
- return msg;
211
- }
212
- parts[existingIndex] = {
213
- ...existing,
214
- status: "error",
215
- errorMessage
216
- };
217
- return { ...msg, parts };
218
- });
241
+ return messages.map((msg) => {
242
+ if (msg.id !== messageId) return msg;
243
+ const parts = [...msg.parts];
244
+ const existingIndex = parts.findIndex((p) => p.type === "structured-output");
245
+ if (existingIndex < 0) {
246
+ parts.push({
247
+ type: "structured-output",
248
+ status: "error",
249
+ raw: "",
250
+ errorMessage
251
+ });
252
+ return {
253
+ ...msg,
254
+ parts
255
+ };
256
+ }
257
+ const existing = parts[existingIndex];
258
+ if (existing.status === "complete") return msg;
259
+ parts[existingIndex] = {
260
+ ...existing,
261
+ status: "error",
262
+ errorMessage
263
+ };
264
+ return {
265
+ ...msg,
266
+ parts
267
+ };
268
+ });
219
269
  }
270
+ /**
271
+ * Update or add a thinking part to a message, keyed by stepId.
272
+ * Each distinct stepId produces its own ThinkingPart.
273
+ */
220
274
  function updateThinkingPart(messages, messageId, stepId, content, signature) {
221
- return messages.map((msg) => {
222
- if (msg.id !== messageId) {
223
- return msg;
224
- }
225
- const parts = [...msg.parts];
226
- const thinkingPartIndex = parts.findIndex(
227
- (p) => p.type === "thinking" && p.stepId === stepId
228
- );
229
- const thinkingPart = {
230
- type: "thinking",
231
- content,
232
- stepId,
233
- ...signature && { signature }
234
- };
235
- if (thinkingPartIndex >= 0) {
236
- parts[thinkingPartIndex] = thinkingPart;
237
- } else {
238
- parts.push(thinkingPart);
239
- }
240
- return { ...msg, parts };
241
- });
275
+ return messages.map((msg) => {
276
+ if (msg.id !== messageId) return msg;
277
+ const parts = [...msg.parts];
278
+ const thinkingPartIndex = parts.findIndex((p) => p.type === "thinking" && p.stepId === stepId);
279
+ const thinkingPart = {
280
+ type: "thinking",
281
+ content,
282
+ stepId,
283
+ ...signature && { signature }
284
+ };
285
+ if (thinkingPartIndex >= 0) parts[thinkingPartIndex] = thinkingPart;
286
+ else parts.push(thinkingPart);
287
+ return {
288
+ ...msg,
289
+ parts
290
+ };
291
+ });
242
292
  }
243
- export {
244
- appendStructuredOutputDelta,
245
- completeStructuredOutputPart,
246
- errorStructuredOutputPart,
247
- updateTextPart,
248
- updateThinkingPart,
249
- updateToolCallApproval,
250
- updateToolCallApprovalResponse,
251
- updateToolCallPart,
252
- updateToolCallWithOutput,
253
- updateToolResultPart
254
- };
255
- //# sourceMappingURL=message-updaters.js.map
293
+ //#endregion
294
+ export { appendStructuredOutputDelta, completeStructuredOutputPart, errorStructuredOutputPart, updateTextPart, updateThinkingPart, updateToolCallApproval, updateToolCallApprovalResponse, updateToolCallPart, updateToolCallWithOutput, updateToolResultPart };
295
+
296
+ //# sourceMappingURL=message-updaters.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-updaters.js","sources":["../../../../../src/activities/chat/stream/message-updaters.ts"],"sourcesContent":["/**\n * Message Updaters (Internal)\n *\n * Internal helper functions for updating UIMessage parts.\n * These are used by StreamProcessor to manage the message array.\n */\n\nimport { parsePartialJSON } from './json-parser'\nimport type {\n ContentPart,\n StructuredOutputPart,\n ThinkingPart,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n} from '../../../types'\nimport type { ToolCallState, ToolResultState } from './types'\n\n/**\n * Update or add a text part to a message.\n *\n * If the last part is a text part, update it (continuing the same text segment).\n * Otherwise, create a new text part (starting a new text segment after tool calls).\n */\nexport function updateTextPart(\n messages: Array<UIMessage>,\n messageId: string,\n content: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const lastPart = parts.length > 0 ? parts[parts.length - 1] : null\n\n if (lastPart && lastPart.type === 'text') {\n // Update the last text part (continuing same text segment)\n parts[parts.length - 1] = { type: 'text', content }\n } else {\n // Create new text part (starting new text segment after tool calls/results)\n parts.push({ type: 'text', content })\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool call part to a message.\n */\nexport function updateToolCallPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCall: {\n id: string\n name: string\n arguments: string\n state: ToolCallState\n /** Parsed input — set when the arguments are complete. */\n input?: unknown\n metadata?: Record<string, unknown>\n },\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existing = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCall.id,\n )\n\n // Carry forward metadata from either the new toolCall or the existing\n // part. Once the adapter has emitted metadata for a tool call (e.g.\n // Gemini's thoughtSignature on TOOL_CALL_START) we must not lose it on\n // subsequent updates that don't re-supply it.\n const metadata = toolCall.metadata ?? existing?.metadata\n // Same for the parsed input: it's supplied once at completion, so\n // subsequent arg-less updates (approval, etc.) must not drop it.\n const input = toolCall.input ?? existing?.input\n\n const toolCallPart: ToolCallPart = {\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.name,\n arguments: toolCall.arguments,\n state: toolCall.state,\n // Carry forward approval, output and parsed input from the existing part\n ...(existing?.approval && { approval: { ...existing.approval } }),\n ...(existing?.output !== undefined && { output: existing.output }),\n ...(input !== undefined && { input }),\n ...(metadata !== undefined && { metadata }),\n }\n\n if (existing) {\n // Update existing tool call\n parts[parts.indexOf(existing)] = toolCallPart\n } else {\n // Add new tool call at the end (preserve natural streaming order)\n parts.push(toolCallPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool result part to a message.\n */\nexport function updateToolResultPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n content: string | Array<ContentPart>,\n state: ToolResultState,\n error?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const resultPartIndex = parts.findIndex(\n (p): p is ToolResultPart =>\n p.type === 'tool-result' && p.toolCallId === toolCallId,\n )\n\n const toolResultPart: ToolResultPart = {\n type: 'tool-result',\n toolCallId,\n content,\n state,\n ...(error && { error }),\n }\n\n if (resultPartIndex >= 0) {\n parts[resultPartIndex] = toolResultPart\n } else {\n parts.push(toolResultPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval request metadata.\n */\nexport function updateToolCallApproval(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n approvalId: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n state: 'approval-requested',\n approval: {\n id: approvalId,\n needsApproval: true,\n },\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part's state (e.g., to \"input-complete\").\n */\nexport function updateToolCallState(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n state: ToolCallState,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = { ...toolCallPart, state }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with output.\n * Searches all messages to find the tool call by ID.\n */\nexport function updateToolCallWithOutput(\n messages: Array<UIMessage>,\n toolCallId: string,\n output: any,\n state?: ToolCallState,\n errorText?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n output: errorText ? { error: errorText } : output,\n state: state ?? (errorText ? 'error' : 'complete'),\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval response.\n * Searches all messages to find the tool call by approval ID.\n */\nexport function updateToolCallApprovalResponse(\n messages: Array<UIMessage>,\n approvalId: string,\n approved: boolean,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart =>\n p.type === 'tool-call' && p.approval?.id === approvalId,\n )\n\n if (toolCallPart && toolCallPart.approval) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n approval: { ...toolCallPart.approval, approved },\n state: 'approval-responded',\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Append a delta to the structured-output part on `messageId`, or create one\n * if absent. Progressive parse of the accumulated buffer fills `partial`.\n *\n * Callers must only invoke this while the part is still in flight — the\n * helper unconditionally writes `status: 'streaming'`, so feeding it a delta\n * after a `complete`/`error` terminal would regress the part. In practice the\n * processor gates calls via `structuredMessageIds`, which is dropped on\n * terminal events.\n *\n * If the progressive parse returns null/undefined (the buffer is not yet a\n * parseable JSON prefix), the previously-good `partial` is preserved so the\n * UI doesn't flicker back to empty for a single render.\n */\nexport function appendStructuredOutputDelta(\n messages: Array<UIMessage>,\n messageId: string,\n delta: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n const existing =\n existingIndex >= 0 ? (parts[existingIndex] as StructuredOutputPart) : null\n\n const nextRaw = (existing?.raw ?? '') + delta\n const progressive = parsePartialJSON(nextRaw)\n const nextPartial =\n progressive !== undefined && progressive !== null\n ? progressive\n : existing?.partial\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'streaming',\n raw: nextRaw,\n ...(nextPartial !== undefined ? { partial: nextPartial } : {}),\n ...(existing?.reasoning !== undefined\n ? { reasoning: existing.reasoning }\n : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Snap the structured-output part on `messageId` to `complete` with the\n * validated `data`. Picks the freshest available `raw` so the wire\n * round-trip stays internally consistent:\n *\n * 1. Caller-supplied `raw` (the original streamed bytes from the model).\n * 2. The existing part's `raw` (deltas accumulated before this terminal).\n * 3. `JSON.stringify(data)` as a defensive fallback for terminal-only\n * completes that never shipped raw — keeps the part self-consistent\n * so downstream consumers never see a complete part with empty raw.\n */\nexport function completeStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n data: unknown,\n raw: string,\n reasoning?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n const existingRaw =\n existingIndex >= 0\n ? (parts[existingIndex] as StructuredOutputPart).raw\n : ''\n let resolvedRaw = raw || existingRaw\n if (resolvedRaw === '' && data !== undefined) {\n try {\n resolvedRaw = JSON.stringify(data)\n } catch {\n // Unserializable (circular, BigInt, throwing toJSON). Leave raw\n // empty. Both downstream paths handle this: `ag-ui-wire.ts`\n // `collectText` skips complete parts with empty raw entirely, and\n // `uiMessageToModelMessages` falls back to a defensive\n // `safeJsonStringify(data)` which itself returns `''` for the same\n // unserializable inputs — so the turn is silently dropped from the\n // next request rather than shipping garbage or crashing the stream.\n }\n }\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'complete',\n data,\n partial: data,\n raw: resolvedRaw,\n ...(reasoning !== undefined ? { reasoning } : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Mark the structured-output part on `messageId` as errored. If no part\n * exists yet — RUN_ERROR fired after `structured-output.start` but before\n * any delta — create an empty errored placeholder so consumers have\n * something renderable. Existing complete parts are left alone (an error\n * after a successful complete should not retroactively un-complete it).\n */\nexport function errorStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n errorMessage: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n if (existingIndex < 0) {\n parts.push({\n type: 'structured-output',\n status: 'error',\n raw: '',\n errorMessage,\n })\n return { ...msg, parts }\n }\n\n const existing = parts[existingIndex] as StructuredOutputPart\n if (existing.status === 'complete') {\n return msg\n }\n parts[existingIndex] = {\n ...existing,\n status: 'error',\n errorMessage,\n }\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a thinking part to a message, keyed by stepId.\n * Each distinct stepId produces its own ThinkingPart.\n */\nexport function updateThinkingPart(\n messages: Array<UIMessage>,\n messageId: string,\n stepId: string,\n content: string,\n signature?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const thinkingPartIndex = parts.findIndex(\n (p) => p.type === 'thinking' && p.stepId === stepId,\n )\n\n const thinkingPart: ThinkingPart = {\n type: 'thinking',\n content,\n stepId,\n ...(signature && { signature }),\n }\n\n if (thinkingPartIndex >= 0) {\n // Update existing thinking part for this step\n parts[thinkingPartIndex] = thinkingPart\n } else {\n // Add new thinking part at the end (preserve natural streaming order)\n parts.push(thinkingPart)\n }\n\n return { ...msg, parts }\n })\n}\n"],"names":[],"mappings":";AAwBO,SAAS,eACd,UACA,WACA,SACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,WAAW,MAAM,SAAS,IAAI,MAAM,MAAM,SAAS,CAAC,IAAI;AAE9D,QAAI,YAAY,SAAS,SAAS,QAAQ;AAExC,YAAM,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,QAAQ,QAAA;AAAA,IAC5C,OAAO;AAEL,YAAM,KAAK,EAAE,MAAM,QAAQ,SAAS;AAAA,IACtC;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAKO,SAAS,mBACd,UACA,WACA,UASkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,WAAW,MAAM;AAAA,MACrB,CAAC,MAAyB,EAAE,SAAS,eAAe,EAAE,OAAO,SAAS;AAAA,IAAA;AAOxE,UAAM,WAAW,SAAS,YAAY,UAAU;AAGhD,UAAM,QAAQ,SAAS,SAAS,UAAU;AAE1C,UAAM,eAA6B;AAAA,MACjC,MAAM;AAAA,MACN,IAAI,SAAS;AAAA,MACb,MAAM,SAAS;AAAA,MACf,WAAW,SAAS;AAAA,MACpB,OAAO,SAAS;AAAA;AAAA,MAEhB,GAAI,UAAU,YAAY,EAAE,UAAU,EAAE,GAAG,SAAS,WAAS;AAAA,MAC7D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,SAAS,OAAA;AAAA,MACzD,GAAI,UAAU,UAAa,EAAE,MAAA;AAAA,MAC7B,GAAI,aAAa,UAAa,EAAE,SAAA;AAAA,IAAS;AAG3C,QAAI,UAAU;AAEZ,YAAM,MAAM,QAAQ,QAAQ,CAAC,IAAI;AAAA,IACnC,OAAO;AAEL,YAAM,KAAK,YAAY;AAAA,IACzB;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAKO,SAAS,qBACd,UACA,WACA,YACA,SACA,OACA,OACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,kBAAkB,MAAM;AAAA,MAC5B,CAAC,MACC,EAAE,SAAS,iBAAiB,EAAE,eAAe;AAAA,IAAA;AAGjD,UAAM,iBAAiC;AAAA,MACrC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,SAAS,EAAE,MAAA;AAAA,IAAM;AAGvB,QAAI,mBAAmB,GAAG;AACxB,YAAM,eAAe,IAAI;AAAA,IAC3B,OAAO;AACL,YAAM,KAAK,cAAc;AAAA,IAC3B;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAKO,SAAS,uBACd,UACA,WACA,YACA,YACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,eAAe,MAAM;AAAA,MACzB,CAAC,MAAyB,EAAE,SAAS,eAAe,EAAE,OAAO;AAAA,IAAA;AAG/D,QAAI,cAAc;AAChB,YAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,YAAM,KAAK,IAAI;AAAA,QACb,GAAG;AAAA,QACH,OAAO;AAAA,QACP,UAAU;AAAA,UACR,IAAI;AAAA,UACJ,eAAe;AAAA,QAAA;AAAA,MACjB;AAAA,IAEJ;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAkCO,SAAS,yBACd,UACA,YACA,QACA,OACA,WACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,eAAe,MAAM;AAAA,MACzB,CAAC,MAAyB,EAAE,SAAS,eAAe,EAAE,OAAO;AAAA,IAAA;AAG/D,QAAI,cAAc;AAChB,YAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,YAAM,KAAK,IAAI;AAAA,QACb,GAAG;AAAA,QACH,QAAQ,YAAY,EAAE,OAAO,cAAc;AAAA,QAC3C,OAAO,UAAU,YAAY,UAAU;AAAA,MAAA;AAAA,IAE3C;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAMO,SAAS,+BACd,UACA,YACA,UACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,eAAe,MAAM;AAAA,MACzB,CAAC,MACC,EAAE,SAAS,eAAe,EAAE,UAAU,OAAO;AAAA,IAAA;AAGjD,QAAI,gBAAgB,aAAa,UAAU;AACzC,YAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,YAAM,KAAK,IAAI;AAAA,QACb,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,aAAa,UAAU,SAAA;AAAA,QACtC,OAAO;AAAA,MAAA;AAAA,IAEX;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAgBO,SAAS,4BACd,UACA,WACA,OACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,gBAAgB,MAAM;AAAA,MAC1B,CAAC,MAAiC,EAAE,SAAS;AAAA,IAAA;AAE/C,UAAM,WACJ,iBAAiB,IAAK,MAAM,aAAa,IAA6B;AAExE,UAAM,WAAW,UAAU,OAAO,MAAM;AACxC,UAAM,cAAc,iBAAiB,OAAO;AAC5C,UAAM,cACJ,gBAAgB,UAAa,gBAAgB,OACzC,cACA,UAAU;AAEhB,UAAM,WAAiC;AAAA,MACrC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,GAAI,gBAAgB,SAAY,EAAE,SAAS,YAAA,IAAgB,CAAA;AAAA,MAC3D,GAAI,UAAU,cAAc,SACxB,EAAE,WAAW,SAAS,cACtB,CAAA;AAAA,IAAC;AAGP,QAAI,iBAAiB,GAAG;AACtB,YAAM,aAAa,IAAI;AAAA,IACzB,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAaO,SAAS,6BACd,UACA,WACA,MACA,KACA,WACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,gBAAgB,MAAM;AAAA,MAC1B,CAAC,MAAiC,EAAE,SAAS;AAAA,IAAA;AAG/C,UAAM,cACJ,iBAAiB,IACZ,MAAM,aAAa,EAA2B,MAC/C;AACN,QAAI,cAAc,OAAO;AACzB,QAAI,gBAAgB,MAAM,SAAS,QAAW;AAC5C,UAAI;AACF,sBAAc,KAAK,UAAU,IAAI;AAAA,MACnC,QAAQ;AAAA,MAQR;AAAA,IACF;AAEA,UAAM,WAAiC;AAAA,MACrC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA,MACT,KAAK;AAAA,MACL,GAAI,cAAc,SAAY,EAAE,cAAc,CAAA;AAAA,IAAC;AAGjD,QAAI,iBAAiB,GAAG;AACtB,YAAM,aAAa,IAAI;AAAA,IACzB,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AASO,SAAS,0BACd,UACA,WACA,cACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,gBAAgB,MAAM;AAAA,MAC1B,CAAC,MAAiC,EAAE,SAAS;AAAA,IAAA;AAG/C,QAAI,gBAAgB,GAAG;AACrB,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,KAAK;AAAA,QACL;AAAA,MAAA,CACD;AACD,aAAO,EAAE,GAAG,KAAK,MAAA;AAAA,IACnB;AAEA,UAAM,WAAW,MAAM,aAAa;AACpC,QAAI,SAAS,WAAW,YAAY;AAClC,aAAO;AAAA,IACT;AACA,UAAM,aAAa,IAAI;AAAA,MACrB,GAAG;AAAA,MACH,QAAQ;AAAA,MACR;AAAA,IAAA;AAEF,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;AAMO,SAAS,mBACd,UACA,WACA,QACA,SACA,WACkB;AAClB,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,QAAI,IAAI,OAAO,WAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,CAAC,GAAG,IAAI,KAAK;AAC3B,UAAM,oBAAoB,MAAM;AAAA,MAC9B,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,WAAW;AAAA,IAAA;AAG/C,UAAM,eAA6B;AAAA,MACjC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,GAAI,aAAa,EAAE,UAAA;AAAA,IAAU;AAG/B,QAAI,qBAAqB,GAAG;AAE1B,YAAM,iBAAiB,IAAI;AAAA,IAC7B,OAAO;AAEL,YAAM,KAAK,YAAY;AAAA,IACzB;AAEA,WAAO,EAAE,GAAG,KAAK,MAAA;AAAA,EACnB,CAAC;AACH;"}
1
+ {"version":3,"file":"message-updaters.js","names":[],"sources":["../../../../../src/activities/chat/stream/message-updaters.ts"],"sourcesContent":["/**\n * Message Updaters (Internal)\n *\n * Internal helper functions for updating UIMessage parts.\n * These are used by StreamProcessor to manage the message array.\n */\n\nimport { parsePartialJSON } from './json-parser'\nimport type {\n ContentPart,\n StructuredOutputPart,\n ThinkingPart,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n} from '../../../types'\nimport type { ToolCallState, ToolResultState } from './types'\n\n/**\n * Update or add a text part to a message.\n *\n * If the last part is a text part, update it (continuing the same text segment).\n * Otherwise, create a new text part (starting a new text segment after tool calls).\n */\nexport function updateTextPart(\n messages: Array<UIMessage>,\n messageId: string,\n content: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const lastPart = parts.length > 0 ? parts[parts.length - 1] : null\n\n if (lastPart && lastPart.type === 'text') {\n // Update the last text part (continuing same text segment)\n parts[parts.length - 1] = { type: 'text', content }\n } else {\n // Create new text part (starting new text segment after tool calls/results)\n parts.push({ type: 'text', content })\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool call part to a message.\n */\nexport function updateToolCallPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCall: {\n id: string\n name: string\n arguments: string\n state: ToolCallState\n /** Parsed input — set when the arguments are complete. */\n input?: unknown\n metadata?: Record<string, unknown>\n },\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existing = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCall.id,\n )\n\n // Carry forward metadata from either the new toolCall or the existing\n // part. Once the adapter has emitted metadata for a tool call (e.g.\n // Gemini's thoughtSignature on TOOL_CALL_START) we must not lose it on\n // subsequent updates that don't re-supply it.\n const metadata = toolCall.metadata ?? existing?.metadata\n // Same for the parsed input: it's supplied once at completion, so\n // subsequent arg-less updates (approval, etc.) must not drop it.\n const input = toolCall.input ?? existing?.input\n\n const toolCallPart: ToolCallPart = {\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.name,\n arguments: toolCall.arguments,\n state: toolCall.state,\n // Carry forward approval, output and parsed input from the existing part\n ...(existing?.approval && { approval: { ...existing.approval } }),\n ...(existing?.output !== undefined && { output: existing.output }),\n ...(input !== undefined && { input }),\n ...(metadata !== undefined && { metadata }),\n }\n\n if (existing) {\n // Update existing tool call\n parts[parts.indexOf(existing)] = toolCallPart\n } else {\n // Add new tool call at the end (preserve natural streaming order)\n parts.push(toolCallPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool result part to a message.\n */\nexport function updateToolResultPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n content: string | Array<ContentPart>,\n state: ToolResultState,\n error?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const resultPartIndex = parts.findIndex(\n (p): p is ToolResultPart =>\n p.type === 'tool-result' && p.toolCallId === toolCallId,\n )\n\n const toolResultPart: ToolResultPart = {\n type: 'tool-result',\n toolCallId,\n content,\n state,\n ...(error && { error }),\n }\n\n if (resultPartIndex >= 0) {\n parts[resultPartIndex] = toolResultPart\n } else {\n parts.push(toolResultPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval request metadata.\n */\nexport function updateToolCallApproval(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n approvalId: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n state: 'approval-requested',\n approval: {\n id: approvalId,\n needsApproval: true,\n },\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part's state (e.g., to \"input-complete\").\n */\nexport function updateToolCallState(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n state: ToolCallState,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = { ...toolCallPart, state }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with output.\n * Searches all messages to find the tool call by ID.\n */\nexport function updateToolCallWithOutput(\n messages: Array<UIMessage>,\n toolCallId: string,\n output: any,\n state?: ToolCallState,\n errorText?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n output: errorText ? { error: errorText } : output,\n state: state ?? (errorText ? 'error' : 'complete'),\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval response.\n * Searches all messages to find the tool call by approval ID.\n */\nexport function updateToolCallApprovalResponse(\n messages: Array<UIMessage>,\n approvalId: string,\n approved: boolean,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart =>\n p.type === 'tool-call' && p.approval?.id === approvalId,\n )\n\n if (toolCallPart && toolCallPart.approval) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n approval: { ...toolCallPart.approval, approved },\n state: 'approval-responded',\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Append a delta to the structured-output part on `messageId`, or create one\n * if absent. Progressive parse of the accumulated buffer fills `partial`.\n *\n * Callers must only invoke this while the part is still in flight — the\n * helper unconditionally writes `status: 'streaming'`, so feeding it a delta\n * after a `complete`/`error` terminal would regress the part. In practice the\n * processor gates calls via `structuredMessageIds`, which is dropped on\n * terminal events.\n *\n * If the progressive parse returns null/undefined (the buffer is not yet a\n * parseable JSON prefix), the previously-good `partial` is preserved so the\n * UI doesn't flicker back to empty for a single render.\n */\nexport function appendStructuredOutputDelta(\n messages: Array<UIMessage>,\n messageId: string,\n delta: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n const existing =\n existingIndex >= 0 ? (parts[existingIndex] as StructuredOutputPart) : null\n\n const nextRaw = (existing?.raw ?? '') + delta\n const progressive = parsePartialJSON(nextRaw)\n const nextPartial =\n progressive !== undefined && progressive !== null\n ? progressive\n : existing?.partial\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'streaming',\n raw: nextRaw,\n ...(nextPartial !== undefined ? { partial: nextPartial } : {}),\n ...(existing?.reasoning !== undefined\n ? { reasoning: existing.reasoning }\n : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Snap the structured-output part on `messageId` to `complete` with the\n * validated `data`. Picks the freshest available `raw` so the wire\n * round-trip stays internally consistent:\n *\n * 1. Caller-supplied `raw` (the original streamed bytes from the model).\n * 2. The existing part's `raw` (deltas accumulated before this terminal).\n * 3. `JSON.stringify(data)` as a defensive fallback for terminal-only\n * completes that never shipped raw — keeps the part self-consistent\n * so downstream consumers never see a complete part with empty raw.\n */\nexport function completeStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n data: unknown,\n raw: string,\n reasoning?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n const existingRaw =\n existingIndex >= 0\n ? (parts[existingIndex] as StructuredOutputPart).raw\n : ''\n let resolvedRaw = raw || existingRaw\n if (resolvedRaw === '' && data !== undefined) {\n try {\n resolvedRaw = JSON.stringify(data)\n } catch {\n // Unserializable (circular, BigInt, throwing toJSON). Leave raw\n // empty. Both downstream paths handle this: `ag-ui-wire.ts`\n // `collectText` skips complete parts with empty raw entirely, and\n // `uiMessageToModelMessages` falls back to a defensive\n // `safeJsonStringify(data)` which itself returns `''` for the same\n // unserializable inputs — so the turn is silently dropped from the\n // next request rather than shipping garbage or crashing the stream.\n }\n }\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'complete',\n data,\n partial: data,\n raw: resolvedRaw,\n ...(reasoning !== undefined ? { reasoning } : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Mark the structured-output part on `messageId` as errored. If no part\n * exists yet — RUN_ERROR fired after `structured-output.start` but before\n * any delta — create an empty errored placeholder so consumers have\n * something renderable. Existing complete parts are left alone (an error\n * after a successful complete should not retroactively un-complete it).\n */\nexport function errorStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n errorMessage: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n if (existingIndex < 0) {\n parts.push({\n type: 'structured-output',\n status: 'error',\n raw: '',\n errorMessage,\n })\n return { ...msg, parts }\n }\n\n const existing = parts[existingIndex] as StructuredOutputPart\n if (existing.status === 'complete') {\n return msg\n }\n parts[existingIndex] = {\n ...existing,\n status: 'error',\n errorMessage,\n }\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a thinking part to a message, keyed by stepId.\n * Each distinct stepId produces its own ThinkingPart.\n */\nexport function updateThinkingPart(\n messages: Array<UIMessage>,\n messageId: string,\n stepId: string,\n content: string,\n signature?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const thinkingPartIndex = parts.findIndex(\n (p) => p.type === 'thinking' && p.stepId === stepId,\n )\n\n const thinkingPart: ThinkingPart = {\n type: 'thinking',\n content,\n stepId,\n ...(signature && { signature }),\n }\n\n if (thinkingPartIndex >= 0) {\n // Update existing thinking part for this step\n parts[thinkingPartIndex] = thinkingPart\n } else {\n // Add new thinking part at the end (preserve natural streaming order)\n parts.push(thinkingPart)\n }\n\n return { ...msg, parts }\n })\n}\n"],"mappings":"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"}