likec4 1.59.4 → 1.60.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 (96) hide show
  1. package/__app__/codegen/react.mjs +6 -6
  2. package/__app__/codegen/webcomponent.mjs +147 -69
  3. package/__app__/src/aichat/index.mjs +10 -5
  4. package/__app__/src/chunks/AIChat.mjs +1134 -693
  5. package/__app__/src/chunks/LikeC4Styles.mjs +3995 -1779
  6. package/__app__/src/chunks/ProjectsOverview.mjs +624 -334
  7. package/__app__/src/chunks/es.mjs +515 -335
  8. package/__app__/src/chunks/hooks.mjs +578 -369
  9. package/__app__/src/chunks/libs/@floating-ui.mjs +2720 -1966
  10. package/__app__/src/chunks/libs/@mantine.mjs +13920 -10057
  11. package/__app__/src/chunks/libs/@tanstack-ai.mjs +2266 -1146
  12. package/__app__/src/chunks/libs/@tanstack.mjs +3152 -1926
  13. package/__app__/src/chunks/libs/@xstate/react.mjs +2924 -1468
  14. package/__app__/src/chunks/libs/@xyflow/react.mjs +6627 -4067
  15. package/__app__/src/chunks/libs/bezier-js.mjs +1312 -726
  16. package/__app__/src/chunks/libs/d3.mjs +3219 -1505
  17. package/__app__/src/chunks/libs/fast-equals.mjs +434 -210
  18. package/__app__/src/chunks/libs/framer.mjs +9251 -3846
  19. package/__app__/src/chunks/libs/nanostores.mjs +174 -0
  20. package/__app__/src/chunks/libs/zod.mjs +4591 -2363
  21. package/__app__/src/chunks/rolldown-runtime.mjs +39 -23
  22. package/__app__/src/chunks/styled-system.mjs +2279 -1951
  23. package/__app__/src/fonts.css +112 -1
  24. package/__app__/src/main.mjs +40817 -21840
  25. package/__app__/src/style.css +18488 -1
  26. package/config/schema.json +122 -97
  27. package/dist/app/render-view-client.css +1 -1
  28. package/dist/app/render-view-client.js +508 -334
  29. package/dist/chunks/enableServer.mjs +1 -1
  30. package/dist/chunks/filenames.mjs +11 -9
  31. package/dist/chunks/generate-likec4.mjs +5 -0
  32. package/dist/chunks/index.d.mts +243 -183
  33. package/dist/chunks/index2.d.mts +2865 -1977
  34. package/dist/chunks/libs/@chevrotain/gast.mjs +27 -1
  35. package/dist/chunks/libs/@chevrotain/regexp-to-ast.mjs +81 -9
  36. package/dist/chunks/libs/@chevrotain/types.d.mts +4 -1
  37. package/dist/chunks/libs/@logtape/logtape.mjs +5 -4
  38. package/dist/chunks/libs/@lume/kiwi.mjs +1 -1
  39. package/dist/chunks/libs/@ts-graphviz/core.mjs +1 -1
  40. package/dist/chunks/libs/birpc.mjs +1 -1
  41. package/dist/chunks/libs/chevrotain-allstar.mjs +2 -2
  42. package/dist/chunks/libs/chevrotain.mjs +87 -35
  43. package/dist/chunks/libs/eventemitter3.mjs +1 -1
  44. package/dist/chunks/libs/json5.mjs +4 -4
  45. package/dist/chunks/libs/langium.d.mts +9038 -6193
  46. package/dist/chunks/libs/langium.mjs +16 -24
  47. package/dist/chunks/libs/merge-error-cause.mjs +1 -1
  48. package/dist/chunks/libs/p-limit.mjs +1 -0
  49. package/dist/chunks/libs/p-queue.mjs +1 -1
  50. package/dist/chunks/libs/package-manager-detector.mjs +1 -1
  51. package/dist/chunks/libs/pako.mjs +1 -1
  52. package/dist/chunks/libs/pretty-ms.mjs +1 -1
  53. package/dist/chunks/libs/remeda.mjs +1 -1
  54. package/dist/chunks/libs/ufo.mjs +1 -1
  55. package/dist/chunks/libs/unstorage.mjs +1 -1
  56. package/dist/chunks/libs/which.mjs +1 -1
  57. package/dist/chunks/node.mjs +59 -58
  58. package/dist/chunks/rolldown-runtime.mjs +1 -1
  59. package/dist/chunks/sequence-view.mjs +1 -1
  60. package/dist/chunks/vite-plugin.mjs +45 -45
  61. package/dist/cli/index.mjs +207 -1315
  62. package/dist/config/index.d.mts +2 -2
  63. package/dist/generators/likec4.d.mts +6578 -0
  64. package/dist/generators/likec4.mjs +1 -0
  65. package/dist/model/index.d.mts +4 -1
  66. package/dist/vite-plugin/index.d.mts +4 -1
  67. package/dist/vite-plugin/index.mjs +1 -1
  68. package/dist/vite-plugin/internal/chunks/rolldown-runtime.mjs +9 -0
  69. package/dist/vite-plugin/internal/index.d.mts +6 -5
  70. package/dist/vite-plugin/internal/index.mjs +83 -30
  71. package/generators/likec4/package.json +4 -0
  72. package/package.json +113 -106
  73. package/react/index.d.mts +8500 -26659
  74. package/react/index.mjs +534 -63936
  75. package/react/rolldown-runtime-DnkiqaRY.js +1 -0
  76. package/skills/likec4-dsl/SKILL.md +428 -0
  77. package/skills/likec4-dsl/evals/evals-public.json +202 -0
  78. package/skills/likec4-dsl/evals/grading-spec.json +589 -0
  79. package/skills/likec4-dsl/references/bridge-leanix-drawio.md +42 -0
  80. package/skills/likec4-dsl/references/cli.md +139 -0
  81. package/skills/likec4-dsl/references/configuration.md +266 -0
  82. package/skills/likec4-dsl/references/deployment.md +160 -0
  83. package/skills/likec4-dsl/references/dynamic-views.md +455 -0
  84. package/skills/likec4-dsl/references/examples.md +370 -0
  85. package/skills/likec4-dsl/references/identifier-validity.md +90 -0
  86. package/skills/likec4-dsl/references/include-predicates-wildcards.md +179 -0
  87. package/skills/likec4-dsl/references/model.md +151 -0
  88. package/skills/likec4-dsl/references/predicates.md +123 -0
  89. package/skills/likec4-dsl/references/relationships-bidirectional.md +176 -0
  90. package/skills/likec4-dsl/references/specification.md +75 -0
  91. package/skills/likec4-dsl/references/style-tokens-colors.md +150 -0
  92. package/skills/likec4-dsl/references/troubleshooting.md +96 -0
  93. package/skills/likec4-dsl/references/views.md +329 -0
  94. package/dist/chunks/libs/picomatch.mjs +0 -1
  95. package/dist/chunks/libs/zod.d.mts +0 -3840
  96. package/dist/chunks/libs/zod.mjs +0 -65
@@ -1,152 +1,234 @@
1
- import { t as e } from "../rolldown-runtime.mjs";
2
- import { createContext as t, useCallback as n, useEffect as r, useId as i, useMemo as a, useRef as o, useState as s } from "react";
3
- import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
1
+ import { t as __commonJSMin } from "../rolldown-runtime.mjs";
2
+ import { createContext, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
3
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region ../../node_modules/.pnpm/@tanstack+devtools-event-client@0.4.3/node_modules/@tanstack/devtools-event-client/dist/esm/plugin.js
5
5
  var EventClient = class {
6
- #e = !0;
7
- #t;
8
- #n;
9
- #r;
10
- #i;
11
- #a;
12
- #o;
13
- #s;
14
- #c = 0;
15
- #l = 5;
16
- #u = !1;
17
- #d = !1;
18
- #f = null;
19
- #p = () => {
20
- this.debugLog("Connected to event bus"), this.#a = !0, this.#u = !1, this.debugLog("Emitting queued events", this.#i), this.#i.forEach((e) => this.emitEventToBus(e)), this.#i = [], this.stopConnectLoop(), this.#n().removeEventListener("tanstack-connect-success", this.#p);
6
+ #enabled = true;
7
+ #pluginId;
8
+ #eventTarget;
9
+ #debug;
10
+ #queuedEvents;
11
+ #connected;
12
+ #connectIntervalId;
13
+ #connectEveryMs;
14
+ #retryCount = 0;
15
+ #maxRetries = 5;
16
+ #connecting = false;
17
+ #failedToConnect = false;
18
+ #internalEventTarget = null;
19
+ #onConnected = () => {
20
+ this.debugLog("Connected to event bus");
21
+ this.#connected = true;
22
+ this.#connecting = false;
23
+ this.debugLog("Emitting queued events", this.#queuedEvents);
24
+ this.#queuedEvents.forEach((event) => this.emitEventToBus(event));
25
+ this.#queuedEvents = [];
26
+ this.stopConnectLoop();
27
+ this.#eventTarget().removeEventListener("tanstack-connect-success", this.#onConnected);
21
28
  };
22
- #m = () => {
23
- if (this.#c < this.#l) {
24
- this.#c++, this.dispatchCustomEvent("tanstack-connect", {});
29
+ #retryConnection = () => {
30
+ if (this.#retryCount < this.#maxRetries) {
31
+ this.#retryCount++;
32
+ this.dispatchCustomEvent("tanstack-connect", {});
25
33
  return;
26
34
  }
27
- this.#n().removeEventListener("tanstack-connect", this.#m), this.#d = !0, this.debugLog("Max retries reached, giving up on connection"), this.stopConnectLoop();
35
+ this.#eventTarget().removeEventListener("tanstack-connect", this.#retryConnection);
36
+ this.#failedToConnect = true;
37
+ this.debugLog("Max retries reached, giving up on connection");
38
+ this.stopConnectLoop();
28
39
  };
29
- #h = () => {
30
- this.#u || (this.#u = !0, this.#n().addEventListener("tanstack-connect-success", this.#p), this.#m());
40
+ #connectFunction = () => {
41
+ if (this.#connecting) return;
42
+ this.#connecting = true;
43
+ this.#eventTarget().addEventListener("tanstack-connect-success", this.#onConnected);
44
+ this.#retryConnection();
31
45
  };
32
- constructor({ pluginId: e, debug: t = !1, enabled: n = !0, reconnectEveryMs: r = 300 }) {
33
- this.#t = e, this.#e = n, this.#n = this.getGlobalTarget, this.#r = t, this.debugLog(" Initializing event subscription for plugin", this.#t), this.#i = [], this.#a = !1, this.#d = !1, this.#o = null, this.#s = r;
46
+ constructor({ pluginId, debug = false, enabled = true, reconnectEveryMs = 300 }) {
47
+ this.#pluginId = pluginId;
48
+ this.#enabled = enabled;
49
+ this.#eventTarget = this.getGlobalTarget;
50
+ this.#debug = debug;
51
+ this.debugLog(" Initializing event subscription for plugin", this.#pluginId);
52
+ this.#queuedEvents = [];
53
+ this.#connected = false;
54
+ this.#failedToConnect = false;
55
+ this.#connectIntervalId = null;
56
+ this.#connectEveryMs = reconnectEveryMs;
34
57
  }
35
58
  startConnectLoop() {
36
- this.#o !== null || this.#a || (this.debugLog(`Starting connect loop (every ${this.#s}ms)`), this.#o = setInterval(this.#m, this.#s));
59
+ if (this.#connectIntervalId !== null || this.#connected) return;
60
+ this.debugLog(`Starting connect loop (every ${this.#connectEveryMs}ms)`);
61
+ this.#connectIntervalId = setInterval(this.#retryConnection, this.#connectEveryMs);
37
62
  }
38
63
  stopConnectLoop() {
39
- this.#u = !1, this.#o !== null && (clearInterval(this.#o), this.#o = null, this.#i = [], this.debugLog("Stopped connect loop"));
64
+ this.#connecting = false;
65
+ if (this.#connectIntervalId === null) return;
66
+ clearInterval(this.#connectIntervalId);
67
+ this.#connectIntervalId = null;
68
+ this.#queuedEvents = [];
69
+ this.debugLog("Stopped connect loop");
40
70
  }
41
- debugLog(...e) {
42
- this.#r && console.log(`🌴 [tanstack-devtools:${this.#t}-plugin]`, ...e);
71
+ debugLog(...args) {
72
+ if (this.#debug) console.log(`🌴 [tanstack-devtools:${this.#pluginId}-plugin]`, ...args);
43
73
  }
44
74
  getGlobalTarget() {
45
- if (typeof globalThis < "u" && globalThis.__TANSTACK_EVENT_TARGET__) return this.debugLog("Using global event target"), globalThis.__TANSTACK_EVENT_TARGET__;
46
- if (typeof window < "u" && window.addEventListener !== void 0) return this.debugLog("Using window as event target"), window;
47
- let e = typeof EventTarget < "u" ? new EventTarget() : void 0;
48
- return e === void 0 || e.addEventListener === void 0 ? (this.debugLog("No event mechanism available, running in non-web environment"), {
49
- addEventListener: () => {},
50
- removeEventListener: () => {},
51
- dispatchEvent: () => !1
52
- }) : (this.debugLog("Using new EventTarget as fallback"), e);
75
+ if (typeof globalThis !== "undefined" && globalThis.__TANSTACK_EVENT_TARGET__) {
76
+ this.debugLog("Using global event target");
77
+ return globalThis.__TANSTACK_EVENT_TARGET__;
78
+ }
79
+ if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
80
+ this.debugLog("Using window as event target");
81
+ return window;
82
+ }
83
+ const eventTarget = typeof EventTarget !== "undefined" ? new EventTarget() : void 0;
84
+ if (typeof eventTarget === "undefined" || typeof eventTarget.addEventListener === "undefined") {
85
+ this.debugLog("No event mechanism available, running in non-web environment");
86
+ return {
87
+ addEventListener: () => {},
88
+ removeEventListener: () => {},
89
+ dispatchEvent: () => false
90
+ };
91
+ }
92
+ this.debugLog("Using new EventTarget as fallback");
93
+ return eventTarget;
53
94
  }
54
95
  getPluginId() {
55
- return this.#t;
96
+ return this.#pluginId;
56
97
  }
57
- dispatchCustomEventShim(e, t) {
98
+ dispatchCustomEventShim(eventName, detail) {
58
99
  try {
59
- let n = new Event(e, { detail: t });
60
- this.#n().dispatchEvent(n);
61
- } catch {
100
+ const event = new Event(eventName, { detail });
101
+ this.#eventTarget().dispatchEvent(event);
102
+ } catch (e) {
62
103
  this.debugLog("Failed to dispatch shim event");
63
104
  }
64
105
  }
65
- dispatchCustomEvent(e, t) {
106
+ dispatchCustomEvent(eventName, detail) {
66
107
  try {
67
- this.#n().dispatchEvent(new CustomEvent(e, { detail: t }));
68
- } catch {
69
- this.dispatchCustomEventShim(e, t);
108
+ this.#eventTarget().dispatchEvent(new CustomEvent(eventName, { detail }));
109
+ } catch (e) {
110
+ this.dispatchCustomEventShim(eventName, detail);
70
111
  }
71
112
  }
72
- emitEventToBus(e) {
73
- this.debugLog("Emitting event to client bus", e), this.dispatchCustomEvent("tanstack-dispatch-event", e);
113
+ emitEventToBus(event) {
114
+ this.debugLog("Emitting event to client bus", event);
115
+ this.dispatchCustomEvent("tanstack-dispatch-event", event);
74
116
  }
75
- createEventPayload(e, t) {
117
+ createEventPayload(eventSuffix, payload) {
76
118
  return {
77
- type: `${this.#t}:${e}`,
78
- payload: t,
79
- pluginId: this.#t
119
+ type: `${this.#pluginId}:${eventSuffix}`,
120
+ payload,
121
+ pluginId: this.#pluginId
80
122
  };
81
123
  }
82
- emit(e, t) {
83
- if (!this.#e) {
84
- this.debugLog("Event bus client is disabled, not emitting event", e, t);
124
+ emit(eventSuffix, payload) {
125
+ if (!this.#enabled) {
126
+ this.debugLog("Event bus client is disabled, not emitting event", eventSuffix, payload);
85
127
  return;
86
128
  }
87
- if (this.#f && (this.debugLog("Emitting event to internal event target", e, t), this.#f.dispatchEvent(new CustomEvent(`${this.#t}:${e}`, { detail: this.createEventPayload(e, t) }))), this.#d) {
129
+ if (this.#internalEventTarget) {
130
+ this.debugLog("Emitting event to internal event target", eventSuffix, payload);
131
+ this.#internalEventTarget.dispatchEvent(new CustomEvent(`${this.#pluginId}:${eventSuffix}`, { detail: this.createEventPayload(eventSuffix, payload) }));
132
+ }
133
+ if (this.#failedToConnect) {
88
134
  this.debugLog("Previously failed to connect, not emitting to bus");
89
135
  return;
90
136
  }
91
- if (!this.#a) {
92
- this.debugLog("Bus not available, will be pushed as soon as connected"), this.#i.push(this.createEventPayload(e, t)), typeof CustomEvent < "u" && !this.#u && (this.#h(), this.startConnectLoop());
137
+ if (!this.#connected) {
138
+ this.debugLog("Bus not available, will be pushed as soon as connected");
139
+ this.#queuedEvents.push(this.createEventPayload(eventSuffix, payload));
140
+ if (typeof CustomEvent !== "undefined" && !this.#connecting) {
141
+ this.#connectFunction();
142
+ this.startConnectLoop();
143
+ }
93
144
  return;
94
145
  }
95
- return this.emitEventToBus(this.createEventPayload(e, t));
96
- }
97
- on(e, t, n) {
98
- let r = n?.withEventTarget ?? !1, i = `${this.#t}:${e}`;
99
- if (r && (this.#f ||= new EventTarget(), this.#f.addEventListener(i, (e) => {
100
- t(e.detail);
101
- })), !this.#e) return this.debugLog("Event bus client is disabled, not registering event", i), () => {};
102
- let handler = (e) => {
103
- this.debugLog("Received event from bus", e.detail), t(e.detail);
146
+ return this.emitEventToBus(this.createEventPayload(eventSuffix, payload));
147
+ }
148
+ on(eventSuffix, cb, options) {
149
+ const withEventTarget = options?.withEventTarget ?? false;
150
+ const eventName = `${this.#pluginId}:${eventSuffix}`;
151
+ if (withEventTarget) {
152
+ if (!this.#internalEventTarget) this.#internalEventTarget = new EventTarget();
153
+ this.#internalEventTarget.addEventListener(eventName, (e) => {
154
+ cb(e.detail);
155
+ });
156
+ }
157
+ if (!this.#enabled) {
158
+ this.debugLog("Event bus client is disabled, not registering event", eventName);
159
+ return () => {};
160
+ }
161
+ const handler = (e) => {
162
+ this.debugLog("Received event from bus", e.detail);
163
+ cb(e.detail);
104
164
  };
105
- return this.#n().addEventListener(i, handler), this.debugLog("Registered event to bus", i), () => {
106
- r && this.#f?.removeEventListener(i, handler), this.#n().removeEventListener(i, handler);
165
+ this.#eventTarget().addEventListener(eventName, handler);
166
+ this.debugLog("Registered event to bus", eventName);
167
+ return () => {
168
+ if (withEventTarget) this.#internalEventTarget?.removeEventListener(eventName, handler);
169
+ this.#eventTarget().removeEventListener(eventName, handler);
107
170
  };
108
171
  }
109
- onAll(e) {
110
- if (!this.#e) return this.debugLog("Event bus client is disabled, not registering event"), () => {};
111
- let handler = (t) => {
112
- let n = t.detail;
113
- e(n);
172
+ onAll(cb) {
173
+ if (!this.#enabled) {
174
+ this.debugLog("Event bus client is disabled, not registering event");
175
+ return () => {};
176
+ }
177
+ const handler = (e) => {
178
+ const event = e.detail;
179
+ cb(event);
114
180
  };
115
- return this.#n().addEventListener("tanstack-devtools-global", handler), () => this.#n().removeEventListener("tanstack-devtools-global", handler);
181
+ this.#eventTarget().addEventListener("tanstack-devtools-global", handler);
182
+ return () => this.#eventTarget().removeEventListener("tanstack-devtools-global", handler);
116
183
  }
117
- onAllPluginEvents(e) {
118
- if (!this.#e) return this.debugLog("Event bus client is disabled, not registering event"), () => {};
119
- let handler = (t) => {
120
- let n = t.detail;
121
- this.#t && n.pluginId !== this.#t || e(n);
184
+ onAllPluginEvents(cb) {
185
+ if (!this.#enabled) {
186
+ this.debugLog("Event bus client is disabled, not registering event");
187
+ return () => {};
188
+ }
189
+ const handler = (e) => {
190
+ const event = e.detail;
191
+ if (this.#pluginId && event.pluginId !== this.#pluginId) return;
192
+ cb(event);
122
193
  };
123
- return this.#n().addEventListener("tanstack-devtools-global", handler), () => this.#n().removeEventListener("tanstack-devtools-global", handler);
194
+ this.#eventTarget().addEventListener("tanstack-devtools-global", handler);
195
+ return () => this.#eventTarget().removeEventListener("tanstack-devtools-global", handler);
124
196
  }
125
- }, AiEventClient = class extends EventClient {
197
+ };
198
+ //#endregion
199
+ //#region ../../node_modules/.pnpm/@tanstack+ai-event-client@0.2.8_@tanstack+ai@0.14.0/node_modules/@tanstack/ai-event-client/dist/esm/index.js
200
+ var AiEventClient = class extends EventClient {
126
201
  constructor() {
127
202
  super({ pluginId: "tanstack-ai-devtools" });
128
203
  }
129
- }, d = new AiEventClient();
204
+ };
205
+ var aiEventClient = new AiEventClient();
130
206
  //#endregion
131
207
  //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
132
- function isContentPart(e) {
133
- return e.type === "text" || e.type === "image" || e.type === "audio" || e.type === "video" || e.type === "document";
208
+ function isContentPart(part) {
209
+ return part.type === "text" || part.type === "image" || part.type === "audio" || part.type === "video" || part.type === "document";
134
210
  }
135
- function collapseContentParts(e) {
136
- return e.length === 0 ? null : e.every((e) => e.type === "text") ? e.map((e) => e.content).join("") || null : e;
211
+ function collapseContentParts(parts) {
212
+ if (parts.length === 0) return null;
213
+ if (parts.every((p) => p.type === "text")) return parts.map((p) => p.content).join("") || null;
214
+ return parts;
137
215
  }
138
- function getTextContent(e) {
139
- return e === null ? "" : typeof e == "string" ? e : e.filter((e) => e.type === "text").map((e) => e.content).join("");
216
+ function getTextContent(content) {
217
+ if (content === null) return "";
218
+ if (typeof content === "string") return content;
219
+ return content.filter((part) => part.type === "text").map((part) => part.content).join("");
140
220
  }
141
- function uiMessageToModelMessages(e) {
142
- return e.role === "system" ? [] : e.role === "assistant" ? buildAssistantMessages(e) : [buildUserOrToolMessage(e)];
221
+ function uiMessageToModelMessages(uiMessage) {
222
+ if (uiMessage.role === "system") return [];
223
+ if (uiMessage.role !== "assistant") return [buildUserOrToolMessage(uiMessage)];
224
+ return buildAssistantMessages(uiMessage);
143
225
  }
144
- function buildUserOrToolMessage(e) {
145
- let t = [];
146
- for (let n of e.parts) isContentPart(n) && t.push(n);
226
+ function buildUserOrToolMessage(uiMessage) {
227
+ const contentParts = [];
228
+ for (const part of uiMessage.parts) if (isContentPart(part)) contentParts.push(part);
147
229
  return {
148
- role: e.role,
149
- content: collapseContentParts(t)
230
+ role: uiMessage.role,
231
+ content: collapseContentParts(contentParts)
150
232
  };
151
233
  }
152
234
  function createSegment() {
@@ -155,101 +237,121 @@ function createSegment() {
155
237
  toolCalls: []
156
238
  };
157
239
  }
158
- function isToolCallIncluded(e) {
159
- return e.state === "input-complete" || e.state === "approval-responded" || e.output !== void 0;
240
+ function isToolCallIncluded(part) {
241
+ return part.state === "input-complete" || part.state === "approval-responded" || part.output !== void 0;
160
242
  }
161
- function buildAssistantMessages(e) {
162
- let t = [], n = createSegment(), r = /* @__PURE__ */ new Set();
243
+ function buildAssistantMessages(uiMessage) {
244
+ const messageList = [];
245
+ let current = createSegment();
246
+ const emittedToolResultIds = /* @__PURE__ */ new Set();
163
247
  function flushSegment() {
164
- let e = collapseContentParts(n.contentParts), r = e !== null, i = n.toolCalls.length > 0;
165
- (r || i) && t.push({
248
+ const content = collapseContentParts(current.contentParts);
249
+ const hasContent = content !== null;
250
+ const hasToolCalls = current.toolCalls.length > 0;
251
+ if (hasContent || hasToolCalls) messageList.push({
166
252
  role: "assistant",
167
- content: e,
168
- ...i && { toolCalls: n.toolCalls }
169
- }), n = createSegment();
253
+ content,
254
+ ...hasToolCalls && { toolCalls: current.toolCalls }
255
+ });
256
+ current = createSegment();
170
257
  }
171
- for (let i of e.parts) switch (i.type) {
258
+ for (const part of uiMessage.parts) switch (part.type) {
172
259
  case "text":
173
260
  case "image":
174
261
  case "audio":
175
262
  case "video":
176
263
  case "document":
177
- n.contentParts.push(i);
264
+ current.contentParts.push(part);
178
265
  break;
179
266
  case "tool-call":
180
- isToolCallIncluded(i) && n.toolCalls.push({
181
- id: i.id,
267
+ if (isToolCallIncluded(part)) current.toolCalls.push({
268
+ id: part.id,
182
269
  type: "function",
183
270
  function: {
184
- name: i.name,
185
- arguments: i.arguments
271
+ name: part.name,
272
+ arguments: part.arguments
186
273
  }
187
274
  });
188
275
  break;
189
- case "tool-result": flushSegment(), (i.state === "complete" || i.state === "error") && !r.has(i.toolCallId) && (t.push({
190
- role: "tool",
191
- content: i.content,
192
- toolCallId: i.toolCallId
193
- }), r.add(i.toolCallId));
276
+ case "tool-result":
277
+ flushSegment();
278
+ if ((part.state === "complete" || part.state === "error") && !emittedToolResultIds.has(part.toolCallId)) {
279
+ messageList.push({
280
+ role: "tool",
281
+ content: part.content,
282
+ toolCallId: part.toolCallId
283
+ });
284
+ emittedToolResultIds.add(part.toolCallId);
285
+ }
194
286
  }
195
287
  flushSegment();
196
- for (let n of e.parts) if (n.type === "tool-call" && (n.output !== void 0 && !r.has(n.id) && (t.push({
197
- role: "tool",
198
- content: JSON.stringify(n.output),
199
- toolCallId: n.id
200
- }), r.add(n.id)), n.output === void 0 && n.state === "approval-responded" && n.approval?.approved !== void 0 && !r.has(n.id))) {
201
- let e = n.approval.approved;
202
- t.push({
203
- role: "tool",
204
- content: JSON.stringify({
205
- approved: e,
206
- ...e && { pendingExecution: !0 },
207
- message: e ? "User approved this action" : "User denied this action"
208
- }),
209
- toolCallId: n.id
210
- }), r.add(n.id);
211
- }
212
- return t.length === 0 && t.push({
288
+ for (const part of uiMessage.parts) {
289
+ if (part.type !== "tool-call") continue;
290
+ if (part.output !== void 0 && !emittedToolResultIds.has(part.id)) {
291
+ messageList.push({
292
+ role: "tool",
293
+ content: JSON.stringify(part.output),
294
+ toolCallId: part.id
295
+ });
296
+ emittedToolResultIds.add(part.id);
297
+ }
298
+ if (part.output === void 0 && part.state === "approval-responded" && part.approval?.approved !== void 0 && !emittedToolResultIds.has(part.id)) {
299
+ const approved = part.approval.approved;
300
+ messageList.push({
301
+ role: "tool",
302
+ content: JSON.stringify({
303
+ approved,
304
+ ...approved && { pendingExecution: true },
305
+ message: approved ? "User approved this action" : "User denied this action"
306
+ }),
307
+ toolCallId: part.id
308
+ });
309
+ emittedToolResultIds.add(part.id);
310
+ }
311
+ }
312
+ if (messageList.length === 0) messageList.push({
213
313
  role: "assistant",
214
314
  content: null
215
- }), t;
315
+ });
316
+ return messageList;
216
317
  }
217
- function modelMessageToUIMessage(e, t) {
218
- let n = [];
219
- if (e.role === "tool" && e.toolCallId) n.push({
318
+ function modelMessageToUIMessage(modelMessage, id) {
319
+ const parts = [];
320
+ if (modelMessage.role === "tool" && modelMessage.toolCallId) parts.push({
220
321
  type: "tool-result",
221
- toolCallId: e.toolCallId,
222
- content: getTextContent(e.content),
322
+ toolCallId: modelMessage.toolCallId,
323
+ content: getTextContent(modelMessage.content),
223
324
  state: "complete"
224
325
  });
225
- else if (Array.isArray(e.content)) for (let t of e.content) n.push(t);
326
+ else if (Array.isArray(modelMessage.content)) for (const part of modelMessage.content) parts.push(part);
226
327
  else {
227
- let t = getTextContent(e.content);
228
- t && n.push({
328
+ const textContent = getTextContent(modelMessage.content);
329
+ if (textContent) parts.push({
229
330
  type: "text",
230
- content: t
331
+ content: textContent
231
332
  });
232
333
  }
233
- if (e.toolCalls && e.toolCalls.length > 0) for (let t of e.toolCalls) n.push({
334
+ if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) for (const toolCall of modelMessage.toolCalls) parts.push({
234
335
  type: "tool-call",
235
- id: t.id,
236
- name: t.function.name,
237
- arguments: t.function.arguments,
336
+ id: toolCall.id,
337
+ name: toolCall.function.name,
338
+ arguments: toolCall.function.arguments,
238
339
  state: "input-complete"
239
340
  });
240
341
  return {
241
- id: t || generateMessageId(),
242
- role: e.role === "tool" ? "assistant" : e.role,
243
- parts: n
342
+ id: id || generateMessageId(),
343
+ role: modelMessage.role === "tool" ? "assistant" : modelMessage.role,
344
+ parts
244
345
  };
245
346
  }
246
- function normalizeToUIMessage(e, t) {
247
- return "parts" in e ? {
248
- ...e,
249
- id: e.id || t(),
250
- createdAt: e.createdAt || /* @__PURE__ */ new Date()
251
- } : {
252
- ...modelMessageToUIMessage(e, t()),
347
+ function normalizeToUIMessage(message, generateId) {
348
+ if ("parts" in message) return {
349
+ ...message,
350
+ id: message.id || generateId(),
351
+ createdAt: message.createdAt || /* @__PURE__ */ new Date()
352
+ };
353
+ else return {
354
+ ...modelMessageToUIMessage(message, generateId()),
253
355
  createdAt: /* @__PURE__ */ new Date()
254
356
  };
255
357
  }
@@ -258,958 +360,1667 @@ function generateMessageId() {
258
360
  }
259
361
  //#endregion
260
362
  //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
261
- function toolDefinition(e) {
363
+ function toolDefinition(config) {
262
364
  return {
263
365
  __toolSide: "definition",
264
- ...e,
265
- server(t) {
366
+ ...config,
367
+ server(execute) {
266
368
  return {
267
369
  __toolSide: "server",
268
- ...e,
269
- execute: t
370
+ ...config,
371
+ execute
270
372
  };
271
373
  },
272
- client(t) {
374
+ client(execute) {
273
375
  return {
274
376
  __toolSide: "client",
275
- ...e,
276
- execute: t
377
+ ...config,
378
+ execute
277
379
  };
278
380
  }
279
381
  };
280
382
  }
281
383
  //#endregion
282
384
  //#region ../../node_modules/.pnpm/partial-json@0.1.7/node_modules/partial-json/dist/options.js
283
- var f = /* @__PURE__ */ e(((e) => {
284
- Object.defineProperty(e, "__esModule", { value: !0 }), e.Allow = e.ALL = e.COLLECTION = e.ATOM = e.SPECIAL = e.INF = e._INFINITY = e.INFINITY = e.NAN = e.BOOL = e.NULL = e.OBJ = e.ARR = e.NUM = e.STR = void 0, e.STR = 1, e.NUM = 2, e.ARR = 4, e.OBJ = 8, e.NULL = 16, e.BOOL = 32, e.NAN = 64, e.INFINITY = 128, e._INFINITY = 256, e.INF = e.INFINITY | e._INFINITY, e.SPECIAL = e.NULL | e.BOOL | e.INF | e.NAN, e.ATOM = e.STR | e.NUM | e.SPECIAL, e.COLLECTION = e.ARR | e.OBJ, e.ALL = e.ATOM | e.COLLECTION, e.Allow = {
285
- STR: e.STR,
286
- NUM: e.NUM,
287
- ARR: e.ARR,
288
- OBJ: e.OBJ,
289
- NULL: e.NULL,
290
- BOOL: e.BOOL,
291
- NAN: e.NAN,
292
- INFINITY: e.INFINITY,
293
- _INFINITY: e._INFINITY,
294
- INF: e.INF,
295
- SPECIAL: e.SPECIAL,
296
- ATOM: e.ATOM,
297
- COLLECTION: e.COLLECTION,
298
- ALL: e.ALL
299
- }, e.default = e.Allow;
300
- })), p = (/* @__PURE__ */ e(((e) => {
301
- var t = e && e.__createBinding || (Object.create ? (function(e, t, n, r) {
302
- r === void 0 && (r = n);
303
- var i = Object.getOwnPropertyDescriptor(t, n);
304
- (!i || ("get" in i ? !t.__esModule : i.writable || i.configurable)) && (i = {
305
- enumerable: !0,
385
+ var require_options = /* @__PURE__ */ __commonJSMin(((exports) => {
386
+ /**
387
+ * Sometimes you don't allow every type to be partially parsed.
388
+ * For example, you may not want a partial number because it may increase its size gradually before it's complete.
389
+ * In this case, you can use the `Allow` object to control what types you allow to be partially parsed.
390
+ * @module
391
+ */
392
+ Object.defineProperty(exports, "__esModule", { value: true });
393
+ exports.Allow = exports.ALL = exports.COLLECTION = exports.ATOM = exports.SPECIAL = exports.INF = exports._INFINITY = exports.INFINITY = exports.NAN = exports.BOOL = exports.NULL = exports.OBJ = exports.ARR = exports.NUM = exports.STR = void 0;
394
+ /**
395
+ * allow partial strings like `"hello \u12` to be parsed as `"hello "`
396
+ */
397
+ exports.STR = 1;
398
+ /**
399
+ * allow partial numbers like `123.` to be parsed as `123`
400
+ */
401
+ exports.NUM = 2;
402
+ /**
403
+ * allow partial arrays like `[1, 2,` to be parsed as `[1, 2]`
404
+ */
405
+ exports.ARR = 4;
406
+ /**
407
+ * allow partial objects like `{"a": 1, "b":` to be parsed as `{"a": 1}`
408
+ */
409
+ exports.OBJ = 8;
410
+ /**
411
+ * allow `nu` to be parsed as `null`
412
+ */
413
+ exports.NULL = 16;
414
+ /**
415
+ * allow `tr` to be parsed as `true`, and `fa` to be parsed as `false`
416
+ */
417
+ exports.BOOL = 32;
418
+ /**
419
+ * allow `Na` to be parsed as `NaN`
420
+ */
421
+ exports.NAN = 64;
422
+ /**
423
+ * allow `Inf` to be parsed as `Infinity`
424
+ */
425
+ exports.INFINITY = 128;
426
+ /**
427
+ * allow `-Inf` to be parsed as `-Infinity`
428
+ */
429
+ exports._INFINITY = 256;
430
+ exports.INF = exports.INFINITY | exports._INFINITY;
431
+ exports.SPECIAL = exports.NULL | exports.BOOL | exports.INF | exports.NAN;
432
+ exports.ATOM = exports.STR | exports.NUM | exports.SPECIAL;
433
+ exports.COLLECTION = exports.ARR | exports.OBJ;
434
+ exports.ALL = exports.ATOM | exports.COLLECTION;
435
+ /**
436
+ * Control what types you allow to be partially parsed.
437
+ * The default is to allow all types to be partially parsed, which in most casees is the best option.
438
+ * @example
439
+ * If you don't want to allow partial objects, you can use the following code:
440
+ * ```ts
441
+ * import { Allow, parse } from "partial-json";
442
+ * parse(`[{"a": 1, "b": 2}, {"a": 3,`, Allow.ARR); // [ { a: 1, b: 2 } ]
443
+ * ```
444
+ * Or you can use `~` to disallow a type:
445
+ * ```ts
446
+ * parse(`[{"a": 1, "b": 2}, {"a": 3,`, ~Allow.OBJ); // [ { a: 1, b: 2 } ]
447
+ * ```
448
+ * @example
449
+ * If you don't want to allow partial strings, you can use the following code:
450
+ * ```ts
451
+ * import { Allow, parse } from "partial-json";
452
+ * parse(`["complete string", "incompl`, ~Allow.STR); // [ 'complete string' ]
453
+ * ```
454
+ */
455
+ exports.Allow = {
456
+ STR: exports.STR,
457
+ NUM: exports.NUM,
458
+ ARR: exports.ARR,
459
+ OBJ: exports.OBJ,
460
+ NULL: exports.NULL,
461
+ BOOL: exports.BOOL,
462
+ NAN: exports.NAN,
463
+ INFINITY: exports.INFINITY,
464
+ _INFINITY: exports._INFINITY,
465
+ INF: exports.INF,
466
+ SPECIAL: exports.SPECIAL,
467
+ ATOM: exports.ATOM,
468
+ COLLECTION: exports.COLLECTION,
469
+ ALL: exports.ALL
470
+ };
471
+ exports.default = exports.Allow;
472
+ }));
473
+ //#endregion
474
+ //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
475
+ var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
476
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
477
+ if (k2 === void 0) k2 = k;
478
+ var desc = Object.getOwnPropertyDescriptor(m, k);
479
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = {
480
+ enumerable: true,
306
481
  get: function() {
307
- return t[n];
482
+ return m[k];
308
483
  }
309
- }), Object.defineProperty(e, r, i);
310
- }) : (function(e, t, n, r) {
311
- r === void 0 && (r = n), e[r] = t[n];
312
- })), n = e && e.__exportStar || function(e, n) {
313
- for (var r in e) r !== "default" && !Object.prototype.hasOwnProperty.call(n, r) && t(n, e, r);
484
+ };
485
+ Object.defineProperty(o, k2, desc);
486
+ }) : (function(o, m, k, k2) {
487
+ if (k2 === void 0) k2 = k;
488
+ o[k2] = m[k];
489
+ }));
490
+ var __exportStar = exports && exports.__exportStar || function(m, exports$1) {
491
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
314
492
  };
315
- Object.defineProperty(e, "__esModule", { value: !0 }), e.Allow = e.MalformedJSON = e.PartialJSON = e.parseJSON = e.parse = void 0;
316
- var r = f();
317
- Object.defineProperty(e, "Allow", {
318
- enumerable: !0,
493
+ Object.defineProperty(exports, "__esModule", { value: true });
494
+ exports.Allow = exports.MalformedJSON = exports.PartialJSON = exports.parseJSON = exports.parse = void 0;
495
+ var options_1 = require_options();
496
+ Object.defineProperty(exports, "Allow", {
497
+ enumerable: true,
319
498
  get: function() {
320
- return r.Allow;
499
+ return options_1.Allow;
321
500
  }
322
- }), n(f(), e);
501
+ });
502
+ __exportStar(require_options(), exports);
323
503
  var PartialJSON = class extends Error {};
324
- e.PartialJSON = PartialJSON;
504
+ exports.PartialJSON = PartialJSON;
325
505
  var MalformedJSON = class extends Error {};
326
- e.MalformedJSON = MalformedJSON;
327
- function parseJSON(e, t = r.Allow.ALL) {
328
- if (typeof e != "string") throw TypeError(`expecting str, got ${typeof e}`);
329
- if (!e.trim()) throw Error(`${e} is empty`);
330
- return _parseJSON(e.trim(), t);
331
- }
332
- e.parseJSON = parseJSON;
333
- var _parseJSON = (e, t) => {
334
- let n = e.length, i = 0, markPartialJSON = (e) => {
335
- throw new PartialJSON(`${e} at position ${i}`);
336
- }, throwMalformedError = (e) => {
337
- throw new MalformedJSON(`${e} at position ${i}`);
338
- }, parseAny = () => (skipBlank(), i >= n && markPartialJSON("Unexpected end of input"), e[i] === "\"" ? parseStr() : e[i] === "{" ? parseObj() : e[i] === "[" ? parseArr() : e.substring(i, i + 4) === "null" || r.Allow.NULL & t && n - i < 4 && "null".startsWith(e.substring(i)) ? (i += 4, null) : e.substring(i, i + 4) === "true" || r.Allow.BOOL & t && n - i < 4 && "true".startsWith(e.substring(i)) ? (i += 4, !0) : e.substring(i, i + 5) === "false" || r.Allow.BOOL & t && n - i < 5 && "false".startsWith(e.substring(i)) ? (i += 5, !1) : e.substring(i, i + 8) === "Infinity" || r.Allow.INFINITY & t && n - i < 8 && "Infinity".startsWith(e.substring(i)) ? (i += 8, Infinity) : e.substring(i, i + 9) === "-Infinity" || r.Allow._INFINITY & t && 1 < n - i && n - i < 9 && "-Infinity".startsWith(e.substring(i)) ? (i += 9, -Infinity) : e.substring(i, i + 3) === "NaN" || r.Allow.NAN & t && n - i < 3 && "NaN".startsWith(e.substring(i)) ? (i += 3, NaN) : parseNum()), parseStr = () => {
339
- let a = i, o = !1;
340
- for (i++; i < n && (e[i] !== "\"" || o && e[i - 1] === "\\");) o = e[i] === "\\" && !o, i++;
341
- if (e.charAt(i) == "\"") try {
342
- return JSON.parse(e.substring(a, ++i - Number(o)));
506
+ exports.MalformedJSON = MalformedJSON;
507
+ /**
508
+ * Parse incomplete JSON
509
+ * @param {string} jsonString Partial JSON to be parsed
510
+ * @param {number} allowPartial Specify what types are allowed to be partial, see {@link Allow} for details
511
+ * @returns The parsed JSON
512
+ * @throws {PartialJSON} If the JSON is incomplete (related to the `allow` parameter)
513
+ * @throws {MalformedJSON} If the JSON is malformed
514
+ */
515
+ function parseJSON(jsonString, allowPartial = options_1.Allow.ALL) {
516
+ if (typeof jsonString !== "string") throw new TypeError(`expecting str, got ${typeof jsonString}`);
517
+ if (!jsonString.trim()) throw new Error(`${jsonString} is empty`);
518
+ return _parseJSON(jsonString.trim(), allowPartial);
519
+ }
520
+ exports.parseJSON = parseJSON;
521
+ var _parseJSON = (jsonString, allow) => {
522
+ const length = jsonString.length;
523
+ let index = 0;
524
+ const markPartialJSON = (msg) => {
525
+ throw new PartialJSON(`${msg} at position ${index}`);
526
+ };
527
+ const throwMalformedError = (msg) => {
528
+ throw new MalformedJSON(`${msg} at position ${index}`);
529
+ };
530
+ const parseAny = () => {
531
+ skipBlank();
532
+ if (index >= length) markPartialJSON("Unexpected end of input");
533
+ if (jsonString[index] === "\"") return parseStr();
534
+ if (jsonString[index] === "{") return parseObj();
535
+ if (jsonString[index] === "[") return parseArr();
536
+ if (jsonString.substring(index, index + 4) === "null" || options_1.Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index))) {
537
+ index += 4;
538
+ return null;
539
+ }
540
+ if (jsonString.substring(index, index + 4) === "true" || options_1.Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index))) {
541
+ index += 4;
542
+ return true;
543
+ }
544
+ if (jsonString.substring(index, index + 5) === "false" || options_1.Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index))) {
545
+ index += 5;
546
+ return false;
547
+ }
548
+ if (jsonString.substring(index, index + 8) === "Infinity" || options_1.Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index))) {
549
+ index += 8;
550
+ return Infinity;
551
+ }
552
+ if (jsonString.substring(index, index + 9) === "-Infinity" || options_1.Allow._INFINITY & allow && 1 < length - index && length - index < 9 && "-Infinity".startsWith(jsonString.substring(index))) {
553
+ index += 9;
554
+ return -Infinity;
555
+ }
556
+ if (jsonString.substring(index, index + 3) === "NaN" || options_1.Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index))) {
557
+ index += 3;
558
+ return NaN;
559
+ }
560
+ return parseNum();
561
+ };
562
+ const parseStr = () => {
563
+ const start = index;
564
+ let escape = false;
565
+ index++;
566
+ while (index < length && (jsonString[index] !== "\"" || escape && jsonString[index - 1] === "\\")) {
567
+ escape = jsonString[index] === "\\" ? !escape : false;
568
+ index++;
569
+ }
570
+ if (jsonString.charAt(index) == "\"") try {
571
+ return JSON.parse(jsonString.substring(start, ++index - Number(escape)));
343
572
  } catch (e) {
344
573
  throwMalformedError(String(e));
345
574
  }
346
- else if (r.Allow.STR & t) try {
347
- return JSON.parse(e.substring(a, i - Number(o)) + "\"");
348
- } catch {
349
- return JSON.parse(e.substring(a, e.lastIndexOf("\\")) + "\"");
575
+ else if (options_1.Allow.STR & allow) try {
576
+ return JSON.parse(jsonString.substring(start, index - Number(escape)) + "\"");
577
+ } catch (e) {
578
+ return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + "\"");
350
579
  }
351
580
  markPartialJSON("Unterminated string literal");
352
- }, parseObj = () => {
353
- i++, skipBlank();
354
- let a = {};
581
+ };
582
+ const parseObj = () => {
583
+ index++;
584
+ skipBlank();
585
+ const obj = {};
355
586
  try {
356
- for (; e[i] !== "}";) {
357
- if (skipBlank(), i >= n && r.Allow.OBJ & t) return a;
358
- let o = parseStr();
359
- skipBlank(), i++;
587
+ while (jsonString[index] !== "}") {
588
+ skipBlank();
589
+ if (index >= length && options_1.Allow.OBJ & allow) return obj;
590
+ const key = parseStr();
591
+ skipBlank();
592
+ index++;
360
593
  try {
361
- a[o] = parseAny();
594
+ obj[key] = parseAny();
362
595
  } catch (e) {
363
- if (r.Allow.OBJ & t) return a;
364
- throw e;
596
+ if (options_1.Allow.OBJ & allow) return obj;
597
+ else throw e;
365
598
  }
366
- skipBlank(), e[i] === "," && i++;
599
+ skipBlank();
600
+ if (jsonString[index] === ",") index++;
367
601
  }
368
- } catch {
369
- if (r.Allow.OBJ & t) return a;
370
- markPartialJSON("Expected '}' at end of object");
602
+ } catch (e) {
603
+ if (options_1.Allow.OBJ & allow) return obj;
604
+ else markPartialJSON("Expected '}' at end of object");
371
605
  }
372
- return i++, a;
373
- }, parseArr = () => {
374
- i++;
375
- let n = [];
606
+ index++;
607
+ return obj;
608
+ };
609
+ const parseArr = () => {
610
+ index++;
611
+ const arr = [];
376
612
  try {
377
- for (; e[i] !== "]";) n.push(parseAny()), skipBlank(), e[i] === "," && i++;
378
- } catch {
379
- if (r.Allow.ARR & t) return n;
613
+ while (jsonString[index] !== "]") {
614
+ arr.push(parseAny());
615
+ skipBlank();
616
+ if (jsonString[index] === ",") index++;
617
+ }
618
+ } catch (e) {
619
+ if (options_1.Allow.ARR & allow) return arr;
380
620
  markPartialJSON("Expected ']' at end of array");
381
621
  }
382
- return i++, n;
383
- }, parseNum = () => {
384
- if (i === 0) {
385
- e === "-" && throwMalformedError("Not sure what '-' is");
622
+ index++;
623
+ return arr;
624
+ };
625
+ const parseNum = () => {
626
+ if (index === 0) {
627
+ if (jsonString === "-") throwMalformedError("Not sure what '-' is");
386
628
  try {
387
- return JSON.parse(e);
388
- } catch (n) {
389
- if (r.Allow.NUM & t) try {
390
- return JSON.parse(e.substring(0, e.lastIndexOf("e")));
391
- } catch {}
392
- throwMalformedError(String(n));
629
+ return JSON.parse(jsonString);
630
+ } catch (e) {
631
+ if (options_1.Allow.NUM & allow) try {
632
+ return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf("e")));
633
+ } catch (e) {}
634
+ throwMalformedError(String(e));
393
635
  }
394
636
  }
395
- let a = i;
396
- for (e[i] === "-" && i++; e[i] && ",]}".indexOf(e[i]) === -1;) i++;
397
- i == n && !(r.Allow.NUM & t) && markPartialJSON("Unterminated number literal");
637
+ const start = index;
638
+ if (jsonString[index] === "-") index++;
639
+ while (jsonString[index] && ",]}".indexOf(jsonString[index]) === -1) index++;
640
+ if (index == length && !(options_1.Allow.NUM & allow)) markPartialJSON("Unterminated number literal");
398
641
  try {
399
- return JSON.parse(e.substring(a, i));
400
- } catch {
401
- e.substring(a, i) === "-" && markPartialJSON("Not sure what '-' is");
642
+ return JSON.parse(jsonString.substring(start, index));
643
+ } catch (e) {
644
+ if (jsonString.substring(start, index) === "-") markPartialJSON("Not sure what '-' is");
402
645
  try {
403
- return JSON.parse(e.substring(a, e.lastIndexOf("e")));
646
+ return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("e")));
404
647
  } catch (e) {
405
648
  throwMalformedError(String(e));
406
649
  }
407
650
  }
408
- }, skipBlank = () => {
409
- for (; i < n && " \n\r ".includes(e[i]);) i++;
651
+ };
652
+ const skipBlank = () => {
653
+ while (index < length && " \n\r ".includes(jsonString[index])) index++;
410
654
  };
411
655
  return parseAny();
412
656
  };
413
- e.parse = parseJSON;
414
- })))(), PartialJSONParser = class {
415
- parse(e) {
416
- if (e && e.trim() !== "") try {
417
- return (0, p.parse)(e);
657
+ exports.parse = parseJSON;
658
+ })))();
659
+ var PartialJSONParser = class {
660
+ /**
661
+ * Parse a potentially incomplete JSON string
662
+ * @param jsonString - The JSON string to parse (may be incomplete)
663
+ * @returns The parsed object, or undefined if parsing fails
664
+ */
665
+ parse(jsonString) {
666
+ if (!jsonString || jsonString.trim() === "") return;
667
+ try {
668
+ return (0, import_dist.parse)(jsonString);
418
669
  } catch {
419
670
  return;
420
671
  }
421
672
  }
422
- }, m = new PartialJSONParser();
673
+ };
674
+ var defaultJSONParser = new PartialJSONParser();
423
675
  //#endregion
424
676
  //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
425
- function updateTextPart(e, t, n) {
426
- return e.map((e) => {
427
- if (e.id !== t) return e;
428
- let r = [...e.parts], i = r.length > 0 ? r[r.length - 1] : null;
429
- return i && i.type === "text" ? r[r.length - 1] = {
677
+ function updateTextPart(messages, messageId, content) {
678
+ return messages.map((msg) => {
679
+ if (msg.id !== messageId) return msg;
680
+ const parts = [...msg.parts];
681
+ const lastPart = parts.length > 0 ? parts[parts.length - 1] : null;
682
+ if (lastPart && lastPart.type === "text") parts[parts.length - 1] = {
430
683
  type: "text",
431
- content: n
432
- } : r.push({
684
+ content
685
+ };
686
+ else parts.push({
433
687
  type: "text",
434
- content: n
435
- }), {
436
- ...e,
437
- parts: r
688
+ content
689
+ });
690
+ return {
691
+ ...msg,
692
+ parts
438
693
  };
439
694
  });
440
695
  }
441
- function updateToolCallPart(e, t, n) {
442
- return e.map((e) => {
443
- if (e.id !== t) return e;
444
- let r = [...e.parts], i = r.find((e) => e.type === "tool-call" && e.id === n.id), a = {
696
+ function updateToolCallPart(messages, messageId, toolCall) {
697
+ return messages.map((msg) => {
698
+ if (msg.id !== messageId) return msg;
699
+ const parts = [...msg.parts];
700
+ const existing = parts.find((p) => p.type === "tool-call" && p.id === toolCall.id);
701
+ const toolCallPart = {
445
702
  type: "tool-call",
446
- id: n.id,
447
- name: n.name,
448
- arguments: n.arguments,
449
- state: n.state,
450
- ...i?.approval && { approval: { ...i.approval } },
451
- ...i?.output !== void 0 && { output: i.output }
703
+ id: toolCall.id,
704
+ name: toolCall.name,
705
+ arguments: toolCall.arguments,
706
+ state: toolCall.state,
707
+ ...existing?.approval && { approval: { ...existing.approval } },
708
+ ...existing?.output !== void 0 && { output: existing.output }
452
709
  };
453
- return i ? r[r.indexOf(i)] = a : r.push(a), {
454
- ...e,
455
- parts: r
710
+ if (existing) parts[parts.indexOf(existing)] = toolCallPart;
711
+ else parts.push(toolCallPart);
712
+ return {
713
+ ...msg,
714
+ parts
456
715
  };
457
716
  });
458
717
  }
459
- function updateToolResultPart(e, t, n, r, i, a) {
460
- return e.map((e) => {
461
- if (e.id !== t) return e;
462
- let o = [...e.parts], s = o.findIndex((e) => e.type === "tool-result" && e.toolCallId === n), c = {
718
+ function updateToolResultPart(messages, messageId, toolCallId, content, state, error) {
719
+ return messages.map((msg) => {
720
+ if (msg.id !== messageId) return msg;
721
+ const parts = [...msg.parts];
722
+ const resultPartIndex = parts.findIndex((p) => p.type === "tool-result" && p.toolCallId === toolCallId);
723
+ const toolResultPart = {
463
724
  type: "tool-result",
464
- toolCallId: n,
465
- content: r,
466
- state: i,
467
- ...a && { error: a }
725
+ toolCallId,
726
+ content,
727
+ state,
728
+ ...error && { error }
468
729
  };
469
- return s >= 0 ? o[s] = c : o.push(c), {
470
- ...e,
471
- parts: o
730
+ if (resultPartIndex >= 0) parts[resultPartIndex] = toolResultPart;
731
+ else parts.push(toolResultPart);
732
+ return {
733
+ ...msg,
734
+ parts
472
735
  };
473
736
  });
474
737
  }
475
- function updateToolCallApproval(e, t, n, r) {
476
- return e.map((e) => {
477
- if (e.id !== t) return e;
478
- let i = [...e.parts], a = i.find((e) => e.type === "tool-call" && e.id === n);
479
- return a && (a.state = "approval-requested", a.approval = {
480
- id: r,
481
- needsApproval: !0
482
- }), {
483
- ...e,
484
- parts: i
738
+ function updateToolCallApproval(messages, messageId, toolCallId, approvalId) {
739
+ return messages.map((msg) => {
740
+ if (msg.id !== messageId) return msg;
741
+ const parts = [...msg.parts];
742
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
743
+ if (toolCallPart) {
744
+ toolCallPart.state = "approval-requested";
745
+ toolCallPart.approval = {
746
+ id: approvalId,
747
+ needsApproval: true
748
+ };
749
+ }
750
+ return {
751
+ ...msg,
752
+ parts
485
753
  };
486
754
  });
487
755
  }
488
- function updateToolCallWithOutput(e, t, n, r, i) {
489
- return e.map((e) => {
490
- let a = [...e.parts], o = a.find((e) => e.type === "tool-call" && e.id === t);
491
- return o && (o.output = i ? { error: i } : n, o.state = r || "input-complete"), {
492
- ...e,
493
- parts: a
756
+ function updateToolCallWithOutput(messages, toolCallId, output, state, errorText) {
757
+ return messages.map((msg) => {
758
+ const parts = [...msg.parts];
759
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
760
+ if (toolCallPart) {
761
+ toolCallPart.output = errorText ? { error: errorText } : output;
762
+ if (state) toolCallPart.state = state;
763
+ else toolCallPart.state = "input-complete";
764
+ }
765
+ return {
766
+ ...msg,
767
+ parts
494
768
  };
495
769
  });
496
770
  }
497
- function updateToolCallApprovalResponse(e, t, n) {
498
- return e.map((e) => {
499
- let r = [...e.parts], i = r.find((e) => e.type === "tool-call" && e.approval?.id === t);
500
- return i && i.approval && (i.approval.approved = n, i.state = "approval-responded"), {
501
- ...e,
502
- parts: r
771
+ function updateToolCallApprovalResponse(messages, approvalId, approved) {
772
+ return messages.map((msg) => {
773
+ const parts = [...msg.parts];
774
+ const toolCallPart = parts.find((p) => p.type === "tool-call" && p.approval?.id === approvalId);
775
+ if (toolCallPart && toolCallPart.approval) {
776
+ toolCallPart.approval.approved = approved;
777
+ toolCallPart.state = "approval-responded";
778
+ }
779
+ return {
780
+ ...msg,
781
+ parts
503
782
  };
504
783
  });
505
784
  }
506
- function updateThinkingPart(e, t, n) {
507
- return e.map((e) => {
508
- if (e.id !== t) return e;
509
- let r = [...e.parts], i = r.findIndex((e) => e.type === "thinking"), a = {
785
+ function updateThinkingPart(messages, messageId, content) {
786
+ return messages.map((msg) => {
787
+ if (msg.id !== messageId) return msg;
788
+ const parts = [...msg.parts];
789
+ const thinkingPartIndex = parts.findIndex((p) => p.type === "thinking");
790
+ const thinkingPart = {
510
791
  type: "thinking",
511
- content: n
792
+ content
512
793
  };
513
- return i >= 0 ? r[i] = a : r.push(a), {
514
- ...e,
515
- parts: r
794
+ if (thinkingPartIndex >= 0) parts[thinkingPartIndex] = thinkingPart;
795
+ else parts.push(thinkingPart);
796
+ return {
797
+ ...msg,
798
+ parts
516
799
  };
517
800
  });
518
801
  }
519
802
  //#endregion
520
803
  //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
521
804
  var ImmediateStrategy = class {
522
- shouldEmit(e, t) {
523
- return !0;
524
- }
525
- }, h = class StreamProcessor {
526
- constructor(e = {}) {
527
- this.messages = [], this.messageStates = /* @__PURE__ */ new Map(), this.activeMessageIds = /* @__PURE__ */ new Set(), this.toolCallToMessage = /* @__PURE__ */ new Map(), this.pendingManualMessageId = null, this.activeRuns = /* @__PURE__ */ new Set(), this.finishReason = null, this.hasError = !1, this.isDone = !1, this.recording = null, this.recordingStartTime = 0, this.chunkStrategy = e.chunkStrategy || new ImmediateStrategy(), this.events = e.events || {}, this.jsonParser = e.jsonParser || m, this.recordingEnabled = e.recording ?? !1, e.initialMessages && (this.messages = [...e.initialMessages]);
528
- }
529
- setMessages(e) {
530
- this.messages = [...e], this.emitMessagesChange();
805
+ shouldEmit(_chunk, _accumulated) {
806
+ return true;
531
807
  }
532
- addUserMessage(e, t) {
533
- let n = typeof e == "string" ? [{
808
+ };
809
+ //#endregion
810
+ //#region ../../node_modules/.pnpm/@tanstack+ai@0.14.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
811
+ var StreamProcessor = class StreamProcessor {
812
+ constructor(options = {}) {
813
+ this.messages = [];
814
+ this.messageStates = /* @__PURE__ */ new Map();
815
+ this.activeMessageIds = /* @__PURE__ */ new Set();
816
+ this.toolCallToMessage = /* @__PURE__ */ new Map();
817
+ this.pendingManualMessageId = null;
818
+ this.activeRuns = /* @__PURE__ */ new Set();
819
+ this.finishReason = null;
820
+ this.hasError = false;
821
+ this.isDone = false;
822
+ this.recording = null;
823
+ this.recordingStartTime = 0;
824
+ this.chunkStrategy = options.chunkStrategy || new ImmediateStrategy();
825
+ this.events = options.events || {};
826
+ this.jsonParser = options.jsonParser || defaultJSONParser;
827
+ this.recordingEnabled = options.recording ?? false;
828
+ if (options.initialMessages) this.messages = [...options.initialMessages];
829
+ }
830
+ /**
831
+ * Set the messages array (e.g., from persisted state)
832
+ */
833
+ setMessages(messages) {
834
+ this.messages = [...messages];
835
+ this.emitMessagesChange();
836
+ }
837
+ /**
838
+ * Add a user message to the conversation.
839
+ * Supports both simple string content and multimodal content arrays.
840
+ *
841
+ * @param content - The message content (string or array of content parts)
842
+ * @param id - Optional custom message ID (generated if not provided)
843
+ * @returns The created UIMessage
844
+ *
845
+ * @example
846
+ * ```ts
847
+ * // Simple text message
848
+ * processor.addUserMessage('Hello!')
849
+ *
850
+ * // Multimodal message with image
851
+ * processor.addUserMessage([
852
+ * { type: 'text', content: 'What is in this image?' },
853
+ * { type: 'image', source: { type: 'url', value: 'https://example.com/photo.jpg' } }
854
+ * ])
855
+ *
856
+ * // With custom ID
857
+ * processor.addUserMessage('Hello!', 'custom-id-123')
858
+ * ```
859
+ */
860
+ addUserMessage(content, id) {
861
+ const parts = typeof content === "string" ? [{
534
862
  type: "text",
535
- content: e
536
- }] : e.map((e) => e), r = {
537
- id: t ?? generateMessageId(),
863
+ content
864
+ }] : content.map((part) => {
865
+ return part;
866
+ });
867
+ const userMessage = {
868
+ id: id ?? generateMessageId(),
538
869
  role: "user",
539
- parts: n,
870
+ parts,
540
871
  createdAt: /* @__PURE__ */ new Date()
541
872
  };
542
- return this.messages = [...this.messages, r], this.emitMessagesChange(), r;
543
- }
873
+ this.messages = [...this.messages, userMessage];
874
+ this.emitMessagesChange();
875
+ return userMessage;
876
+ }
877
+ /**
878
+ * Prepare for a new assistant message stream.
879
+ * Does NOT create the message immediately -- the message is created lazily
880
+ * when the first content-bearing chunk arrives via ensureAssistantMessage().
881
+ * This prevents empty assistant messages from flickering in the UI when
882
+ * auto-continuation produces no content.
883
+ */
544
884
  prepareAssistantMessage() {
545
885
  this.resetStreamState();
546
886
  }
547
- startAssistantMessage(e) {
887
+ /**
888
+ * @deprecated Use prepareAssistantMessage() instead. This eagerly creates
889
+ * an assistant message which can cause empty message flicker.
890
+ */
891
+ startAssistantMessage(messageId) {
548
892
  this.prepareAssistantMessage();
549
- let { messageId: t } = this.ensureAssistantMessage(e);
550
- return this.pendingManualMessageId = t, t;
551
- }
893
+ const { messageId: id } = this.ensureAssistantMessage(messageId);
894
+ this.pendingManualMessageId = id;
895
+ return id;
896
+ }
897
+ /**
898
+ * Get the current assistant message ID (if one has been created).
899
+ * Returns null if prepareAssistantMessage() was called but no content
900
+ * has arrived yet.
901
+ */
552
902
  getCurrentAssistantMessageId() {
553
- let e = null;
554
- for (let [t, n] of this.messageStates) n.role === "assistant" && (e = t);
555
- return e;
556
- }
557
- addToolResult(e, t, n) {
558
- let r = this.messages.find((t) => t.parts.some((t) => t.type === "tool-call" && t.id === e));
559
- if (!r) {
560
- console.warn(`[StreamProcessor] Could not find message with tool call ${e}`);
903
+ let lastId = null;
904
+ for (const [id, state] of this.messageStates) if (state.role === "assistant") lastId = id;
905
+ return lastId;
906
+ }
907
+ /**
908
+ * Add a tool result (called by client after handling onToolCall)
909
+ */
910
+ addToolResult(toolCallId, output, error) {
911
+ const messageWithToolCall = this.messages.find((msg) => msg.parts.some((p) => p.type === "tool-call" && p.id === toolCallId));
912
+ if (!messageWithToolCall) {
913
+ console.warn(`[StreamProcessor] Could not find message with tool call ${toolCallId}`);
561
914
  return;
562
915
  }
563
- let i = updateToolCallWithOutput(this.messages, e, t, n ? "input-complete" : void 0, n), a = typeof t == "string" ? t : JSON.stringify(t), o = n ? "error" : "complete";
564
- i = updateToolResultPart(i, r.id, e, a, o, n), this.messages = i, this.emitMessagesChange();
565
- }
566
- addToolApprovalResponse(e, t) {
567
- this.messages = updateToolCallApprovalResponse(this.messages, e, t), this.emitMessagesChange();
568
- }
916
+ let updatedMessages = updateToolCallWithOutput(this.messages, toolCallId, output, error ? "input-complete" : void 0, error);
917
+ const content = typeof output === "string" ? output : JSON.stringify(output);
918
+ const toolResultState = error ? "error" : "complete";
919
+ updatedMessages = updateToolResultPart(updatedMessages, messageWithToolCall.id, toolCallId, content, toolResultState, error);
920
+ this.messages = updatedMessages;
921
+ this.emitMessagesChange();
922
+ }
923
+ /**
924
+ * Add an approval response (called by client after handling onApprovalRequest)
925
+ */
926
+ addToolApprovalResponse(approvalId, approved) {
927
+ this.messages = updateToolCallApprovalResponse(this.messages, approvalId, approved);
928
+ this.emitMessagesChange();
929
+ }
930
+ /**
931
+ * Get the conversation as ModelMessages (for sending to LLM)
932
+ */
569
933
  toModelMessages() {
570
- let e = [];
571
- for (let t of this.messages) e.push(...uiMessageToModelMessages(t));
572
- return e;
934
+ const modelMessages = [];
935
+ for (const msg of this.messages) modelMessages.push(...uiMessageToModelMessages(msg));
936
+ return modelMessages;
573
937
  }
938
+ /**
939
+ * Get current messages
940
+ */
574
941
  getMessages() {
575
942
  return this.messages;
576
943
  }
944
+ /**
945
+ * Check if all tool calls in the last assistant message are complete
946
+ * Useful for auto-continue logic
947
+ */
577
948
  areAllToolsComplete() {
578
- let e = this.messages.findLast((e) => e.role === "assistant");
579
- if (!e) return !0;
580
- let t = e.parts.filter((e) => e.type === "tool-call");
581
- if (t.length === 0) return !0;
582
- let n = new Set(e.parts.filter((e) => e.type === "tool-result").map((e) => e.toolCallId));
583
- return t.every((e) => e.state === "approval-responded" || e.output !== void 0 && !e.approval || n.has(e.id));
584
- }
585
- removeMessagesAfter(e) {
586
- this.messages = this.messages.slice(0, e + 1), this.emitMessagesChange();
587
- }
949
+ const lastAssistant = this.messages.findLast((m) => m.role === "assistant");
950
+ if (!lastAssistant) return true;
951
+ const toolParts = lastAssistant.parts.filter((p) => p.type === "tool-call");
952
+ if (toolParts.length === 0) return true;
953
+ const toolResultIds = new Set(lastAssistant.parts.filter((p) => p.type === "tool-result").map((p) => p.toolCallId));
954
+ return toolParts.every((part) => part.state === "approval-responded" || part.output !== void 0 && !part.approval || toolResultIds.has(part.id));
955
+ }
956
+ /**
957
+ * Remove messages after a certain index (for reload/retry)
958
+ */
959
+ removeMessagesAfter(index) {
960
+ this.messages = this.messages.slice(0, index + 1);
961
+ this.emitMessagesChange();
962
+ }
963
+ /**
964
+ * Clear all messages
965
+ */
588
966
  clearMessages() {
589
- this.messages = [], this.messageStates.clear(), this.activeMessageIds.clear(), this.toolCallToMessage.clear(), this.pendingManualMessageId = null, this.emitMessagesChange();
590
- }
591
- async process(e) {
592
- this.resetStreamState(), this.recordingEnabled && this.startRecording();
593
- for await (let t of e) this.processChunk(t);
594
- return this.finalizeStream(), this.recording && (this.recording.result = this.getResult()), this.getResult();
595
- }
596
- processChunk(e) {
597
- switch (this.recording && this.recording.chunks.push({
598
- chunk: e,
967
+ this.messages = [];
968
+ this.messageStates.clear();
969
+ this.activeMessageIds.clear();
970
+ this.toolCallToMessage.clear();
971
+ this.pendingManualMessageId = null;
972
+ this.emitMessagesChange();
973
+ }
974
+ /**
975
+ * Process a stream and emit events through handlers
976
+ */
977
+ async process(stream) {
978
+ this.resetStreamState();
979
+ if (this.recordingEnabled) this.startRecording();
980
+ for await (const chunk of stream) this.processChunk(chunk);
981
+ this.finalizeStream();
982
+ if (this.recording) this.recording.result = this.getResult();
983
+ return this.getResult();
984
+ }
985
+ /**
986
+ * Process a single chunk from the stream.
987
+ *
988
+ * Central dispatch for all AG-UI events. Each event type maps to a specific
989
+ * handler. Events not listed in the switch are intentionally ignored
990
+ * (STEP_STARTED, STATE_SNAPSHOT, STATE_DELTA).
991
+ *
992
+ * @see docs/chat-architecture.md#adapter-contract — Expected event types and ordering
993
+ */
994
+ processChunk(chunk) {
995
+ if (this.recording) this.recording.chunks.push({
996
+ chunk,
599
997
  timestamp: Date.now(),
600
998
  index: this.recording.chunks.length
601
- }), e.type) {
999
+ });
1000
+ switch (chunk.type) {
602
1001
  case "TEXT_MESSAGE_START":
603
- this.handleTextMessageStartEvent(e);
1002
+ this.handleTextMessageStartEvent(chunk);
604
1003
  break;
605
1004
  case "TEXT_MESSAGE_CONTENT":
606
- this.handleTextMessageContentEvent(e);
1005
+ this.handleTextMessageContentEvent(chunk);
607
1006
  break;
608
1007
  case "TEXT_MESSAGE_END":
609
- this.handleTextMessageEndEvent(e);
1008
+ this.handleTextMessageEndEvent(chunk);
610
1009
  break;
611
1010
  case "TOOL_CALL_START":
612
- this.handleToolCallStartEvent(e);
1011
+ this.handleToolCallStartEvent(chunk);
613
1012
  break;
614
1013
  case "TOOL_CALL_ARGS":
615
- this.handleToolCallArgsEvent(e);
1014
+ this.handleToolCallArgsEvent(chunk);
616
1015
  break;
617
1016
  case "TOOL_CALL_END":
618
- this.handleToolCallEndEvent(e);
1017
+ this.handleToolCallEndEvent(chunk);
619
1018
  break;
620
1019
  case "RUN_FINISHED":
621
- this.handleRunFinishedEvent(e);
1020
+ this.handleRunFinishedEvent(chunk);
622
1021
  break;
623
1022
  case "RUN_ERROR":
624
- this.handleRunErrorEvent(e);
1023
+ this.handleRunErrorEvent(chunk);
625
1024
  break;
626
1025
  case "STEP_FINISHED":
627
- this.handleStepFinishedEvent(e);
1026
+ this.handleStepFinishedEvent(chunk);
628
1027
  break;
629
1028
  case "MESSAGES_SNAPSHOT":
630
- this.handleMessagesSnapshotEvent(e);
1029
+ this.handleMessagesSnapshotEvent(chunk);
631
1030
  break;
632
1031
  case "CUSTOM":
633
- this.handleCustomEvent(e);
1032
+ this.handleCustomEvent(chunk);
634
1033
  break;
635
1034
  case "RUN_STARTED":
636
- this.handleRunStartedEvent(e);
1035
+ this.handleRunStartedEvent(chunk);
637
1036
  break;
638
1037
  case "REASONING_START":
639
1038
  case "REASONING_MESSAGE_START":
640
1039
  case "REASONING_MESSAGE_END":
641
1040
  case "REASONING_END": break;
642
1041
  case "REASONING_MESSAGE_CONTENT":
643
- this.handleReasoningMessageContentEvent(e);
1042
+ this.handleReasoningMessageContentEvent(chunk);
644
1043
  break;
645
- case "TOOL_CALL_RESULT": this.handleToolCallResultEvent(e);
1044
+ case "TOOL_CALL_RESULT": this.handleToolCallResultEvent(chunk);
646
1045
  }
647
1046
  }
648
- createMessageState(e, t) {
649
- let n = {
650
- id: e,
651
- role: t,
1047
+ /**
1048
+ * Create a new MessageStreamState for a message
1049
+ */
1050
+ createMessageState(messageId, role) {
1051
+ const state = {
1052
+ id: messageId,
1053
+ role,
652
1054
  totalTextContent: "",
653
1055
  currentSegmentText: "",
654
1056
  lastEmittedText: "",
655
1057
  thinkingContent: "",
656
- hasSeenReasoningEvents: !1,
1058
+ hasSeenReasoningEvents: false,
657
1059
  toolCalls: /* @__PURE__ */ new Map(),
658
1060
  toolCallOrder: [],
659
- hasToolCallsSinceTextStart: !1,
660
- isComplete: !1
1061
+ hasToolCallsSinceTextStart: false,
1062
+ isComplete: false
661
1063
  };
662
- return this.messageStates.set(e, n), n;
663
- }
664
- getMessageState(e) {
665
- return this.messageStates.get(e);
666
- }
1064
+ this.messageStates.set(messageId, state);
1065
+ return state;
1066
+ }
1067
+ /**
1068
+ * Get the MessageStreamState for a message
1069
+ */
1070
+ getMessageState(messageId) {
1071
+ return this.messageStates.get(messageId);
1072
+ }
1073
+ /**
1074
+ * Get the most recent active assistant message ID.
1075
+ * Used as fallback for events that don't include a messageId.
1076
+ */
667
1077
  getActiveAssistantMessageId() {
668
- let e = Array.from(this.activeMessageIds);
669
- for (let t = e.length - 1; t >= 0; t--) {
670
- let n = e[t], r = this.messageStates.get(n);
671
- if (r && r.role === "assistant") return n;
1078
+ const ids = Array.from(this.activeMessageIds);
1079
+ for (let i = ids.length - 1; i >= 0; i--) {
1080
+ const id = ids[i];
1081
+ const state = this.messageStates.get(id);
1082
+ if (state && state.role === "assistant") return id;
672
1083
  }
673
1084
  return null;
674
1085
  }
675
- ensureAssistantMessage(e) {
676
- if (e) {
677
- let t = this.getMessageState(e);
678
- if (t) return {
679
- messageId: e,
680
- state: t
1086
+ /**
1087
+ * Ensure an active assistant message exists, creating one if needed.
1088
+ * Used for backward compat when events arrive without prior TEXT_MESSAGE_START.
1089
+ *
1090
+ * On reconnect/resume, a TEXT_MESSAGE_CONTENT may arrive for a message that
1091
+ * already exists in this.messages (e.g. from initialMessages or a prior
1092
+ * MESSAGES_SNAPSHOT) but whose transient state was cleared. In that case we
1093
+ * hydrate state from the existing message rather than creating a duplicate.
1094
+ */
1095
+ ensureAssistantMessage(preferredId) {
1096
+ if (preferredId) {
1097
+ const state2 = this.getMessageState(preferredId);
1098
+ if (state2) return {
1099
+ messageId: preferredId,
1100
+ state: state2
681
1101
  };
682
1102
  }
683
- let t = this.getActiveAssistantMessageId();
684
- if (t) return {
685
- messageId: t,
686
- state: this.getMessageState(t)
1103
+ const activeId = this.getActiveAssistantMessageId();
1104
+ if (activeId) return {
1105
+ messageId: activeId,
1106
+ state: this.getMessageState(activeId)
687
1107
  };
688
- if (e) {
689
- let t = this.messages.find((t) => t.id === e);
690
- if (t) {
691
- let n = this.createMessageState(e, t.role);
692
- this.activeMessageIds.add(e);
693
- let r = t.parts.length > 0 ? t.parts[t.parts.length - 1] : null;
694
- return r && r.type === "text" && (n.currentSegmentText = r.content, n.lastEmittedText = r.content, n.totalTextContent = r.content), {
695
- messageId: e,
696
- state: n
1108
+ if (preferredId) {
1109
+ const existingMsg = this.messages.find((m) => m.id === preferredId);
1110
+ if (existingMsg) {
1111
+ const state2 = this.createMessageState(preferredId, existingMsg.role);
1112
+ this.activeMessageIds.add(preferredId);
1113
+ const lastPart = existingMsg.parts.length > 0 ? existingMsg.parts[existingMsg.parts.length - 1] : null;
1114
+ if (lastPart && lastPart.type === "text") {
1115
+ state2.currentSegmentText = lastPart.content;
1116
+ state2.lastEmittedText = lastPart.content;
1117
+ state2.totalTextContent = lastPart.content;
1118
+ }
1119
+ return {
1120
+ messageId: preferredId,
1121
+ state: state2
697
1122
  };
698
1123
  }
699
1124
  }
700
- let n = e || generateMessageId(), r = {
701
- id: n,
1125
+ const id = preferredId || generateMessageId();
1126
+ const assistantMessage = {
1127
+ id,
702
1128
  role: "assistant",
703
1129
  parts: [],
704
1130
  createdAt: /* @__PURE__ */ new Date()
705
1131
  };
706
- this.messages = [...this.messages, r];
707
- let i = this.createMessageState(n, "assistant");
708
- return this.activeMessageIds.add(n), this.pendingManualMessageId = n, this.events.onStreamStart?.(), this.emitMessagesChange(), {
709
- messageId: n,
710
- state: i
1132
+ this.messages = [...this.messages, assistantMessage];
1133
+ const state = this.createMessageState(id, "assistant");
1134
+ this.activeMessageIds.add(id);
1135
+ this.pendingManualMessageId = id;
1136
+ this.events.onStreamStart?.();
1137
+ this.emitMessagesChange();
1138
+ return {
1139
+ messageId: id,
1140
+ state
711
1141
  };
712
1142
  }
713
- handleTextMessageStartEvent(e) {
714
- let { messageId: t, role: n } = e, r = n === "user" || n === "system" ? n : "assistant";
1143
+ /**
1144
+ * Handle TEXT_MESSAGE_START event
1145
+ */
1146
+ handleTextMessageStartEvent(chunk) {
1147
+ const { messageId, role } = chunk;
1148
+ const uiRole = role === "user" || role === "system" ? role : "assistant";
715
1149
  if (this.pendingManualMessageId) {
716
- let e = this.pendingManualMessageId;
717
- if (this.pendingManualMessageId = null, e !== t) {
718
- this.messages = this.messages.map((n) => n.id === e ? {
719
- ...n,
720
- id: t
721
- } : n);
722
- let n = this.messageStates.get(e);
723
- n && (n.id = t, this.messageStates.delete(e), this.messageStates.set(t, n)), this.activeMessageIds.delete(e), this.activeMessageIds.add(t);
1150
+ const pendingId = this.pendingManualMessageId;
1151
+ this.pendingManualMessageId = null;
1152
+ if (pendingId !== messageId) {
1153
+ this.messages = this.messages.map((msg) => msg.id === pendingId ? {
1154
+ ...msg,
1155
+ id: messageId
1156
+ } : msg);
1157
+ const existingState = this.messageStates.get(pendingId);
1158
+ if (existingState) {
1159
+ existingState.id = messageId;
1160
+ this.messageStates.delete(pendingId);
1161
+ this.messageStates.set(messageId, existingState);
1162
+ }
1163
+ this.activeMessageIds.delete(pendingId);
1164
+ this.activeMessageIds.add(messageId);
1165
+ }
1166
+ if (!this.messageStates.has(messageId)) {
1167
+ this.createMessageState(messageId, uiRole);
1168
+ this.activeMessageIds.add(messageId);
724
1169
  }
725
- this.messageStates.has(t) || (this.createMessageState(t, r), this.activeMessageIds.add(t)), this.emitMessagesChange();
1170
+ this.emitMessagesChange();
726
1171
  return;
727
1172
  }
728
- if (this.messages.find((e) => e.id === t)) {
729
- if (this.activeMessageIds.add(t), !this.messageStates.has(t)) this.createMessageState(t, r);
1173
+ if (this.messages.find((m) => m.id === messageId)) {
1174
+ this.activeMessageIds.add(messageId);
1175
+ if (!this.messageStates.has(messageId)) this.createMessageState(messageId, uiRole);
730
1176
  else {
731
- let e = this.messageStates.get(t);
732
- e.hasToolCallsSinceTextStart &&= (e.currentSegmentText !== e.lastEmittedText && this.emitTextUpdateForMessage(t), e.currentSegmentText = "", e.lastEmittedText = "", !1);
1177
+ const existingState = this.messageStates.get(messageId);
1178
+ if (existingState.hasToolCallsSinceTextStart) {
1179
+ if (existingState.currentSegmentText !== existingState.lastEmittedText) this.emitTextUpdateForMessage(messageId);
1180
+ existingState.currentSegmentText = "";
1181
+ existingState.lastEmittedText = "";
1182
+ existingState.hasToolCallsSinceTextStart = false;
1183
+ }
733
1184
  }
734
1185
  return;
735
1186
  }
736
- let i = {
737
- id: t,
738
- role: r,
1187
+ const newMessage = {
1188
+ id: messageId,
1189
+ role: uiRole,
739
1190
  parts: [],
740
1191
  createdAt: /* @__PURE__ */ new Date()
741
1192
  };
742
- this.messages = [...this.messages, i], this.createMessageState(t, r), this.activeMessageIds.add(t), this.events.onStreamStart?.(), this.emitMessagesChange();
743
- }
744
- handleTextMessageEndEvent(e) {
745
- let { messageId: t } = e, n = this.getMessageState(t);
746
- n && (n.isComplete || (n.currentSegmentText !== n.lastEmittedText && this.emitTextUpdateForMessage(t), this.completeAllToolCallsForMessage(t)));
747
- }
748
- handleMessagesSnapshotEvent(e) {
749
- this.resetStreamState(), this.messages = [...e.messages], this.emitMessagesChange();
750
- }
751
- handleTextMessageContentEvent(e) {
752
- let { messageId: t, state: n } = this.ensureAssistantMessage(e.messageId);
753
- this.completeAllToolCallsForMessage(t);
754
- let r = n.currentSegmentText;
755
- n.hasToolCallsSinceTextStart && r.length > 0 && this.isNewTextSegment(e, r) && (r !== n.lastEmittedText && this.emitTextUpdateForMessage(t), n.currentSegmentText = "", n.lastEmittedText = "", n.hasToolCallsSinceTextStart = !1);
756
- let i = n.currentSegmentText, a = i, o = e.delta || "";
757
- o === "" ? e.content !== void 0 && e.content !== "" && (a = e.content.startsWith(i) ? e.content : i.startsWith(e.content) ? i : i + e.content) : a = i + o;
758
- let s = a.slice(i.length);
759
- n.currentSegmentText = a, n.totalTextContent += s;
760
- let c = e.delta || e.content || "";
761
- this.chunkStrategy.shouldEmit(c, n.currentSegmentText) && n.currentSegmentText !== n.lastEmittedText && this.emitTextUpdateForMessage(t);
762
- }
763
- handleToolCallStartEvent(e) {
764
- let t = e.parentMessageId ?? this.getActiveAssistantMessageId(), { messageId: n, state: r } = this.ensureAssistantMessage(t ?? void 0);
765
- r.hasToolCallsSinceTextStart = !0;
766
- let i = e.toolCallId;
767
- if (!r.toolCalls.get(i)) {
768
- let t = "awaiting-input", a = e.toolCallName, o = {
769
- id: e.toolCallId,
770
- name: a,
1193
+ this.messages = [...this.messages, newMessage];
1194
+ this.createMessageState(messageId, uiRole);
1195
+ this.activeMessageIds.add(messageId);
1196
+ this.events.onStreamStart?.();
1197
+ this.emitMessagesChange();
1198
+ }
1199
+ /**
1200
+ * Handle TEXT_MESSAGE_END event
1201
+ */
1202
+ handleTextMessageEndEvent(chunk) {
1203
+ const { messageId } = chunk;
1204
+ const state = this.getMessageState(messageId);
1205
+ if (!state) return;
1206
+ if (state.isComplete) return;
1207
+ if (state.currentSegmentText !== state.lastEmittedText) this.emitTextUpdateForMessage(messageId);
1208
+ this.completeAllToolCallsForMessage(messageId);
1209
+ }
1210
+ /**
1211
+ * Handle MESSAGES_SNAPSHOT event
1212
+ */
1213
+ handleMessagesSnapshotEvent(chunk) {
1214
+ this.resetStreamState();
1215
+ this.messages = [...chunk.messages];
1216
+ this.emitMessagesChange();
1217
+ }
1218
+ /**
1219
+ * Handle TEXT_MESSAGE_CONTENT event.
1220
+ *
1221
+ * Accumulates delta into both currentSegmentText (for UI emission) and
1222
+ * totalTextContent (for ProcessorResult). Lazily creates the assistant
1223
+ * UIMessage on first content. Uses updateTextPart() which replaces the
1224
+ * last TextPart or creates a new one depending on part ordering.
1225
+ *
1226
+ * @see docs/chat-architecture.md#single-shot-text-response — Text accumulation step-by-step
1227
+ * @see docs/chat-architecture.md#uimessage-part-ordering-invariants — Replace vs. push logic
1228
+ */
1229
+ handleTextMessageContentEvent(chunk) {
1230
+ const { messageId, state } = this.ensureAssistantMessage(chunk.messageId);
1231
+ this.completeAllToolCallsForMessage(messageId);
1232
+ const previousSegment = state.currentSegmentText;
1233
+ if (state.hasToolCallsSinceTextStart && previousSegment.length > 0 && this.isNewTextSegment(chunk, previousSegment)) {
1234
+ if (previousSegment !== state.lastEmittedText) this.emitTextUpdateForMessage(messageId);
1235
+ state.currentSegmentText = "";
1236
+ state.lastEmittedText = "";
1237
+ state.hasToolCallsSinceTextStart = false;
1238
+ }
1239
+ const currentText = state.currentSegmentText;
1240
+ let nextText = currentText;
1241
+ const delta = chunk.delta || "";
1242
+ if (delta !== "") nextText = currentText + delta;
1243
+ else if (chunk.content !== void 0 && chunk.content !== "") {
1244
+ if (chunk.content.startsWith(currentText)) nextText = chunk.content;
1245
+ else if (currentText.startsWith(chunk.content)) nextText = currentText;
1246
+ else nextText = currentText + chunk.content;
1247
+ }
1248
+ const textDelta = nextText.slice(currentText.length);
1249
+ state.currentSegmentText = nextText;
1250
+ state.totalTextContent += textDelta;
1251
+ const chunkPortion = chunk.delta || chunk.content || "";
1252
+ if (this.chunkStrategy.shouldEmit(chunkPortion, state.currentSegmentText) && state.currentSegmentText !== state.lastEmittedText) this.emitTextUpdateForMessage(messageId);
1253
+ }
1254
+ /**
1255
+ * Handle TOOL_CALL_START event.
1256
+ *
1257
+ * Creates a new InternalToolCallState entry in the toolCalls Map and appends
1258
+ * a ToolCallPart to the UIMessage. Duplicate toolCallId is a no-op.
1259
+ *
1260
+ * CRITICAL: This MUST be received before any TOOL_CALL_ARGS for the same
1261
+ * toolCallId. Args for unknown IDs are silently dropped.
1262
+ *
1263
+ * @see docs/chat-architecture.md#single-shot-tool-call-response — Tool call state transitions
1264
+ * @see docs/chat-architecture.md#parallel-tool-calls-single-shot — Parallel tracking by ID
1265
+ * @see docs/chat-architecture.md#adapter-contract — Ordering requirements
1266
+ */
1267
+ handleToolCallStartEvent(chunk) {
1268
+ const targetMessageId = chunk.parentMessageId ?? this.getActiveAssistantMessageId();
1269
+ const { messageId, state } = this.ensureAssistantMessage(targetMessageId ?? void 0);
1270
+ state.hasToolCallsSinceTextStart = true;
1271
+ const toolCallId = chunk.toolCallId;
1272
+ if (!state.toolCalls.get(toolCallId)) {
1273
+ const initialState = "awaiting-input";
1274
+ const toolName = chunk.toolCallName;
1275
+ const newToolCall = {
1276
+ id: chunk.toolCallId,
1277
+ name: toolName,
771
1278
  arguments: "",
772
- state: t,
1279
+ state: initialState,
773
1280
  parsedArguments: void 0,
774
- index: e.index ?? r.toolCalls.size
1281
+ index: chunk.index ?? state.toolCalls.size
775
1282
  };
776
- r.toolCalls.set(i, o), r.toolCallOrder.push(i), this.toolCallToMessage.set(i, n), this.messages = updateToolCallPart(this.messages, n, {
777
- id: e.toolCallId,
778
- name: a,
1283
+ state.toolCalls.set(toolCallId, newToolCall);
1284
+ state.toolCallOrder.push(toolCallId);
1285
+ this.toolCallToMessage.set(toolCallId, messageId);
1286
+ this.messages = updateToolCallPart(this.messages, messageId, {
1287
+ id: chunk.toolCallId,
1288
+ name: toolName,
779
1289
  arguments: "",
780
- state: t
781
- }), this.emitMessagesChange(), this.events.onToolCallStateChange?.(n, e.toolCallId, t, "");
1290
+ state: initialState
1291
+ });
1292
+ this.emitMessagesChange();
1293
+ this.events.onToolCallStateChange?.(messageId, chunk.toolCallId, initialState, "");
782
1294
  }
783
1295
  }
784
- handleToolCallArgsEvent(e) {
785
- let t = e.toolCallId, n = this.toolCallToMessage.get(t);
786
- if (!n) return;
787
- let r = this.getMessageState(n);
788
- if (!r) return;
789
- let i = r.toolCalls.get(t);
790
- if (!i) return;
791
- let a = i.state === "awaiting-input";
792
- i.arguments += e.delta || "", a && e.delta && (i.state = "input-streaming"), i.parsedArguments = this.jsonParser.parse(i.arguments), this.messages = updateToolCallPart(this.messages, n, {
793
- id: i.id,
794
- name: i.name,
795
- arguments: i.arguments,
796
- state: i.state
797
- }), this.emitMessagesChange(), this.events.onToolCallStateChange?.(n, i.id, i.state, i.arguments);
798
- }
799
- handleToolCallEndEvent(e) {
800
- let t = this.toolCallToMessage.get(e.toolCallId);
801
- if (!t) return;
802
- let n = this.getMessageState(t);
803
- if (!n) return;
804
- let r = n.toolCalls.get(e.toolCallId);
805
- if (r && r.state !== "input-complete") {
806
- e.input !== void 0 && !r.arguments && (r.arguments = JSON.stringify(e.input));
807
- let i = n.toolCallOrder.indexOf(e.toolCallId);
808
- this.completeToolCall(t, i, r), e.input !== void 0 && (r.parsedArguments = e.input);
1296
+ /**
1297
+ * Handle TOOL_CALL_ARGS event.
1298
+ *
1299
+ * Appends the delta to the tool call's accumulated arguments string.
1300
+ * Transitions state from awaiting-input → input-streaming on first non-empty delta.
1301
+ * Attempts partial JSON parse on each update for UI preview.
1302
+ *
1303
+ * If toolCallId is not found in the Map (no preceding TOOL_CALL_START),
1304
+ * this event is silently dropped.
1305
+ *
1306
+ * @see docs/chat-architecture.md#single-shot-tool-call-response — Step-by-step tool call processing
1307
+ */
1308
+ handleToolCallArgsEvent(chunk) {
1309
+ const toolCallId = chunk.toolCallId;
1310
+ const messageId = this.toolCallToMessage.get(toolCallId);
1311
+ if (!messageId) return;
1312
+ const state = this.getMessageState(messageId);
1313
+ if (!state) return;
1314
+ const existingToolCall = state.toolCalls.get(toolCallId);
1315
+ if (!existingToolCall) return;
1316
+ const wasAwaitingInput = existingToolCall.state === "awaiting-input";
1317
+ existingToolCall.arguments += chunk.delta || "";
1318
+ if (wasAwaitingInput && chunk.delta) existingToolCall.state = "input-streaming";
1319
+ existingToolCall.parsedArguments = this.jsonParser.parse(existingToolCall.arguments);
1320
+ this.messages = updateToolCallPart(this.messages, messageId, {
1321
+ id: existingToolCall.id,
1322
+ name: existingToolCall.name,
1323
+ arguments: existingToolCall.arguments,
1324
+ state: existingToolCall.state
1325
+ });
1326
+ this.emitMessagesChange();
1327
+ this.events.onToolCallStateChange?.(messageId, existingToolCall.id, existingToolCall.state, existingToolCall.arguments);
1328
+ }
1329
+ /**
1330
+ * Handle TOOL_CALL_END event — authoritative signal that a tool call's input is finalized.
1331
+ *
1332
+ * This event has a DUAL ROLE:
1333
+ * - Without `result`: Signals arguments are done (from adapter). Transitions to input-complete.
1334
+ * - With `result`: Signals tool was executed and result is available (from TextEngine).
1335
+ * Creates both output on the tool-call part AND a tool-result part.
1336
+ *
1337
+ * If `input` is provided, it overrides the accumulated string parse as the
1338
+ * canonical parsed arguments.
1339
+ *
1340
+ * @see docs/chat-architecture.md#tool-results-and-the-tool_call_end-dual-role — Full explanation
1341
+ * @see docs/chat-architecture.md#single-shot-tool-call-response — End-to-end flow
1342
+ */
1343
+ handleToolCallEndEvent(chunk) {
1344
+ const messageId = this.toolCallToMessage.get(chunk.toolCallId);
1345
+ if (!messageId) return;
1346
+ const msgState = this.getMessageState(messageId);
1347
+ if (!msgState) return;
1348
+ const existingToolCall = msgState.toolCalls.get(chunk.toolCallId);
1349
+ if (existingToolCall && existingToolCall.state !== "input-complete") {
1350
+ if (chunk.input !== void 0 && !existingToolCall.arguments) existingToolCall.arguments = JSON.stringify(chunk.input);
1351
+ const index = msgState.toolCallOrder.indexOf(chunk.toolCallId);
1352
+ this.completeToolCall(messageId, index, existingToolCall);
1353
+ if (chunk.input !== void 0) existingToolCall.parsedArguments = chunk.input;
809
1354
  }
810
- if (e.result) {
811
- let n;
1355
+ if (chunk.result) {
1356
+ let output;
812
1357
  try {
813
- n = JSON.parse(e.result);
1358
+ output = JSON.parse(chunk.result);
814
1359
  } catch {
815
- n = e.result;
1360
+ output = chunk.result;
816
1361
  }
817
- this.messages = updateToolCallWithOutput(this.messages, e.toolCallId, n), this.messages = updateToolResultPart(this.messages, t, e.toolCallId, e.result, "complete"), this.emitMessagesChange();
1362
+ this.messages = updateToolCallWithOutput(this.messages, chunk.toolCallId, output);
1363
+ const resultState = "complete";
1364
+ this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, chunk.result, resultState);
1365
+ this.emitMessagesChange();
818
1366
  }
819
1367
  }
820
- handleToolCallResultEvent(e) {
821
- let t = this.toolCallToMessage.get(e.toolCallId);
822
- if (!t) return;
823
- let n;
1368
+ /**
1369
+ * Handle TOOL_CALL_RESULT event (AG-UI spec).
1370
+ *
1371
+ * Creates a tool-result part and updates the tool-call output field,
1372
+ * mirroring the logic from TOOL_CALL_END when it carries a result.
1373
+ * This is the spec-compliant path for delivering tool results to the client.
1374
+ */
1375
+ handleToolCallResultEvent(chunk) {
1376
+ const messageId = this.toolCallToMessage.get(chunk.toolCallId);
1377
+ if (!messageId) return;
1378
+ let output;
824
1379
  try {
825
- n = JSON.parse(e.content);
1380
+ output = JSON.parse(chunk.content);
826
1381
  } catch {
827
- n = e.content;
1382
+ output = chunk.content;
1383
+ }
1384
+ this.messages = updateToolCallWithOutput(this.messages, chunk.toolCallId, output);
1385
+ const resultState = "complete";
1386
+ this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, chunk.content, resultState);
1387
+ this.emitMessagesChange();
1388
+ }
1389
+ /**
1390
+ * Handle RUN_STARTED event.
1391
+ *
1392
+ * Registers the run so that RUN_FINISHED can determine whether other
1393
+ * runs are still active before finalizing.
1394
+ */
1395
+ handleRunStartedEvent(chunk) {
1396
+ this.activeRuns.add(chunk.runId);
1397
+ }
1398
+ /**
1399
+ * Handle RUN_FINISHED event.
1400
+ *
1401
+ * Records the finishReason and removes the run from activeRuns.
1402
+ * Only finalizes when no more runs are active, so that concurrent
1403
+ * runs don't interfere with each other.
1404
+ *
1405
+ * @see docs/chat-architecture.md#single-shot-tool-call-response — finishReason semantics
1406
+ * @see docs/chat-architecture.md#adapter-contract — Why RUN_FINISHED is mandatory
1407
+ */
1408
+ handleRunFinishedEvent(chunk) {
1409
+ this.finishReason = chunk.finishReason ?? null;
1410
+ this.activeRuns.delete(chunk.runId);
1411
+ if (this.activeRuns.size === 0) {
1412
+ this.isDone = true;
1413
+ this.completeAllToolCalls();
1414
+ this.finalizeStream();
828
1415
  }
829
- this.messages = updateToolCallWithOutput(this.messages, e.toolCallId, n), this.messages = updateToolResultPart(this.messages, t, e.toolCallId, e.content, "complete"), this.emitMessagesChange();
830
- }
831
- handleRunStartedEvent(e) {
832
- this.activeRuns.add(e.runId);
833
- }
834
- handleRunFinishedEvent(e) {
835
- this.finishReason = e.finishReason ?? null, this.activeRuns.delete(e.runId), this.activeRuns.size === 0 && (this.isDone = !0, this.completeAllToolCalls(), this.finalizeStream());
836
- }
837
- handleRunErrorEvent(e) {
838
- this.hasError = !0;
839
- let t = e.runId;
840
- t ? this.activeRuns.delete(t) : this.activeRuns.clear(), this.ensureAssistantMessage();
841
- let n = e.message || e.error?.message || "An error occurred";
842
- this.events.onError?.(Error(n));
843
- }
844
- handleStepFinishedEvent(e) {
845
- let { messageId: t, state: n } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
846
- if (n.hasSeenReasoningEvents) return;
847
- let r = n.thinkingContent, i = r;
848
- e.delta && e.delta !== "" ? i = r + e.delta : e.content && e.content !== "" && (i = e.content.startsWith(r) ? e.content : r.startsWith(e.content) ? r : r + e.content), n.thinkingContent = i, this.messages = updateThinkingPart(this.messages, t, n.thinkingContent), this.emitMessagesChange(), this.events.onThinkingUpdate?.(t, n.thinkingContent);
849
- }
850
- handleReasoningMessageContentEvent(e) {
851
- let { messageId: t, state: n } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
852
- n.hasSeenReasoningEvents = !0;
853
- let r = e.delta || "";
854
- n.thinkingContent += r, this.messages = updateThinkingPart(this.messages, t, n.thinkingContent), this.emitMessagesChange(), this.events.onThinkingUpdate?.(t, n.thinkingContent);
855
- }
856
- handleCustomEvent(e) {
857
- let t = this.getActiveAssistantMessageId();
858
- if (e.name === "tool-input-available" && e.value) {
859
- let { toolCallId: t, toolName: n, input: r } = e.value;
1416
+ }
1417
+ /**
1418
+ * Handle RUN_ERROR event
1419
+ */
1420
+ handleRunErrorEvent(chunk) {
1421
+ this.hasError = true;
1422
+ const runId = chunk.runId;
1423
+ if (runId) this.activeRuns.delete(runId);
1424
+ else this.activeRuns.clear();
1425
+ this.ensureAssistantMessage();
1426
+ const errorMessage = chunk.message || chunk.error?.message || "An error occurred";
1427
+ this.events.onError?.(new Error(errorMessage));
1428
+ }
1429
+ /**
1430
+ * Handle STEP_FINISHED event (for thinking/reasoning content).
1431
+ *
1432
+ * Accumulates delta into thinkingContent and updates a single ThinkingPart
1433
+ * in the UIMessage (replaced in-place, not appended).
1434
+ *
1435
+ * @see docs/chat-architecture.md#thinkingreasoning-content — Thinking flow
1436
+ */
1437
+ handleStepFinishedEvent(chunk) {
1438
+ const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
1439
+ if (state.hasSeenReasoningEvents) return;
1440
+ const previous = state.thinkingContent;
1441
+ let nextThinking = previous;
1442
+ if (chunk.delta && chunk.delta !== "") nextThinking = previous + chunk.delta;
1443
+ else if (chunk.content && chunk.content !== "") {
1444
+ if (chunk.content.startsWith(previous)) nextThinking = chunk.content;
1445
+ else if (previous.startsWith(chunk.content)) nextThinking = previous;
1446
+ else nextThinking = previous + chunk.content;
1447
+ }
1448
+ state.thinkingContent = nextThinking;
1449
+ this.messages = updateThinkingPart(this.messages, messageId, state.thinkingContent);
1450
+ this.emitMessagesChange();
1451
+ this.events.onThinkingUpdate?.(messageId, state.thinkingContent);
1452
+ }
1453
+ /**
1454
+ * Handle REASONING_MESSAGE_CONTENT event (AG-UI reasoning protocol).
1455
+ *
1456
+ * Accumulates reasoning delta into thinkingContent and updates the ThinkingPart
1457
+ * in the UIMessage.
1458
+ */
1459
+ handleReasoningMessageContentEvent(chunk) {
1460
+ const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
1461
+ state.hasSeenReasoningEvents = true;
1462
+ const delta = chunk.delta || "";
1463
+ state.thinkingContent = state.thinkingContent + delta;
1464
+ this.messages = updateThinkingPart(this.messages, messageId, state.thinkingContent);
1465
+ this.emitMessagesChange();
1466
+ this.events.onThinkingUpdate?.(messageId, state.thinkingContent);
1467
+ }
1468
+ /**
1469
+ * Handle CUSTOM event.
1470
+ *
1471
+ * Handles special custom events emitted by the TextEngine (not adapters):
1472
+ * - 'tool-input-available': Client tool needs execution. Fires onToolCall.
1473
+ * - 'approval-requested': Tool needs user approval. Updates tool-call part
1474
+ * state and fires onApprovalRequest.
1475
+ *
1476
+ * @see docs/chat-architecture.md#client-tools-and-approval-flows — Full flow details
1477
+ */
1478
+ handleCustomEvent(chunk) {
1479
+ const messageId = this.getActiveAssistantMessageId();
1480
+ if (chunk.name === "tool-input-available" && chunk.value) {
1481
+ const { toolCallId, toolName, input } = chunk.value;
860
1482
  this.events.onToolCall?.({
861
- toolCallId: t,
862
- toolName: n,
863
- input: r
1483
+ toolCallId,
1484
+ toolName,
1485
+ input
864
1486
  });
865
1487
  return;
866
1488
  }
867
- if (e.name === "approval-requested" && e.value) {
868
- let { toolCallId: n, toolName: r, input: i, approval: a } = e.value, o = t ?? this.toolCallToMessage.get(n);
869
- o && (this.messages = updateToolCallApproval(this.messages, o, n, a.id), this.emitMessagesChange()), this.events.onApprovalRequest?.({
870
- toolCallId: n,
871
- toolName: r,
872
- input: i,
873
- approvalId: a.id
1489
+ if (chunk.name === "approval-requested" && chunk.value) {
1490
+ const { toolCallId, toolName, input, approval } = chunk.value;
1491
+ const resolvedMessageId = messageId ?? this.toolCallToMessage.get(toolCallId);
1492
+ if (resolvedMessageId) {
1493
+ this.messages = updateToolCallApproval(this.messages, resolvedMessageId, toolCallId, approval.id);
1494
+ this.emitMessagesChange();
1495
+ }
1496
+ this.events.onApprovalRequest?.({
1497
+ toolCallId,
1498
+ toolName,
1499
+ input,
1500
+ approvalId: approval.id
874
1501
  });
875
1502
  return;
876
1503
  }
877
1504
  if (this.events.onCustomEvent) {
878
- let t = e.value && typeof e.value == "object" ? e.value.toolCallId : void 0;
879
- this.events.onCustomEvent(e.name, e.value, { toolCallId: t });
1505
+ const toolCallId = chunk.value && typeof chunk.value === "object" ? chunk.value.toolCallId : void 0;
1506
+ this.events.onCustomEvent(chunk.name, chunk.value, { toolCallId });
880
1507
  }
881
1508
  }
882
- isNewTextSegment(e, t) {
883
- return e.content !== void 0 && (e.content.length < t.length || !e.content.startsWith(t) && !t.startsWith(e.content));
884
- }
1509
+ /**
1510
+ * Detect if an incoming content chunk represents a NEW text segment
1511
+ */
1512
+ isNewTextSegment(chunk, previous) {
1513
+ if (chunk.content !== void 0) {
1514
+ if (chunk.content.length < previous.length) return true;
1515
+ if (!chunk.content.startsWith(previous) && !previous.startsWith(chunk.content)) return true;
1516
+ }
1517
+ return false;
1518
+ }
1519
+ /**
1520
+ * Complete all tool calls across all active messages — safety net for stream termination.
1521
+ *
1522
+ * Called by RUN_FINISHED and finalizeStream(). Force-transitions any tool call
1523
+ * not yet in input-complete state. Handles cases where TOOL_CALL_END was
1524
+ * missed (adapter bug, network error, aborted stream).
1525
+ *
1526
+ * @see docs/chat-architecture.md#single-shot-tool-call-response — Safety net behavior
1527
+ */
885
1528
  completeAllToolCalls() {
886
- for (let e of this.activeMessageIds) this.completeAllToolCallsForMessage(e);
887
- }
888
- completeAllToolCallsForMessage(e) {
889
- let t = this.getMessageState(e);
890
- t && t.toolCalls.forEach((n, r) => {
891
- if (n.state !== "input-complete") {
892
- let i = t.toolCallOrder.indexOf(r);
893
- this.completeToolCall(e, i, n);
1529
+ for (const messageId of this.activeMessageIds) this.completeAllToolCallsForMessage(messageId);
1530
+ }
1531
+ /**
1532
+ * Complete all tool calls for a specific message
1533
+ */
1534
+ completeAllToolCallsForMessage(messageId) {
1535
+ const state = this.getMessageState(messageId);
1536
+ if (!state) return;
1537
+ state.toolCalls.forEach((toolCall, id) => {
1538
+ if (toolCall.state !== "input-complete") {
1539
+ const index = state.toolCallOrder.indexOf(id);
1540
+ this.completeToolCall(messageId, index, toolCall);
894
1541
  }
895
1542
  });
896
1543
  }
897
- completeToolCall(e, t, n) {
898
- n.state = "input-complete", n.parsedArguments = this.jsonParser.parse(n.arguments), this.messages = updateToolCallPart(this.messages, e, {
899
- id: n.id,
900
- name: n.name,
901
- arguments: n.arguments,
1544
+ /**
1545
+ * Mark a tool call as complete and emit event
1546
+ */
1547
+ completeToolCall(messageId, _index, toolCall) {
1548
+ toolCall.state = "input-complete";
1549
+ toolCall.parsedArguments = this.jsonParser.parse(toolCall.arguments);
1550
+ this.messages = updateToolCallPart(this.messages, messageId, {
1551
+ id: toolCall.id,
1552
+ name: toolCall.name,
1553
+ arguments: toolCall.arguments,
902
1554
  state: "input-complete"
903
- }), this.emitMessagesChange(), this.events.onToolCallStateChange?.(e, n.id, "input-complete", n.arguments);
904
- }
905
- emitTextUpdateForMessage(e) {
906
- let t = this.getMessageState(e);
907
- t && (t.lastEmittedText = t.currentSegmentText, this.messages = updateTextPart(this.messages, e, t.currentSegmentText), this.emitMessagesChange(), this.events.onTextUpdate?.(e, t.currentSegmentText));
908
- }
1555
+ });
1556
+ this.emitMessagesChange();
1557
+ this.events.onToolCallStateChange?.(messageId, toolCall.id, "input-complete", toolCall.arguments);
1558
+ }
1559
+ /**
1560
+ * Emit pending text update for a specific message.
1561
+ *
1562
+ * Calls updateTextPart() which has critical append-vs-replace logic:
1563
+ * - If last UIMessage part is TextPart → replaces its content (same segment).
1564
+ * - If last part is anything else → pushes new TextPart (new segment after tools).
1565
+ *
1566
+ * @see docs/chat-architecture.md#uimessage-part-ordering-invariants — Replace vs. push logic
1567
+ */
1568
+ emitTextUpdateForMessage(messageId) {
1569
+ const state = this.getMessageState(messageId);
1570
+ if (!state) return;
1571
+ state.lastEmittedText = state.currentSegmentText;
1572
+ this.messages = updateTextPart(this.messages, messageId, state.currentSegmentText);
1573
+ this.emitMessagesChange();
1574
+ this.events.onTextUpdate?.(messageId, state.currentSegmentText);
1575
+ }
1576
+ /**
1577
+ * Emit messages change event
1578
+ */
909
1579
  emitMessagesChange() {
910
1580
  this.events.onMessagesChange?.([...this.messages]);
911
1581
  }
1582
+ /**
1583
+ * Finalize the stream — complete all pending operations.
1584
+ *
1585
+ * Called when the async iterable ends (stream closed). Acts as the final
1586
+ * safety net: completes any remaining tool calls, flushes un-emitted text,
1587
+ * and fires onStreamEnd.
1588
+ *
1589
+ * @see docs/chat-architecture.md#single-shot-text-response — Finalization step
1590
+ */
912
1591
  finalizeStream() {
913
- let e;
914
- for (let t of this.activeMessageIds) {
915
- let n = this.getMessageState(t);
916
- if (!n) continue;
917
- this.completeAllToolCallsForMessage(t), n.currentSegmentText !== n.lastEmittedText && this.emitTextUpdateForMessage(t), n.isComplete = !0;
918
- let r = this.messages.find((e) => e.id === t);
919
- r && r.role === "assistant" && (e = r);
1592
+ let lastAssistantMessage;
1593
+ for (const messageId of this.activeMessageIds) {
1594
+ const state = this.getMessageState(messageId);
1595
+ if (!state) continue;
1596
+ this.completeAllToolCallsForMessage(messageId);
1597
+ if (state.currentSegmentText !== state.lastEmittedText) this.emitTextUpdateForMessage(messageId);
1598
+ state.isComplete = true;
1599
+ const msg = this.messages.find((m) => m.id === messageId);
1600
+ if (msg && msg.role === "assistant") lastAssistantMessage = msg;
920
1601
  }
921
- if (this.activeMessageIds.clear(), e && !this.hasError && this.isWhitespaceOnlyMessage(e)) {
922
- this.messages = this.messages.filter((t) => t.id !== e.id), this.emitMessagesChange();
923
- return;
1602
+ this.activeMessageIds.clear();
1603
+ if (lastAssistantMessage && !this.hasError) {
1604
+ if (this.isWhitespaceOnlyMessage(lastAssistantMessage)) {
1605
+ this.messages = this.messages.filter((m) => m.id !== lastAssistantMessage.id);
1606
+ this.emitMessagesChange();
1607
+ return;
1608
+ }
924
1609
  }
925
- e && this.events.onStreamEnd?.(e);
1610
+ if (lastAssistantMessage) this.events.onStreamEnd?.(lastAssistantMessage);
926
1611
  }
1612
+ /**
1613
+ * Get completed tool calls in API format (aggregated across all messages)
1614
+ */
927
1615
  getCompletedToolCalls() {
928
- let e = [];
929
- for (let t of this.messageStates.values()) for (let n of t.toolCalls.values()) n.state === "input-complete" && e.push({
930
- id: n.id,
1616
+ const result = [];
1617
+ for (const state of this.messageStates.values()) for (const tc of state.toolCalls.values()) if (tc.state === "input-complete") result.push({
1618
+ id: tc.id,
931
1619
  type: "function",
932
1620
  function: {
933
- name: n.name,
934
- arguments: n.arguments
1621
+ name: tc.name,
1622
+ arguments: tc.arguments
935
1623
  }
936
1624
  });
937
- return e;
1625
+ return result;
938
1626
  }
1627
+ /**
1628
+ * Get current result (aggregated across all messages)
1629
+ */
939
1630
  getResult() {
940
- let e = this.getCompletedToolCalls(), t = "", n = "";
941
- for (let e of this.messageStates.values()) t += e.totalTextContent, n += e.thinkingContent;
1631
+ const toolCalls = this.getCompletedToolCalls();
1632
+ let content = "";
1633
+ let thinking = "";
1634
+ for (const state of this.messageStates.values()) {
1635
+ content += state.totalTextContent;
1636
+ thinking += state.thinkingContent;
1637
+ }
942
1638
  return {
943
- content: t,
944
- thinking: n || void 0,
945
- toolCalls: e.length > 0 ? e : void 0,
1639
+ content,
1640
+ thinking: thinking || void 0,
1641
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
946
1642
  finishReason: this.finishReason
947
1643
  };
948
1644
  }
1645
+ /**
1646
+ * Get current processor state (aggregated across all messages)
1647
+ */
949
1648
  getState() {
950
- let e = "", t = "", n = /* @__PURE__ */ new Map(), r = [];
951
- for (let i of this.messageStates.values()) {
952
- e += i.totalTextContent, t += i.thinkingContent;
953
- for (let [e, t] of i.toolCalls) n.set(e, t);
954
- r.push(...i.toolCallOrder);
1649
+ let content = "";
1650
+ let thinking = "";
1651
+ const toolCalls = /* @__PURE__ */ new Map();
1652
+ const toolCallOrder = [];
1653
+ for (const state of this.messageStates.values()) {
1654
+ content += state.totalTextContent;
1655
+ thinking += state.thinkingContent;
1656
+ for (const [id, tc] of state.toolCalls) toolCalls.set(id, tc);
1657
+ toolCallOrder.push(...state.toolCallOrder);
955
1658
  }
956
1659
  return {
957
- content: e,
958
- thinking: t,
959
- toolCalls: n,
960
- toolCallOrder: r,
1660
+ content,
1661
+ thinking,
1662
+ toolCalls,
1663
+ toolCallOrder,
961
1664
  finishReason: this.finishReason,
962
1665
  done: this.isDone
963
1666
  };
964
1667
  }
1668
+ /**
1669
+ * Start recording chunks
1670
+ */
965
1671
  startRecording() {
966
- this.recordingEnabled = !0, this.recordingStartTime = Date.now(), this.recording = {
1672
+ this.recordingEnabled = true;
1673
+ this.recordingStartTime = Date.now();
1674
+ this.recording = {
967
1675
  version: "1.0",
968
1676
  timestamp: this.recordingStartTime,
969
1677
  chunks: []
970
1678
  };
971
1679
  }
1680
+ /**
1681
+ * Get the current recording
1682
+ */
972
1683
  getRecording() {
973
1684
  return this.recording;
974
1685
  }
1686
+ /**
1687
+ * Reset stream state (but keep messages)
1688
+ */
975
1689
  resetStreamState() {
976
- this.messageStates.clear(), this.activeMessageIds.clear(), this.activeRuns.clear(), this.toolCallToMessage.clear(), this.pendingManualMessageId = null, this.finishReason = null, this.hasError = !1, this.isDone = !1, this.chunkStrategy.reset?.();
977
- }
1690
+ this.messageStates.clear();
1691
+ this.activeMessageIds.clear();
1692
+ this.activeRuns.clear();
1693
+ this.toolCallToMessage.clear();
1694
+ this.pendingManualMessageId = null;
1695
+ this.finishReason = null;
1696
+ this.hasError = false;
1697
+ this.isDone = false;
1698
+ this.chunkStrategy.reset?.();
1699
+ }
1700
+ /**
1701
+ * Full reset (including messages)
1702
+ */
978
1703
  reset() {
979
- this.resetStreamState(), this.messages = [];
980
- }
981
- isWhitespaceOnlyMessage(e) {
982
- return e.parts.length !== 0 && e.parts.every((e) => e.type === "text" && e.content.trim() === "");
983
- }
984
- static async replay(e, t) {
985
- return new StreamProcessor(t).process(createReplayStream(e));
1704
+ this.resetStreamState();
1705
+ this.messages = [];
1706
+ }
1707
+ /**
1708
+ * Check if a message contains only whitespace text and no other meaningful parts
1709
+ * (no tool calls, tool results, thinking, etc.)
1710
+ */
1711
+ isWhitespaceOnlyMessage(message) {
1712
+ if (message.parts.length === 0) return false;
1713
+ return message.parts.every((part) => part.type === "text" && part.content.trim() === "");
1714
+ }
1715
+ /**
1716
+ * Replay a recording through the processor
1717
+ */
1718
+ static async replay(recording, options) {
1719
+ return new StreamProcessor(options).process(createReplayStream(recording));
986
1720
  }
987
1721
  };
988
- function createReplayStream(e) {
1722
+ function createReplayStream(recording) {
989
1723
  return { async *[Symbol.asyncIterator]() {
990
- for (let { chunk: t } of e.chunks) yield t;
1724
+ for (const { chunk } of recording.chunks) yield chunk;
991
1725
  } };
992
1726
  }
993
1727
  //#endregion
994
1728
  //#region ../../node_modules/.pnpm/@tanstack+ai-client@0.8.0/node_modules/@tanstack/ai-client/dist/esm/events.js
995
1729
  var ChatClientEventEmitter = class {
996
- constructor(e) {
997
- this.clientId = e;
998
- }
999
- clientCreated(e) {
1000
- this.emitEvent("client:created", { initialMessageCount: e });
1001
- }
1002
- loadingChanged(e) {
1003
- this.emitEvent("client:loading:changed", { isLoading: e });
1004
- }
1005
- errorChanged(e) {
1006
- this.emitEvent("client:error:changed", { error: e });
1007
- }
1008
- textUpdated(e, t, n) {
1730
+ constructor(clientId) {
1731
+ this.clientId = clientId;
1732
+ }
1733
+ /**
1734
+ * Emit client created event
1735
+ */
1736
+ clientCreated(initialMessageCount) {
1737
+ this.emitEvent("client:created", { initialMessageCount });
1738
+ }
1739
+ /**
1740
+ * Emit loading state changed event
1741
+ */
1742
+ loadingChanged(isLoading) {
1743
+ this.emitEvent("client:loading:changed", { isLoading });
1744
+ }
1745
+ /**
1746
+ * Emit error state changed event
1747
+ */
1748
+ errorChanged(error) {
1749
+ this.emitEvent("client:error:changed", { error });
1750
+ }
1751
+ /**
1752
+ * Emit text update events (combines processor and client events)
1753
+ */
1754
+ textUpdated(streamId, messageId, content) {
1009
1755
  this.emitEvent("text:chunk:content", {
1010
- streamId: e,
1011
- messageId: t,
1012
- content: n
1756
+ streamId,
1757
+ messageId,
1758
+ content
1013
1759
  });
1014
1760
  }
1015
- toolCallStateChanged(e, t, n, r, i, a) {
1761
+ /**
1762
+ * Emit tool call state change events (combines processor and client events)
1763
+ */
1764
+ toolCallStateChanged(streamId, messageId, toolCallId, toolName, state, args) {
1016
1765
  this.emitEvent("tools:call:updated", {
1017
- streamId: e,
1018
- messageId: t,
1019
- toolCallId: n,
1020
- toolName: r,
1021
- state: i,
1022
- arguments: a
1766
+ streamId,
1767
+ messageId,
1768
+ toolCallId,
1769
+ toolName,
1770
+ state,
1771
+ arguments: args
1023
1772
  });
1024
1773
  }
1025
- thinkingUpdated(e, t, n, r) {
1774
+ /**
1775
+ * Emit tool result state change event
1776
+ */
1777
+ /**
1778
+ * Emit thinking update event
1779
+ */
1780
+ thinkingUpdated(streamId, messageId, content, delta) {
1026
1781
  this.emitEvent("text:chunk:thinking", {
1027
- streamId: e,
1028
- messageId: t,
1029
- content: n,
1030
- delta: r
1782
+ streamId,
1783
+ messageId,
1784
+ content,
1785
+ delta
1031
1786
  });
1032
1787
  }
1033
- approvalRequested(e, t, n, r, i, a) {
1788
+ /**
1789
+ * Emit approval requested event
1790
+ */
1791
+ approvalRequested(streamId, messageId, toolCallId, toolName, input, approvalId) {
1034
1792
  this.emitEvent("tools:approval:requested", {
1035
- streamId: e,
1036
- messageId: t,
1037
- toolCallId: n,
1038
- toolName: r,
1039
- input: i,
1040
- approvalId: a
1793
+ streamId,
1794
+ messageId,
1795
+ toolCallId,
1796
+ toolName,
1797
+ input,
1798
+ approvalId
1041
1799
  });
1042
1800
  }
1043
- messageAppended(e, t) {
1044
- let n = e.parts.filter((e) => e.type === "text").map((e) => e.content).join(" ");
1801
+ /**
1802
+ * Emit message appended event
1803
+ */
1804
+ messageAppended(uiMessage, streamId) {
1805
+ const content = uiMessage.parts.filter((part) => part.type === "text").map((part) => part.content).join(" ");
1045
1806
  this.emitEvent("text:message:created", {
1046
- streamId: t,
1047
- messageId: e.id,
1048
- role: e.role,
1049
- content: n,
1050
- parts: e.parts
1807
+ streamId,
1808
+ messageId: uiMessage.id,
1809
+ role: uiMessage.role,
1810
+ content,
1811
+ parts: uiMessage.parts
1051
1812
  });
1052
1813
  }
1053
- messageSent(e, t) {
1054
- let n = typeof t == "string" ? t : t.filter((e) => e.type === "text").map((e) => e.content).join("");
1814
+ /**
1815
+ * Emit message sent event.
1816
+ * Supports both simple string content and multimodal content arrays.
1817
+ *
1818
+ * @param messageId - The ID of the sent message
1819
+ * @param content - The message content (string or array of ContentPart for multimodal)
1820
+ */
1821
+ messageSent(messageId, content) {
1822
+ const textContent = typeof content === "string" ? content : content.filter((part) => part.type === "text").map((part) => part.content).join("");
1055
1823
  this.emitEvent("text:message:created", {
1056
- messageId: e,
1824
+ messageId,
1057
1825
  role: "user",
1058
- content: n,
1059
- ...Array.isArray(t) && { parts: t }
1060
- }), this.emitEvent("text:message:user", {
1061
- messageId: e,
1826
+ content: textContent,
1827
+ ...Array.isArray(content) && { parts: content }
1828
+ });
1829
+ this.emitEvent("text:message:user", {
1830
+ messageId,
1062
1831
  role: "user",
1063
- content: n,
1064
- ...Array.isArray(t) && { parts: t }
1832
+ content: textContent,
1833
+ ...Array.isArray(content) && { parts: content }
1065
1834
  });
1066
1835
  }
1067
- reloaded(e) {
1068
- this.emitEvent("client:reloaded", { fromMessageIndex: e });
1836
+ /**
1837
+ * Emit reloaded event
1838
+ */
1839
+ reloaded(fromMessageIndex) {
1840
+ this.emitEvent("client:reloaded", { fromMessageIndex });
1069
1841
  }
1842
+ /**
1843
+ * Emit stopped event
1844
+ */
1070
1845
  stopped() {
1071
1846
  this.emitEvent("client:stopped");
1072
1847
  }
1848
+ /**
1849
+ * Emit messages cleared event
1850
+ */
1073
1851
  messagesCleared() {
1074
1852
  this.emitEvent("client:messages:cleared");
1075
1853
  }
1076
- toolResultAdded(e, t, n, r) {
1854
+ /**
1855
+ * Emit tool result added event
1856
+ */
1857
+ toolResultAdded(toolCallId, toolName, output, state) {
1077
1858
  this.emitEvent("tools:result:added", {
1078
- toolCallId: e,
1079
- toolName: t,
1080
- output: n,
1081
- state: r
1859
+ toolCallId,
1860
+ toolName,
1861
+ output,
1862
+ state
1082
1863
  });
1083
1864
  }
1084
- toolApprovalResponded(e, t, n) {
1865
+ /**
1866
+ * Emit tool approval responded event
1867
+ */
1868
+ toolApprovalResponded(approvalId, toolCallId, approved) {
1085
1869
  this.emitEvent("tools:approval:responded", {
1086
- approvalId: e,
1087
- toolCallId: t,
1088
- approved: n
1870
+ approvalId,
1871
+ toolCallId,
1872
+ approved
1089
1873
  });
1090
1874
  }
1091
- }, DefaultChatClientEventEmitter = class extends ChatClientEventEmitter {
1092
- emitEvent(e, t) {
1093
- e.startsWith("client:") || e.startsWith("tools:") || e.startsWith("text:") ? d.emit(e, {
1094
- ...t,
1875
+ };
1876
+ var DefaultChatClientEventEmitter = class extends ChatClientEventEmitter {
1877
+ /**
1878
+ * Emit an event with automatic clientId and timestamp for client/tool events
1879
+ */
1880
+ emitEvent(eventName, data) {
1881
+ if (eventName.startsWith("client:") || eventName.startsWith("tools:") || eventName.startsWith("text:")) aiEventClient.emit(eventName, {
1882
+ ...data,
1095
1883
  clientId: this.clientId,
1096
1884
  source: "client",
1097
1885
  timestamp: Date.now()
1098
- }) : d.emit(e, {
1099
- ...t,
1886
+ });
1887
+ else aiEventClient.emit(eventName, {
1888
+ ...data,
1100
1889
  timestamp: Date.now()
1101
1890
  });
1102
1891
  }
1103
1892
  };
1104
1893
  //#endregion
1105
1894
  //#region ../../node_modules/.pnpm/@tanstack+ai-client@0.8.0/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
1106
- function mergeHeaders(e) {
1107
- if (!e) return {};
1108
- if (e instanceof Headers) {
1109
- let t = {};
1110
- return e.forEach((e, n) => {
1111
- t[n] = e;
1112
- }), t;
1113
- }
1114
- return e;
1895
+ function mergeHeaders(customHeaders) {
1896
+ if (!customHeaders) return {};
1897
+ if (customHeaders instanceof Headers) {
1898
+ const result = {};
1899
+ customHeaders.forEach((value, key) => {
1900
+ result[key] = value;
1901
+ });
1902
+ return result;
1903
+ }
1904
+ return customHeaders;
1115
1905
  }
1116
- async function* readStreamLines(e, t) {
1906
+ async function* readStreamLines(reader, abortSignal) {
1117
1907
  try {
1118
- let n = new TextDecoder(), r = "";
1119
- for (; !t?.aborted;) {
1120
- let { done: t, value: i } = await e.read();
1121
- if (t) break;
1122
- r += n.decode(i, { stream: !0 });
1123
- let a = r.split("\n");
1124
- r = a.pop() || "";
1125
- for (let e of a) e.trim() && (yield e);
1908
+ const decoder = new TextDecoder();
1909
+ let buffer = "";
1910
+ while (true) {
1911
+ if (abortSignal?.aborted) break;
1912
+ const { done, value } = await reader.read();
1913
+ if (done) break;
1914
+ buffer += decoder.decode(value, { stream: true });
1915
+ const lines = buffer.split("\n");
1916
+ buffer = lines.pop() || "";
1917
+ for (const line of lines) if (line.trim()) yield line;
1126
1918
  }
1127
- r.trim() && (yield r);
1919
+ if (buffer.trim()) yield buffer;
1128
1920
  } finally {
1129
- e.releaseLock();
1921
+ reader.releaseLock();
1130
1922
  }
1131
1923
  }
1132
- function normalizeConnectionAdapter(e) {
1133
- if (!e) throw Error("Connection adapter is required");
1134
- let t = "connect" in e, n = "subscribe" in e, r = "send" in e;
1135
- if (t && (n || r)) throw Error("Connection adapter must provide either connect or both subscribe and send, not both modes");
1136
- if (n && r) return {
1137
- subscribe: e.subscribe.bind(e),
1138
- send: e.send.bind(e)
1924
+ function normalizeConnectionAdapter(connection) {
1925
+ if (!connection) throw new Error("Connection adapter is required");
1926
+ const hasConnect = "connect" in connection;
1927
+ const hasSubscribe = "subscribe" in connection;
1928
+ const hasSend = "send" in connection;
1929
+ if (hasConnect && (hasSubscribe || hasSend)) throw new Error("Connection adapter must provide either connect or both subscribe and send, not both modes");
1930
+ if (hasSubscribe && hasSend) return {
1931
+ subscribe: connection.subscribe.bind(connection),
1932
+ send: connection.send.bind(connection)
1139
1933
  };
1140
- if (!t) throw Error("Connection adapter must provide either connect or both subscribe and send");
1141
- let i = [], a = [];
1142
- function push(e) {
1143
- let t = a.shift();
1144
- t ? t(e) : i.push(e);
1934
+ if (!hasConnect) throw new Error("Connection adapter must provide either connect or both subscribe and send");
1935
+ let activeBuffer = [];
1936
+ let activeWaiters = [];
1937
+ function push(chunk) {
1938
+ const waiter = activeWaiters.shift();
1939
+ if (waiter) waiter(chunk);
1940
+ else activeBuffer.push(chunk);
1145
1941
  }
1146
1942
  return {
1147
- subscribe(e) {
1148
- let t = i.splice(0), n = [];
1149
- return i = t, a = n, (async function* () {
1150
- for (; !e?.aborted;) {
1151
- let r;
1152
- r = t.length > 0 ? t.shift() : await new Promise((t) => {
1153
- let onAbort = () => t(null);
1154
- n.push((n) => {
1155
- e?.removeEventListener("abort", onAbort), t(n);
1156
- }), e?.addEventListener("abort", onAbort, { once: !0 });
1157
- }), r !== null && (yield r);
1943
+ subscribe(abortSignal) {
1944
+ const myBuffer = activeBuffer.splice(0);
1945
+ const myWaiters = [];
1946
+ activeBuffer = myBuffer;
1947
+ activeWaiters = myWaiters;
1948
+ return (async function* () {
1949
+ while (!abortSignal?.aborted) {
1950
+ let chunk;
1951
+ if (myBuffer.length > 0) chunk = myBuffer.shift();
1952
+ else chunk = await new Promise((resolve) => {
1953
+ const onAbort = () => resolve(null);
1954
+ myWaiters.push((c) => {
1955
+ abortSignal?.removeEventListener("abort", onAbort);
1956
+ resolve(c);
1957
+ });
1958
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
1959
+ });
1960
+ if (chunk !== null) yield chunk;
1158
1961
  }
1159
1962
  })();
1160
1963
  },
1161
- async send(t, n, r) {
1162
- let i = !1;
1964
+ async send(messages, data, abortSignal) {
1965
+ let hasTerminalEvent = false;
1163
1966
  try {
1164
- let a = e.connect(t, n, r);
1165
- for await (let e of a) (e.type === "RUN_FINISHED" || e.type === "RUN_ERROR") && (i = !0), push(e);
1166
- !r?.aborted && !i && push({
1967
+ const stream2 = connection.connect(messages, data, abortSignal);
1968
+ for await (const chunk of stream2) {
1969
+ if (chunk.type === "RUN_FINISHED" || chunk.type === "RUN_ERROR") hasTerminalEvent = true;
1970
+ push(chunk);
1971
+ }
1972
+ if (!abortSignal?.aborted && !hasTerminalEvent) push({
1167
1973
  type: "RUN_FINISHED",
1168
1974
  runId: `run-${Date.now()}`,
1169
1975
  model: "connect-wrapper",
1170
1976
  timestamp: Date.now(),
1171
1977
  finishReason: "stop"
1172
1978
  });
1173
- } catch (e) {
1174
- throw !r?.aborted && !i && push({
1979
+ } catch (err) {
1980
+ if (!abortSignal?.aborted && !hasTerminalEvent) push({
1175
1981
  type: "RUN_ERROR",
1176
1982
  timestamp: Date.now(),
1177
- message: e instanceof Error ? e.message : "Unknown error in connect()",
1178
- error: { message: e instanceof Error ? e.message : "Unknown error in connect()" }
1179
- }), e;
1983
+ message: err instanceof Error ? err.message : "Unknown error in connect()",
1984
+ error: { message: err instanceof Error ? err.message : "Unknown error in connect()" }
1985
+ });
1986
+ throw err;
1180
1987
  }
1181
1988
  }
1182
1989
  };
1183
1990
  }
1184
- function fetchServerSentEvents(e, t = {}) {
1185
- return { async *connect(n, r, i) {
1186
- let a = typeof e == "function" ? e() : e, o = typeof t == "function" ? await t() : t, s = {
1991
+ function fetchServerSentEvents(url, options = {}) {
1992
+ return { async *connect(messages, data, abortSignal) {
1993
+ const resolvedUrl = typeof url === "function" ? url() : url;
1994
+ const resolvedOptions = typeof options === "function" ? await options() : options;
1995
+ const requestHeaders = {
1187
1996
  "Content-Type": "application/json",
1188
- ...mergeHeaders(o.headers)
1189
- }, c = {
1190
- messages: n,
1191
- data: r,
1192
- ...o.body
1193
- }, l = await (o.fetchClient ?? fetch)(a, {
1997
+ ...mergeHeaders(resolvedOptions.headers)
1998
+ };
1999
+ const requestBody = {
2000
+ messages,
2001
+ data,
2002
+ ...resolvedOptions.body
2003
+ };
2004
+ const response = await (resolvedOptions.fetchClient ?? fetch)(resolvedUrl, {
1194
2005
  method: "POST",
1195
- headers: s,
1196
- body: JSON.stringify(c),
1197
- credentials: o.credentials || "same-origin",
1198
- signal: i || o.signal
2006
+ headers: requestHeaders,
2007
+ body: JSON.stringify(requestBody),
2008
+ credentials: resolvedOptions.credentials || "same-origin",
2009
+ signal: abortSignal || resolvedOptions.signal
1199
2010
  });
1200
- if (!l.ok) throw Error(`HTTP error! status: ${l.status} ${l.statusText}`);
1201
- let u = l.body?.getReader();
1202
- if (!u) throw Error("Response body is not readable");
1203
- for await (let e of readStreamLines(u, i)) {
1204
- let t = e.startsWith("data: ") ? e.slice(6) : e;
1205
- if (t === "[DONE]") {
2011
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
2012
+ const reader = response.body?.getReader();
2013
+ if (!reader) throw new Error("Response body is not readable");
2014
+ for await (const line of readStreamLines(reader, abortSignal)) {
2015
+ const data2 = line.startsWith("data: ") ? line.slice(6) : line;
2016
+ if (data2 === "[DONE]") {
1206
2017
  console.warn("[@tanstack/ai-client] Received [DONE] sentinel. This is deprecated — upgrade your @tanstack/ai server package. RUN_FINISHED is the stream terminator.");
1207
2018
  continue;
1208
2019
  }
1209
2020
  try {
1210
- yield JSON.parse(t);
1211
- } catch {
1212
- console.warn("Failed to parse SSE chunk:", t);
2021
+ yield JSON.parse(data2);
2022
+ } catch (parseError) {
2023
+ console.warn("Failed to parse SSE chunk:", data2);
1213
2024
  }
1214
2025
  }
1215
2026
  } };
@@ -1217,176 +2028,315 @@ function fetchServerSentEvents(e, t = {}) {
1217
2028
  //#endregion
1218
2029
  //#region ../../node_modules/.pnpm/@tanstack+ai-client@0.8.0/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
1219
2030
  var ChatClient = class {
1220
- constructor(e) {
1221
- if (this.body = {}, this.pendingMessageBody = void 0, this.isLoading = !1, this.isSubscribed = !1, this.error = void 0, this.status = "ready", this.connectionStatus = "disconnected", this.abortController = null, this.currentStreamId = null, this.currentMessageId = null, this.postStreamActions = [], this.pendingToolExecutions = /* @__PURE__ */ new Map(), this.continuationPending = !1, this.subscriptionAbortController = null, this.processingResolve = null, this.errorReportedGeneration = null, this.streamGeneration = 0, this.continuationSkipped = !1, this.draining = !1, this.sessionGenerating = !1, this.activeRunIds = /* @__PURE__ */ new Set(), this.uniqueId = e.id || this.generateUniqueId("chat"), this.body = e.body || {}, this.connection = normalizeConnectionAdapter(e.connection), this.events = new DefaultChatClientEventEmitter(this.uniqueId), this.clientToolsRef = { current: /* @__PURE__ */ new Map() }, e.tools) for (let t of e.tools) this.clientToolsRef.current.set(t.name, t);
2031
+ constructor(options) {
2032
+ this.body = {};
2033
+ this.pendingMessageBody = void 0;
2034
+ this.isLoading = false;
2035
+ this.isSubscribed = false;
2036
+ this.error = void 0;
2037
+ this.status = "ready";
2038
+ this.connectionStatus = "disconnected";
2039
+ this.abortController = null;
2040
+ this.currentStreamId = null;
2041
+ this.currentMessageId = null;
2042
+ this.postStreamActions = [];
2043
+ this.pendingToolExecutions = /* @__PURE__ */ new Map();
2044
+ this.continuationPending = false;
2045
+ this.subscriptionAbortController = null;
2046
+ this.processingResolve = null;
2047
+ this.errorReportedGeneration = null;
2048
+ this.streamGeneration = 0;
2049
+ this.continuationSkipped = false;
2050
+ this.draining = false;
2051
+ this.sessionGenerating = false;
2052
+ this.activeRunIds = /* @__PURE__ */ new Set();
2053
+ this.uniqueId = options.id || this.generateUniqueId("chat");
2054
+ this.body = options.body || {};
2055
+ this.connection = normalizeConnectionAdapter(options.connection);
2056
+ this.events = new DefaultChatClientEventEmitter(this.uniqueId);
2057
+ this.clientToolsRef = { current: /* @__PURE__ */ new Map() };
2058
+ if (options.tools) for (const tool of options.tools) this.clientToolsRef.current.set(tool.name, tool);
1222
2059
  this.callbacksRef = { current: {
1223
- onResponse: e.onResponse || (() => {}),
1224
- onChunk: e.onChunk || (() => {}),
1225
- onFinish: e.onFinish || (() => {}),
1226
- onError: e.onError || (() => {}),
1227
- onMessagesChange: e.onMessagesChange || (() => {}),
1228
- onLoadingChange: e.onLoadingChange || (() => {}),
1229
- onErrorChange: e.onErrorChange || (() => {}),
1230
- onStatusChange: e.onStatusChange || (() => {}),
1231
- onSubscriptionChange: e.onSubscriptionChange || (() => {}),
1232
- onConnectionStatusChange: e.onConnectionStatusChange || (() => {}),
1233
- onSessionGeneratingChange: e.onSessionGeneratingChange || (() => {}),
1234
- onCustomEvent: e.onCustomEvent || (() => {})
1235
- } }, this.processor = new h({
1236
- chunkStrategy: e.streamProcessor?.chunkStrategy,
1237
- initialMessages: e.initialMessages,
2060
+ onResponse: options.onResponse || (() => {}),
2061
+ onChunk: options.onChunk || (() => {}),
2062
+ onFinish: options.onFinish || (() => {}),
2063
+ onError: options.onError || (() => {}),
2064
+ onMessagesChange: options.onMessagesChange || (() => {}),
2065
+ onLoadingChange: options.onLoadingChange || (() => {}),
2066
+ onErrorChange: options.onErrorChange || (() => {}),
2067
+ onStatusChange: options.onStatusChange || (() => {}),
2068
+ onSubscriptionChange: options.onSubscriptionChange || (() => {}),
2069
+ onConnectionStatusChange: options.onConnectionStatusChange || (() => {}),
2070
+ onSessionGeneratingChange: options.onSessionGeneratingChange || (() => {}),
2071
+ onCustomEvent: options.onCustomEvent || (() => {})
2072
+ } };
2073
+ this.processor = new StreamProcessor({
2074
+ chunkStrategy: options.streamProcessor?.chunkStrategy,
2075
+ initialMessages: options.initialMessages,
1238
2076
  events: {
1239
- onMessagesChange: (e) => {
1240
- this.callbacksRef.current.onMessagesChange(e);
2077
+ onMessagesChange: (messages) => {
2078
+ this.callbacksRef.current.onMessagesChange(messages);
1241
2079
  },
1242
2080
  onStreamStart: () => {
1243
2081
  this.setStatus("streaming");
1244
- let e = this.processor.getCurrentAssistantMessageId();
1245
- if (!e) return;
1246
- let t = this.processor.getMessages().find((t) => t.id === e);
1247
- t && (this.currentMessageId = t.id, this.events.messageAppended(t, this.currentStreamId || void 0));
2082
+ const assistantMessageId = this.processor.getCurrentAssistantMessageId();
2083
+ if (!assistantMessageId) return;
2084
+ const assistantMessage = this.processor.getMessages().find((m) => m.id === assistantMessageId);
2085
+ if (assistantMessage) {
2086
+ this.currentMessageId = assistantMessage.id;
2087
+ this.events.messageAppended(assistantMessage, this.currentStreamId || void 0);
2088
+ }
1248
2089
  },
1249
- onStreamEnd: (e) => {
1250
- this.callbacksRef.current.onFinish(e), this.setStatus("ready"), this.resolveProcessing();
2090
+ onStreamEnd: (message) => {
2091
+ this.callbacksRef.current.onFinish(message);
2092
+ this.setStatus("ready");
2093
+ this.resolveProcessing();
1251
2094
  },
1252
- onError: (e) => {
1253
- this.reportStreamError(e);
2095
+ onError: (error) => {
2096
+ this.reportStreamError(error);
1254
2097
  },
1255
- onTextUpdate: (e, t) => {
1256
- this.currentStreamId && this.events.textUpdated(this.currentStreamId, e, t);
2098
+ onTextUpdate: (messageId, content) => {
2099
+ if (this.currentStreamId) this.events.textUpdated(this.currentStreamId, messageId, content);
1257
2100
  },
1258
- onThinkingUpdate: (e, t) => {
1259
- this.currentStreamId && this.events.thinkingUpdated(this.currentStreamId, e, t);
2101
+ onThinkingUpdate: (messageId, content) => {
2102
+ if (this.currentStreamId) this.events.thinkingUpdated(this.currentStreamId, messageId, content);
1260
2103
  },
1261
- onToolCallStateChange: (e, t, n, r) => {
1262
- let i = this.processor.getMessages().find((t) => t.id === e)?.parts.find((e) => e.type === "tool-call" && e.id === t)?.name || "unknown";
1263
- this.currentStreamId && this.events.toolCallStateChanged(this.currentStreamId, e, t, i, n, r);
2104
+ onToolCallStateChange: (messageId, toolCallId, state, args) => {
2105
+ const toolName = (this.processor.getMessages().find((m) => m.id === messageId)?.parts.find((p) => p.type === "tool-call" && p.id === toolCallId))?.name || "unknown";
2106
+ if (this.currentStreamId) this.events.toolCallStateChanged(this.currentStreamId, messageId, toolCallId, toolName, state, args);
1264
2107
  },
1265
- onToolCall: (e) => {
1266
- let t = this.clientToolsRef.current.get(e.toolName)?.execute;
1267
- if (t) {
1268
- let n = (async () => {
2108
+ onToolCall: (args) => {
2109
+ const executeFunc = this.clientToolsRef.current.get(args.toolName)?.execute;
2110
+ if (executeFunc) {
2111
+ const executionPromise = (async () => {
1269
2112
  try {
1270
- let n = await t(e.input);
2113
+ const output = await executeFunc(args.input);
1271
2114
  await this.addToolResult({
1272
- toolCallId: e.toolCallId,
1273
- tool: e.toolName,
1274
- output: n,
2115
+ toolCallId: args.toolCallId,
2116
+ tool: args.toolName,
2117
+ output,
1275
2118
  state: "output-available"
1276
2119
  });
1277
- } catch (t) {
2120
+ } catch (error) {
1278
2121
  await this.addToolResult({
1279
- toolCallId: e.toolCallId,
1280
- tool: e.toolName,
2122
+ toolCallId: args.toolCallId,
2123
+ tool: args.toolName,
1281
2124
  output: null,
1282
2125
  state: "output-error",
1283
- errorText: t.message
2126
+ errorText: error.message
1284
2127
  });
1285
2128
  } finally {
1286
- this.pendingToolExecutions.delete(e.toolCallId);
2129
+ this.pendingToolExecutions.delete(args.toolCallId);
1287
2130
  }
1288
2131
  })();
1289
- this.pendingToolExecutions.set(e.toolCallId, n);
2132
+ this.pendingToolExecutions.set(args.toolCallId, executionPromise);
1290
2133
  }
1291
2134
  },
1292
- onApprovalRequest: (e) => {
1293
- this.currentStreamId && this.events.approvalRequested(this.currentStreamId, this.currentMessageId || "", e.toolCallId, e.toolName, e.input, e.approvalId);
2135
+ onApprovalRequest: (args) => {
2136
+ if (this.currentStreamId) this.events.approvalRequested(this.currentStreamId, this.currentMessageId || "", args.toolCallId, args.toolName, args.input, args.approvalId);
1294
2137
  },
1295
- onCustomEvent: (e, t, n) => {
1296
- this.callbacksRef.current.onCustomEvent(e, t, n);
2138
+ onCustomEvent: (eventType, data, context) => {
2139
+ this.callbacksRef.current.onCustomEvent(eventType, data, context);
1297
2140
  }
1298
2141
  }
1299
- }), this.events.clientCreated(this.processor.getMessages().length);
2142
+ });
2143
+ this.events.clientCreated(this.processor.getMessages().length);
1300
2144
  }
1301
- generateUniqueId(e) {
1302
- return `${e}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
2145
+ generateUniqueId(prefix) {
2146
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1303
2147
  }
1304
- setIsLoading(e) {
1305
- this.isLoading = e, this.callbacksRef.current.onLoadingChange(e), this.events.loadingChanged(e);
2148
+ setIsLoading(isLoading) {
2149
+ this.isLoading = isLoading;
2150
+ this.callbacksRef.current.onLoadingChange(isLoading);
2151
+ this.events.loadingChanged(isLoading);
1306
2152
  }
1307
- setStatus(e) {
1308
- this.status = e, this.callbacksRef.current.onStatusChange(e);
2153
+ setStatus(status) {
2154
+ this.status = status;
2155
+ this.callbacksRef.current.onStatusChange(status);
1309
2156
  }
1310
- setIsSubscribed(e) {
1311
- this.isSubscribed = e, this.callbacksRef.current.onSubscriptionChange(e);
2157
+ setIsSubscribed(isSubscribed) {
2158
+ this.isSubscribed = isSubscribed;
2159
+ this.callbacksRef.current.onSubscriptionChange(isSubscribed);
1312
2160
  }
1313
- setConnectionStatus(e) {
1314
- this.connectionStatus = e, this.callbacksRef.current.onConnectionStatusChange(e);
2161
+ setConnectionStatus(status) {
2162
+ this.connectionStatus = status;
2163
+ this.callbacksRef.current.onConnectionStatusChange(status);
1315
2164
  }
1316
- setSessionGenerating(e) {
1317
- this.sessionGenerating !== e && (this.sessionGenerating = e, this.callbacksRef.current.onSessionGeneratingChange(e));
2165
+ setSessionGenerating(isGenerating) {
2166
+ if (this.sessionGenerating === isGenerating) return;
2167
+ this.sessionGenerating = isGenerating;
2168
+ this.callbacksRef.current.onSessionGeneratingChange(isGenerating);
1318
2169
  }
1319
2170
  resetSessionGenerating() {
1320
- this.activeRunIds.clear(), this.setSessionGenerating(!1);
2171
+ this.activeRunIds.clear();
2172
+ this.setSessionGenerating(false);
1321
2173
  }
1322
- setError(e) {
1323
- this.error = e, this.callbacksRef.current.onErrorChange(e), this.events.errorChanged(e?.message || null);
2174
+ setError(error) {
2175
+ this.error = error;
2176
+ this.callbacksRef.current.onErrorChange(error);
2177
+ this.events.errorChanged(error?.message || null);
1324
2178
  }
1325
2179
  abortSubscriptionLoop() {
1326
- this.subscriptionAbortController?.abort(), this.subscriptionAbortController = null;
2180
+ this.subscriptionAbortController?.abort();
2181
+ this.subscriptionAbortController = null;
1327
2182
  }
1328
2183
  resolveProcessing() {
1329
- this.processingResolve?.(), this.processingResolve = null;
1330
- }
1331
- cancelInFlightStream(e) {
1332
- this.abortController?.abort(), this.abortController = null, e?.abortSubscription && this.abortSubscriptionLoop(), this.resolveProcessing(), this.setIsLoading(!1), e?.setReadyStatus && this.setStatus("ready");
1333
- }
1334
- reportStreamError(e) {
1335
- let t = this.errorReportedGeneration === this.streamGeneration;
1336
- this.setError(e), (this.isLoading || this.status === "submitted" || this.status === "streaming") && this.setStatus("error"), t || (this.errorReportedGeneration = this.streamGeneration, this.callbacksRef.current.onError(e));
2184
+ this.processingResolve?.();
2185
+ this.processingResolve = null;
2186
+ }
2187
+ cancelInFlightStream(options) {
2188
+ this.abortController?.abort();
2189
+ this.abortController = null;
2190
+ if (options?.abortSubscription) this.abortSubscriptionLoop();
2191
+ this.resolveProcessing();
2192
+ this.setIsLoading(false);
2193
+ if (options?.setReadyStatus) this.setStatus("ready");
2194
+ }
2195
+ reportStreamError(error) {
2196
+ const alreadyReported = this.errorReportedGeneration === this.streamGeneration;
2197
+ this.setError(error);
2198
+ if (this.isLoading || this.status === "submitted" || this.status === "streaming") this.setStatus("error");
2199
+ if (!alreadyReported) {
2200
+ this.errorReportedGeneration = this.streamGeneration;
2201
+ this.callbacksRef.current.onError(error);
2202
+ }
1337
2203
  }
2204
+ /**
2205
+ * Start the background subscription loop.
2206
+ */
1338
2207
  startSubscription() {
1339
2208
  this.subscriptionAbortController = new AbortController();
1340
- let e = this.subscriptionAbortController.signal;
1341
- this.consumeSubscription(e).catch((e) => {
1342
- e instanceof Error && e.name !== "AbortError" && (this.setConnectionStatus("error"), this.resetSessionGenerating(), this.setIsSubscribed(!1), this.reportStreamError(e)), this.resolveProcessing();
2209
+ const signal = this.subscriptionAbortController.signal;
2210
+ this.consumeSubscription(signal).catch((err) => {
2211
+ if (err instanceof Error && err.name !== "AbortError") {
2212
+ this.setConnectionStatus("error");
2213
+ this.resetSessionGenerating();
2214
+ this.setIsSubscribed(false);
2215
+ this.reportStreamError(err);
2216
+ }
2217
+ this.resolveProcessing();
1343
2218
  }).finally(() => {
1344
- this.subscriptionAbortController?.signal === e && (this.subscriptionAbortController = null, !e.aborted && this.isSubscribed && (this.setIsSubscribed(!1), this.connectionStatus !== "error" && this.setConnectionStatus("disconnected")));
2219
+ if (this.subscriptionAbortController?.signal !== signal) return;
2220
+ this.subscriptionAbortController = null;
2221
+ if (!signal.aborted && this.isSubscribed) {
2222
+ this.setIsSubscribed(false);
2223
+ if (this.connectionStatus !== "error") this.setConnectionStatus("disconnected");
2224
+ }
1345
2225
  });
1346
2226
  }
1347
- async consumeSubscription(e) {
1348
- let t = this.connection.subscribe(e);
1349
- for await (let n of t) {
1350
- if (e.aborted) break;
1351
- if (this.connectionStatus === "connecting" && this.setConnectionStatus("connected"), this.callbacksRef.current.onChunk(n), this.processor.processChunk(n), n.type === "RUN_STARTED" && (this.activeRunIds.add(n.runId), this.setSessionGenerating(!0)), n.type === "RUN_FINISHED" || n.type === "RUN_ERROR") {
1352
- let e = n.type === "RUN_FINISHED" ? n.runId : void 0;
1353
- e ? this.activeRunIds.delete(e) : n.type === "RUN_ERROR" && this.activeRunIds.clear(), this.setSessionGenerating(this.activeRunIds.size > 0), this.resolveProcessing();
2227
+ /**
2228
+ * Consume chunks from the connection subscription.
2229
+ */
2230
+ async consumeSubscription(signal) {
2231
+ const stream = this.connection.subscribe(signal);
2232
+ for await (const chunk of stream) {
2233
+ if (signal.aborted) break;
2234
+ if (this.connectionStatus === "connecting") this.setConnectionStatus("connected");
2235
+ this.callbacksRef.current.onChunk(chunk);
2236
+ this.processor.processChunk(chunk);
2237
+ if (chunk.type === "RUN_STARTED") {
2238
+ this.activeRunIds.add(chunk.runId);
2239
+ this.setSessionGenerating(true);
1354
2240
  }
1355
- await new Promise((e) => setTimeout(e, 0));
2241
+ if (chunk.type === "RUN_FINISHED" || chunk.type === "RUN_ERROR") {
2242
+ const runId = chunk.type === "RUN_FINISHED" ? chunk.runId : void 0;
2243
+ if (runId) this.activeRunIds.delete(runId);
2244
+ else if (chunk.type === "RUN_ERROR") this.activeRunIds.clear();
2245
+ this.setSessionGenerating(this.activeRunIds.size > 0);
2246
+ this.resolveProcessing();
2247
+ }
2248
+ await new Promise((resolve) => setTimeout(resolve, 0));
1356
2249
  }
1357
2250
  }
2251
+ /**
2252
+ * Ensure subscription loop is running, starting it if needed.
2253
+ */
1358
2254
  ensureSubscription() {
1359
2255
  if (!this.isSubscribed) {
1360
2256
  this.subscribe();
1361
2257
  return;
1362
2258
  }
1363
- (!this.subscriptionAbortController || this.subscriptionAbortController.signal.aborted) && this.subscribe({ restart: !0 });
2259
+ if (!this.subscriptionAbortController || this.subscriptionAbortController.signal.aborted) this.subscribe({ restart: true });
1364
2260
  }
2261
+ /**
2262
+ * Create a promise that resolves when onStreamEnd fires.
2263
+ * Used by streamResponse to await processing completion.
2264
+ */
1365
2265
  waitForProcessing() {
1366
- return this.resolveProcessing(), new Promise((e) => {
1367
- this.processingResolve = e;
2266
+ this.resolveProcessing();
2267
+ return new Promise((resolve) => {
2268
+ this.processingResolve = resolve;
1368
2269
  });
1369
2270
  }
1370
- async sendMessage(e, t) {
1371
- if (typeof e == "string" && !e.trim() || this.isLoading) return;
1372
- let n = this.normalizeMessageInput(e);
1373
- this.pendingMessageBody = t;
1374
- let r = this.processor.addUserMessage(n.content, n.id);
1375
- this.events.messageSent(r.id, n.content), await this.streamResponse();
1376
- }
1377
- normalizeMessageInput(e) {
1378
- return typeof e == "string" ? { content: e.trim() } : {
1379
- content: e.content,
1380
- id: e.id
2271
+ /**
2272
+ * Send a message and stream the response.
2273
+ * Supports both simple string content and multimodal content (images, audio, video, documents).
2274
+ *
2275
+ * @param content - The message content. Can be:
2276
+ * - A simple string for text-only messages
2277
+ * - A MultimodalContent object with content array and optional custom ID
2278
+ * @param body - Optional body parameters to merge with the client's base body for this request.
2279
+ * Uses shallow merge with per-message body taking priority.
2280
+ *
2281
+ * @example
2282
+ * ```ts
2283
+ * // Simple text message
2284
+ * await client.sendMessage('Hello!')
2285
+ *
2286
+ * // Text message with custom body params
2287
+ * await client.sendMessage('Hello!', { temperature: 0.7 })
2288
+ *
2289
+ * // Multimodal message with image
2290
+ * await client.sendMessage({
2291
+ * content: [
2292
+ * { type: 'text', content: 'What is in this image?' },
2293
+ * { type: 'image', source: { type: 'url', value: 'https://example.com/photo.jpg' } }
2294
+ * ]
2295
+ * })
2296
+ *
2297
+ * // Multimodal message with custom ID and body params
2298
+ * await client.sendMessage(
2299
+ * {
2300
+ * content: [
2301
+ * { type: 'text', content: 'Describe this audio' },
2302
+ * { type: 'audio', source: { type: 'data', value: 'base64...' } }
2303
+ * ],
2304
+ * id: 'custom-message-id'
2305
+ * },
2306
+ * { model: 'gpt-4-audio' }
2307
+ * )
2308
+ * ```
2309
+ */
2310
+ async sendMessage(content, body) {
2311
+ if (typeof content === "string" && !content.trim() || this.isLoading) return;
2312
+ const normalizedContent = this.normalizeMessageInput(content);
2313
+ this.pendingMessageBody = body;
2314
+ const userMessage = this.processor.addUserMessage(normalizedContent.content, normalizedContent.id);
2315
+ this.events.messageSent(userMessage.id, normalizedContent.content);
2316
+ await this.streamResponse();
2317
+ }
2318
+ /**
2319
+ * Normalize the message input to extract content and optional id.
2320
+ * Trims string content automatically.
2321
+ */
2322
+ normalizeMessageInput(input) {
2323
+ if (typeof input === "string") return { content: input.trim() };
2324
+ return {
2325
+ content: input.content,
2326
+ id: input.id
1381
2327
  };
1382
2328
  }
1383
- async append(e) {
1384
- let t = normalizeToUIMessage(e, generateMessageId);
1385
- if (t.role === "system") return;
1386
- let n = t;
1387
- this.events.messageAppended(n);
1388
- let r = this.processor.getMessages();
1389
- if (this.processor.setMessages([...r, n]), this.isLoading) {
2329
+ /**
2330
+ * Append a message and stream the response
2331
+ */
2332
+ async append(message) {
2333
+ const normalizedMessage = normalizeToUIMessage(message, generateMessageId);
2334
+ if (normalizedMessage.role === "system") return;
2335
+ const uiMessage = normalizedMessage;
2336
+ this.events.messageAppended(uiMessage);
2337
+ const messages = this.processor.getMessages();
2338
+ this.processor.setMessages([...messages, uiMessage]);
2339
+ if (this.isLoading) {
1390
2340
  this.queuePostStreamAction(async () => {
1391
2341
  await this.streamResponse();
1392
2342
  });
@@ -1394,375 +2344,545 @@ var ChatClient = class {
1394
2344
  }
1395
2345
  await this.streamResponse();
1396
2346
  }
2347
+ /**
2348
+ * Stream a response from the LLM.
2349
+ * Returns true if the stream completed successfully, false on abort or error.
2350
+ */
1397
2351
  async streamResponse() {
1398
- if (this.isLoading) return !1;
1399
- let e = ++this.streamGeneration;
1400
- this.setIsLoading(!0), this.setStatus("submitted"), this.setError(void 0), this.errorReportedGeneration = null, this.abortController = new AbortController(), this.pendingToolExecutions.clear();
1401
- let t = !1;
2352
+ if (this.isLoading) return false;
2353
+ const generation = ++this.streamGeneration;
2354
+ this.setIsLoading(true);
2355
+ this.setStatus("submitted");
2356
+ this.setError(void 0);
2357
+ this.errorReportedGeneration = null;
2358
+ this.abortController = new AbortController();
2359
+ this.pendingToolExecutions.clear();
2360
+ let streamCompletedSuccessfully = false;
1402
2361
  try {
1403
- let n = this.processor.getMessages();
2362
+ const messages = this.processor.getMessages();
1404
2363
  await this.callbacksRef.current.onResponse();
1405
- let r = {
2364
+ const mergedBody = {
1406
2365
  ...this.body,
1407
2366
  ...this.pendingMessageBody,
1408
2367
  conversationId: this.uniqueId
1409
2368
  };
1410
- this.pendingMessageBody = void 0, this.currentStreamId = this.generateUniqueId("stream"), this.currentMessageId = null, this.processor.prepareAssistantMessage(), this.ensureSubscription();
1411
- let i = this.waitForProcessing();
1412
- if (await this.connection.send(n, r, this.abortController.signal), await i, e !== this.streamGeneration || this.status === "error") return !1;
1413
- this.pendingToolExecutions.size > 0 && await Promise.all(this.pendingToolExecutions.values()), this.processor.finalizeStream(), t = !0;
1414
- } catch (t) {
1415
- if (t instanceof Error) {
1416
- if (t.name === "AbortError") return !1;
1417
- e === this.streamGeneration && this.reportStreamError(t);
2369
+ this.pendingMessageBody = void 0;
2370
+ this.currentStreamId = this.generateUniqueId("stream");
2371
+ this.currentMessageId = null;
2372
+ this.processor.prepareAssistantMessage();
2373
+ this.ensureSubscription();
2374
+ const processingComplete = this.waitForProcessing();
2375
+ await this.connection.send(messages, mergedBody, this.abortController.signal);
2376
+ await processingComplete;
2377
+ if (generation !== this.streamGeneration) return false;
2378
+ if (this.status === "error") return false;
2379
+ if (this.pendingToolExecutions.size > 0) await Promise.all(this.pendingToolExecutions.values());
2380
+ this.processor.finalizeStream();
2381
+ streamCompletedSuccessfully = true;
2382
+ } catch (err) {
2383
+ if (err instanceof Error) {
2384
+ if (err.name === "AbortError") return false;
2385
+ if (generation === this.streamGeneration) this.reportStreamError(err);
1418
2386
  }
1419
2387
  } finally {
1420
- if (e === this.streamGeneration && (this.currentStreamId = null, this.currentMessageId = null, this.abortController = null, this.setIsLoading(!1), this.pendingMessageBody = void 0, await this.drainPostStreamActions(), t)) {
1421
- let e = this.processor.getMessages().at(-1)?.parts.at(-1), { finishReason: t } = this.processor.getState();
1422
- if (e?.type === "tool-result" && t !== "stop" && this.shouldAutoSend()) try {
1423
- await this.checkForContinuation();
1424
- } catch (e) {
1425
- console.error("Failed to continue flow after tool result:", e);
2388
+ if (generation === this.streamGeneration) {
2389
+ this.currentStreamId = null;
2390
+ this.currentMessageId = null;
2391
+ this.abortController = null;
2392
+ this.setIsLoading(false);
2393
+ this.pendingMessageBody = void 0;
2394
+ await this.drainPostStreamActions();
2395
+ if (streamCompletedSuccessfully) {
2396
+ const lastPart = this.processor.getMessages().at(-1)?.parts.at(-1);
2397
+ const { finishReason } = this.processor.getState();
2398
+ if (lastPart?.type === "tool-result" && finishReason !== "stop" && this.shouldAutoSend()) try {
2399
+ await this.checkForContinuation();
2400
+ } catch (error) {
2401
+ console.error("Failed to continue flow after tool result:", error);
2402
+ }
1426
2403
  }
1427
2404
  }
1428
2405
  }
1429
- return t;
1430
- }
1431
- subscribe(e) {
1432
- let t = e?.restart === !0;
1433
- (!this.isSubscribed || t) && (this.isSubscribed && t && this.abortSubscriptionLoop(), this.setIsSubscribed(!0), this.setConnectionStatus("connecting"), this.startSubscription());
1434
- }
2406
+ return streamCompletedSuccessfully;
2407
+ }
2408
+ /**
2409
+ * Start the client subscription loop.
2410
+ * This controls the connection lifecycle independently from request lifecycle.
2411
+ */
2412
+ subscribe(options) {
2413
+ const restart = options?.restart === true;
2414
+ if (this.isSubscribed && !restart) return;
2415
+ if (this.isSubscribed && restart) this.abortSubscriptionLoop();
2416
+ this.setIsSubscribed(true);
2417
+ this.setConnectionStatus("connecting");
2418
+ this.startSubscription();
2419
+ }
2420
+ /**
2421
+ * Unsubscribe and fully tear down live behavior.
2422
+ * This aborts an in-flight request and the subscription loop.
2423
+ */
1435
2424
  unsubscribe() {
1436
2425
  this.cancelInFlightStream({
1437
- setReadyStatus: !0,
1438
- abortSubscription: !0
1439
- }), this.resetSessionGenerating(), this.setIsSubscribed(!1), this.setConnectionStatus("disconnected");
2426
+ setReadyStatus: true,
2427
+ abortSubscription: true
2428
+ });
2429
+ this.resetSessionGenerating();
2430
+ this.setIsSubscribed(false);
2431
+ this.setConnectionStatus("disconnected");
1440
2432
  }
2433
+ /**
2434
+ * Reload the last assistant message
2435
+ */
1441
2436
  async reload() {
1442
- let e = this.processor.getMessages();
1443
- if (e.length === 0) return;
1444
- let t = e.findLastIndex((e) => e.role === "user");
1445
- t !== -1 && (this.isLoading && this.cancelInFlightStream(), this.events.reloaded(t), this.processor.removeMessagesAfter(t), await this.streamResponse());
2437
+ const messages = this.processor.getMessages();
2438
+ if (messages.length === 0) return;
2439
+ const lastUserMessageIndex = messages.findLastIndex((m) => m.role === "user");
2440
+ if (lastUserMessageIndex === -1) return;
2441
+ if (this.isLoading) this.cancelInFlightStream();
2442
+ this.events.reloaded(lastUserMessageIndex);
2443
+ this.processor.removeMessagesAfter(lastUserMessageIndex);
2444
+ await this.streamResponse();
1446
2445
  }
2446
+ /**
2447
+ * Stop the current stream
2448
+ */
1447
2449
  stop() {
1448
- this.cancelInFlightStream({ setReadyStatus: !0 }), this.events.stopped();
2450
+ this.cancelInFlightStream({ setReadyStatus: true });
2451
+ this.events.stopped();
1449
2452
  }
2453
+ /**
2454
+ * Clear all messages
2455
+ */
1450
2456
  clear() {
1451
- this.processor.clearMessages(), this.setError(void 0), this.events.messagesCleared();
1452
- }
1453
- async addToolResult(e) {
1454
- if (this.events.toolResultAdded(e.toolCallId, e.tool, e.output, e.state || "output-available"), this.processor.addToolResult(e.toolCallId, e.output, e.errorText), this.isLoading) {
2457
+ this.processor.clearMessages();
2458
+ this.setError(void 0);
2459
+ this.events.messagesCleared();
2460
+ }
2461
+ /**
2462
+ * Add the result of a client-side tool execution
2463
+ */
2464
+ async addToolResult(result) {
2465
+ this.events.toolResultAdded(result.toolCallId, result.tool, result.output, result.state || "output-available");
2466
+ this.processor.addToolResult(result.toolCallId, result.output, result.errorText);
2467
+ if (this.isLoading) {
1455
2468
  this.queuePostStreamAction(() => this.checkForContinuation());
1456
2469
  return;
1457
2470
  }
1458
2471
  await this.checkForContinuation();
1459
2472
  }
1460
- async addToolApprovalResponse(e) {
1461
- let t = this.processor.getMessages(), n;
1462
- for (let r of t) {
1463
- let t = r.parts.find((t) => t.type === "tool-call" && t.approval?.id === e.id);
1464
- if (t) {
1465
- n = t.id;
2473
+ /**
2474
+ * Respond to a tool approval request
2475
+ */
2476
+ async addToolApprovalResponse(response) {
2477
+ const messages = this.processor.getMessages();
2478
+ let foundToolCallId;
2479
+ for (const msg of messages) {
2480
+ const toolCallPart = msg.parts.find((p) => p.type === "tool-call" && p.approval?.id === response.id);
2481
+ if (toolCallPart) {
2482
+ foundToolCallId = toolCallPart.id;
1466
2483
  break;
1467
2484
  }
1468
2485
  }
1469
- if (n && this.events.toolApprovalResponded(e.id, n, e.approved), this.processor.addToolApprovalResponse(e.id, e.approved), this.isLoading) {
2486
+ if (foundToolCallId) this.events.toolApprovalResponded(response.id, foundToolCallId, response.approved);
2487
+ this.processor.addToolApprovalResponse(response.id, response.approved);
2488
+ if (this.isLoading) {
1470
2489
  this.queuePostStreamAction(() => this.checkForContinuation());
1471
2490
  return;
1472
2491
  }
1473
2492
  await this.checkForContinuation();
1474
2493
  }
1475
- queuePostStreamAction(e) {
1476
- this.postStreamActions.push(e);
2494
+ /**
2495
+ * Queue an action to be executed after the current stream ends
2496
+ */
2497
+ queuePostStreamAction(action) {
2498
+ this.postStreamActions.push(action);
1477
2499
  }
2500
+ /**
2501
+ * Drain and execute all queued post-stream actions
2502
+ */
1478
2503
  async drainPostStreamActions() {
1479
- if (!this.draining) {
1480
- this.draining = !0;
1481
- try {
1482
- for (; this.postStreamActions.length > 0;) await this.postStreamActions.shift()();
1483
- } finally {
1484
- this.draining = !1;
1485
- }
2504
+ if (this.draining) return;
2505
+ this.draining = true;
2506
+ try {
2507
+ while (this.postStreamActions.length > 0) await this.postStreamActions.shift()();
2508
+ } finally {
2509
+ this.draining = false;
1486
2510
  }
1487
2511
  }
2512
+ /**
2513
+ * Check if we should continue the flow and do so if needed
2514
+ */
1488
2515
  async checkForContinuation() {
1489
2516
  if (this.continuationPending || this.isLoading) {
1490
- this.continuationSkipped = !0;
2517
+ this.continuationSkipped = true;
1491
2518
  return;
1492
2519
  }
1493
2520
  if (this.shouldAutoSend()) {
1494
- this.continuationPending = !0, this.continuationSkipped = !1;
1495
- let e = !1;
2521
+ this.continuationPending = true;
2522
+ this.continuationSkipped = false;
2523
+ let succeeded = false;
1496
2524
  try {
1497
- e = await this.streamResponse();
2525
+ succeeded = await this.streamResponse();
1498
2526
  } finally {
1499
- this.continuationPending = !1;
2527
+ this.continuationPending = false;
2528
+ }
2529
+ if (this.continuationSkipped && succeeded) {
2530
+ this.continuationSkipped = false;
2531
+ await this.checkForContinuation();
1500
2532
  }
1501
- this.continuationSkipped && e && (this.continuationSkipped = !1, await this.checkForContinuation());
1502
2533
  }
1503
2534
  }
2535
+ /**
2536
+ * Check if all tool calls are complete and we should auto-send.
2537
+ * Requires that there is at least one tool call in the last assistant message;
2538
+ * a text-only response has nothing to auto-send.
2539
+ */
1504
2540
  shouldAutoSend() {
1505
- let e = this.processor.getMessages().findLast((e) => e.role === "assistant");
1506
- return !e || !e.parts.some((e) => e.type === "tool-call") ? !1 : this.processor.areAllToolsComplete();
1507
- }
2541
+ const lastAssistant = this.processor.getMessages().findLast((m) => m.role === "assistant");
2542
+ if (!lastAssistant) return false;
2543
+ if (!lastAssistant.parts.some((p) => p.type === "tool-call")) return false;
2544
+ return this.processor.areAllToolsComplete();
2545
+ }
2546
+ /**
2547
+ * Get current messages
2548
+ */
1508
2549
  getMessages() {
1509
2550
  return this.processor.getMessages();
1510
2551
  }
2552
+ /**
2553
+ * Get loading state
2554
+ */
1511
2555
  getIsLoading() {
1512
2556
  return this.isLoading;
1513
2557
  }
2558
+ /**
2559
+ * Get current status
2560
+ */
1514
2561
  getStatus() {
1515
2562
  return this.status;
1516
2563
  }
2564
+ /**
2565
+ * Get whether the subscription loop is active
2566
+ */
1517
2567
  getIsSubscribed() {
1518
2568
  return this.isSubscribed;
1519
2569
  }
2570
+ /**
2571
+ * Get current connection lifecycle status
2572
+ */
1520
2573
  getConnectionStatus() {
1521
2574
  return this.connectionStatus;
1522
2575
  }
2576
+ /**
2577
+ * Whether the shared session is actively generating.
2578
+ * Derived from stream run events (RUN_STARTED / RUN_FINISHED / RUN_ERROR).
2579
+ * Unlike `isLoading` (request-local), this reflects shared generation
2580
+ * activity visible to all subscribers (e.g. across tabs/devices).
2581
+ */
1523
2582
  getSessionGenerating() {
1524
2583
  return this.sessionGenerating;
1525
2584
  }
2585
+ /**
2586
+ * Get current error
2587
+ */
1526
2588
  getError() {
1527
2589
  return this.error;
1528
2590
  }
1529
- setMessagesManually(e) {
1530
- this.processor.setMessages(e);
1531
- }
1532
- updateOptions(e) {
1533
- if (e.connection !== void 0) {
1534
- let t = this.isSubscribed;
1535
- this.isLoading ? this.cancelInFlightStream({
1536
- setReadyStatus: !0,
1537
- abortSubscription: !0
1538
- }) : t && this.abortSubscriptionLoop(), this.resetSessionGenerating(), this.setIsSubscribed(!1), this.setConnectionStatus("disconnected"), this.connection = normalizeConnectionAdapter(e.connection), t && this.subscribe();
2591
+ /**
2592
+ * Manually set messages
2593
+ */
2594
+ setMessagesManually(messages) {
2595
+ this.processor.setMessages(messages);
2596
+ }
2597
+ /**
2598
+ * Update options refs (for use in React hooks to avoid recreating client)
2599
+ */
2600
+ updateOptions(options) {
2601
+ if (options.connection !== void 0) {
2602
+ const wasSubscribed = this.isSubscribed;
2603
+ if (this.isLoading) this.cancelInFlightStream({
2604
+ setReadyStatus: true,
2605
+ abortSubscription: true
2606
+ });
2607
+ else if (wasSubscribed) this.abortSubscriptionLoop();
2608
+ this.resetSessionGenerating();
2609
+ this.setIsSubscribed(false);
2610
+ this.setConnectionStatus("disconnected");
2611
+ this.connection = normalizeConnectionAdapter(options.connection);
2612
+ if (wasSubscribed) this.subscribe();
1539
2613
  }
1540
- if (e.body !== void 0 && (this.body = e.body), e.tools !== void 0) {
2614
+ if (options.body !== void 0) this.body = options.body;
2615
+ if (options.tools !== void 0) {
1541
2616
  this.clientToolsRef.current = /* @__PURE__ */ new Map();
1542
- for (let t of e.tools) this.clientToolsRef.current.set(t.name, t);
2617
+ for (const tool of options.tools) this.clientToolsRef.current.set(tool.name, tool);
1543
2618
  }
1544
- e.onResponse !== void 0 && (this.callbacksRef.current.onResponse = e.onResponse), e.onChunk !== void 0 && (this.callbacksRef.current.onChunk = e.onChunk), e.onFinish !== void 0 && (this.callbacksRef.current.onFinish = e.onFinish), e.onError !== void 0 && (this.callbacksRef.current.onError = e.onError), e.onSubscriptionChange !== void 0 && (this.callbacksRef.current.onSubscriptionChange = e.onSubscriptionChange), e.onConnectionStatusChange !== void 0 && (this.callbacksRef.current.onConnectionStatusChange = e.onConnectionStatusChange), e.onSessionGeneratingChange !== void 0 && (this.callbacksRef.current.onSessionGeneratingChange = e.onSessionGeneratingChange), e.onCustomEvent !== void 0 && (this.callbacksRef.current.onCustomEvent = e.onCustomEvent);
2619
+ if (options.onResponse !== void 0) this.callbacksRef.current.onResponse = options.onResponse;
2620
+ if (options.onChunk !== void 0) this.callbacksRef.current.onChunk = options.onChunk;
2621
+ if (options.onFinish !== void 0) this.callbacksRef.current.onFinish = options.onFinish;
2622
+ if (options.onError !== void 0) this.callbacksRef.current.onError = options.onError;
2623
+ if (options.onSubscriptionChange !== void 0) this.callbacksRef.current.onSubscriptionChange = options.onSubscriptionChange;
2624
+ if (options.onConnectionStatusChange !== void 0) this.callbacksRef.current.onConnectionStatusChange = options.onConnectionStatusChange;
2625
+ if (options.onSessionGeneratingChange !== void 0) this.callbacksRef.current.onSessionGeneratingChange = options.onSessionGeneratingChange;
2626
+ if (options.onCustomEvent !== void 0) this.callbacksRef.current.onCustomEvent = options.onCustomEvent;
1545
2627
  }
1546
2628
  };
1547
2629
  //#endregion
1548
2630
  //#region ../../node_modules/.pnpm/@tanstack+ai-client@0.8.0/node_modules/@tanstack/ai-client/dist/esm/types.js
1549
- function clientTools(...e) {
1550
- return e;
2631
+ function clientTools(...tools) {
2632
+ return tools;
1551
2633
  }
1552
2634
  //#endregion
1553
- //#region ../../node_modules/.pnpm/@tanstack+ai-react@0.8.0_@tanstack+ai@0.14.0_@types+react@19.2.18_react@19.2.8/node_modules/@tanstack/ai-react/dist/esm/use-chat.js
1554
- function useChat(e) {
1555
- let t = i(), c = e.id || t, [l, u] = s(e.initialMessages || []), [d, f] = s(!1), [p, m] = s(void 0), [h, g] = s("ready"), [_, v] = s(!1), [y, b] = s("disconnected"), [x, S] = s(!1), C = o(e.initialMessages || []), w = o(!0);
1556
- C.current = l;
1557
- let T = o(e);
1558
- T.current = e;
1559
- let E = a(() => {
1560
- let t = w.current ? e.initialMessages || [] : C.current;
1561
- return w.current = !1, new ChatClient({
1562
- connection: T.current.connection,
1563
- id: c,
1564
- initialMessages: t,
1565
- body: T.current.body,
1566
- onResponse: (e) => T.current.onResponse?.(e),
1567
- onChunk: (e) => T.current.onChunk?.(e),
1568
- onFinish: (e) => {
1569
- T.current.onFinish?.(e);
2635
+ //#region ../../node_modules/.pnpm/@tanstack+ai-react@0.8.0_@tanstack+ai@0.14.0_@types+react@19.3.0_react@19.3.0/node_modules/@tanstack/ai-react/dist/esm/use-chat.js
2636
+ function useChat(options) {
2637
+ const hookId = useId();
2638
+ const clientId = options.id || hookId;
2639
+ const [messages, setMessages] = useState(options.initialMessages || []);
2640
+ const [isLoading, setIsLoading] = useState(false);
2641
+ const [error, setError] = useState(void 0);
2642
+ const [status, setStatus] = useState("ready");
2643
+ const [isSubscribed, setIsSubscribed] = useState(false);
2644
+ const [connectionStatus, setConnectionStatus] = useState("disconnected");
2645
+ const [sessionGenerating, setSessionGenerating] = useState(false);
2646
+ const messagesRef = useRef(options.initialMessages || []);
2647
+ const isFirstMountRef = useRef(true);
2648
+ messagesRef.current = messages;
2649
+ const optionsRef = useRef(options);
2650
+ optionsRef.current = options;
2651
+ const client = useMemo(() => {
2652
+ const messagesToUse = isFirstMountRef.current ? options.initialMessages || [] : messagesRef.current;
2653
+ isFirstMountRef.current = false;
2654
+ return new ChatClient({
2655
+ connection: optionsRef.current.connection,
2656
+ id: clientId,
2657
+ initialMessages: messagesToUse,
2658
+ body: optionsRef.current.body,
2659
+ onResponse: (response) => optionsRef.current.onResponse?.(response),
2660
+ onChunk: (chunk) => optionsRef.current.onChunk?.(chunk),
2661
+ onFinish: (message) => {
2662
+ optionsRef.current.onFinish?.(message);
1570
2663
  },
1571
- onError: (e) => {
1572
- T.current.onError?.(e);
2664
+ onError: (error2) => {
2665
+ optionsRef.current.onError?.(error2);
1573
2666
  },
1574
- tools: T.current.tools,
1575
- onCustomEvent: (e, t, n) => T.current.onCustomEvent?.(e, t, n),
1576
- streamProcessor: e.streamProcessor,
1577
- onMessagesChange: (e) => {
1578
- u(e);
2667
+ tools: optionsRef.current.tools,
2668
+ onCustomEvent: (eventType, data, context) => optionsRef.current.onCustomEvent?.(eventType, data, context),
2669
+ streamProcessor: options.streamProcessor,
2670
+ onMessagesChange: (newMessages) => {
2671
+ setMessages(newMessages);
1579
2672
  },
1580
- onLoadingChange: (e) => {
1581
- f(e);
2673
+ onLoadingChange: (newIsLoading) => {
2674
+ setIsLoading(newIsLoading);
1582
2675
  },
1583
- onErrorChange: (e) => {
1584
- m(e);
2676
+ onErrorChange: (newError) => {
2677
+ setError(newError);
1585
2678
  },
1586
- onStatusChange: (e) => {
1587
- g(e);
2679
+ onStatusChange: (status2) => {
2680
+ setStatus(status2);
1588
2681
  },
1589
- onSubscriptionChange: (e) => {
1590
- v(e);
2682
+ onSubscriptionChange: (nextIsSubscribed) => {
2683
+ setIsSubscribed(nextIsSubscribed);
1591
2684
  },
1592
- onConnectionStatusChange: (e) => {
1593
- b(e);
2685
+ onConnectionStatusChange: (nextStatus) => {
2686
+ setConnectionStatus(nextStatus);
1594
2687
  },
1595
- onSessionGeneratingChange: (e) => {
1596
- S(e);
2688
+ onSessionGeneratingChange: (isGenerating) => {
2689
+ setSessionGenerating(isGenerating);
1597
2690
  }
1598
2691
  });
1599
- }, [c]);
1600
- r(() => {
1601
- E.updateOptions({ body: e.body });
1602
- }, [E, e.body]), r(() => {
1603
- e.initialMessages && e.initialMessages.length > 0 && l.length === 0 && E.setMessagesManually(e.initialMessages);
1604
- }, []), r(() => {
1605
- e.live ? E.subscribe() : E.unsubscribe();
1606
- }, [E, e.live]), r(() => () => {
1607
- e.live ? E.unsubscribe() : E.stop();
1608
- }, [E, e.live]);
1609
- let D = n(async (e) => {
1610
- await E.sendMessage(e);
1611
- }, [E]), O = n(async (e) => {
1612
- await E.append(e);
1613
- }, [E]), k = n(async () => {
1614
- await E.reload();
1615
- }, [E]), A = n(() => {
1616
- E.stop();
1617
- }, [E]), j = n(() => {
1618
- E.clear();
1619
- }, [E]);
2692
+ }, [clientId]);
2693
+ useEffect(() => {
2694
+ client.updateOptions({ body: options.body });
2695
+ }, [client, options.body]);
2696
+ useEffect(() => {
2697
+ if (options.initialMessages && options.initialMessages.length > 0) {
2698
+ if (messages.length === 0) client.setMessagesManually(options.initialMessages);
2699
+ }
2700
+ }, []);
2701
+ useEffect(() => {
2702
+ if (options.live) client.subscribe();
2703
+ else client.unsubscribe();
2704
+ }, [client, options.live]);
2705
+ useEffect(() => {
2706
+ return () => {
2707
+ if (options.live) client.unsubscribe();
2708
+ else client.stop();
2709
+ };
2710
+ }, [client, options.live]);
2711
+ const sendMessage = useCallback(async (content) => {
2712
+ await client.sendMessage(content);
2713
+ }, [client]);
2714
+ const append = useCallback(async (message) => {
2715
+ await client.append(message);
2716
+ }, [client]);
2717
+ const reload = useCallback(async () => {
2718
+ await client.reload();
2719
+ }, [client]);
2720
+ const stop = useCallback(() => {
2721
+ client.stop();
2722
+ }, [client]);
2723
+ const clear = useCallback(() => {
2724
+ client.clear();
2725
+ }, [client]);
1620
2726
  return {
1621
- messages: l,
1622
- sendMessage: D,
1623
- append: O,
1624
- reload: k,
1625
- stop: A,
1626
- isLoading: d,
1627
- error: p,
1628
- status: h,
1629
- isSubscribed: _,
1630
- connectionStatus: y,
1631
- sessionGenerating: x,
1632
- setMessages: n((e) => {
1633
- E.setMessagesManually(e);
1634
- }, [E]),
1635
- clear: j,
1636
- addToolResult: n(async (e) => {
1637
- await E.addToolResult(e);
1638
- }, [E]),
1639
- addToolApprovalResponse: n(async (e) => {
1640
- await E.addToolApprovalResponse(e);
1641
- }, [E])
2727
+ messages,
2728
+ sendMessage,
2729
+ append,
2730
+ reload,
2731
+ stop,
2732
+ isLoading,
2733
+ error,
2734
+ status,
2735
+ isSubscribed,
2736
+ connectionStatus,
2737
+ sessionGenerating,
2738
+ setMessages: useCallback((newMessages) => {
2739
+ client.setMessagesManually(newMessages);
2740
+ }, [client]),
2741
+ clear,
2742
+ addToolResult: useCallback(async (result) => {
2743
+ await client.addToolResult(result);
2744
+ }, [client]),
2745
+ addToolApprovalResponse: useCallback(async (response) => {
2746
+ await client.addToolApprovalResponse(response);
2747
+ }, [client])
1642
2748
  };
1643
2749
  }
1644
- (/* @__PURE__ */ new Uint8Array(128)).fill(128), t(null);
2750
+ (/* @__PURE__ */ new Uint8Array(128)).fill(128);
2751
+ createContext(null);
1645
2752
  //#endregion
1646
- //#region ../../node_modules/.pnpm/@tanstack+ai-react-ui@0.6.2_@tanstack+ai-client@0.8.0_@tanstack+ai-react@0.8.0_@tanstac_faab93d927ce4b35707b996a3d98975c/node_modules/@tanstack/ai-react-ui/dist/esm/thinking-part.js
1647
- function ThinkingPart({ content: e, className: t = "", isComplete: n = !1 }) {
1648
- let [i, a] = s(!1);
1649
- return r(() => {
1650
- n && a(!0);
1651
- }, [n]), /* @__PURE__ */ u("div", {
1652
- className: t || void 0,
2753
+ //#region ../../node_modules/.pnpm/@tanstack+ai-react-ui@0.6.2_@tanstack+ai-client@0.8.0_@tanstack+ai-react@0.8.0_@tanstac_f31ad401e8e50c178d70c0e33691bf47/node_modules/@tanstack/ai-react-ui/dist/esm/thinking-part.js
2754
+ function ThinkingPart({ content, className = "", isComplete = false }) {
2755
+ const [isCollapsed, setIsCollapsed] = useState(false);
2756
+ useEffect(() => {
2757
+ if (isComplete) setIsCollapsed(true);
2758
+ }, [isComplete]);
2759
+ return /* @__PURE__ */ jsxs("div", {
2760
+ className: className || void 0,
1653
2761
  "data-part-type": "thinking",
1654
- "data-part-content": !0,
1655
- children: [/* @__PURE__ */ u("button", {
1656
- onClick: () => a(!i),
2762
+ "data-part-content": true,
2763
+ children: [/* @__PURE__ */ jsxs("button", {
2764
+ onClick: () => setIsCollapsed(!isCollapsed),
1657
2765
  className: "flex items-center gap-2 text-sm text-gray-400 hover:text-gray-300 transition-colors mb-2",
1658
- "aria-expanded": !i,
1659
- "aria-label": i ? "Expand thinking" : "Collapse thinking",
2766
+ "aria-expanded": !isCollapsed,
2767
+ "aria-label": isCollapsed ? "Expand thinking" : "Collapse thinking",
1660
2768
  children: [
1661
- /* @__PURE__ */ l("span", {
2769
+ /* @__PURE__ */ jsx("span", {
1662
2770
  className: "text-xs",
1663
- children: i ? "▶" : "▼"
2771
+ children: isCollapsed ? "▶" : "▼"
1664
2772
  }),
1665
- /* @__PURE__ */ l("span", {
2773
+ /* @__PURE__ */ jsx("span", {
1666
2774
  className: "italic",
1667
2775
  children: "💭 Thinking..."
1668
2776
  }),
1669
- n && /* @__PURE__ */ l("span", {
2777
+ isComplete && /* @__PURE__ */ jsx("span", {
1670
2778
  className: "text-xs text-gray-500",
1671
2779
  children: "(complete)"
1672
2780
  })
1673
2781
  ]
1674
- }), !i && /* @__PURE__ */ l("div", {
2782
+ }), !isCollapsed && /* @__PURE__ */ jsx("div", {
1675
2783
  className: "text-gray-300 whitespace-pre-wrap font-mono text-sm",
1676
- children: e
2784
+ children: content
1677
2785
  })]
1678
2786
  });
1679
2787
  }
1680
2788
  //#endregion
1681
- //#region ../../node_modules/.pnpm/@tanstack+ai-react-ui@0.6.2_@tanstack+ai-client@0.8.0_@tanstack+ai-react@0.8.0_@tanstac_faab93d927ce4b35707b996a3d98975c/node_modules/@tanstack/ai-react-ui/dist/esm/chat-message.js
1682
- function ChatMessage({ message: e, className: t = "", userClassName: n = "", assistantClassName: r = "", textPartRenderer: i, thinkingPartRenderer: a, toolsRenderer: o, defaultToolRenderer: s, toolResultRenderer: c }) {
1683
- let u = [t, e.role === "user" ? n : r].filter(Boolean).join(" ");
1684
- return /* @__PURE__ */ l("div", {
1685
- className: u || void 0,
1686
- "data-message-id": e.id,
1687
- "data-message-role": e.role,
1688
- "data-message-created": e.createdAt?.toISOString(),
1689
- children: e.parts.map((t, n) => {
1690
- let r = t.type === "thinking" && e.parts.slice(n + 1).some((e) => e.type === "text");
1691
- return /* @__PURE__ */ l(MessagePart, {
1692
- part: t,
1693
- isThinkingComplete: r,
1694
- textPartRenderer: i,
1695
- thinkingPartRenderer: a,
1696
- toolsRenderer: o,
1697
- defaultToolRenderer: s,
1698
- toolResultRenderer: c
1699
- }, `${e.id}-part-${n}`);
2789
+ //#region ../../node_modules/.pnpm/@tanstack+ai-react-ui@0.6.2_@tanstack+ai-client@0.8.0_@tanstack+ai-react@0.8.0_@tanstac_f31ad401e8e50c178d70c0e33691bf47/node_modules/@tanstack/ai-react-ui/dist/esm/chat-message.js
2790
+ function ChatMessage({ message, className = "", userClassName = "", assistantClassName = "", textPartRenderer, thinkingPartRenderer, toolsRenderer, defaultToolRenderer, toolResultRenderer }) {
2791
+ const combinedClassName = [className, message.role === "user" ? userClassName : assistantClassName].filter(Boolean).join(" ");
2792
+ return /* @__PURE__ */ jsx("div", {
2793
+ className: combinedClassName || void 0,
2794
+ "data-message-id": message.id,
2795
+ "data-message-role": message.role,
2796
+ "data-message-created": message.createdAt?.toISOString(),
2797
+ children: message.parts.map((part, index) => {
2798
+ const isThinkingComplete = part.type === "thinking" && message.parts.slice(index + 1).some((p) => p.type === "text");
2799
+ return /* @__PURE__ */ jsx(MessagePart, {
2800
+ part,
2801
+ isThinkingComplete,
2802
+ textPartRenderer,
2803
+ thinkingPartRenderer,
2804
+ toolsRenderer,
2805
+ defaultToolRenderer,
2806
+ toolResultRenderer
2807
+ }, `${message.id}-part-${index}`);
1700
2808
  })
1701
2809
  });
1702
2810
  }
1703
- function MessagePart({ part: e, isThinkingComplete: t, textPartRenderer: n, thinkingPartRenderer: r, toolsRenderer: i, defaultToolRenderer: a, toolResultRenderer: o }) {
1704
- if (e.type === "text") return n ? /* @__PURE__ */ l(c, { children: n({ content: e.content }) }) : /* @__PURE__ */ l("div", {
1705
- "data-part-type": "text",
1706
- "data-part-content": !0,
1707
- children: e.content
1708
- });
1709
- if (e.type === "thinking") return r ? /* @__PURE__ */ l(c, { children: r({
1710
- content: e.content,
1711
- isComplete: t
1712
- }) }) : /* @__PURE__ */ l(ThinkingPart, {
1713
- content: e.content,
1714
- isComplete: t
1715
- });
1716
- if (e.type === "tool-call") {
1717
- let t = {
1718
- id: e.id,
1719
- name: e.name,
1720
- arguments: e.arguments,
1721
- state: e.state,
1722
- approval: e.approval,
1723
- output: e.output
2811
+ function MessagePart({ part, isThinkingComplete, textPartRenderer, thinkingPartRenderer, toolsRenderer, defaultToolRenderer, toolResultRenderer }) {
2812
+ if (part.type === "text") {
2813
+ if (textPartRenderer) return /* @__PURE__ */ jsx(Fragment$1, { children: textPartRenderer({ content: part.content }) });
2814
+ return /* @__PURE__ */ jsx("div", {
2815
+ "data-part-type": "text",
2816
+ "data-part-content": true,
2817
+ children: part.content
2818
+ });
2819
+ }
2820
+ if (part.type === "thinking") {
2821
+ if (thinkingPartRenderer) return /* @__PURE__ */ jsx(Fragment$1, { children: thinkingPartRenderer({
2822
+ content: part.content,
2823
+ isComplete: isThinkingComplete
2824
+ }) });
2825
+ return /* @__PURE__ */ jsx(ThinkingPart, {
2826
+ content: part.content,
2827
+ isComplete: isThinkingComplete
2828
+ });
2829
+ }
2830
+ if (part.type === "tool-call") {
2831
+ const toolProps = {
2832
+ id: part.id,
2833
+ name: part.name,
2834
+ arguments: part.arguments,
2835
+ state: part.state,
2836
+ approval: part.approval,
2837
+ output: part.output
1724
2838
  };
1725
- return i?.[e.name] ? /* @__PURE__ */ l(c, { children: i[e.name]?.(t) }) : a ? /* @__PURE__ */ l(c, { children: a(t) }) : /* @__PURE__ */ u("div", {
2839
+ if (toolsRenderer?.[part.name]) return /* @__PURE__ */ jsx(Fragment$1, { children: toolsRenderer[part.name]?.(toolProps) });
2840
+ if (defaultToolRenderer) return /* @__PURE__ */ jsx(Fragment$1, { children: defaultToolRenderer(toolProps) });
2841
+ return /* @__PURE__ */ jsxs("div", {
1726
2842
  "data-part-type": "tool-call",
1727
- "data-tool-name": e.name,
1728
- "data-tool-state": e.state,
1729
- "data-tool-id": e.id,
2843
+ "data-tool-name": part.name,
2844
+ "data-tool-state": part.state,
2845
+ "data-tool-id": part.id,
1730
2846
  children: [
1731
- /* @__PURE__ */ u("div", {
1732
- "data-tool-header": !0,
1733
- children: [/* @__PURE__ */ l("strong", { children: e.name }), /* @__PURE__ */ l("span", {
1734
- "data-tool-state-badge": !0,
1735
- children: e.state
2847
+ /* @__PURE__ */ jsxs("div", {
2848
+ "data-tool-header": true,
2849
+ children: [/* @__PURE__ */ jsx("strong", { children: part.name }), /* @__PURE__ */ jsx("span", {
2850
+ "data-tool-state-badge": true,
2851
+ children: part.state
1736
2852
  })]
1737
2853
  }),
1738
- e.arguments && /* @__PURE__ */ l("div", {
1739
- "data-tool-arguments": !0,
1740
- children: /* @__PURE__ */ l("pre", { children: e.arguments })
2854
+ part.arguments && /* @__PURE__ */ jsx("div", {
2855
+ "data-tool-arguments": true,
2856
+ children: /* @__PURE__ */ jsx("pre", { children: part.arguments })
1741
2857
  }),
1742
- e.approval && /* @__PURE__ */ l("div", {
1743
- "data-tool-approval": !0,
1744
- children: e.approval.approved === void 0 ? "⏳ Awaiting approval..." : e.approval.approved ? "✓ Approved" : "✗ Denied"
2858
+ part.approval && /* @__PURE__ */ jsx("div", {
2859
+ "data-tool-approval": true,
2860
+ children: part.approval.approved !== void 0 ? part.approval.approved ? "✓ Approved" : "✗ Denied" : "⏳ Awaiting approval..."
1745
2861
  }),
1746
- e.output && /* @__PURE__ */ l("div", {
1747
- "data-tool-output": !0,
1748
- children: /* @__PURE__ */ l("pre", { children: JSON.stringify(e.output, null, 2) })
2862
+ part.output && /* @__PURE__ */ jsx("div", {
2863
+ "data-tool-output": true,
2864
+ children: /* @__PURE__ */ jsx("pre", { children: JSON.stringify(part.output, null, 2) })
1749
2865
  })
1750
2866
  ]
1751
2867
  });
1752
2868
  }
1753
- return e.type === "tool-result" ? o ? /* @__PURE__ */ l(c, { children: o({
1754
- toolCallId: e.toolCallId,
1755
- content: e.content,
1756
- state: e.state
1757
- }) }) : /* @__PURE__ */ l("div", {
1758
- "data-part-type": "tool-result",
1759
- "data-tool-call-id": e.toolCallId,
1760
- "data-tool-result-state": e.state,
1761
- children: /* @__PURE__ */ l("div", {
1762
- "data-tool-result-content": !0,
1763
- children: e.content
1764
- })
1765
- }) : null;
2869
+ if (part.type === "tool-result") {
2870
+ if (toolResultRenderer) return /* @__PURE__ */ jsx(Fragment$1, { children: toolResultRenderer({
2871
+ toolCallId: part.toolCallId,
2872
+ content: part.content,
2873
+ state: part.state
2874
+ }) });
2875
+ return /* @__PURE__ */ jsx("div", {
2876
+ "data-part-type": "tool-result",
2877
+ "data-tool-call-id": part.toolCallId,
2878
+ "data-tool-result-state": part.state,
2879
+ children: /* @__PURE__ */ jsx("div", {
2880
+ "data-tool-result-content": true,
2881
+ children: part.content
2882
+ })
2883
+ });
2884
+ }
2885
+ return null;
1766
2886
  }
1767
2887
  //#endregion
1768
2888
  export { toolDefinition as a, fetchServerSentEvents as i, useChat as n, clientTools as r, ChatMessage as t };