@astralbeam/sdk 0.20.3 → 0.22.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.
@@ -1,4 +1,4 @@
1
- import { A as getCurrentUser, At as personalMcpTestConnection, Bt as astralBeamChatFetch, C as getChatConfig, Ct as personalMcpAuthorizeConnection, Dt as personalMcpDisconnectConnection, Et as personalMcpCreateConnection, Ht as resolveApiUrl, It as updateChatThread, Ot as personalMcpGetCatalog, S as getChatAttachment, Tt as personalMcpCompleteAuthorization, Vt as isAstralBeamApiError, at as getResolveChatToolResultUrl, gt as listChatMessages, kt as personalMcpSetHeaders, ot as getRunChatUrl, v as createChatThread, vt as listChatThreads, w as getChatFile, wt as personalMcpBindBrowser, x as deleteChatThread, zt as uploadChatFile } from "./api-B3UxSTtl.js";
1
+ import { Bt as resolveApiUrl, Ct as personalMcpCompleteAuthorization, Dt as personalMcpSetHeaders, Et as personalMcpGetCatalog, Lt as uploadChatFile, O as getCurrentUser, Ot as personalMcpTestConnection, Pt as updateChatThread, Rt as astralBeamChatFetch, S as getChatConfig, St as personalMcpBindBrowser, Tt as personalMcpDisconnectConnection, gt as listChatThreads, lt as getThreadAttachment, mt as listChatMessages, nt as getResolveChatToolResultUrl, rt as getRunChatUrl, v as createChatThread, wt as personalMcpCreateConnection, x as deleteChatThread, xt as personalMcpAuthorizeConnection, zt as isAstralBeamApiError } from "./api-SpkUzEv3.js";
2
2
  import { _ as strictDecoder, i as isObject, l as decode, p as JWTInvalid } from "./validate-BOw-BAyv.js";
3
3
  //#region \0rolldown/runtime.js
4
4
  var __defProp = Object.defineProperty;
@@ -36,7 +36,442 @@ function decodeJwt(jwt) {
36
36
  return result;
37
37
  }
38
38
  //#endregion
39
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
39
+ //#region ../node_modules/.bun/@tanstack+store@0.11.2/node_modules/@tanstack/store/dist/alien.js
40
+ /* @__NO_SIDE_EFFECTS__ */
41
+ function createReactiveSystem({ update, notify, unwatched }) {
42
+ return {
43
+ link,
44
+ unlink,
45
+ propagate,
46
+ checkDirty,
47
+ shallowPropagate
48
+ };
49
+ function link(dep, sub, version) {
50
+ const prevDep = sub.depsTail;
51
+ if (prevDep !== void 0 && prevDep.dep === dep) return;
52
+ const nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;
53
+ if (nextDep !== void 0 && nextDep.dep === dep) {
54
+ nextDep.version = version;
55
+ sub.depsTail = nextDep;
56
+ return;
57
+ }
58
+ const prevSub = dep.subsTail;
59
+ if (prevSub !== void 0 && prevSub.version === version && prevSub.sub === sub) return;
60
+ const newLink = sub.depsTail = dep.subsTail = {
61
+ version,
62
+ dep,
63
+ sub,
64
+ prevDep,
65
+ nextDep,
66
+ prevSub,
67
+ nextSub: void 0
68
+ };
69
+ if (nextDep !== void 0) nextDep.prevDep = newLink;
70
+ if (prevDep !== void 0) prevDep.nextDep = newLink;
71
+ else sub.deps = newLink;
72
+ if (prevSub !== void 0) prevSub.nextSub = newLink;
73
+ else dep.subs = newLink;
74
+ }
75
+ function unlink(link, sub = link.sub) {
76
+ const dep = link.dep;
77
+ const prevDep = link.prevDep;
78
+ const nextDep = link.nextDep;
79
+ const nextSub = link.nextSub;
80
+ const prevSub = link.prevSub;
81
+ if (nextDep !== void 0) nextDep.prevDep = prevDep;
82
+ else sub.depsTail = prevDep;
83
+ if (prevDep !== void 0) prevDep.nextDep = nextDep;
84
+ else sub.deps = nextDep;
85
+ if (nextSub !== void 0) nextSub.prevSub = prevSub;
86
+ else dep.subsTail = prevSub;
87
+ if (prevSub !== void 0) prevSub.nextSub = nextSub;
88
+ else if ((dep.subs = nextSub) === void 0) unwatched(dep);
89
+ return nextDep;
90
+ }
91
+ function propagate(link) {
92
+ let next = link.nextSub;
93
+ let stack;
94
+ top: do {
95
+ const sub = link.sub;
96
+ let flags = sub.flags;
97
+ if (!(flags & 60)) sub.flags = flags | 32;
98
+ else if (!(flags & 12)) flags = 0;
99
+ else if (!(flags & 4)) sub.flags = flags & -9 | 32;
100
+ else if (!(flags & 48) && isValidLink(link, sub)) {
101
+ sub.flags = flags | 40;
102
+ flags &= 1;
103
+ } else flags = 0;
104
+ if (flags & 2) notify(sub);
105
+ if (flags & 1) {
106
+ const subSubs = sub.subs;
107
+ if (subSubs !== void 0) {
108
+ const nextSub = (link = subSubs).nextSub;
109
+ if (nextSub !== void 0) {
110
+ stack = {
111
+ value: next,
112
+ prev: stack
113
+ };
114
+ next = nextSub;
115
+ }
116
+ continue;
117
+ }
118
+ }
119
+ if ((link = next) !== void 0) {
120
+ next = link.nextSub;
121
+ continue;
122
+ }
123
+ while (stack !== void 0) {
124
+ link = stack.value;
125
+ stack = stack.prev;
126
+ if (link !== void 0) {
127
+ next = link.nextSub;
128
+ continue top;
129
+ }
130
+ }
131
+ break;
132
+ } while (true);
133
+ }
134
+ function checkDirty(link, sub) {
135
+ let stack;
136
+ let checkDepth = 0;
137
+ let dirty = false;
138
+ top: do {
139
+ const dep = link.dep;
140
+ const flags = dep.flags;
141
+ if (sub.flags & 16) dirty = true;
142
+ else if ((flags & 17) === 17) {
143
+ if (update(dep)) {
144
+ const subs = dep.subs;
145
+ if (subs.nextSub !== void 0) shallowPropagate(subs);
146
+ dirty = true;
147
+ }
148
+ } else if ((flags & 33) === 33) {
149
+ if (link.nextSub !== void 0 || link.prevSub !== void 0) stack = {
150
+ value: link,
151
+ prev: stack
152
+ };
153
+ link = dep.deps;
154
+ sub = dep;
155
+ ++checkDepth;
156
+ continue;
157
+ }
158
+ if (!dirty) {
159
+ const nextDep = link.nextDep;
160
+ if (nextDep !== void 0) {
161
+ link = nextDep;
162
+ continue;
163
+ }
164
+ }
165
+ while (checkDepth--) {
166
+ const firstSub = sub.subs;
167
+ const hasMultipleSubs = firstSub.nextSub !== void 0;
168
+ if (hasMultipleSubs) {
169
+ link = stack.value;
170
+ stack = stack.prev;
171
+ } else link = firstSub;
172
+ if (dirty) {
173
+ if (update(sub)) {
174
+ if (hasMultipleSubs) shallowPropagate(firstSub);
175
+ sub = link.sub;
176
+ continue;
177
+ }
178
+ dirty = false;
179
+ } else sub.flags &= -33;
180
+ sub = link.sub;
181
+ const nextDep = link.nextDep;
182
+ if (nextDep !== void 0) {
183
+ link = nextDep;
184
+ continue top;
185
+ }
186
+ }
187
+ return dirty;
188
+ } while (true);
189
+ }
190
+ function shallowPropagate(link) {
191
+ do {
192
+ const sub = link.sub;
193
+ const flags = sub.flags;
194
+ if ((flags & 48) === 32) {
195
+ sub.flags = flags | 16;
196
+ if ((flags & 6) === 2) notify(sub);
197
+ }
198
+ } while ((link = link.nextSub) !== void 0);
199
+ }
200
+ function isValidLink(checkLink, sub) {
201
+ let link = sub.depsTail;
202
+ while (link !== void 0) {
203
+ if (link === checkLink) return true;
204
+ link = link.prevDep;
205
+ }
206
+ return false;
207
+ }
208
+ }
209
+ //#endregion
210
+ //#region ../node_modules/.bun/@tanstack+store@0.11.2/node_modules/@tanstack/store/dist/atom.js
211
+ function toObserver(nextHandler, errorHandler, completionHandler) {
212
+ const isObserver = typeof nextHandler === "object";
213
+ const self = isObserver ? nextHandler : void 0;
214
+ return {
215
+ next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
216
+ error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
217
+ complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
218
+ };
219
+ }
220
+ const queuedEffects = [];
221
+ let cycle = 0;
222
+ const { link, unlink, propagate, checkDirty, shallowPropagate } = /* @__PURE__ */ createReactiveSystem({
223
+ update(atom) {
224
+ return atom._update();
225
+ },
226
+ notify(effect) {
227
+ queuedEffects[queuedEffectsLength++] = effect;
228
+ effect.flags &= -3;
229
+ },
230
+ unwatched(atom) {
231
+ if (atom.depsTail !== void 0) {
232
+ atom.depsTail = void 0;
233
+ atom.flags = 17;
234
+ purgeDeps(atom);
235
+ }
236
+ }
237
+ });
238
+ let notifyIndex = 0;
239
+ let queuedEffectsLength = 0;
240
+ let activeSub;
241
+ function purgeDeps(sub) {
242
+ const depsTail = sub.depsTail;
243
+ let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
244
+ while (dep !== void 0) dep = unlink(dep, sub);
245
+ }
246
+ function flush() {
247
+ while (notifyIndex < queuedEffectsLength) {
248
+ const effect = queuedEffects[notifyIndex];
249
+ queuedEffects[notifyIndex++] = void 0;
250
+ effect.notify();
251
+ }
252
+ notifyIndex = 0;
253
+ queuedEffectsLength = 0;
254
+ }
255
+ function createAtom(valueOrFn, options) {
256
+ const isComputed = typeof valueOrFn === "function";
257
+ const getter = valueOrFn;
258
+ const atom = {
259
+ _snapshot: isComputed ? void 0 : valueOrFn,
260
+ subs: void 0,
261
+ subsTail: void 0,
262
+ deps: void 0,
263
+ depsTail: void 0,
264
+ flags: isComputed ? 0 : 1,
265
+ get() {
266
+ if (activeSub !== void 0) link(atom, activeSub, cycle);
267
+ return atom._snapshot;
268
+ },
269
+ subscribe(observerOrFn) {
270
+ const obs = toObserver(observerOrFn);
271
+ const observed = { current: false };
272
+ const e = effect(() => {
273
+ atom.get();
274
+ if (!observed.current) observed.current = true;
275
+ else {
276
+ activeSub = void 0;
277
+ obs.next?.(atom._snapshot);
278
+ }
279
+ });
280
+ return { unsubscribe: () => {
281
+ e.stop();
282
+ } };
283
+ },
284
+ _update(getValue) {
285
+ const prevSub = activeSub;
286
+ const compare = options?.compare ?? Object.is;
287
+ if (isComputed) {
288
+ activeSub = atom;
289
+ ++cycle;
290
+ atom.depsTail = void 0;
291
+ } else if (getValue === void 0) return false;
292
+ if (isComputed) atom.flags = 5;
293
+ try {
294
+ const oldValue = atom._snapshot;
295
+ const newValue = typeof getValue === "function" ? getValue(oldValue) : getValue === void 0 && isComputed ? getter(oldValue) : getValue;
296
+ if (oldValue === void 0 || !compare(oldValue, newValue)) {
297
+ atom._snapshot = newValue;
298
+ return true;
299
+ }
300
+ return false;
301
+ } finally {
302
+ activeSub = prevSub;
303
+ if (isComputed) atom.flags &= -5;
304
+ purgeDeps(atom);
305
+ }
306
+ }
307
+ };
308
+ if (isComputed) {
309
+ atom.flags = 17;
310
+ atom.get = function() {
311
+ const flags = atom.flags;
312
+ if (flags & 16 || flags & 32 && checkDirty(atom.deps, atom)) {
313
+ if (atom._update()) {
314
+ const subs = atom.subs;
315
+ if (subs !== void 0) shallowPropagate(subs);
316
+ }
317
+ } else if (flags & 32) atom.flags = flags & -33;
318
+ if (activeSub !== void 0) link(atom, activeSub, cycle);
319
+ return atom._snapshot;
320
+ };
321
+ } else atom.set = function(valueOrFn) {
322
+ if (atom._update(valueOrFn)) {
323
+ const subs = atom.subs;
324
+ if (subs !== void 0) {
325
+ propagate(subs);
326
+ shallowPropagate(subs);
327
+ flush();
328
+ }
329
+ }
330
+ };
331
+ return atom;
332
+ }
333
+ function effect(fn) {
334
+ const run = () => {
335
+ const prevSub = activeSub;
336
+ activeSub = effectObj;
337
+ ++cycle;
338
+ effectObj.depsTail = void 0;
339
+ effectObj.flags = 6;
340
+ try {
341
+ return fn();
342
+ } finally {
343
+ activeSub = prevSub;
344
+ effectObj.flags &= -5;
345
+ purgeDeps(effectObj);
346
+ }
347
+ };
348
+ const effectObj = {
349
+ deps: void 0,
350
+ depsTail: void 0,
351
+ subs: void 0,
352
+ subsTail: void 0,
353
+ flags: 6,
354
+ notify() {
355
+ const flags = this.flags;
356
+ if (flags & 16 || flags & 32 && checkDirty(this.deps, this)) run();
357
+ else this.flags = 2;
358
+ },
359
+ stop() {
360
+ this.flags = 0;
361
+ this.depsTail = void 0;
362
+ purgeDeps(this);
363
+ }
364
+ };
365
+ run();
366
+ return effectObj;
367
+ }
368
+ //#endregion
369
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/snapshot-atom.js
370
+ function isPlainObject(value) {
371
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
372
+ const proto = Object.getPrototypeOf(value);
373
+ return proto === Object.prototype || proto === null;
374
+ }
375
+ /**
376
+ * Report an error thrown by a listener without stopping the caller. The
377
+ * browser's `reportError` reaches `window.onerror` and error trackers. Other
378
+ * runtimes log it.
379
+ */
380
+ function reportListenerError(error) {
381
+ if (typeof globalThis.reportError === "function") globalThis.reportError(error);
382
+ else console.error(error);
383
+ }
384
+ /** Deep-freeze plain JSON. Class instances stay as they are. */
385
+ function freezePlainData(value) {
386
+ if (Array.isArray(value)) return Object.freeze(value.map(freezePlainData));
387
+ if (!isPlainObject(value)) return value;
388
+ const copy = {};
389
+ for (const key of Object.keys(value)) copy[key] = freezePlainData(value[key]);
390
+ return Object.freeze(copy);
391
+ }
392
+ /**
393
+ * Freeze a copy of one message part. Tool `input` / `output`, `source`,
394
+ * `approval`, tool-result `content`, and subagent transcripts are copies.
395
+ * A subagent `stop` function stays the live function.
396
+ */
397
+ function freezeSnapshotPart(part, cache = /* @__PURE__ */ new WeakMap()) {
398
+ const record = part;
399
+ const copy = { ...record };
400
+ if (isPlainObject(record.source)) copy.source = Object.freeze({ ...record.source });
401
+ if (record.type === "tool-call" && isPlainObject(record.approval)) copy.approval = Object.freeze({ ...record.approval });
402
+ if (record.type === "tool-result" && Array.isArray(record.content)) copy.content = Object.freeze(record.content.map((contentPart) => typeof contentPart === "object" && contentPart !== null ? freezeSnapshotPart(contentPart, cache) : contentPart));
403
+ if ("input" in record) copy.input = freezePlainData(record.input);
404
+ if ("output" in record) copy.output = freezePlainData(record.output);
405
+ if (record.type === "subagent" && isPlainObject(record.subagent)) {
406
+ const sub = record.subagent;
407
+ copy.subagent = Object.freeze(Array.isArray(sub.messages) ? {
408
+ ...sub,
409
+ messages: freezeSnapshotMessages(cache, sub.messages)
410
+ } : { ...sub });
411
+ }
412
+ return Object.freeze(copy);
413
+ }
414
+ function cached(cache, value, freeze) {
415
+ let frozen = cache.get(value);
416
+ if (!frozen) {
417
+ frozen = freeze(value);
418
+ cache.set(value, frozen);
419
+ }
420
+ return frozen;
421
+ }
422
+ /**
423
+ * Freeze a copy of each message and its parts. The client replaces a message
424
+ * or a part object when it changes, so `cache` gives an unchanged message or
425
+ * part the same frozen copy. UI memo keys on message identity, and a streamed
426
+ * token copies only the part that changed.
427
+ */
428
+ function freezeSnapshotMessages(cache, messages) {
429
+ return Object.freeze(messages.map((message) => cached(cache, message, () => Object.freeze({
430
+ ...message,
431
+ parts: Object.freeze(message.parts.map((part) => cached(cache, part, () => freezeSnapshotPart(part, cache))))
432
+ }))));
433
+ }
434
+ /**
435
+ * Merge a partial update into an object atom and freeze the result. Skips
436
+ * notify when every provided field is `Object.is`-equal to the current value.
437
+ */
438
+ function patchAtom(atom, patch) {
439
+ atom.set((prev) => {
440
+ let changed = false;
441
+ const next = { ...prev };
442
+ for (const key of Object.keys(patch)) {
443
+ if (Object.is(prev[key], patch[key])) continue;
444
+ next[key] = patch[key];
445
+ changed = true;
446
+ }
447
+ return changed ? Object.freeze(next) : prev;
448
+ });
449
+ }
450
+ var MAX_LISTENER_REENTRY = 8;
451
+ /**
452
+ * Subscribe to an atom with the `() => void` unsubscribe that framework
453
+ * stores expect.
454
+ */
455
+ function subscribeAtom(atom, listener) {
456
+ const { unsubscribe } = atom.subscribe(() => {
457
+ let seen;
458
+ let spins = 0;
459
+ do {
460
+ seen = atom.get();
461
+ try {
462
+ listener();
463
+ } catch (error) {
464
+ reportListenerError(error);
465
+ }
466
+ spins++;
467
+ } while (atom.get() !== seen && spins < MAX_LISTENER_REENTRY);
468
+ });
469
+ return unsubscribe;
470
+ }
471
+ new TextEncoder();
472
+ new TextDecoder();
473
+ //#endregion
474
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
40
475
  var UnsupportedResponseStreamError = class extends Error {
41
476
  missingFeature;
42
477
  constructor(missingFeature) {
@@ -58,14 +493,14 @@ function createResponseStreamTextDecoder() {
58
493
  return new globalThis.TextDecoder();
59
494
  }
60
495
  //#endregion
61
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/sse-utils.js
496
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/sse-utils.js
62
497
  function parseSseDataLine(line) {
63
498
  if (!line.startsWith("data:")) return line;
64
499
  const data = line.slice(5);
65
500
  return data.startsWith(" ") ? data.slice(1) : data;
66
501
  }
67
502
  //#endregion
68
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/message-date-normalizer.js
503
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/message-date-normalizer.js
69
504
  function validDate(value) {
70
505
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value;
71
506
  if (typeof value !== "string") return void 0;
@@ -97,7 +532,7 @@ function normalizeMessagesDates(messages) {
97
532
  return messages.map(normalizeMessageDates);
98
533
  }
99
534
  //#endregion
100
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-usage.js
535
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-usage.js
101
536
  function definedDetails(value) {
102
537
  return Object.keys(value).length > 0 ? value : void 0;
103
538
  }
@@ -142,7 +577,7 @@ function fromSpecTokenUsage(usage, leftover) {
142
577
  };
143
578
  }
144
579
  //#endregion
145
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/merge-metadata.js
580
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/merge-metadata.js
146
581
  function isPlainRecord$1(value) {
147
582
  return value != null && typeof value === "object" && !Array.isArray(value);
148
583
  }
@@ -221,7 +656,172 @@ let EventType = /* @__PURE__ */ function(EventType) {
221
656
  return EventType;
222
657
  }({});
223
658
  //#endregion
224
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/reasoning-encrypted-value.js
659
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/tool-call-arguments.js
660
+ function sameJsonValue(left, right) {
661
+ if (Object.is(left, right)) return true;
662
+ if (Array.isArray(left) && Array.isArray(right)) return left.length === right.length && left.every((value, index) => sameJsonValue(value, right[index]));
663
+ if (left === null || right === null || typeof left !== "object" || typeof right !== "object" || Array.isArray(left) || Array.isArray(right)) return false;
664
+ const leftKeys = Object.keys(left);
665
+ const rightKeys = Object.keys(right);
666
+ return leftKeys.length === rightKeys.length && leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && sameJsonValue(Reflect.get(left, key), Reflect.get(right, key)));
667
+ }
668
+ function scanJson(raw, parsed) {
669
+ let cursor = 0;
670
+ const whitespace = () => {
671
+ while (raw[cursor] === " " || raw[cursor] === " " || raw[cursor] === "\r" || raw[cursor] === "\n") cursor++;
672
+ };
673
+ const stringToken = () => {
674
+ const start = cursor++;
675
+ while (cursor < raw.length) if (raw[cursor] === "\\") cursor += 2;
676
+ else if (raw[cursor++] === "\"") break;
677
+ return raw.slice(start, cursor);
678
+ };
679
+ const value = (parsedValue) => {
680
+ whitespace();
681
+ const start = cursor;
682
+ if (raw[cursor] === "{") {
683
+ cursor++;
684
+ whitespace();
685
+ const properties = /* @__PURE__ */ new Map();
686
+ while (raw[cursor] !== "}") {
687
+ const keyToken = stringToken();
688
+ const key = JSON.parse(keyToken);
689
+ whitespace();
690
+ cursor++;
691
+ const child = parsedValue !== null && typeof parsedValue === "object" && typeof key === "string" ? Reflect.get(parsedValue, key) : void 0;
692
+ const childNode = value(child);
693
+ if (typeof key === "string") properties.set(key, {
694
+ ...childNode,
695
+ keyToken
696
+ });
697
+ whitespace();
698
+ if (raw[cursor] !== ",") break;
699
+ cursor++;
700
+ whitespace();
701
+ }
702
+ cursor++;
703
+ return {
704
+ start,
705
+ end: cursor,
706
+ value: parsedValue,
707
+ properties
708
+ };
709
+ }
710
+ if (raw[cursor] === "[") {
711
+ cursor++;
712
+ whitespace();
713
+ const items = [];
714
+ while (raw[cursor] !== "]") {
715
+ items.push(value(Array.isArray(parsedValue) ? parsedValue[items.length] : void 0));
716
+ whitespace();
717
+ if (raw[cursor] !== ",") break;
718
+ cursor++;
719
+ }
720
+ cursor++;
721
+ return {
722
+ start,
723
+ end: cursor,
724
+ value: parsedValue,
725
+ items
726
+ };
727
+ }
728
+ if (raw[cursor] === "\"") stringToken();
729
+ else while (cursor < raw.length && !/[\s,}\]]/.test(raw[cursor] ?? "")) cursor++;
730
+ return {
731
+ start,
732
+ end: cursor,
733
+ value: parsedValue
734
+ };
735
+ };
736
+ return value(parsed);
737
+ }
738
+ function serializeValue(value, raw, node, seen) {
739
+ if (node && sameJsonValue(node.value, value)) return raw.slice(node.start, node.end);
740
+ if (typeof value === "number") {
741
+ if (Object.is(value, -0)) return "-0";
742
+ if (value === Infinity) return "1e999";
743
+ if (value === -Infinity) return "-1e999";
744
+ return JSON.stringify(value);
745
+ }
746
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
747
+ if (seen.has(value)) throw new TypeError("Cannot serialize circular tool input");
748
+ seen.add(value);
749
+ try {
750
+ if (Array.isArray(value)) return "[" + Array.from(value, (item, index) => serializeValue(item, raw, node?.items?.[index], seen) ?? "null").join(",") + "]";
751
+ const properties = [];
752
+ for (const key of Object.keys(value)) {
753
+ const serialized = serializeValue(Reflect.get(value, key), raw, node?.properties?.get(key), seen);
754
+ if (serialized !== void 0) properties.push((node?.properties?.get(key)?.keyToken ?? JSON.stringify(key)) + ":" + serialized);
755
+ }
756
+ return "{" + properties.join(",") + "}";
757
+ } finally {
758
+ seen.delete(value);
759
+ }
760
+ }
761
+ /**
762
+ * Keep `raw` when it is the same JSON value as `input`. When they differ,
763
+ * write `input` again and keep the raw tokens of the values that did not
764
+ * change. Empty or missing raw arguments use the input.
765
+ */
766
+ function reconcileToolCallArguments(raw, input) {
767
+ if (input === void 0) return raw ?? "";
768
+ if (raw === void 0) return serializeValue(input, "", void 0, /* @__PURE__ */ new Set()) ?? "";
769
+ let parsed;
770
+ try {
771
+ parsed = JSON.parse(raw);
772
+ } catch {
773
+ if (raw.trim() === "") return serializeValue(input, "", void 0, /* @__PURE__ */ new Set()) ?? raw;
774
+ return raw;
775
+ }
776
+ if (sameJsonValue(parsed, input)) return raw;
777
+ return serializeValue(input, raw, scanJson(raw, parsed), /* @__PURE__ */ new Set()) ?? raw;
778
+ }
779
+ /**
780
+ * The input of a tool call from its raw arguments: `{}` for an empty string,
781
+ * `undefined` when the arguments are not complete JSON (for example cut off)
782
+ * or are `null`.
783
+ */
784
+ function parseToolArguments(args) {
785
+ if (args.trim() === "") return {};
786
+ try {
787
+ return JSON.parse(args) ?? void 0;
788
+ } catch {
789
+ return;
790
+ }
791
+ }
792
+ /**
793
+ * The final arguments and input of a tool call at TOOL_CALL_END. `streamed`
794
+ * is the text of its TOOL_CALL_ARGS deltas. The END's raw `args` (the
795
+ * provider's own string) win over it, and stay as they are when they are the
796
+ * same JSON value as the END's `input`. Malformed arguments also stay, so the
797
+ * tool reports the error and the model can repair them. `input` is always
798
+ * the parse of `args`.
799
+ */
800
+ function finishToolCallArguments(streamed, end) {
801
+ const metadata = tanstackMetadata(end);
802
+ const endArgs = end.args ?? metadata?.args;
803
+ const rawArgs = typeof endArgs === "string" ? endArgs : void 0;
804
+ const endInput = end.input ?? metadata?.input;
805
+ const input = endInput !== null && typeof endInput === "object" ? endInput : void 0;
806
+ let raw = rawArgs ?? streamed;
807
+ if (rawArgs === void 0 && input !== void 0) try {
808
+ JSON.parse(raw);
809
+ } catch {
810
+ raw = void 0;
811
+ }
812
+ let args;
813
+ try {
814
+ args = reconcileToolCallArguments(raw, input);
815
+ } catch {
816
+ args = raw ?? streamed;
817
+ }
818
+ return {
819
+ args,
820
+ input: parseToolArguments(args)
821
+ };
822
+ }
823
+ //#endregion
824
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/reasoning-encrypted-value.js
225
825
  /**
226
826
  * Id prefix for the reasoning message of a redacted thinking block (Anthropic
227
827
  * `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of
@@ -233,7 +833,7 @@ function isRedactedThinkingId(id) {
233
833
  return typeof id === "string" && id.startsWith("redacted_thinking-");
234
834
  }
235
835
  //#endregion
236
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-serialization.js
836
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-serialization.js
237
837
  var SHA256_K = new Uint32Array([
238
838
  1116352408,
239
839
  1899447441,
@@ -408,7 +1008,7 @@ function cloneAndDeepFreezeJson(value) {
408
1008
  return clone;
409
1009
  }
410
1010
  //#endregion
411
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupts.js
1011
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupts.js
412
1012
  function canonicalizeInterruptResolutions(resolutions) {
413
1013
  const frozen = cloneAndDeepFreezeJson([...resolutions].sort((left, right) => left.interruptId.localeCompare(right.interruptId)));
414
1014
  const canonicalResolutions = canonicalInterruptJson(frozen);
@@ -419,7 +1019,7 @@ function canonicalizeInterruptResolutions(resolutions) {
419
1019
  });
420
1020
  }
421
1021
  //#endregion
422
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/schema-converter.js
1022
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/schema-converter.js
423
1023
  /**
424
1024
  * Build a JSONSchema object from any plain key/value source. The `JSONSchema`
425
1025
  * interface's `[key: string]: any` index signature makes every property
@@ -687,7 +1287,7 @@ async function validateWithStandardSchema(schema, data) {
687
1287
  };
688
1288
  }
689
1289
  //#endregion
690
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/approval-schema.js
1290
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/approval-schema.js
691
1291
  var jsonSchemaKeywords = /* @__PURE__ */ new Set([
692
1292
  "$schema",
693
1293
  "$id",
@@ -801,7 +1401,7 @@ function hashSchemaInput(schema) {
801
1401
  return digestInterruptJson(canonicalInterruptJson(schemaToWire(schema).jsonSchema ?? { standardValidator: "unserialized" }));
802
1402
  }
803
1403
  //#endregion
804
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-resume.js
1404
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-resume.js
805
1405
  /**
806
1406
  * The `Interrupt.metadata` key under which this package's resume binding
807
1407
  * travels.
@@ -922,7 +1522,7 @@ function readInterruptBinding(descriptor) {
922
1522
  };
923
1523
  }
924
1524
  //#endregion
925
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-definition.js
1525
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/interrupt-definition.js
926
1526
  var INTERRUPT_PAYLOAD_METADATA_KEY = "tanstack:interruptPayload";
927
1527
  function schemaJson(schema, name) {
928
1528
  if (!isStandardJSONSchema(schema)) throw new TypeError(`${name} must be a Standard Schema with a JSON Schema converter.`);
@@ -947,7 +1547,7 @@ function hashInterruptDefinitionSchema(schema) {
947
1547
  return digestInterruptJson(schemaJson(schema, "Interrupt schema").canonicalJson);
948
1548
  }
949
1549
  //#endregion
950
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/generic-interrupt-continuation.js
1550
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/generic-interrupt-continuation.js
951
1551
  /**
952
1552
  * `ResumeEntry.metadata` key for a first-party generic request.
953
1553
  *
@@ -986,100 +1586,19 @@ function genericInterruptContinuationFromDescriptor(interrupt) {
986
1586
  };
987
1587
  }
988
1588
  //#endregion
989
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/provider-executed.js
990
- /**
991
- * Narrow a tool call's opaque `metadata` to the provider-executed convention.
992
- * Returns the typed metadata when the call is provider-executed, else `null`.
993
- *
994
- * @see ProviderExecutedToolMetadata
995
- */
996
- function getProviderExecutedMetadata(toolCall) {
997
- const metadata = toolCall?.metadata;
998
- if (typeof metadata === "object" && metadata !== null && metadata.providerExecuted === true) return metadata;
999
- return null;
1000
- }
1001
- /**
1002
- * True when a tool call was executed by the provider (e.g. Anthropic
1003
- * `web_search` / `web_fetch` server tools) rather than the agent loop. Such
1004
- * calls must not be routed to client-side execution and are already "complete".
1005
- */
1006
- function isProviderExecutedToolCall(toolCall) {
1007
- return getProviderExecutedMetadata(toolCall) !== null;
1008
- }
1009
- /**
1010
- * True when `id` is a `${parentId}-segment-${n}` message. The wire and the
1011
- * run loop split one provider turn into segments at thinking that follows a
1012
- * provider-executed tool call, to keep signed thinking order. Readers fold a
1013
- * segment back into its parent so the UI still shows one message.
1014
- */
1015
- function isAssistantSegmentOf(id, parentId) {
1016
- return id?.startsWith(`${parentId}-segment-`) === true;
1017
- }
1018
- //#endregion
1019
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/tool-result.js
1020
- var CONTENT_PART_TYPES = /* @__PURE__ */ new Set([
1021
- "text",
1022
- "image",
1023
- "audio",
1024
- "video",
1025
- "document"
1026
- ]);
1027
- function isToolResultOutcome(value) {
1028
- return value === "cancelled" || value === "denied";
1029
- }
1030
- /**
1031
- * Structural check for a single `ContentPart`. A text part must carry a string
1032
- * `content`. Every other part carries a source with a string `value`; a file
1033
- * source's `value` is a non-empty opaque handle, and its optional `provider`
1034
- * is a string.
1035
- */
1036
- function isContentPart$1(value) {
1037
- if (typeof value !== "object" || value === null) return false;
1038
- const part = value;
1039
- if (typeof part.type !== "string" || !CONTENT_PART_TYPES.has(part.type)) return false;
1040
- if (part.type === "text") return typeof part.content === "string";
1041
- const source = part.source;
1042
- if (typeof source !== "object" || source === null) return false;
1043
- const src = source;
1044
- if (typeof src.value !== "string") return false;
1045
- if (src.type === "file") return src.value.length > 0 && (src.provider === void 0 || typeof src.provider === "string");
1046
- if (src.type === "data") return typeof src.mimeType === "string";
1047
- return src.type === "url";
1048
- }
1049
- /**
1050
- * True iff `value` is a NON-EMPTY array whose every element is a valid
1051
- * `ContentPart`. Empty arrays and mixed arrays return false so they continue
1052
- * to be treated as ordinary (stringified) data — this keeps the auto-detection
1053
- * footgun narrow.
1054
- */
1055
- function isContentPartArray(value) {
1056
- return Array.isArray(value) && value.length > 0 && value.every(isContentPart$1);
1057
- }
1058
- /**
1059
- * Error text for a failed tool result: `output.error` when it is a string,
1060
- * else the output itself when it is a string, else a generic message.
1061
- * `StreamProcessor` and `chat()` history share it, so a reload shows the
1062
- * same text as the live stream.
1063
- */
1064
- function toolResultErrorText(output) {
1065
- if (output && typeof output === "object" && "error" in output && typeof output.error === "string") return output.error;
1066
- return typeof output === "string" ? output : "Tool execution failed";
1589
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/subagent-wire.js
1590
+ function isRecord$2(value) {
1591
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1067
1592
  }
1593
+ /** Key of a child's checked input in `SUBAGENT_STARTED` metadata (`metadata.tanstack`). */
1594
+ var SUBAGENT_INPUT_KEY = "subagentInput";
1068
1595
  /**
1069
- * Normalize a tool's return value for transport:
1070
- * - string → unchanged
1071
- * - ContentPart array → unchanged (multimodal, passed through to the adapter)
1072
- * - anything else → `JSON.stringify`
1596
+ * The checked input of a child that an agent with `inputSchema` got, read
1597
+ * from the `metadata` of its card or of its `SUBAGENT_STARTED` event.
1073
1598
  */
1074
- function normalizeToolResult(result) {
1075
- if (typeof result === "string") return result;
1076
- if (isContentPartArray(result)) return result;
1077
- return JSON.stringify(result);
1078
- }
1079
- //#endregion
1080
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/subagent-wire.js
1081
- function isRecord$2(value) {
1082
- return typeof value === "object" && value !== null && !Array.isArray(value);
1599
+ function subagentInputOf(metadata) {
1600
+ if (!isRecord$2(metadata) || !isRecord$2(metadata.tanstack)) return void 0;
1601
+ return metadata.tanstack[SUBAGENT_INPUT_KEY];
1083
1602
  }
1084
1603
  function wireSubagentRunId(message) {
1085
1604
  if (!isRecord$2(message) || "parts" in message) return void 0;
@@ -1181,7 +1700,186 @@ function splitSubagentWire(messages) {
1181
1700
  };
1182
1701
  }
1183
1702
  //#endregion
1184
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
1703
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/provider-executed.js
1704
+ /**
1705
+ * Narrow a tool call's opaque `metadata` to the provider-executed convention.
1706
+ * Returns the typed metadata when the call is provider-executed, else `null`.
1707
+ *
1708
+ * @see ProviderExecutedToolMetadata
1709
+ */
1710
+ function getProviderExecutedMetadata(toolCall) {
1711
+ const metadata = toolCall?.metadata;
1712
+ if (typeof metadata === "object" && metadata !== null && metadata.providerExecuted === true) return metadata;
1713
+ return null;
1714
+ }
1715
+ /**
1716
+ * True when a tool call was executed by the provider (e.g. Anthropic
1717
+ * `web_search` / `web_fetch` server tools) rather than the agent loop. Such
1718
+ * calls must not be routed to client-side execution and are already "complete".
1719
+ */
1720
+ function isProviderExecutedToolCall(toolCall) {
1721
+ return getProviderExecutedMetadata(toolCall) !== null;
1722
+ }
1723
+ /**
1724
+ * True when `id` is a `${parentId}-segment-${n}` message. The wire and the
1725
+ * run loop split one provider turn into segments at thinking that follows a
1726
+ * provider-executed tool call, to keep signed thinking order. Readers fold a
1727
+ * segment back into its parent so the UI still shows one message.
1728
+ */
1729
+ function isAssistantSegmentOf(id, parentId) {
1730
+ return id?.startsWith(`${parentId}-segment-`) === true;
1731
+ }
1732
+ //#endregion
1733
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/tool-result.js
1734
+ var CONTENT_PART_TYPES = /* @__PURE__ */ new Set([
1735
+ "text",
1736
+ "image",
1737
+ "audio",
1738
+ "video",
1739
+ "document"
1740
+ ]);
1741
+ function isToolResultOutcome(value) {
1742
+ return value === "cancelled" || value === "denied";
1743
+ }
1744
+ /**
1745
+ * Structural check for a single `ContentPart`. A text part must carry a string
1746
+ * `content`. Every other part carries a source with a string `value`; a file
1747
+ * source's `value` is a non-empty opaque handle, and its optional `provider`
1748
+ * is a string.
1749
+ */
1750
+ function isContentPart$1(value) {
1751
+ if (typeof value !== "object" || value === null) return false;
1752
+ const part = value;
1753
+ if (typeof part.type !== "string" || !CONTENT_PART_TYPES.has(part.type)) return false;
1754
+ if (part.type === "text") return typeof part.content === "string";
1755
+ const source = part.source;
1756
+ if (typeof source !== "object" || source === null) return false;
1757
+ const src = source;
1758
+ if (typeof src.value !== "string") return false;
1759
+ if (src.type === "file") return src.value.length > 0 && (src.provider === void 0 || typeof src.provider === "string");
1760
+ if (src.type === "data") return typeof src.mimeType === "string";
1761
+ return src.type === "url";
1762
+ }
1763
+ /**
1764
+ * True iff `value` is a NON-EMPTY array whose every element is a valid
1765
+ * `ContentPart`. Empty arrays and mixed arrays return false so they continue
1766
+ * to be treated as ordinary (stringified) data — this keeps the auto-detection
1767
+ * footgun narrow.
1768
+ */
1769
+ function isContentPartArray(value) {
1770
+ return Array.isArray(value) && value.length > 0 && value.every(isContentPart$1);
1771
+ }
1772
+ /**
1773
+ * Error text for a failed tool result: `output.error` when it is a string,
1774
+ * else the output itself when it is a string, else a generic message.
1775
+ * `StreamProcessor` and `chat()` history share it, so a reload shows the
1776
+ * same text as the live stream.
1777
+ */
1778
+ function toolResultErrorText(output) {
1779
+ if (output && typeof output === "object" && "error" in output && typeof output.error === "string") return output.error;
1780
+ return typeof output === "string" ? output : "Tool execution failed";
1781
+ }
1782
+ /**
1783
+ * Normalize a tool's return value for transport:
1784
+ * - string → unchanged
1785
+ * - ContentPart array → unchanged (multimodal, passed through to the adapter)
1786
+ * - anything else → `JSON.stringify`
1787
+ */
1788
+ function normalizeToolResult(result) {
1789
+ if (typeof result === "string") return result;
1790
+ if (isContentPartArray(result)) return result;
1791
+ return JSON.stringify(result);
1792
+ }
1793
+ //#endregion
1794
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/block-order.js
1795
+ /**
1796
+ * The order map for these entries in produced order, or undefined when they
1797
+ * are in the default order (all thinking, then text, then tool calls).
1798
+ * Adjacent text entries merge into one, and empty text is left out. The n-th
1799
+ * thinking entry gets index n.
1800
+ */
1801
+ function buildBlockOrder(entries) {
1802
+ const blocks = [];
1803
+ let thinking = 0;
1804
+ let isDefault = true;
1805
+ for (const entry of entries) {
1806
+ const last = blocks.at(-1);
1807
+ if (entry.type === "thinking") {
1808
+ if (last !== void 0 && last.type !== "thinking") isDefault = false;
1809
+ blocks.push({
1810
+ type: "thinking",
1811
+ index: thinking++
1812
+ });
1813
+ } else if (entry.type === "text") {
1814
+ if (entry.text === "") continue;
1815
+ if (last?.type === "text") {
1816
+ last.length += entry.text.length;
1817
+ continue;
1818
+ }
1819
+ if (last?.type === "tool-call") isDefault = false;
1820
+ blocks.push({
1821
+ type: "text",
1822
+ length: entry.text.length
1823
+ });
1824
+ } else blocks.push({
1825
+ type: "tool-call",
1826
+ id: entry.id
1827
+ });
1828
+ }
1829
+ return isDefault ? void 0 : blocks;
1830
+ }
1831
+ /**
1832
+ * The blocks of an assistant message in map order, or undefined when the
1833
+ * message has no map or the map does not match the message. A map matches
1834
+ * when it uses each `thinking` entry and each `toolCalls` entry exactly once,
1835
+ * and its text lengths add up to the length of the text content (`null`
1836
+ * content counts as no text). Readers use the default order when this
1837
+ * returns undefined.
1838
+ */
1839
+ function orderedAssistantBlocks(message) {
1840
+ const order = message.blockOrder;
1841
+ if (!Array.isArray(order) || order.length === 0) return void 0;
1842
+ const content = message.content ?? "";
1843
+ if (typeof content !== "string") return void 0;
1844
+ const thinking = message.thinking ?? [];
1845
+ const toolCalls = message.toolCalls ?? [];
1846
+ const usedThinking = /* @__PURE__ */ new Set();
1847
+ const usedCalls = /* @__PURE__ */ new Set();
1848
+ const blocks = [];
1849
+ let offset = 0;
1850
+ for (const block of order) {
1851
+ if (typeof block !== "object" || block === null) return void 0;
1852
+ if (block.type === "thinking") {
1853
+ const entry = Number.isInteger(block.index) ? thinking[block.index] : void 0;
1854
+ if (entry === void 0 || usedThinking.has(block.index)) return;
1855
+ usedThinking.add(block.index);
1856
+ blocks.push({
1857
+ type: "thinking",
1858
+ thinking: entry
1859
+ });
1860
+ } else if (block.type === "text") {
1861
+ const end = offset + block.length;
1862
+ if (!Number.isInteger(block.length) || block.length <= 0 || end > content.length) return;
1863
+ blocks.push({
1864
+ type: "text",
1865
+ text: content.slice(offset, end)
1866
+ });
1867
+ offset = end;
1868
+ } else if (block.type === "tool-call") {
1869
+ const toolCall = toolCalls.find((candidate) => candidate.id === block.id);
1870
+ if (toolCall === void 0 || usedCalls.has(block.id)) return void 0;
1871
+ usedCalls.add(block.id);
1872
+ blocks.push({
1873
+ type: "tool-call",
1874
+ toolCall
1875
+ });
1876
+ } else return;
1877
+ }
1878
+ if (offset !== content.length || usedThinking.size !== thinking.length || usedCalls.size !== toolCalls.length) return;
1879
+ return blocks;
1880
+ }
1881
+ //#endregion
1882
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
1185
1883
  function isRecord$1(value) {
1186
1884
  return typeof value === "object" && value !== null && !Array.isArray(value);
1187
1885
  }
@@ -1341,12 +2039,19 @@ function appendUiResources(ui, resources) {
1341
2039
  function assistantMetadata(uiMessage) {
1342
2040
  const fromParts = uiMessage.parts.filter(isUiResourcePart);
1343
2041
  const current = uiMessage.metadata ?? {};
1344
- const previous = tanstackMetadata(uiMessage);
1345
- const tanstack = {};
1346
- if (previous?.model !== void 0) tanstack.model = previous.model;
1347
- if (previous?.runId !== void 0) tanstack.runId = previous.runId;
1348
- if (previous?.run?.id !== void 0) tanstack.run = { id: previous.run.id };
1349
- if (previous?.signature !== void 0) tanstack.signature = previous.signature;
2042
+ const tanstack = { ...tanstackMetadata(uiMessage) };
2043
+ if (tanstack.run) {
2044
+ tanstack.run = { ...tanstack.run };
2045
+ delete tanstack.run.startedAt;
2046
+ delete tanstack.run.finishedAt;
2047
+ }
2048
+ delete tanstack.createdAt;
2049
+ delete tanstack.continues;
2050
+ delete tanstack.structuredOutput;
2051
+ delete tanstack.toolCallMetadata;
2052
+ delete tanstack.toolResult;
2053
+ delete tanstack.toolResultOutcome;
2054
+ delete tanstack.uiResources;
1350
2055
  if (fromParts.length > 0) tanstack.uiResources = fromParts;
1351
2056
  const result = { ...current };
1352
2057
  if (Object.keys(tanstack).length > 0) result.tanstack = tanstack;
@@ -1397,7 +2102,8 @@ function buildUserOrToolMessage(uiMessage) {
1397
2102
  function createSegment() {
1398
2103
  return {
1399
2104
  contentParts: [],
1400
- toolCalls: []
2105
+ toolCalls: [],
2106
+ order: []
1401
2107
  };
1402
2108
  }
1403
2109
  function isToolCallIncluded(part) {
@@ -1432,6 +2138,7 @@ function buildAssistantMessages(uiMessage) {
1432
2138
  const hasContent = content !== null;
1433
2139
  const hasToolCalls = current.toolCalls.length > 0;
1434
2140
  const hasThinking = pendingThinking.length > 0;
2141
+ const blockOrder = Array.isArray(content) ? void 0 : buildBlockOrder(current.order);
1435
2142
  if (force || hasContent || hasToolCalls || hasThinking) {
1436
2143
  messageList.push({
1437
2144
  ...assistantFields,
@@ -1439,7 +2146,8 @@ function buildAssistantMessages(uiMessage) {
1439
2146
  content,
1440
2147
  ...hasToolCalls && { toolCalls: current.toolCalls },
1441
2148
  ...hasThinking && { thinking: pendingThinking },
1442
- ...current.structuredOutput && { structuredOutput: current.structuredOutput }
2149
+ ...current.structuredOutput && { structuredOutput: current.structuredOutput },
2150
+ ...blockOrder && { blockOrder }
1443
2151
  });
1444
2152
  pendingThinking = [];
1445
2153
  }
@@ -1447,6 +2155,12 @@ function buildAssistantMessages(uiMessage) {
1447
2155
  }
1448
2156
  for (const part of uiMessage.parts) switch (part.type) {
1449
2157
  case "text":
2158
+ current.contentParts.push(part);
2159
+ current.order.push({
2160
+ type: "text",
2161
+ text: part.content
2162
+ });
2163
+ break;
1450
2164
  case "image":
1451
2165
  case "audio":
1452
2166
  case "video":
@@ -1454,15 +2168,21 @@ function buildAssistantMessages(uiMessage) {
1454
2168
  current.contentParts.push(part);
1455
2169
  break;
1456
2170
  case "tool-call":
1457
- if (isToolCallIncluded(part)) current.toolCalls.push({
1458
- id: part.id,
1459
- type: "function",
1460
- function: {
1461
- name: part.name,
1462
- arguments: part.arguments
1463
- },
1464
- ...part.metadata !== void 0 && { metadata: part.metadata }
1465
- });
2171
+ if (isToolCallIncluded(part)) {
2172
+ current.toolCalls.push({
2173
+ id: part.id,
2174
+ type: "function",
2175
+ function: {
2176
+ name: part.name,
2177
+ arguments: part.arguments
2178
+ },
2179
+ ...part.metadata !== void 0 && { metadata: part.metadata }
2180
+ });
2181
+ current.order.push({
2182
+ type: "tool-call",
2183
+ id: part.id
2184
+ });
2185
+ }
1466
2186
  break;
1467
2187
  case "tool-result":
1468
2188
  flushSegment(messageList.length === 0);
@@ -1489,6 +2209,7 @@ function buildAssistantMessages(uiMessage) {
1489
2209
  ...part.signature && { signature: part.signature },
1490
2210
  ...part.redacted && { redacted: true }
1491
2211
  });
2212
+ current.order.push({ type: "thinking" });
1492
2213
  }
1493
2214
  break;
1494
2215
  case "structured-output":
@@ -1499,6 +2220,10 @@ function buildAssistantMessages(uiMessage) {
1499
2220
  type: "text",
1500
2221
  content: serialized
1501
2222
  });
2223
+ current.order.push({
2224
+ type: "text",
2225
+ text: serialized
2226
+ });
1502
2227
  current.structuredOutput = part;
1503
2228
  }
1504
2229
  }
@@ -1508,10 +2233,14 @@ function buildAssistantMessages(uiMessage) {
1508
2233
  case "subagent": {
1509
2234
  const block = part.subagent.parentToolCallId === void 0 ? subagentHistoryText(part) : "";
1510
2235
  if (block !== "") {
1511
- const prefix = current.contentParts.length > 0 ? "\n\n" : "";
2236
+ const text = `${current.contentParts.length > 0 ? "\n\n" : ""}${block}`;
1512
2237
  current.contentParts.push({
1513
2238
  type: "text",
1514
- content: `${prefix}${block}`
2239
+ content: text
2240
+ });
2241
+ current.order.push({
2242
+ type: "text",
2243
+ text
1515
2244
  });
1516
2245
  }
1517
2246
  break;
@@ -1550,6 +2279,31 @@ function buildAssistantMessages(uiMessage) {
1550
2279
  });
1551
2280
  return messageList;
1552
2281
  }
2282
+ function thinkingToPart(thinking) {
2283
+ return {
2284
+ type: "thinking",
2285
+ content: thinking.content,
2286
+ ...thinking.signature && { signature: thinking.signature },
2287
+ ...thinking.redacted && { redacted: true }
2288
+ };
2289
+ }
2290
+ function toolCallToPart(toolCall) {
2291
+ let input;
2292
+ try {
2293
+ input = JSON.parse(toolCall.function.arguments);
2294
+ } catch {
2295
+ input = void 0;
2296
+ }
2297
+ return {
2298
+ type: "tool-call",
2299
+ id: toolCall.id,
2300
+ name: toolCall.function.name,
2301
+ arguments: toolCall.function.arguments,
2302
+ state: "input-complete",
2303
+ ...input !== void 0 && { input },
2304
+ ...toolCall.metadata !== void 0 && { metadata: toolCall.metadata }
2305
+ };
2306
+ }
1553
2307
  /**
1554
2308
  * Convert a ModelMessage to UIMessage
1555
2309
  *
@@ -1567,12 +2321,7 @@ function modelMessageToUIMessage(modelMessage, id) {
1567
2321
  const createdAt = coerceCreatedAt(modelMessage.createdAt);
1568
2322
  if (modelMessage.role === "assistant" && modelMessage.thinking?.length) for (const thinking of modelMessage.thinking) {
1569
2323
  if (!thinking.content && !thinking.signature) continue;
1570
- parts.push({
1571
- type: "thinking",
1572
- content: thinking.content,
1573
- ...thinking.signature && { signature: thinking.signature },
1574
- ...thinking.redacted && { redacted: true }
1575
- });
2324
+ parts.push(thinkingToPart(thinking));
1576
2325
  }
1577
2326
  const structuredOutput = modelMessage.structuredOutput ?? snapshotStructuredOutput(tanstackMetadata(modelMessage)?.structuredOutput);
1578
2327
  if (modelMessage.role === "assistant" && structuredOutput) {
@@ -1609,23 +2358,16 @@ function modelMessageToUIMessage(modelMessage, id) {
1609
2358
  content: textContent
1610
2359
  });
1611
2360
  }
1612
- if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) for (const toolCall of modelMessage.toolCalls) {
1613
- let input;
1614
- try {
1615
- input = JSON.parse(toolCall.function.arguments);
1616
- } catch {
1617
- input = void 0;
1618
- }
1619
- parts.push({
1620
- type: "tool-call",
1621
- id: toolCall.id,
1622
- name: toolCall.function.name,
1623
- arguments: toolCall.function.arguments,
1624
- state: "input-complete",
1625
- ...input !== void 0 && { input },
1626
- ...toolCall.metadata !== void 0 && { metadata: toolCall.metadata }
1627
- });
1628
- }
2361
+ if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) for (const toolCall of modelMessage.toolCalls) parts.push(toolCallToPart(toolCall));
2362
+ const ordered = modelMessage.role === "assistant" && structuredOutput === void 0 ? orderedAssistantBlocks(modelMessage) : void 0;
2363
+ if (ordered) parts.splice(0, parts.length, ...ordered.flatMap((block) => {
2364
+ if (block.type === "text") return [{
2365
+ type: "text",
2366
+ content: block.text
2367
+ }];
2368
+ if (block.type === "tool-call") return [toolCallToPart(block.toolCall)];
2369
+ return block.thinking.content || block.thinking.signature ? [thinkingToPart(block.thinking)] : [];
2370
+ }));
1629
2371
  const ui = {
1630
2372
  id: id || generateMessageId(),
1631
2373
  role: modelMessage.role === "tool" ? "assistant" : modelMessage.role,
@@ -1849,7 +2591,7 @@ function generateMessageId() {
1849
2591
  return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1850
2592
  }
1851
2593
  //#endregion
1852
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-wire.js
2594
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-wire.js
1853
2595
  function isRecord(value) {
1854
2596
  return typeof value === "object" && value !== null && !Array.isArray(value);
1855
2597
  }
@@ -1882,7 +2624,10 @@ function rebuiltToolMetadata(metadata, createdAt, id, content, anchorOwnsUiResou
1882
2624
  * server consumers. Set `includeSnapshotStructuredOutput` to retain complete
1883
2625
  * structured-output metadata for UI snapshots. Set `includeActivity` to emit
1884
2626
  * AG-UI `ActivityMessage` rows (MESSAGES_SNAPSHOT only — default omit so
1885
- * RunAgentInput never carries activity).
2627
+ * RunAgentInput never carries activity). An assistant message whose
2628
+ * parts leave the default block order goes out as several rows in the real
2629
+ * order (see `TanStackMessageMetadata.continues`). A tool result also ends a
2630
+ * row, and its tool row follows that row.
1886
2631
  */
1887
2632
  function uiMessagesToWire(messages, options) {
1888
2633
  const wire = [];
@@ -1934,20 +2679,72 @@ function uiMessagesToWire(messages, options) {
1934
2679
  wire.push(toAnchor(uiMessage, "user", { content: parts.length > 0 ? collectUserContent(parts) : msg.content ?? "" }, parts, includeSnapshotStructuredOutput));
1935
2680
  continue;
1936
2681
  }
1937
- let current = {
2682
+ const newSegment = (continues) => ({
1938
2683
  thinking: [],
1939
- parts: []
1940
- };
2684
+ parts: [],
2685
+ continues,
2686
+ closed: false
2687
+ });
2688
+ let current = newSegment(false);
1941
2689
  const segments = [current];
1942
- for (const part of parts) if (part.type === "thinking") {
1943
- if (current.parts.some((p) => p.type === "tool-call" && isProviderExecutedToolCall(p))) {
1944
- current = {
1945
- thinking: [part],
1946
- parts: []
1947
- };
2690
+ for (const part of parts) {
2691
+ if (current.closed && (part.type === "thinking" || part.type === "text" || part.type === "tool-call")) {
2692
+ current = newSegment(false);
2693
+ segments.push(current);
2694
+ }
2695
+ const afterCall = current.parts.some((p) => p.type === "tool-call");
2696
+ if (part.type === "thinking") {
2697
+ if (current.parts.some((p) => p.type === "tool-call" && isProviderExecutedToolCall(p))) {
2698
+ current = newSegment(false);
2699
+ segments.push(current);
2700
+ } else if (afterCall || current.parts.some((p) => p.type === "text")) {
2701
+ current = newSegment(true);
2702
+ segments.push(current);
2703
+ }
2704
+ current.thinking.push(part);
2705
+ } else if (part.type === "text" && afterCall) {
2706
+ current = newSegment(true);
1948
2707
  segments.push(current);
1949
- } else current.thinking.push(part);
1950
- } else current.parts.push(part);
2708
+ current.parts.push(part);
2709
+ } else {
2710
+ current.parts.push(part);
2711
+ if (part.type === "tool-result") current.closed = true;
2712
+ }
2713
+ }
2714
+ const explicitToolResults = new Set(parts.flatMap((part) => part.type === "tool-result" ? [part.toolCallId] : []));
2715
+ const pushToolRows = (rowParts) => {
2716
+ for (const part of rowParts) if (part.type === "tool-result") {
2717
+ const id = uniqueToolWireId(part.id ?? deriveToolMessageId(part.toolCallId), usedWireIds);
2718
+ const metadata = rebuiltToolMetadata(part.metadata, part.createdAt, part.id, part.content, true, part.outcome);
2719
+ wire.push({
2720
+ role: "tool",
2721
+ id,
2722
+ toolCallId: part.toolCallId,
2723
+ ...part.name !== void 0 && { name: part.name },
2724
+ content: typeof part.content === "string" ? part.content : JSON.stringify(part.content),
2725
+ ...part.error !== void 0 && { error: part.error },
2726
+ ...metadata !== void 0 && { metadata }
2727
+ });
2728
+ } else if (part.type === "tool-call") {
2729
+ const approved = part.approval?.approved;
2730
+ if (explicitToolResults.has(part.id) || part.output === void 0 && (part.state !== "approval-responded" || approved === void 0)) continue;
2731
+ const result = part.output !== void 0 ? normalizeToolResult(part.output) : JSON.stringify({
2732
+ approved,
2733
+ ...approved && { pendingExecution: true },
2734
+ message: approved ? "User approved this action" : "User denied this action"
2735
+ });
2736
+ const content = typeof result === "string" ? result : JSON.stringify(result);
2737
+ wire.push({
2738
+ role: "tool",
2739
+ id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),
2740
+ toolCallId: part.id,
2741
+ content,
2742
+ metadata: rebuiltToolMetadata(void 0, void 0, void 0, result, false, part.approval?.approved === false ? "denied" : void 0)
2743
+ });
2744
+ }
2745
+ };
2746
+ let previousAnchorId = uiMessage.id;
2747
+ let toolParts = [];
1951
2748
  segments.forEach((segment, index) => {
1952
2749
  for (const part of segment.thinking) {
1953
2750
  const reasoning = {
@@ -1960,45 +2757,31 @@ function uiMessagesToWire(messages, options) {
1960
2757
  }
1961
2758
  const text = collectText(segment.parts);
1962
2759
  const toolCalls = collectToolCalls(segment.parts);
1963
- const anchorMessage = index === 0 ? uiMessage : {
2760
+ const anchor = toAnchor(index === 0 ? uiMessage : {
1964
2761
  ...uiMessage,
1965
2762
  id: uniqueWireId(`${uiMessage.id}-segment-${index}`, usedWireIds)
1966
- };
1967
- wire.push(toAnchor(anchorMessage, "assistant", {
2763
+ }, "assistant", {
1968
2764
  ...text !== "" && { content: text },
1969
2765
  ...toolCalls && { toolCalls }
1970
- }, segment.parts, includeSnapshotStructuredOutput));
2766
+ }, segment.parts, includeSnapshotStructuredOutput);
2767
+ if (segment.continues) {
2768
+ const metadata = anchor.metadata ?? {};
2769
+ anchor.metadata = {
2770
+ ...metadata,
2771
+ tanstack: {
2772
+ ...isRecord(metadata.tanstack) ? metadata.tanstack : {},
2773
+ continues: previousAnchorId
2774
+ }
2775
+ };
2776
+ }
2777
+ wire.push(anchor);
2778
+ previousAnchorId = anchor.id;
2779
+ toolParts.push(...segment.parts);
2780
+ if (segment.closed || index === segments.length - 1) {
2781
+ pushToolRows(toolParts);
2782
+ toolParts = [];
2783
+ }
1971
2784
  });
1972
- const explicitToolResults = new Set(parts.flatMap((part) => part.type === "tool-result" ? [part.toolCallId] : []));
1973
- for (const part of parts) if (part.type === "tool-result") {
1974
- const id = uniqueToolWireId(part.id ?? deriveToolMessageId(part.toolCallId), usedWireIds);
1975
- const metadata = rebuiltToolMetadata(part.metadata, part.createdAt, part.id, part.content, true, part.outcome);
1976
- wire.push({
1977
- role: "tool",
1978
- id,
1979
- toolCallId: part.toolCallId,
1980
- ...part.name !== void 0 && { name: part.name },
1981
- content: typeof part.content === "string" ? part.content : JSON.stringify(part.content),
1982
- ...part.error !== void 0 && { error: part.error },
1983
- ...metadata !== void 0 && { metadata }
1984
- });
1985
- } else if (part.type === "tool-call") {
1986
- const approved = part.approval?.approved;
1987
- if (explicitToolResults.has(part.id) || part.output === void 0 && (part.state !== "approval-responded" || approved === void 0)) continue;
1988
- const result = part.output !== void 0 ? normalizeToolResult(part.output) : JSON.stringify({
1989
- approved,
1990
- ...approved && { pendingExecution: true },
1991
- message: approved ? "User approved this action" : "User denied this action"
1992
- });
1993
- const content = typeof result === "string" ? result : JSON.stringify(result);
1994
- wire.push({
1995
- role: "tool",
1996
- id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),
1997
- toolCallId: part.id,
1998
- content,
1999
- metadata: rebuiltToolMetadata(void 0, void 0, void 0, result, false, part.approval?.approved === false ? "denied" : void 0)
2000
- });
2001
- }
2002
2785
  for (const part of parts) if (part.type === "subagent") wire.push(...subagentToWire(part, options));
2003
2786
  }
2004
2787
  return wire;
@@ -2029,12 +2812,19 @@ function toAnchor(msg, role, extras, parts, includeSnapshotStructuredOutput) {
2029
2812
  }
2030
2813
  function messageMetadata(msg, parts, includeSnapshotStructuredOutput) {
2031
2814
  const base = { ...msg.metadata ?? {} };
2032
- const previousTanstack = tanstackMetadata(msg);
2033
- const tanstack = {};
2034
- if (previousTanstack?.model !== void 0) tanstack.model = previousTanstack.model;
2035
- if (previousTanstack?.runId !== void 0) tanstack.runId = previousTanstack.runId;
2036
- if (previousTanstack?.run?.id !== void 0) tanstack.run = { id: previousTanstack.run.id };
2037
- if (previousTanstack?.signature !== void 0) tanstack.signature = previousTanstack.signature;
2815
+ const tanstack = { ...tanstackMetadata(msg) };
2816
+ if (tanstack.run) {
2817
+ tanstack.run = { ...tanstack.run };
2818
+ delete tanstack.run.startedAt;
2819
+ delete tanstack.run.finishedAt;
2820
+ }
2821
+ delete tanstack.createdAt;
2822
+ delete tanstack.continues;
2823
+ delete tanstack.structuredOutput;
2824
+ delete tanstack.toolCallMetadata;
2825
+ delete tanstack.toolResult;
2826
+ delete tanstack.toolResultOutcome;
2827
+ delete tanstack.uiResources;
2038
2828
  const createdAt = coerceCreatedAt(msg.createdAt);
2039
2829
  if (createdAt !== void 0) tanstack.createdAt = createdAt.toISOString();
2040
2830
  const structuredOutput = serializedStructuredOutput(parts, includeSnapshotStructuredOutput);
@@ -2184,11 +2974,11 @@ function hashContent(s) {
2184
2974
  return Math.abs(h).toString(36);
2185
2975
  }
2186
2976
  //#endregion
2187
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/restore-inbound-chunk.js
2977
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/restore-inbound-chunk.js
2188
2978
  /**
2189
2979
  * Rebuild TanStack `TokenUsage` (`promptTokens`) from spec `usage[]` plus
2190
- * leftover fields in `metadata.tanstack.usage`. Restore in-process aliases
2191
- * that the wire does not keep (`toolName`, `TOOL_CALL_END.input`). Mutates
2980
+ * leftover fields in `metadata.tanstack.usage`. Restore the in-process field
2981
+ * that the wire does not keep (`TOOL_CALL_END.input`). Mutates
2192
2982
  * in place so WeakMap run-id stamps stay attached.
2193
2983
  */
2194
2984
  function restorePublicUsage(chunk) {
@@ -2196,9 +2986,9 @@ function restorePublicUsage(chunk) {
2196
2986
  const rebuilt = rebuildTokenUsage(chunk.usage, tanstackMetadata(chunk)?.usage);
2197
2987
  if (rebuilt !== void 0) chunk.usage = rebuilt;
2198
2988
  }
2199
- if (chunk.type === EventType.TOOL_CALL_START && chunk.toolName === void 0 && chunk.toolCallName) chunk.toolName = chunk.toolCallName;
2200
2989
  if (chunk.type === EventType.TOOL_CALL_END && chunk.input === void 0) {
2201
- const input = tanstackMetadata(chunk)?.input;
2990
+ const tanstack = tanstackMetadata(chunk);
2991
+ const input = tanstack?.input ?? (typeof tanstack?.args === "string" ? parseToolArguments(tanstack.args) : void 0);
2202
2992
  if (input !== void 0) chunk.input = input;
2203
2993
  }
2204
2994
  return chunk;
@@ -2221,7 +3011,7 @@ function restoreInboundChunk(chunk) {
2221
3011
  return next;
2222
3012
  }
2223
3013
  //#endregion
2224
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
3014
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
2225
3015
  /**
2226
3016
  * Create an isomorphic tool definition that can be used directly or instantiated for server/client
2227
3017
  *
@@ -2319,7 +3109,7 @@ function toolDefinition(config) {
2319
3109
  };
2320
3110
  }
2321
3111
  //#endregion
2322
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/chunk-ids.js
3112
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/chunk-ids.js
2323
3113
  function stringField(value) {
2324
3114
  return typeof value === "string" && value !== "" ? value : void 0;
2325
3115
  }
@@ -2422,7 +3212,7 @@ var require_options = /* @__PURE__ */ __commonJSMin(((exports) => {
2422
3212
  exports.default = exports.Allow;
2423
3213
  }));
2424
3214
  //#endregion
2425
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
3215
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
2426
3216
  var import_dist = (/* @__PURE__ */ __commonJSMin(((exports, module, this$1) => {
2427
3217
  var __createBinding = this$1 && this$1.__createBinding || (Object.create ? (function(o, m, k, k2) {
2428
3218
  if (k2 === void 0) k2 = k;
@@ -2644,7 +3434,7 @@ function parsePartialJSON(jsonString) {
2644
3434
  return defaultJSONParser.parse(jsonString);
2645
3435
  }
2646
3436
  //#endregion
2647
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
3437
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
2648
3438
  /**
2649
3439
  * Immediate Strategy - emit on every chunk (default behavior)
2650
3440
  */
@@ -2654,16 +3444,14 @@ var ImmediateStrategy = class {
2654
3444
  }
2655
3445
  };
2656
3446
  //#endregion
2657
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/errors.js
3447
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/utilities/errors.js
2658
3448
  /**
2659
3449
  * Convert an AG-UI RUN_ERROR event to the Error shape exposed to consumers.
2660
- * Preserves the provider code and sanitized raw event when available, while
2661
- * accepting the deprecated nested error payload for backward compatibility.
3450
+ * Preserves the provider code and sanitized raw event when available.
2662
3451
  */
2663
3452
  function runErrorEventToError(chunk) {
2664
- const error = new Error(chunk.message || chunk.error?.message || "An error occurred");
2665
- const code = chunk.code ?? chunk.error?.code;
2666
- if (code !== void 0) Object.assign(error, { code });
3453
+ const error = new Error(chunk.message || "An error occurred");
3454
+ if (chunk.code !== void 0) Object.assign(error, { code: chunk.code });
2667
3455
  if (chunk.rawEvent !== void 0) Object.assign(error, { rawEvent: chunk.rawEvent });
2668
3456
  return error;
2669
3457
  }
@@ -3317,7 +4105,7 @@ var fast_json_patch_default = Object.assign({}, core_exports, duplex_exports, {
3317
4105
  unescapePathComponent
3318
4106
  });
3319
4107
  //#endregion
3320
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/activity-records.js
4108
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/activity-records.js
3321
4109
  function isActivityPart(part) {
3322
4110
  return part.type === "activity";
3323
4111
  }
@@ -3393,7 +4181,7 @@ function applyActivityDeltaToUIMessages(messages, chunk) {
3393
4181
  }
3394
4182
  }
3395
4183
  //#endregion
3396
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
4184
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
3397
4185
  /**
3398
4186
  * Message Updaters (Internal)
3399
4187
  *
@@ -3695,7 +4483,7 @@ function updateThinkingPart(messages, messageId, stepId, content, signature) {
3695
4483
  });
3696
4484
  }
3697
4485
  //#endregion
3698
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
4486
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
3699
4487
  /**
3700
4488
  * Unified Stream Processor
3701
4489
  *
@@ -3747,35 +4535,6 @@ function interruptBatchHasGeneric(interrupts) {
3747
4535
  });
3748
4536
  }
3749
4537
  /**
3750
- * The canonical arguments string for a `TOOL_CALL_END.input`, or `undefined`
3751
- * when JSON cannot carry it: `JSON.stringify` returns `undefined` (despite
3752
- * its declared type) for a top-level function or symbol and throws on BigInt
3753
- * and circular references. `null` is not tool arguments either, so it also
3754
- * keeps the streamed value instead of writing `arguments = "null"`.
3755
- */
3756
- function serializeToolInput(input) {
3757
- if (input === void 0 || input === null) return void 0;
3758
- try {
3759
- const serialized = JSON.stringify(input);
3760
- return typeof serialized === "string" ? serialized : void 0;
3761
- } catch {
3762
- return;
3763
- }
3764
- }
3765
- /**
3766
- * The input of a tool call from its raw arguments: `{}` for an empty string,
3767
- * `undefined` when the arguments are not complete JSON (for example cut off)
3768
- * or are `null`.
3769
- */
3770
- function parseToolArguments(args) {
3771
- if (args.trim() === "") return {};
3772
- try {
3773
- return JSON.parse(args) ?? void 0;
3774
- } catch {
3775
- return;
3776
- }
3777
- }
3778
- /**
3779
4538
  * StreamProcessor - State machine for processing AI response streams
3780
4539
  *
3781
4540
  * Manages the full UIMessage[] conversation and emits events on changes.
@@ -3801,11 +4560,14 @@ var StreamProcessor = class StreamProcessor {
3801
4560
  activeMessageIds = /* @__PURE__ */ new Set();
3802
4561
  toolCallToMessage = /* @__PURE__ */ new Map();
3803
4562
  pendingManualMessageId = null;
3804
- pendingThinkingStepId = null;
3805
4563
  openChunk = null;
3806
4564
  structuredMessageIds = /* @__PURE__ */ new Set();
3807
4565
  structuredOutputUpdateBatches = /* @__PURE__ */ new Map();
3808
4566
  activeRuns = /* @__PURE__ */ new Set();
4567
+ callMessageIds = /* @__PURE__ */ new Map();
4568
+ unassignedCallMessageIds = /* @__PURE__ */ new Set();
4569
+ sealedMessageIds = /* @__PURE__ */ new Set();
4570
+ thinkingOwners = /* @__PURE__ */ new Map();
3809
4571
  runToolCallIds = [];
3810
4572
  toolCallsSentToClient = /* @__PURE__ */ new Set();
3811
4573
  childProcessors = /* @__PURE__ */ new Map();
@@ -3912,16 +4674,6 @@ var StreamProcessor = class StreamProcessor {
3912
4674
  this.resetStreamState();
3913
4675
  }
3914
4676
  /**
3915
- * @deprecated Use prepareAssistantMessage() instead. This eagerly creates
3916
- * an assistant message which can cause empty message flicker.
3917
- */
3918
- startAssistantMessage(messageId) {
3919
- this.prepareAssistantMessage();
3920
- const { messageId: id } = this.ensureAssistantMessage(messageId);
3921
- this.pendingManualMessageId = id;
3922
- return id;
3923
- }
3924
- /**
3925
4677
  * Get the current assistant message ID (if one has been created).
3926
4678
  * Returns null if prepareAssistantMessage() was called but no content
3927
4679
  * has arrived yet.
@@ -4000,6 +4752,11 @@ var StreamProcessor = class StreamProcessor {
4000
4752
  for (const id of this.messageStates.keys()) if (!keptIds.has(id)) this.messageStates.delete(id);
4001
4753
  for (const [toolCallId, msgId] of this.toolCallToMessage) if (!keptIds.has(msgId)) this.toolCallToMessage.delete(toolCallId);
4002
4754
  for (const id of this.activeMessageIds) if (!keptIds.has(id)) this.activeMessageIds.delete(id);
4755
+ if (this.pendingManualMessageId && !keptIds.has(this.pendingManualMessageId)) this.pendingManualMessageId = null;
4756
+ for (const ids of this.callMessageIds.values()) for (const id of ids) if (!keptIds.has(id)) ids.delete(id);
4757
+ for (const id of this.unassignedCallMessageIds) if (!keptIds.has(id)) this.unassignedCallMessageIds.delete(id);
4758
+ for (const id of this.sealedMessageIds) if (!keptIds.has(id)) this.sealedMessageIds.delete(id);
4759
+ for (const [key, owner] of this.thinkingOwners) if (!keptIds.has(owner.messageId)) this.thinkingOwners.delete(key);
4003
4760
  this.messages = this.messages.slice(0, index + 1);
4004
4761
  this.emitMessagesChange();
4005
4762
  }
@@ -4007,6 +4764,8 @@ var StreamProcessor = class StreamProcessor {
4007
4764
  * Clear all messages
4008
4765
  */
4009
4766
  clearMessages() {
4767
+ for (const ids of this.callMessageIds.values()) ids.clear();
4768
+ this.unassignedCallMessageIds.clear();
4010
4769
  this.messages = [];
4011
4770
  this.messageStates.clear();
4012
4771
  this.activeMessageIds.clear();
@@ -4014,6 +4773,8 @@ var StreamProcessor = class StreamProcessor {
4014
4773
  this.structuredMessageIds.clear();
4015
4774
  this.structuredOutputUpdateBatches.clear();
4016
4775
  this.pendingManualMessageId = null;
4776
+ this.sealedMessageIds.clear();
4777
+ this.thinkingOwners.clear();
4017
4778
  this.openChunk = null;
4018
4779
  this.childProcessors.clear();
4019
4780
  this.childToolCalls.clear();
@@ -4084,9 +4845,6 @@ var StreamProcessor = class StreamProcessor {
4084
4845
  case "RUN_ERROR":
4085
4846
  this.handleRunErrorEvent(chunk);
4086
4847
  break;
4087
- case "STEP_FINISHED":
4088
- this.handleStepFinishedEvent(chunk);
4089
- break;
4090
4848
  case "MESSAGES_SNAPSHOT":
4091
4849
  this.handleMessagesSnapshotEvent(chunk);
4092
4850
  break;
@@ -4097,9 +4855,18 @@ var StreamProcessor = class StreamProcessor {
4097
4855
  this.handleRunStartedEvent(chunk);
4098
4856
  break;
4099
4857
  case "REASONING_START":
4100
- case "REASONING_MESSAGE_START":
4101
4858
  case "REASONING_MESSAGE_END":
4102
4859
  case "REASONING_END": break;
4860
+ case "REASONING_MESSAGE_START": {
4861
+ const start = chunk;
4862
+ const target = this.unscopedAssistant(start);
4863
+ const current = target.id ? this.getMessageState(target.id) : void 0;
4864
+ if (current) current.currentThinkingStepId = null;
4865
+ if (start.metadata == null) break;
4866
+ const { messageId } = this.ensureAssistantMessage(target.id ?? void 0, !target.create);
4867
+ this.mergeMessageMetadata(messageId, start.metadata);
4868
+ break;
4869
+ }
4103
4870
  case "REASONING_MESSAGE_CONTENT":
4104
4871
  this.handleReasoningMessageContentEvent(chunk);
4105
4872
  break;
@@ -4109,9 +4876,6 @@ var StreamProcessor = class StreamProcessor {
4109
4876
  case "TOOL_CALL_RESULT":
4110
4877
  this.handleToolCallResultEvent(chunk);
4111
4878
  break;
4112
- case "STEP_STARTED":
4113
- this.handleStepStartedEvent(chunk);
4114
- break;
4115
4879
  case "ACTIVITY_SNAPSHOT":
4116
4880
  this.handleActivitySnapshotEvent(chunk);
4117
4881
  break;
@@ -4293,7 +5057,6 @@ var StreamProcessor = class StreamProcessor {
4293
5057
  totalTextContent: "",
4294
5058
  currentSegmentText: "",
4295
5059
  lastEmittedText: "",
4296
- hasSeenReasoningEvents: false,
4297
5060
  thinkingSteps: /* @__PURE__ */ new Map(),
4298
5061
  thinkingStepSignatures: /* @__PURE__ */ new Map(),
4299
5062
  thinkingStepOrder: [],
@@ -4307,40 +5070,97 @@ var StreamProcessor = class StreamProcessor {
4307
5070
  return state;
4308
5071
  }
4309
5072
  /**
4310
- * Get the MessageStreamState for a message
4311
- */
4312
- getMessageState(messageId) {
4313
- return this.messageStates.get(messageId);
4314
- }
4315
- /**
4316
- * Promote a pending stepId from a STEP_STARTED that fired before the
4317
- * assistant message existed onto the given message state, so the next
4318
- * thinking event (STEP_FINISHED or REASONING_MESSAGE_CONTENT) attributes
4319
- * to the correct step.
4320
- */
4321
- consumePendingThinkingStep(state) {
4322
- if (!this.pendingThinkingStepId) return;
4323
- const stepId = this.pendingThinkingStepId;
4324
- state.currentThinkingStepId = stepId;
4325
- if (!state.thinkingSteps.has(stepId)) {
4326
- state.thinkingSteps.set(stepId, "");
4327
- state.thinkingStepOrder.push(stepId);
4328
- }
4329
- this.pendingThinkingStepId = null;
5073
+ * Get the MessageStreamState for a message
5074
+ */
5075
+ getMessageState(messageId) {
5076
+ return this.messageStates.get(messageId);
4330
5077
  }
4331
5078
  /**
4332
5079
  * Get the most recent active assistant message ID.
4333
5080
  * Used as fallback for events that don't include a messageId.
4334
5081
  */
4335
5082
  getActiveAssistantMessageId() {
5083
+ const belongsToCurrentCall = (id) => this.activeRuns.size === 0 || [...this.activeRuns].some((runId) => this.callMessageIds.get(runId)?.has(id)) || this.pendingManualMessageId === id && !this.messageStates.get(id)?.isComplete && !this.isDone;
4336
5084
  const ids = Array.from(this.activeMessageIds).reverse();
4337
5085
  for (const id of ids) {
5086
+ if (this.sealedMessageIds.has(id)) continue;
4338
5087
  const state = this.messageStates.get(id);
4339
- if (state && state.role === "assistant") return id;
5088
+ if (state && state.role === "assistant" && belongsToCurrentCall(id)) return id;
5089
+ }
5090
+ for (const [id, state] of [...this.messageStates].reverse()) {
5091
+ if (this.sealedMessageIds.has(id)) continue;
5092
+ if (state.role === "assistant" && belongsToCurrentCall(id)) return id;
5093
+ }
5094
+ return null;
5095
+ }
5096
+ /** The run that currently owns `messageId`, if one was recorded. */
5097
+ runOfMessage(messageId) {
5098
+ for (const [runId, ids] of this.callMessageIds) if (ids.has(messageId)) return runId;
5099
+ }
5100
+ /** Latest unsealed assistant message written by `runId`. */
5101
+ openMessageOfRun(runId) {
5102
+ const ids = this.callMessageIds.get(runId);
5103
+ if (!ids) return null;
5104
+ for (const id of [...ids].reverse()) {
5105
+ if (this.sealedMessageIds.has(id)) continue;
5106
+ if (this.messageStates.get(id)?.role === "assistant") return id;
4340
5107
  }
4341
- for (const [id, state] of [...this.messageStates].reverse()) if (state.role === "assistant") return id;
4342
5108
  return null;
4343
5109
  }
5110
+ /**
5111
+ * Where an event with no assistant message id belongs.
5112
+ * `create` means open a new message. Do not borrow another run's.
5113
+ */
5114
+ unscopedAssistant(chunk) {
5115
+ const explicit = getChunkRunId(chunk);
5116
+ const onlyRun = this.activeRuns.size === 1 ? [...this.activeRuns][0] : void 0;
5117
+ const runId = explicit ?? onlyRun;
5118
+ if (runId !== void 0) {
5119
+ const open = this.openMessageOfRun(runId);
5120
+ if (open) return {
5121
+ id: open,
5122
+ create: false
5123
+ };
5124
+ if (explicit !== void 0 || this.activeRuns.has(runId)) return {
5125
+ id: null,
5126
+ create: true
5127
+ };
5128
+ }
5129
+ const active = this.getActiveAssistantMessageId();
5130
+ if (active) return {
5131
+ id: active,
5132
+ create: false
5133
+ };
5134
+ return {
5135
+ id: null,
5136
+ create: true
5137
+ };
5138
+ }
5139
+ rememberThinking(messageId, stepId, reasoningMessageId) {
5140
+ const owner = {
5141
+ messageId,
5142
+ stepId
5143
+ };
5144
+ this.thinkingOwners.set(stepId, owner);
5145
+ if (reasoningMessageId !== void 0 && reasoningMessageId !== stepId) this.thinkingOwners.set(reasoningMessageId, owner);
5146
+ }
5147
+ /** Put `signature` on the thinking step `namedId` already belongs to. */
5148
+ applyKnownSignature(namedId, signature) {
5149
+ if (!namedId) return false;
5150
+ const owner = this.thinkingOwners.get(namedId);
5151
+ if (!owner) return false;
5152
+ const state = this.getMessageState(owner.messageId);
5153
+ if (!state) return false;
5154
+ state.thinkingStepSignatures.set(owner.stepId, signature);
5155
+ const content = state.thinkingSteps.get(owner.stepId) ?? "";
5156
+ if (!state.thinkingSteps.has(owner.stepId)) {
5157
+ state.thinkingSteps.set(owner.stepId, content);
5158
+ state.thinkingStepOrder.push(owner.stepId);
5159
+ }
5160
+ this.messages = updateThinkingPart(this.messages, owner.messageId, owner.stepId, content, signature);
5161
+ this.emitMessagesChange();
5162
+ return true;
5163
+ }
4344
5164
  resumeAssistantState(id, state) {
4345
5165
  this.activeMessageIds.add(id);
4346
5166
  if (state.isComplete || this.isDone) {
@@ -4350,7 +5170,8 @@ var StreamProcessor = class StreamProcessor {
4350
5170
  }
4351
5171
  /**
4352
5172
  * Ensure an active assistant message exists, creating one if needed.
4353
- * Used for backward compat when events arrive without prior TEXT_MESSAGE_START.
5173
+ * Used when content (reasoning, tool calls, errors) arrives without a
5174
+ * prior TEXT_MESSAGE_START.
4354
5175
  *
4355
5176
  * On reconnect/resume, a TEXT_MESSAGE_CONTENT may arrive for a message that
4356
5177
  * already exists in this.messages (e.g. from initialMessages or a prior
@@ -4359,6 +5180,11 @@ var StreamProcessor = class StreamProcessor {
4359
5180
  */
4360
5181
  ensureAssistantMessage(preferredId, fallbackToActive = true) {
4361
5182
  if (preferredId) {
5183
+ const pendingId = this.pendingManualMessageId;
5184
+ if (pendingId && pendingId !== preferredId && this.messageStates.get(pendingId)?.isComplete === false && !this.messages.some((message) => message.id === preferredId)) {
5185
+ this.renameMessage(pendingId, preferredId);
5186
+ this.pendingManualMessageId = preferredId;
5187
+ }
4362
5188
  const state = this.getMessageState(preferredId);
4363
5189
  if (state) {
4364
5190
  this.resumeAssistantState(preferredId, state);
@@ -4368,7 +5194,7 @@ var StreamProcessor = class StreamProcessor {
4368
5194
  };
4369
5195
  }
4370
5196
  }
4371
- const activeId = fallbackToActive ? this.getActiveAssistantMessageId() : null;
5197
+ const activeId = fallbackToActive && preferredId === void 0 ? this.getActiveAssistantMessageId() : null;
4372
5198
  if (activeId) {
4373
5199
  const state = this.getMessageState(activeId);
4374
5200
  if (state) {
@@ -4422,6 +5248,12 @@ var StreamProcessor = class StreamProcessor {
4422
5248
  * Rebuilds `createdAt` when `tanstack.createdAt` is an ISO string.
4423
5249
  */
4424
5250
  mergeMessageMetadata(messageId, incoming) {
5251
+ const runId = tanstackMetadata({ metadata: incoming !== null && typeof incoming === "object" ? { ...incoming } : void 0 })?.runId ?? (this.activeRuns.size === 1 ? [...this.activeRuns][0] : void 0);
5252
+ if (runId !== void 0) {
5253
+ const ids = this.callMessageIds.get(runId) ?? /* @__PURE__ */ new Set();
5254
+ ids.add(messageId);
5255
+ this.callMessageIds.set(runId, ids);
5256
+ } else this.unassignedCallMessageIds.add(messageId);
4425
5257
  if (incoming == null || typeof incoming !== "object" || Array.isArray(incoming)) return;
4426
5258
  const message = this.messages.find((msg) => msg.id === messageId);
4427
5259
  if (!message) return;
@@ -4622,6 +5454,13 @@ var StreamProcessor = class StreamProcessor {
4622
5454
  this.structuredOutputUpdateBatches.delete(fromId);
4623
5455
  this.structuredOutputUpdateBatches.set(toId, batch);
4624
5456
  }
5457
+ for (const ids of this.callMessageIds.values()) if (ids.delete(fromId)) ids.add(toId);
5458
+ if (this.unassignedCallMessageIds.delete(fromId)) this.unassignedCallMessageIds.add(toId);
5459
+ if (this.sealedMessageIds.delete(fromId)) this.sealedMessageIds.add(toId);
5460
+ for (const [key, owner] of this.thinkingOwners) if (owner.messageId === fromId) this.thinkingOwners.set(key, {
5461
+ messageId: toId,
5462
+ stepId: owner.stepId
5463
+ });
4625
5464
  }
4626
5465
  /**
4627
5466
  * Handle TEXT_MESSAGE_START event
@@ -4633,8 +5472,10 @@ var StreamProcessor = class StreamProcessor {
4633
5472
  return;
4634
5473
  }
4635
5474
  const uiRole = role === "user" || role === "system" ? role : "assistant";
4636
- if (this.pendingManualMessageId) {
4637
- const pendingId = this.pendingManualMessageId;
5475
+ const pendingId = this.pendingManualMessageId;
5476
+ const pendingRun = pendingId ? this.runOfMessage(pendingId) : void 0;
5477
+ const targetRun = this.runOfMessage(messageId);
5478
+ if (pendingId && !(pendingRun !== void 0 && targetRun !== void 0 && pendingRun !== targetRun)) {
4638
5479
  this.pendingManualMessageId = null;
4639
5480
  if (pendingId !== messageId) this.renameMessage(pendingId, messageId);
4640
5481
  let pendingState = this.messageStates.get(messageId);
@@ -4835,6 +5676,8 @@ var StreamProcessor = class StreamProcessor {
4835
5676
  * message. Fold leading thinking-only messages into the next real
4836
5677
  * assistant. Do not fold into a tool-result-only message (`role: 'tool'`
4837
5678
  * on the wire). `reconcileSnapshotToolCalls` anchors those results.
5679
+ * A `<id>-segment-<n>` row folds into its message, together with the
5680
+ * tool-result rows between them (a tool result ends a wire segment).
4838
5681
  */
4839
5682
  mergeReasoningFanOut(messages) {
4840
5683
  const out = [];
@@ -4859,12 +5702,19 @@ var StreamProcessor = class StreamProcessor {
4859
5702
  };
4860
5703
  pending = [];
4861
5704
  } else flushPending();
4862
- const prev = out.at(-1);
4863
- if (prev?.role === "assistant" && next.role === "assistant" && isAssistantSegmentOf(next.id, prev.id)) {
4864
- out[out.length - 1] = {
4865
- ...prev,
4866
- parts: [...prev.parts, ...next.parts]
4867
- };
5705
+ let parentIndex = out.length - 1;
5706
+ while (parentIndex >= 0) {
5707
+ const candidate = out[parentIndex];
5708
+ if (!candidate || !isToolResultOnly(candidate)) break;
5709
+ parentIndex--;
5710
+ }
5711
+ const parent = out[parentIndex];
5712
+ if (parent?.role === "assistant" && next.role === "assistant" && isAssistantSegmentOf(next.id, parent.id)) {
5713
+ const folded = out.slice(parentIndex).flatMap((message) => message.parts);
5714
+ out.splice(parentIndex, out.length - parentIndex, {
5715
+ ...parent,
5716
+ parts: [...folded, ...next.parts]
5717
+ });
4868
5718
  continue;
4869
5719
  }
4870
5720
  out.push(next);
@@ -5012,10 +5862,13 @@ var StreamProcessor = class StreamProcessor {
5012
5862
  if (pendingId && parentId && parentId !== pendingId) {
5013
5863
  const parent = this.messages.find((m) => m.id === parentId);
5014
5864
  const placeholder = this.messages.find((m) => m.id === pendingId);
5865
+ const pendingRun = this.runOfMessage(pendingId);
5866
+ const parentRun = parent ? this.runOfMessage(parent.id) : void 0;
5867
+ const separateRuns = pendingRun !== void 0 && parentRun !== void 0 && pendingRun !== parentRun;
5015
5868
  if (!parent) {
5016
5869
  this.pendingManualMessageId = null;
5017
5870
  this.renameMessage(pendingId, parentId);
5018
- } else if (parent.role === "assistant" && placeholder) {
5871
+ } else if (!separateRuns && parent.role === "assistant" && placeholder) {
5019
5872
  this.pendingManualMessageId = null;
5020
5873
  this.messages = this.messages.filter((m) => m.id !== pendingId).map((m) => m.id === parentId ? {
5021
5874
  ...m,
@@ -5026,6 +5879,8 @@ var StreamProcessor = class StreamProcessor {
5026
5879
  }
5027
5880
  const targetMessageId = chunk.parentMessageId ?? this.getActiveAssistantMessageId();
5028
5881
  const { messageId, state } = this.ensureAssistantMessage(targetMessageId ?? void 0, chunk.parentMessageId === void 0);
5882
+ const tanstack = tanstackMetadata(chunk);
5883
+ this.mergeMessageMetadata(messageId, tanstack === void 0 ? void 0 : { tanstack });
5029
5884
  state.hasToolCallsSinceTextStart = true;
5030
5885
  const toolCallId = chunk.toolCallId;
5031
5886
  if (!state.toolCalls.get(toolCallId)) {
@@ -5095,9 +5950,9 @@ var StreamProcessor = class StreamProcessor {
5095
5950
  * Handle TOOL_CALL_END event — arguments are finalized (input-complete).
5096
5951
  * Tool output arrives on TOOL_CALL_RESULT, not on this event.
5097
5952
  *
5098
- * If TOOL_CALL_END carries parsed `input`, it is the canonical arguments:
5099
- * write it into the accumulated string and override the rendered part's
5100
- * `input` with it. That covers adapters that deliver the whole input on END
5953
+ * The END's raw `args` and parsed `input` replace the streamed arguments
5954
+ * (see `finishToolCallArguments`), and the part's `input` is parsed from
5955
+ * the result. That covers adapters that deliver the whole input on END
5101
5956
  * (e.g. Anthropic server_tool_use / web_search — issue #839) and adapters
5102
5957
  * that stream the wire arguments and then normalize them (OpenAI strict-mode
5103
5958
  * null widening, undone by the adapter after #939), so `arguments` and
@@ -5110,25 +5965,11 @@ var StreamProcessor = class StreamProcessor {
5110
5965
  if (!messageId) return;
5111
5966
  const msgState = this.getMessageState(messageId);
5112
5967
  if (!msgState) return;
5113
- const input = chunk.input !== void 0 ? chunk.input : tanstackMetadata(chunk)?.input;
5114
5968
  const existingToolCall = msgState.toolCalls.get(chunk.toolCallId);
5115
5969
  if (existingToolCall && existingToolCall.state !== "input-complete") {
5116
- const serializedInput = serializeToolInput(input);
5117
- if (serializedInput !== void 0) existingToolCall.arguments = serializedInput;
5970
+ existingToolCall.arguments = finishToolCallArguments(existingToolCall.arguments, chunk).args;
5118
5971
  const index = msgState.toolCallOrder.indexOf(chunk.toolCallId);
5119
5972
  this.completeToolCall(messageId, index, existingToolCall);
5120
- if (serializedInput !== void 0) {
5121
- existingToolCall.parsedArguments = input;
5122
- this.messages = updateToolCallPart(this.messages, messageId, {
5123
- id: existingToolCall.id,
5124
- name: existingToolCall.name,
5125
- arguments: existingToolCall.arguments,
5126
- state: "input-complete",
5127
- input,
5128
- ...existingToolCall.metadata !== void 0 && { metadata: existingToolCall.metadata }
5129
- });
5130
- this.emitMessagesChange();
5131
- }
5132
5973
  }
5133
5974
  }
5134
5975
  /**
@@ -5166,6 +6007,7 @@ var StreamProcessor = class StreamProcessor {
5166
6007
  if (this.activeRuns.size === 0) {
5167
6008
  this.runToolCallIds = [];
5168
6009
  this.toolCallsSentToClient.clear();
6010
+ this.streamEndEmitted = false;
5169
6011
  }
5170
6012
  this.activeRuns.add(chunk.runId);
5171
6013
  }
@@ -5181,12 +6023,26 @@ var StreamProcessor = class StreamProcessor {
5181
6023
  */
5182
6024
  handleRunFinishedEvent(chunk) {
5183
6025
  const extra = chunk;
6026
+ const incoming = tanstackMetadata(chunk);
6027
+ const model = chunk.model ?? incoming?.model;
6028
+ const responseId = chunk.responseId ?? incoming?.responseId;
6029
+ const ids = this.callMessageIds.get(chunk.runId) ?? (this.activeRuns.has(chunk.runId) ? /* @__PURE__ */ new Set() : new Set(this.unassignedCallMessageIds));
6030
+ for (const messageId of ids) this.mergeMessageMetadata(messageId, withTanstackMetadata(chunk, {
6031
+ ...model !== void 0 ? { model } : {},
6032
+ ...responseId !== void 0 ? { responseId } : {}
6033
+ }).metadata);
6034
+ if (this.pendingManualMessageId && ids.has(this.pendingManualMessageId)) this.pendingManualMessageId = null;
6035
+ this.callMessageIds.delete(chunk.runId);
6036
+ for (const id of ids) this.unassignedCallMessageIds.delete(id);
5184
6037
  this.finishReason = extra.finishReason !== void 0 ? extra.finishReason : tanstackMetadata(chunk)?.finishReason ?? null;
5185
6038
  this.activeRuns.delete(chunk.runId);
5186
6039
  if (chunk.outcome?.type === "interrupt") this.handleInterrupts(chunk.outcome.interrupts);
5187
6040
  if (this.activeRuns.size === 0) {
5188
6041
  this.completeAllToolCalls();
5189
- if (this.finishReason === "tool_calls" && chunk.outcome?.type !== "interrupt") return;
6042
+ if (this.finishReason === "tool_calls" && chunk.outcome?.type !== "interrupt") {
6043
+ for (const id of ids) this.sealedMessageIds.add(id);
6044
+ return;
6045
+ }
5190
6046
  if (!chunk.outcome || chunk.outcome.type === "success") this.handlePendingToolCalls(chunk.outcome?.pendingToolCallIds);
5191
6047
  this.isDone = true;
5192
6048
  this.finalizeStream();
@@ -5206,6 +6062,7 @@ var StreamProcessor = class StreamProcessor {
5206
6062
  if (this.toolCallsSentToClient.has(toolCallId)) continue;
5207
6063
  const part = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
5208
6064
  if (!part || isProviderExecutedToolCall(part) || part.output !== void 0 || parts.some((p) => p.type === "tool-result" && p.toolCallId === toolCallId) || this.isToolCallPartTerminal(toolCallId) || this.isToolCallPartAwaitingUserAction(toolCallId)) continue;
6065
+ if (this.finishReason === "length") continue;
5209
6066
  const input = part.input ?? parseToolArguments(part.arguments);
5210
6067
  if (input === void 0) {
5211
6068
  console.warn(`[StreamProcessor] Did not run tool call ${toolCallId}: the arguments of ${part.name} are not complete JSON`);
@@ -5235,7 +6092,7 @@ var StreamProcessor = class StreamProcessor {
5235
6092
  if (owner !== void 0) this.updateChild(owner, (child) => child.handleInterrupts([interrupt], false));
5236
6093
  const toolName = typeof metadata.toolName === "string" ? metadata.toolName : this.findToolCallName(toolCallId);
5237
6094
  const input = Object.hasOwn(metadata, "input") ? metadata.input : {};
5238
- if (kind === "approval" || interrupt.reason === "approval_required") {
6095
+ if (kind === "approval") {
5239
6096
  if (owner !== void 0) {
5240
6097
  if (emit) this.events.onApprovalRequest?.({
5241
6098
  toolCallId,
@@ -5259,7 +6116,7 @@ var StreamProcessor = class StreamProcessor {
5259
6116
  });
5260
6117
  continue;
5261
6118
  }
5262
- if (kind === "client_tool" || interrupt.reason === "client_tool_input") {
6119
+ if (kind === "client_tool") {
5263
6120
  if (hasGeneric || !emit) continue;
5264
6121
  this.toolCallsSentToClient.add(toolCallId);
5265
6122
  this.events.onToolCall?.({
@@ -5282,13 +6139,20 @@ var StreamProcessor = class StreamProcessor {
5282
6139
  */
5283
6140
  handleRunErrorEvent(chunk) {
5284
6141
  this.hasError = true;
5285
- const runId = getChunkRunId(chunk);
6142
+ const runId = getChunkRunId(chunk) ?? (this.activeRuns.size === 1 ? [...this.activeRuns][0] : void 0);
6143
+ const currentIds = runId !== void 0 ? this.callMessageIds.get(runId) ?? this.unassignedCallMessageIds : this.unassignedCallMessageIds;
5286
6144
  if (runId) this.activeRuns.delete(runId);
5287
6145
  else this.activeRuns.clear();
5288
- const { messageId } = this.ensureAssistantMessage();
6146
+ const messageId = runId !== void 0 && this.callMessageIds.has(runId) && currentIds.size === 0 ? void 0 : this.ensureAssistantMessage([...currentIds].at(-1) ?? generateMessageId(), false).messageId;
6147
+ const ids = new Set(currentIds);
6148
+ if (messageId !== void 0) ids.add(messageId);
6149
+ for (const id of ids) this.mergeMessageMetadata(id, withTanstackMetadata(chunk, { stopReason: tanstackMetadata(chunk)?.stopReason ?? "error" }).metadata);
6150
+ if (this.pendingManualMessageId && ids.has(this.pendingManualMessageId)) this.pendingManualMessageId = null;
6151
+ if (runId !== void 0) this.callMessageIds.delete(runId);
6152
+ for (const id of ids) this.unassignedCallMessageIds.delete(id);
5289
6153
  const errorMessage = chunk.message || "An error occurred";
5290
6154
  if (!chunk.message) console.error("[StreamProcessor] RUN_ERROR with no message; original chunk:", chunk);
5291
- if (this.structuredMessageIds.has(messageId)) {
6155
+ if (messageId !== void 0 && this.structuredMessageIds.has(messageId)) {
5292
6156
  this.flushStructuredOutputUpdate(messageId);
5293
6157
  this.messages = errorStructuredOutputPart(this.messages, messageId, errorMessage);
5294
6158
  this.structuredMessageIds.delete(messageId);
@@ -5298,30 +6162,6 @@ var StreamProcessor = class StreamProcessor {
5298
6162
  this.events.onError?.(runErrorEventToError(chunk));
5299
6163
  }
5300
6164
  /**
5301
- * Handle STEP_STARTED event (for thinking/reasoning content).
5302
- *
5303
- * Records the stepId so later REASONING_MESSAGE_CONTENT deltas accumulate
5304
- * into their own ThinkingPart. Does not create a message — the message
5305
- * is lazily created when the first REASONING_MESSAGE_CONTENT arrives.
5306
- */
5307
- handleStepStartedEvent(chunk) {
5308
- const stepId = chunk.stepName || generateMessageId();
5309
- const activeId = this.getActiveAssistantMessageId();
5310
- if (activeId) {
5311
- const state = this.getMessageState(activeId);
5312
- if (state) {
5313
- state.currentThinkingStepId = stepId;
5314
- if (!state.thinkingSteps.has(stepId)) {
5315
- state.thinkingSteps.set(stepId, "");
5316
- state.thinkingStepOrder.push(stepId);
5317
- }
5318
- this.pendingThinkingStepId = null;
5319
- return;
5320
- }
5321
- }
5322
- this.pendingThinkingStepId = stepId;
5323
- }
5324
- /**
5325
6165
  * Handle ACTIVITY_SNAPSHOT. Creates or replaces a frontend-only activity
5326
6166
  * message. Does not create MessageStreamState (that path feeds
5327
6167
  * ProcessorResult.content).
@@ -5340,44 +6180,23 @@ var StreamProcessor = class StreamProcessor {
5340
6180
  this.emitMessagesChange();
5341
6181
  }
5342
6182
  /**
5343
- * Handle STEP_FINISHED event.
5344
- *
5345
- * Thinking *content* comes from REASONING_MESSAGE_CONTENT, not STEP_FINISHED.
5346
- * But some adapters (e.g. BytePlus thinking-summary) carry the provider
5347
- * signature blob ONLY on the STEP_FINISHED event, so still extract that here
5348
- * and attach it to the thinking step the reasoning events already built.
5349
- */
5350
- handleStepFinishedEvent(chunk) {
5351
- const extra = chunk;
5352
- const signature = extra.signature;
5353
- if (!signature) return;
5354
- const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
5355
- const stepId = state.currentThinkingStepId ?? extra.stepId;
5356
- if (!stepId) return;
5357
- const thinking = state.thinkingSteps.get(stepId);
5358
- if (thinking === void 0) return;
5359
- state.thinkingStepSignatures.set(stepId, signature);
5360
- this.messages = updateThinkingPart(this.messages, messageId, stepId, thinking, signature);
5361
- this.emitMessagesChange();
5362
- }
5363
- /**
5364
6183
  * Handle REASONING_MESSAGE_CONTENT event (AG-UI reasoning protocol).
5365
6184
  *
5366
6185
  * Accumulates reasoning delta into thinking content and updates the
5367
6186
  * corresponding ThinkingPart in the UIMessage.
5368
6187
  */
5369
6188
  handleReasoningMessageContentEvent(chunk) {
5370
- const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
6189
+ const target = this.unscopedAssistant(chunk);
6190
+ const { messageId, state } = this.ensureAssistantMessage(target.id ?? void 0, !target.create);
5371
6191
  this.mergeMessageMetadata(messageId, chunk.metadata);
5372
- state.hasSeenReasoningEvents = true;
5373
6192
  const delta = chunk.delta || "";
5374
- this.consumePendingThinkingStep(state);
5375
6193
  const stepId = state.currentThinkingStepId ?? chunk.messageId;
5376
6194
  if (!state.thinkingSteps.has(stepId)) {
5377
6195
  state.thinkingSteps.set(stepId, "");
5378
6196
  state.thinkingStepOrder.push(stepId);
5379
6197
  state.currentThinkingStepId = stepId;
5380
6198
  }
6199
+ this.rememberThinking(messageId, stepId, chunk.messageId);
5381
6200
  const nextThinking = (state.thinkingSteps.get(stepId) ?? "") + delta;
5382
6201
  state.thinkingSteps.set(stepId, nextThinking);
5383
6202
  this.messages = updateThinkingPart(this.messages, messageId, stepId, nextThinking, state.thinkingStepSignatures.get(stepId));
@@ -5396,8 +6215,12 @@ var StreamProcessor = class StreamProcessor {
5396
6215
  this.attachToolCallSignature(chunk.entityId, encryptedValue);
5397
6216
  return;
5398
6217
  }
5399
- const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
6218
+ if (this.applyKnownSignature(chunk.entityId, encryptedValue)) return;
6219
+ const target = this.unscopedAssistant(chunk);
6220
+ const { messageId, state } = this.ensureAssistantMessage(target.id ?? void 0, !target.create);
5400
6221
  const stepId = state.currentThinkingStepId ?? chunk.entityId;
6222
+ this.rememberThinking(messageId, stepId, chunk.entityId);
6223
+ this.mergeMessageMetadata(messageId, chunk.metadata);
5401
6224
  state.thinkingStepSignatures.set(stepId, encryptedValue);
5402
6225
  const content = state.thinkingSteps.get(stepId) ?? "";
5403
6226
  if (!state.thinkingSteps.has(stepId)) {
@@ -5439,23 +6262,15 @@ var StreamProcessor = class StreamProcessor {
5439
6262
  /**
5440
6263
  * Handle CUSTOM event.
5441
6264
  *
5442
- * Handles custom events consumed by the processor:
5443
- * - 'tool-input-available': Legacy/replay-compatible input for client tool
5444
- * execution. Fires onToolCall.
5445
- * - 'approval-requested': Legacy/replay-compatible input for tool approval.
5446
- * Updates tool-call part state and fires onApprovalRequest.
5447
- *
5448
- * Current core streams represent user-actionable waits through
5449
- * RUN_FINISHED.outcome.type === 'interrupt'; these custom events are not the
5450
- * source of truth for new emissions.
5451
- *
5452
- * @see docs/chat-architecture.md#client-tools-and-approval-flows — Full flow details
6265
+ * Handles structured-output and ui-resource events, and forwards the rest
6266
+ * to onCustomEvent. Client tools and approvals arrive as RUN_FINISHED
6267
+ * interrupt outcomes, not as custom events.
5453
6268
  */
5454
6269
  handleCustomEvent(chunk) {
5455
6270
  const messageId = this.getActiveAssistantMessageId();
5456
6271
  if (chunk.name === "structured-output.start" && chunk.value) {
5457
6272
  const v = chunk.value;
5458
- const { messageId: targetId } = this.ensureAssistantMessage(v.messageId ?? messageId ?? void 0);
6273
+ const { messageId: targetId } = this.ensureAssistantMessage(v.messageId && this.getMessageState(v.messageId) ? v.messageId : messageId ?? v.messageId);
5459
6274
  if (targetId) {
5460
6275
  this.structuredMessageIds.add(targetId);
5461
6276
  this.structuredOutputUpdateBatches.delete(targetId);
@@ -5470,7 +6285,7 @@ var StreamProcessor = class StreamProcessor {
5470
6285
  }
5471
6286
  if (chunk.name === "structured-output.complete" && chunk.value) {
5472
6287
  const v = chunk.value;
5473
- const { messageId: targetId } = this.ensureAssistantMessage(v.messageId ?? messageId ?? void 0);
6288
+ const { messageId: targetId } = this.ensureAssistantMessage(v.messageId && this.getMessageState(v.messageId) ? v.messageId : messageId ?? v.messageId);
5474
6289
  if (targetId) {
5475
6290
  this.flushStructuredOutputUpdate(targetId);
5476
6291
  this.messages = completeStructuredOutputPart(this.messages, targetId, v.object, v.raw ?? "", v.reasoning);
@@ -5479,31 +6294,6 @@ var StreamProcessor = class StreamProcessor {
5479
6294
  this.emitMessagesChange();
5480
6295
  }
5481
6296
  }
5482
- if (chunk.name === "tool-input-available" && chunk.value) {
5483
- const { toolCallId, toolName, input } = chunk.value;
5484
- this.toolCallsSentToClient.add(toolCallId);
5485
- this.events.onToolCall?.({
5486
- toolCallId,
5487
- toolName,
5488
- input
5489
- });
5490
- return;
5491
- }
5492
- if (chunk.name === "approval-requested" && chunk.value) {
5493
- const { toolCallId, toolName, input, approval } = chunk.value;
5494
- const resolvedMessageId = messageId ?? this.toolCallToMessage.get(toolCallId);
5495
- if (resolvedMessageId) {
5496
- this.messages = updateToolCallApproval(this.messages, resolvedMessageId, toolCallId, approval.id);
5497
- this.emitMessagesChange();
5498
- }
5499
- this.events.onApprovalRequest?.({
5500
- toolCallId,
5501
- toolName,
5502
- input,
5503
- approvalId: approval.id
5504
- });
5505
- return;
5506
- }
5507
6297
  if (chunk.name === "ui-resource" && chunk.value) {
5508
6298
  const v = chunk.value;
5509
6299
  const resolvedMessageId = this.toolCallToMessage.get(v.toolCallId) ?? messageId;
@@ -5772,13 +6562,16 @@ var StreamProcessor = class StreamProcessor {
5772
6562
  */
5773
6563
  resetStreamState() {
5774
6564
  this.messageStates.clear();
6565
+ this.callMessageIds.clear();
6566
+ this.unassignedCallMessageIds.clear();
5775
6567
  this.activeMessageIds.clear();
5776
6568
  this.activeRuns.clear();
5777
6569
  this.toolCallToMessage.clear();
5778
6570
  this.structuredMessageIds.clear();
5779
6571
  this.structuredOutputUpdateBatches.clear();
5780
6572
  this.pendingManualMessageId = null;
5781
- this.pendingThinkingStepId = null;
6573
+ this.sealedMessageIds.clear();
6574
+ this.thinkingOwners.clear();
5782
6575
  this.openChunk = null;
5783
6576
  this.finishReason = null;
5784
6577
  this.hasError = false;
@@ -5819,27 +6612,7 @@ function createReplayStream(recording) {
5819
6612
  } };
5820
6613
  }
5821
6614
  //#endregion
5822
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/providers.js
5823
- /** `[a-z][a-z0-9-]{0,63}` — lowercase, no underscores, max 64 chars. */
5824
- var BYOK_PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
5825
- function isProviderId(value) {
5826
- return typeof value === "string" && BYOK_PROVIDER_ID_PATTERN.test(value);
5827
- }
5828
- //#endregion
5829
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/missing.js
5830
- function isByokMissingBody(value) {
5831
- if (typeof value !== "object" || value === null) return false;
5832
- if (!("error" in value)) return false;
5833
- const error = value.error;
5834
- if (typeof error !== "object" || error === null) return false;
5835
- if (!("type" in error) || error.type !== "byok_missing") return false;
5836
- if (!("provider" in error) || typeof error.provider !== "string") return false;
5837
- if (!isProviderId(error.provider)) return false;
5838
- if (!("message" in error) || typeof error.message !== "string") return false;
5839
- return true;
5840
- }
5841
- //#endregion
5842
- //#region ../node_modules/.bun/@tanstack+ai@0.68.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/errors.js
6615
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/errors.js
5843
6616
  var ByokMissingError = class extends Error {
5844
6617
  provider;
5845
6618
  constructor(provider) {
@@ -5865,7 +6638,27 @@ var ByokUnresolvedProviderError = class extends Error {
5865
6638
  }
5866
6639
  };
5867
6640
  //#endregion
5868
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
6641
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/providers.js
6642
+ /** `[a-z][a-z0-9-]{0,63}` — lowercase, no underscores, max 64 chars. */
6643
+ var BYOK_PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
6644
+ function isProviderId(value) {
6645
+ return typeof value === "string" && BYOK_PROVIDER_ID_PATTERN.test(value);
6646
+ }
6647
+ //#endregion
6648
+ //#region ../node_modules/.bun/@tanstack+ai@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai/dist/esm/byok/missing.js
6649
+ function isByokMissingBody(value) {
6650
+ if (typeof value !== "object" || value === null) return false;
6651
+ if (!("error" in value)) return false;
6652
+ const error = value.error;
6653
+ if (typeof error !== "object" || error === null) return false;
6654
+ if (!("type" in error) || error.type !== "byok_missing") return false;
6655
+ if (!("provider" in error) || typeof error.provider !== "string") return false;
6656
+ if (!isProviderId(error.provider)) return false;
6657
+ if (!("message" in error) || typeof error.message !== "string") return false;
6658
+ return true;
6659
+ }
6660
+ //#endregion
6661
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
5869
6662
  /**
5870
6663
  * Associates connect-wrapped chunks with the run they were produced under.
5871
6664
  * Content events (TEXT_MESSAGE_CONTENT, TOOL_CALL_*, …) carry no `runId` of
@@ -5917,19 +6710,59 @@ var DurableStreamIncompleteError = class extends Error {
5917
6710
  * reconnecting without end.
5918
6711
  */
5919
6712
  var StreamReconnectLimitError = class extends Error {
5920
- constructor(attempts) {
5921
- super(`Durable run exceeded its reconnect ceiling of ${attempts} attempts — giving up.`);
6713
+ constructor(attempts, budgetMs) {
6714
+ super(budgetMs === void 0 ? `Durable run exceeded its reconnect ceiling of ${attempts} attempts — giving up.` : `Durable run did not reconnect within its budget of ${budgetMs} ms (${attempts} attempts) — giving up.`);
5922
6715
  this.name = "StreamReconnectLimitError";
5923
6716
  }
5924
6717
  };
6718
+ /** HTTP statuses that a proxy or server sends while it restarts or sheds load. */
6719
+ var TEMPORARY_HTTP_STATUSES = /* @__PURE__ */ new Set([
6720
+ 408,
6721
+ 429,
6722
+ 502,
6723
+ 503,
6724
+ 504
6725
+ ]);
6726
+ /**
6727
+ * A non-2xx response. A reconnect retries it when the status is temporary
6728
+ * (408, 429, 502, 503, 504), and waits for its `Retry-After` when present.
6729
+ */
6730
+ var StreamHttpError = class extends Error {
6731
+ status;
6732
+ retryAfterMs;
6733
+ constructor(message, status, retryAfter) {
6734
+ super(message);
6735
+ this.status = status;
6736
+ this.name = "StreamHttpError";
6737
+ this.retryAfterMs = parseRetryAfterMs(retryAfter);
6738
+ }
6739
+ };
6740
+ /** `Retry-After` in seconds or as an HTTP date, in ms. */
6741
+ function parseRetryAfterMs(value) {
6742
+ if (!value) return void 0;
6743
+ const seconds = Number(value);
6744
+ if (Number.isFinite(seconds)) return seconds >= 0 ? seconds * 1e3 : void 0;
6745
+ const date = Date.parse(value);
6746
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - Date.now());
6747
+ }
6748
+ function isTemporaryHttpError(error) {
6749
+ return error instanceof StreamHttpError && TEMPORARY_HTTP_STATUSES.has(error.status);
6750
+ }
5925
6751
  function resolveReconnectOptions(options) {
5926
- const maxAttempts = options?.maxAttempts ?? 5;
5927
- const delayMs = options?.delayMs ?? 250;
5928
- if (!Number.isInteger(maxAttempts) || maxAttempts < 0) throw new Error(`Invalid reconnect.maxAttempts: ${maxAttempts}. Must be a non-negative integer.`);
5929
- if (!Number.isFinite(delayMs) || delayMs < 0) throw new Error(`Invalid reconnect.delayMs: ${delayMs}. Must be a non-negative finite number.`);
6752
+ const budgetMs = options?.budgetMs;
6753
+ const maxAttempts = options?.maxAttempts ?? (budgetMs === void 0 ? 5 : Infinity);
6754
+ const initialDelayMs = options?.initialDelayMs ?? options?.delayMs ?? 250;
6755
+ const maxDelayMs = options?.maxDelayMs ?? Math.max(5e3, initialDelayMs);
6756
+ if (options?.maxAttempts !== void 0) {
6757
+ if (!Number.isInteger(maxAttempts) || maxAttempts < 0) throw new Error(`Invalid reconnect.maxAttempts: ${maxAttempts}. Must be a non-negative integer.`);
6758
+ }
6759
+ for (const [name, value] of [["initialDelayMs", initialDelayMs], ["maxDelayMs", maxDelayMs]]) if (!Number.isFinite(value) || value < 0) throw new Error(`Invalid reconnect.${name}: ${value}. Must be a non-negative finite number.`);
6760
+ if (budgetMs !== void 0 && (!Number.isFinite(budgetMs) || budgetMs <= 0)) throw new Error(`Invalid reconnect.budgetMs: ${budgetMs}. Must be a positive finite number.`);
5930
6761
  return {
5931
6762
  maxAttempts,
5932
- delayMs
6763
+ initialDelayMs,
6764
+ maxDelayMs,
6765
+ budgetMs
5933
6766
  };
5934
6767
  }
5935
6768
  /** Create a {@link ReconnectTracker} bound to the given reconnect bounds. */
@@ -5938,6 +6771,7 @@ function createReconnectTracker(options) {
5938
6771
  const seen = /* @__PURE__ */ new Set();
5939
6772
  let lastEventId;
5940
6773
  let reconnectAttempts = 0;
6774
+ let failingSince;
5941
6775
  return {
5942
6776
  get lastEventId() {
5943
6777
  return lastEventId;
@@ -5954,13 +6788,19 @@ function createReconnectTracker(options) {
5954
6788
  lastEventId = id;
5955
6789
  return "new";
5956
6790
  },
5957
- async waitBeforeReconnect(madeProgress, signal) {
5958
- if (madeProgress) reconnectAttempts = 0;
5959
- else {
6791
+ async waitBeforeReconnect(madeProgress, signal, retryAfterMs) {
6792
+ if (madeProgress) {
6793
+ reconnectAttempts = 0;
6794
+ failingSince = void 0;
6795
+ } else {
5960
6796
  reconnectAttempts += 1;
6797
+ failingSince ??= Date.now();
5961
6798
  if (reconnectAttempts > reconnect.maxAttempts) throw new StreamReconnectLimitError(reconnect.maxAttempts);
5962
6799
  }
5963
- await abortableDelay(reconnect.delayMs, signal);
6800
+ const backoff = reconnect.initialDelayMs === 0 ? 0 : Math.min(reconnect.maxDelayMs, reconnect.initialDelayMs * 2 ** Math.max(0, reconnectAttempts - 1));
6801
+ const delayMs = retryAfterMs === void 0 ? backoff * (.5 + Math.random() / 2) : Math.min(retryAfterMs, reconnect.maxDelayMs);
6802
+ if (reconnect.budgetMs !== void 0 && failingSince !== void 0 && Date.now() - failingSince + delayMs > reconnect.budgetMs) throw new StreamReconnectLimitError(reconnectAttempts - 1, reconnect.budgetMs);
6803
+ await abortableDelay(delayMs, signal);
5964
6804
  }
5965
6805
  };
5966
6806
  }
@@ -5979,19 +6819,6 @@ function abortableDelay(ms, signal) {
5979
6819
  signal?.addEventListener("abort", onAbort, { once: true });
5980
6820
  });
5981
6821
  }
5982
- function generateRunId(prefix) {
5983
- return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5984
- }
5985
- /**
5986
- * Asserts an id is present when synthesizing a terminal event. The chat
5987
- * client always supplies `runContext.threadId` / `runContext.runId`, so an
5988
- * absent id at this layer indicates the adapter was wired up by a caller
5989
- * that bypassed that contract — surface it rather than fabricating one.
5990
- */
5991
- function requireSyntheticId(value, field) {
5992
- if (!value) throw new Error(`Cannot synthesize terminal event: ${field} not supplied via runContext and not observed in the upstream stream.`);
5993
- return value;
5994
- }
5995
6822
  /**
5996
6823
  * Merge custom headers into request headers
5997
6824
  */
@@ -6017,7 +6844,7 @@ function mergeHeaders(customHeaders) {
6017
6844
  */
6018
6845
  var RUN_ID_HEADER = "X-Run-Id";
6019
6846
  function runIdHeader(runId) {
6020
- return runId === void 0 ? {} : { [RUN_ID_HEADER]: runId };
6847
+ return { [RUN_ID_HEADER]: runId };
6021
6848
  }
6022
6849
  function withSearchParams(url, values) {
6023
6850
  const hashIndex = url.indexOf("#");
@@ -6064,19 +6891,6 @@ async function* readStreamLines(reader, abortSignal) {
6064
6891
  reader.releaseLock();
6065
6892
  }
6066
6893
  }
6067
- /** Rebuild pre-wire extras after SSE/NDJSON ingest. */
6068
- function restoreInboundUsage(chunk) {
6069
- return restoreInboundChunk(chunk);
6070
- }
6071
- function sseChunkModel(chunk) {
6072
- const tanstackModel = tanstackMetadata(chunk)?.model;
6073
- if (typeof tanstackModel === "string") return tanstackModel;
6074
- const usage = "usage" in chunk ? chunk.usage : void 0;
6075
- if (Array.isArray(usage)) {
6076
- const model = usage[0]?.model;
6077
- if (typeof model === "string") return model;
6078
- }
6079
- }
6080
6894
  /**
6081
6895
  * Parse SSE-format lines into stream events, pairing each chunk with the `id:`
6082
6896
  * offset of the event it arrived on. Shared by the fetch- and XHR-backed SSE
@@ -6084,17 +6898,11 @@ function sseChunkModel(chunk) {
6084
6898
  *
6085
6899
  * Accepts either `data: {...}` lines or bare JSON lines. Skips comments
6086
6900
  * starting with `:` (proxies and CDNs inject these as keepalives) and the
6087
- * `event:` / `retry:` SSE control fields. A `[DONE]` sentinel is treated as a
6088
- * terminal event: a synthesized RUN_FINISHED is yielded using the most recent
6089
- * upstream `threadId` / `runId` (falling back to `fallbackIds`), so the
6090
- * consumer sees a clean terminal event with real correlation ids.
6901
+ * `event:` / `retry:` SSE control fields.
6091
6902
  *
6092
6903
  * A JSON parse failure throws — the consumer surfaces it as an error.
6093
6904
  */
6094
- async function* linesToSSEEvents(lines, fallbackIds) {
6095
- let lastThreadId;
6096
- let lastRunId;
6097
- let lastModel;
6905
+ async function* linesToSSEEvents(lines) {
6098
6906
  let pendingId;
6099
6907
  for await (const line of lines) {
6100
6908
  if (line === "id" || line.startsWith("id:")) {
@@ -6104,23 +6912,7 @@ async function* linesToSSEEvents(lines, fallbackIds) {
6104
6912
  }
6105
6913
  if (line.startsWith(":") || line.startsWith("event:") || line.startsWith("retry:")) continue;
6106
6914
  const data = parseSseDataLine(line);
6107
- if (data === "[DONE]") {
6108
- yield { chunk: withTanstackMetadata({
6109
- type: EventType.RUN_FINISHED,
6110
- threadId: lastThreadId ?? fallbackIds?.threadId ?? "",
6111
- runId: lastRunId ?? fallbackIds?.runId ?? "",
6112
- timestamp: Date.now()
6113
- }, {
6114
- finishReason: "stop",
6115
- ...lastModel !== void 0 ? { model: lastModel } : {}
6116
- }) };
6117
- return;
6118
- }
6119
- const chunk = restoreInboundUsage(JSON.parse(data));
6120
- if ("threadId" in chunk && typeof chunk.threadId === "string") lastThreadId = chunk.threadId;
6121
- if ("runId" in chunk && typeof chunk.runId === "string") lastRunId = chunk.runId;
6122
- const model = sseChunkModel(chunk);
6123
- if (model !== void 0) lastModel = model;
6915
+ const chunk = restoreInboundChunk(JSON.parse(data));
6124
6916
  const id = pendingId;
6125
6917
  pendingId = void 0;
6126
6918
  yield {
@@ -6135,7 +6927,7 @@ async function assertResponseOk(response) {
6135
6927
  const body = await response.clone().json().catch(() => null);
6136
6928
  if (isByokMissingBody(body)) throw new ByokMissingError(body.error.provider);
6137
6929
  }
6138
- throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
6930
+ throw new StreamHttpError(`HTTP error! status: ${response.status} ${response.statusText}`, response.status, response.headers.get("retry-after"));
6139
6931
  }
6140
6932
  function chatHydrationSearchParams(threadId, options) {
6141
6933
  const values = { threadId };
@@ -6216,9 +7008,9 @@ async function fetchGenerationHydration(fetchClient, url, headers, credentials,
6216
7008
  };
6217
7009
  }
6218
7010
  /** Yield SSE stream events (chunk + offset) from a fetch Response body. */
6219
- async function* responseToSSEEvents(response, abortSignal, fallbackIds) {
7011
+ async function* responseToSSEEvents(response, abortSignal) {
6220
7012
  await assertResponseOk(response);
6221
- yield* linesToSSEEvents(readStreamLines(getResponseStreamReader(response), abortSignal), fallbackIds);
7013
+ yield* linesToSSEEvents(readStreamLines(getResponseStreamReader(response), abortSignal));
6222
7014
  }
6223
7015
  async function* responseToSSEChunks(response, abortSignal) {
6224
7016
  for await (const { chunk } of responseToSSEEvents(response, abortSignal)) yield chunk;
@@ -6273,8 +7065,8 @@ async function* resumableStream(openEventSource, abortSignal, reconnectOptions)
6273
7065
  }
6274
7066
  } catch (error) {
6275
7067
  if (abortSignal?.aborted) return;
6276
- if ((error instanceof StreamTruncatedError || error instanceof StreamReadError) && tracker.lastEventId !== void 0) {
6277
- await tracker.waitBeforeReconnect(progressed, abortSignal);
7068
+ if ((error instanceof StreamTruncatedError || error instanceof StreamReadError || isTemporaryHttpError(error)) && tracker.lastEventId !== void 0) {
7069
+ await tracker.waitBeforeReconnect(progressed, abortSignal, isTemporaryHttpError(error) ? error.retryAfterMs : void 0);
6278
7070
  continue;
6279
7071
  }
6280
7072
  throw error;
@@ -6372,28 +7164,28 @@ function normalizeConnectionAdapter(connection) {
6372
7164
  if ("threadId" in chunk && typeof chunk.threadId === "string") upstreamThreadId = chunk.threadId;
6373
7165
  if ("runId" in chunk && typeof chunk.runId === "string") upstreamRunId = chunk.runId;
6374
7166
  if (chunk.type === "RUN_FINISHED" || chunk.type === "RUN_ERROR") hasTerminalEvent = true;
6375
- push(chunk, runContext?.runId);
7167
+ push(chunk, runContext.runId);
6376
7168
  }
6377
7169
  if (!abortSignal?.aborted && !hasTerminalEvent) push(withTanstackMetadata({
6378
7170
  type: EventType.RUN_FINISHED,
6379
- threadId: requireSyntheticId(upstreamThreadId ?? runContext?.threadId, "threadId"),
6380
- runId: requireSyntheticId(upstreamRunId ?? runContext?.runId, "runId"),
7171
+ threadId: upstreamThreadId ?? runContext.threadId,
7172
+ runId: upstreamRunId ?? runContext.runId,
6381
7173
  timestamp: Date.now()
6382
7174
  }, {
6383
7175
  finishReason: "stop",
6384
7176
  model: "connect-wrapper"
6385
- }), runContext?.runId);
7177
+ }), runContext.runId);
6386
7178
  } catch (err) {
6387
- if (!abortSignal?.aborted && !hasTerminalEvent) try {
7179
+ if (!abortSignal?.aborted && !hasTerminalEvent) {
6388
7180
  const message = err instanceof Error ? err.message : "Unknown error in connect()";
6389
7181
  push({
6390
7182
  type: EventType.RUN_ERROR,
6391
- threadId: requireSyntheticId(upstreamThreadId ?? runContext?.threadId, "threadId"),
6392
- runId: requireSyntheticId(upstreamRunId ?? runContext?.runId, "runId"),
7183
+ threadId: upstreamThreadId ?? runContext.threadId,
7184
+ runId: upstreamRunId ?? runContext.runId,
6393
7185
  timestamp: Date.now(),
6394
7186
  message
6395
- }, runContext?.runId);
6396
- } catch {}
7187
+ }, runContext.runId);
7188
+ }
6397
7189
  throw err;
6398
7190
  }
6399
7191
  await waitUntilSubscriberIdle(abortSignal);
@@ -6406,23 +7198,23 @@ function normalizeConnectionAdapter(connection) {
6406
7198
  };
6407
7199
  }
6408
7200
  function buildRunAgentInputBody(messages, data, runContext, options) {
7201
+ if (!runContext) throw new Error("Connection adapter: connect() and send() need a run context with a threadId. ChatClient and the generation clients pass one. Pass it when you call the adapter yourself.");
6409
7202
  const wireMessages = uiMessagesToWire(messages);
6410
7203
  const forwardedProps = {
6411
7204
  ...options.body,
6412
- ...runContext?.forwardedProps ?? {},
7205
+ ...runContext.forwardedProps,
6413
7206
  ...data
6414
7207
  };
6415
7208
  return {
6416
- threadId: runContext?.threadId ?? generateRunId("thread"),
6417
- runId: runContext?.runId ?? generateRunId("run"),
6418
- ...runContext?.parentRunId !== void 0 && { parentRunId: runContext.parentRunId },
6419
- ...runContext?.resume !== void 0 && { resume: runContext.resume },
7209
+ threadId: runContext.threadId,
7210
+ runId: runContext.runId,
7211
+ ...runContext.parentRunId !== void 0 && { parentRunId: runContext.parentRunId },
7212
+ ...runContext.resume !== void 0 && { resume: runContext.resume },
6420
7213
  state: {},
6421
7214
  messages: wireMessages,
6422
- tools: runContext?.clientTools ?? [],
7215
+ tools: runContext.clientTools ?? [],
6423
7216
  context: [],
6424
- forwardedProps,
6425
- data: { ...forwardedProps }
7217
+ forwardedProps
6426
7218
  };
6427
7219
  }
6428
7220
  /**
@@ -6467,8 +7259,8 @@ function fetchServerSentEvents(url, options = {}) {
6467
7259
  const requestHeaders = {
6468
7260
  "Content-Type": "application/json",
6469
7261
  ...mergeHeaders(resolvedOptions.headers),
6470
- ...mergeHeaders(runContext?.headers),
6471
- ...runIdHeader(runContext?.runId)
7262
+ ...mergeHeaders(runContext.headers),
7263
+ ...runIdHeader(runContext.runId)
6472
7264
  };
6473
7265
  const requestBody = buildRunAgentInputBody(messages, data, runContext, resolvedOptions);
6474
7266
  const fetchClient = resolvedOptions.fetchClient ?? fetch;
@@ -6478,10 +7270,7 @@ function fetchServerSentEvents(url, options = {}) {
6478
7270
  headers: requestHeaders,
6479
7271
  body: JSON.stringify(requestBody),
6480
7272
  credentials: resolvedOptions.credentials || "same-origin"
6481
- }, (response, sseSignal) => responseToSSEEvents(response, sseSignal, {
6482
- ...runContext?.threadId !== void 0 ? { threadId: runContext.threadId } : {},
6483
- ...runContext?.runId !== void 0 ? { runId: runContext.runId } : {}
6484
- })), signal, resolvedOptions.reconnect);
7273
+ }, responseToSSEEvents), signal, resolvedOptions.reconnect);
6485
7274
  },
6486
7275
  async *joinRun(runId, abortSignal) {
6487
7276
  const resolvedUrl = typeof url === "function" ? url() : url;
@@ -6497,7 +7286,7 @@ function fetchServerSentEvents(url, options = {}) {
6497
7286
  method: "GET",
6498
7287
  headers: requestHeaders,
6499
7288
  credentials: resolvedOptions.credentials || "same-origin"
6500
- }, (response, sseSignal) => responseToSSEEvents(response, sseSignal, { runId })), signal, resolvedOptions.reconnect);
7289
+ }, responseToSSEEvents), signal, resolvedOptions.reconnect);
6501
7290
  },
6502
7291
  async hydrate(threadId, hydrateOptions) {
6503
7292
  const resolvedUrl = typeof url === "function" ? url() : url;
@@ -6563,7 +7352,7 @@ async function* abortableIterable(iterable, signal) {
6563
7352
  }
6564
7353
  }
6565
7354
  //#endregion
6566
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/interrupt-manager.js
7355
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/interrupt-manager.js
6567
7356
  function isClientOwnedInterrupt(item) {
6568
7357
  return item.resumable;
6569
7358
  }
@@ -6586,8 +7375,7 @@ var itemErrorCodes = /* @__PURE__ */ new Set([
6586
7375
  "unknown-interrupt",
6587
7376
  "expired",
6588
7377
  "stale",
6589
- "conflict",
6590
- "legacy-unsupported"
7378
+ "conflict"
6591
7379
  ]);
6592
7380
  var batchErrorCodes = /* @__PURE__ */ new Set([
6593
7381
  "incomplete-batch",
@@ -6602,27 +7390,11 @@ var batchErrorCodes = /* @__PURE__ */ new Set([
6602
7390
  "invalid-response-schema",
6603
7391
  "expired",
6604
7392
  "stale",
6605
- "conflict",
6606
- "legacy-submit-failed"
7393
+ "conflict"
6607
7394
  ]);
6608
7395
  function isUnknownObject(value) {
6609
7396
  return value !== null && typeof value === "object" && !Array.isArray(value);
6610
7397
  }
6611
- function isLegacyApprovalMetadata(value) {
6612
- return isUnknownObject(value) && value["kind"] === "approval" && typeof value["toolName"] === "string" && "input" in value;
6613
- }
6614
- function isLegacyClientToolMetadata(value) {
6615
- return isUnknownObject(value) && value["kind"] === "client_tool" && typeof value["toolName"] === "string" && "input" in value;
6616
- }
6617
- /**
6618
- * Does this descriptor carry the pre-binding TanStack metadata marker?
6619
- *
6620
- * Descriptors emitted before the resume binding existed are still ours to
6621
- * resume, so they must not be mistaken for another producer's interrupt.
6622
- */
6623
- function isLegacyInterruptMetadata(interrupt) {
6624
- return isLegacyApprovalMetadata(interrupt.metadata) || isLegacyClientToolMetadata(interrupt.metadata);
6625
- }
6626
7398
  function getDescriptorBinding(interrupt) {
6627
7399
  return readInterruptBinding(interrupt);
6628
7400
  }
@@ -6642,13 +7414,6 @@ function hasFirstPartyGenericMarker(interrupt) {
6642
7414
  function getInterruptPayload(interrupt) {
6643
7415
  return interrupt.metadata?.["tanstack:interruptPayload"];
6644
7416
  }
6645
- /**
6646
- * Only used to route *legacy* (pre-binding) descriptors, which have no binding
6647
- * to classify off. Current descriptors are classified by their binding alone.
6648
- */
6649
- function isClientToolExecutionReason(reason) {
6650
- return reason === "tanstack:client_tool_execution" || reason === "client_tool_input";
6651
- }
6652
7417
  function responseSchemaHash(interrupt) {
6653
7418
  if (interrupt.responseSchema === void 0) return void 0;
6654
7419
  try {
@@ -6752,7 +7517,6 @@ function genericBinding(interrupt, hydration, candidate) {
6752
7517
  function baseSnapshot(item, hydration) {
6753
7518
  const descriptor = cloneAndDeepFreezeJson(item.descriptor);
6754
7519
  const errors = item.error === void 0 ? Object.freeze([]) : Object.freeze([cloneAndDeepFreezeJson(item.error)]);
6755
- const error = errors[0];
6756
7520
  return {
6757
7521
  id: descriptor.id,
6758
7522
  interruptId: descriptor.id,
@@ -6766,7 +7530,6 @@ function baseSnapshot(item, hydration) {
6766
7530
  generation: hydration.generation,
6767
7531
  status: item.status,
6768
7532
  errors,
6769
- ...error !== void 0 ? { error } : {},
6770
7533
  canResolve: item.canResolve
6771
7534
  };
6772
7535
  }
@@ -6779,7 +7542,6 @@ var InterruptManager = class {
6779
7542
  submissionRootErrors = Object.freeze([]);
6780
7543
  state = Object.freeze({
6781
7544
  interrupts: this.snapshot,
6782
- pendingInterrupts: this.snapshot,
6783
7545
  interruptErrors: this.rootErrors,
6784
7546
  resuming: false
6785
7547
  });
@@ -6787,6 +7549,7 @@ var InterruptManager = class {
6787
7549
  activeSubmissionOperation;
6788
7550
  retrySubmission;
6789
7551
  resuming = false;
7552
+ warnedSchemaMismatches = /* @__PURE__ */ new Set();
6790
7553
  tools;
6791
7554
  interruptDefinitions;
6792
7555
  constructor(options) {
@@ -6847,7 +7610,6 @@ var InterruptManager = class {
6847
7610
  this.resuming = false;
6848
7611
  this.state = Object.freeze({
6849
7612
  interrupts: this.snapshot,
6850
- pendingInterrupts: this.snapshot,
6851
7613
  interruptErrors: this.rootErrors,
6852
7614
  resuming: false
6853
7615
  });
@@ -6905,12 +7667,8 @@ var InterruptManager = class {
6905
7667
  });
6906
7668
  }
6907
7669
  resolveClientToolResult(toolCallId, result) {
6908
- const item = this.items.find((candidate) => candidate.kind === "client-tool-execution" && candidate.binding?.kind === "client-tool-execution" && candidate.binding.toolCallId === toolCallId || candidate.kind === "generic" && isClientToolExecutionReason(candidate.descriptor.reason) && candidate.descriptor.toolCallId === toolCallId && isLegacyClientToolMetadata(candidate.descriptor.metadata));
7670
+ const item = this.items.find((candidate) => candidate.kind === "client-tool-execution" && candidate.binding?.kind === "client-tool-execution" && candidate.binding.toolCallId === toolCallId) ?? this.items.find((candidate) => candidate.kind === "generic" && candidate.canResolve && candidate.descriptor.toolCallId === toolCallId);
6909
7671
  if (!item) return false;
6910
- if (item.kind !== "client-tool-execution") {
6911
- this.resolveItem(item.descriptor.id, result.state === "output-error" ? { error: result.errorText } : result.output);
6912
- return true;
6913
- }
6914
7672
  if (result.state === "output-available") {
6915
7673
  this.resolveItem(item.descriptor.id, result.output);
6916
7674
  return true;
@@ -6938,17 +7696,20 @@ var InterruptManager = class {
6938
7696
  this.publish();
6939
7697
  this.maybeSubmit();
6940
7698
  }
6941
- resolveToolApprovalDecision(interruptId, approved) {
6942
- const item = this.items.find((candidate) => candidate.descriptor.id === interruptId && (candidate.kind === "tool-approval" || candidate.kind === "generic" && candidate.descriptor.reason === "approval_required" && isLegacyApprovalMetadata(candidate.descriptor.metadata)));
6943
- if (!item) return false;
6944
- this.resolveItem(item.descriptor.id, { approved });
6945
- return true;
7699
+ /**
7700
+ * The local tool exists, but its schemas differ from the hashes the server
7701
+ * put in the binding, so the interrupt falls back to generic. Warn once per
7702
+ * interrupt so the fallback is not silent.
7703
+ */
7704
+ warnSchemaMismatch(interruptId, toolName, error) {
7705
+ if (this.warnedSchemaMismatches.has(interruptId)) return;
7706
+ this.warnedSchemaMismatches.add(interruptId);
7707
+ console.warn(`[TanStack AI] Interrupt "${interruptId}" for tool "${toolName}": the server and client tool schemas differ, so it is handled as a generic interrupt. Use the same tool definition on the server and the client.`, ...error === void 0 ? [] : [error]);
6946
7708
  }
6947
7709
  hydrateInterrupt(descriptor, hydration, firstPartyIndexes) {
6948
7710
  const interrupt = cloneAndDeepFreezeJson(descriptor);
6949
7711
  const candidate = getDescriptorBinding(interrupt);
6950
- const legacyResumable = candidate === void 0 && isLegacyInterruptMetadata(interrupt);
6951
- if (candidate === void 0 && !legacyResumable) {
7712
+ if (candidate === void 0) {
6952
7713
  if (hasReservedFirstPartyBindingMarker(interrupt)) return {
6953
7714
  descriptor: interrupt,
6954
7715
  binding: genericBinding(interrupt, hydration, void 0),
@@ -6969,9 +7730,9 @@ var InterruptManager = class {
6969
7730
  validationGeneration: 0
6970
7731
  };
6971
7732
  }
6972
- const correlated = candidate !== void 0 && candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && responseSchemaHash(interrupt) === candidate.responseSchemaHash;
6973
- const structurallyCorrelated = candidate !== void 0 && candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && candidate.responseSchemaHash === (responseSchemaHash(interrupt) ?? candidate.responseSchemaHash);
6974
- if (candidate !== void 0 && hasFirstPartyGenericMarker(interrupt) && (!structurallyCorrelated || candidate.kind !== "generic" || candidate.definitionId === void 0 || candidate.key === void 0 || candidate.batchIndex === void 0)) return {
7733
+ const correlated = candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && responseSchemaHash(interrupt) === candidate.responseSchemaHash;
7734
+ const structurallyCorrelated = candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && candidate.responseSchemaHash === (responseSchemaHash(interrupt) ?? candidate.responseSchemaHash);
7735
+ if (hasFirstPartyGenericMarker(interrupt) && (!structurallyCorrelated || candidate.kind !== "generic" || candidate.definitionId === void 0 || candidate.key === void 0 || candidate.batchIndex === void 0)) return {
6975
7736
  descriptor: interrupt,
6976
7737
  binding: genericBinding(interrupt, hydration, candidate),
6977
7738
  kind: "generic",
@@ -6995,22 +7756,28 @@ var InterruptManager = class {
6995
7756
  tool,
6996
7757
  validationGeneration: 0
6997
7758
  };
6998
- } catch {}
7759
+ this.warnSchemaMismatch(interrupt.id, candidate.toolName);
7760
+ } catch (error) {
7761
+ this.warnSchemaMismatch(interrupt.id, candidate.toolName, error);
7762
+ }
6999
7763
  }
7000
7764
  if (structurallyCorrelated && candidate.kind === "client-tool-execution") {
7001
7765
  const tool = this.tools?.find((configured) => configured.name === candidate.toolName);
7002
- if (tool !== void 0 && interrupt.toolCallId === candidate.toolCallId && hashSchemaInput(tool.outputSchema) === candidate.outputSchemaHash) return {
7003
- descriptor: interrupt,
7004
- binding: cloneAndDeepFreezeJson(candidate),
7005
- kind: "client-tool-execution",
7006
- status: "pending",
7007
- canResolve: true,
7008
- resumable: true,
7009
- tool,
7010
- validationGeneration: 0
7011
- };
7766
+ if (tool !== void 0 && interrupt.toolCallId === candidate.toolCallId) {
7767
+ if (hashSchemaInput(tool.outputSchema) === candidate.outputSchemaHash) return {
7768
+ descriptor: interrupt,
7769
+ binding: cloneAndDeepFreezeJson(candidate),
7770
+ kind: "client-tool-execution",
7771
+ status: "pending",
7772
+ canResolve: true,
7773
+ resumable: true,
7774
+ tool,
7775
+ validationGeneration: 0
7776
+ };
7777
+ this.warnSchemaMismatch(interrupt.id, candidate.toolName);
7778
+ }
7012
7779
  }
7013
- if (candidate !== void 0 && candidate.kind === "generic" && candidate.definitionId !== void 0 && candidate.key !== void 0 && candidate.batchIndex !== void 0 && candidate.key.length > 0 && firstPartyIndexes.get(candidate.batchIndex) !== 1) return {
7780
+ if (candidate.kind === "generic" && candidate.definitionId !== void 0 && candidate.key !== void 0 && candidate.batchIndex !== void 0 && candidate.key.length > 0 && firstPartyIndexes.get(candidate.batchIndex) !== 1) return {
7014
7781
  descriptor: interrupt,
7015
7782
  binding: cloneAndDeepFreezeJson(candidate),
7016
7783
  kind: "generic",
@@ -7037,7 +7804,7 @@ var InterruptManager = class {
7037
7804
  };
7038
7805
  }
7039
7806
  }
7040
- const resumable = legacyResumable || candidate !== void 0 && candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && (candidate.kind !== "generic" || responseSchemaHash(interrupt) === void 0 || candidate.responseSchemaHash === responseSchemaHash(interrupt));
7807
+ const resumable = candidate.interruptId === interrupt.id && candidate.interruptedRunId === hydration.interruptedRunId && candidate.generation === hydration.generation && (candidate.kind !== "generic" || responseSchemaHash(interrupt) === void 0 || candidate.responseSchemaHash === responseSchemaHash(interrupt));
7041
7808
  return {
7042
7809
  descriptor: interrupt,
7043
7810
  binding: genericBinding(interrupt, hydration, candidate),
@@ -7121,7 +7888,6 @@ var InterruptManager = class {
7121
7888
  this.snapshot = Object.freeze([]);
7122
7889
  this.state = Object.freeze({
7123
7890
  interrupts: this.snapshot,
7124
- pendingInterrupts: this.snapshot,
7125
7891
  interruptErrors: this.rootErrors,
7126
7892
  resuming: this.resuming
7127
7893
  });
@@ -7131,7 +7897,6 @@ var InterruptManager = class {
7131
7897
  this.snapshot = this.buildSnapshot();
7132
7898
  this.state = Object.freeze({
7133
7899
  interrupts: this.snapshot,
7134
- pendingInterrupts: this.snapshot,
7135
7900
  interruptErrors: this.rootErrors,
7136
7901
  resuming: this.resuming
7137
7902
  });
@@ -7505,7 +8270,7 @@ var InterruptManager = class {
7505
8270
  }
7506
8271
  };
7507
8272
  //#endregion
7508
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/byok/client.js
8273
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/byok/client.js
7509
8274
  var registeredProviderIds = /* @__PURE__ */ new WeakMap();
7510
8275
  /**
7511
8276
  * Provider to stamp when the caller did not pass a slug.
@@ -7518,7 +8283,7 @@ function byokFallbackProviderId(byok) {
7518
8283
  if (registered.length === 1) return registered[0];
7519
8284
  }
7520
8285
  //#endregion
7521
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/byok/resolve.js
8286
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/byok/resolve.js
7522
8287
  function resolveByokProviderId(byokProvider, ...candidates) {
7523
8288
  const fromFn = byokProvider?.();
7524
8289
  if (isProviderId(fromFn)) return fromFn;
@@ -7534,7 +8299,7 @@ async function prepareResolvedByokHeaders(byok, provider) {
7534
8299
  return byok.headers(provider);
7535
8300
  }
7536
8301
  //#endregion
7537
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/events.js
8302
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/events.js
7538
8303
  /**
7539
8304
  * Abstract base class for ChatClient event emission
7540
8305
  */
@@ -7690,17 +8455,6 @@ var ChatClientEventEmitter = class {
7690
8455
  });
7691
8456
  }
7692
8457
  /**
7693
- * Emit tool approval responded event
7694
- */
7695
- toolApprovalResponded(approvalId, toolCallId, approved, context) {
7696
- this.emitEvent("tools:approval:responded", {
7697
- approvalId,
7698
- toolCallId,
7699
- approved,
7700
- ...context
7701
- });
7702
- }
7703
- /**
7704
8458
  * Emit tool fixture applied event.
7705
8459
  */
7706
8460
  toolFixtureApplied(fixture) {
@@ -7708,7 +8462,7 @@ var ChatClientEventEmitter = class {
7708
8462
  }
7709
8463
  };
7710
8464
  //#endregion
7711
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/devtools-noop.js
8465
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/devtools-noop.js
7712
8466
  var NoOpChatClientEventEmitter = class extends ChatClientEventEmitter {
7713
8467
  emitEvent() {}
7714
8468
  };
@@ -7753,12 +8507,7 @@ var NoOpChatDevtoolsBridge = class {
7753
8507
  };
7754
8508
  var createNoOpChatDevtoolsBridge = (options) => new NoOpChatDevtoolsBridge(options);
7755
8509
  //#endregion
7756
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/client-persistor.js
7757
- /** Normalize a raw `getItem` result (legacy bare array or combined record). */
7758
- function normalizePersistedState(raw) {
7759
- if (Array.isArray(raw)) return { messages: raw };
7760
- if (raw && Array.isArray(raw.messages)) return raw;
7761
- }
8510
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/client-persistor.js
7762
8511
  function getChunkToolCallId$1(chunk) {
7763
8512
  return "toolCallId" in chunk && typeof chunk.toolCallId === "string" ? chunk.toolCallId : void 0;
7764
8513
  }
@@ -7800,6 +8549,7 @@ var ChatPersistor = class {
7800
8549
  messagesGeneration = 0;
7801
8550
  lastMessages = [];
7802
8551
  lastResume = null;
8552
+ legacyStored = false;
7803
8553
  clearedMessageIds = /* @__PURE__ */ new Set();
7804
8554
  clearedRunIds = /* @__PURE__ */ new Set();
7805
8555
  ignoredActiveRunIds = /* @__PURE__ */ new Set();
@@ -7813,6 +8563,7 @@ var ChatPersistor = class {
7813
8563
  }
7814
8564
  /** Persist the current state as one combined `{ messages, resume? }` record. */
7815
8565
  writeState() {
8566
+ if (this.legacyStored) return;
7816
8567
  const messages = [...this.lastMessages];
7817
8568
  if (messages.length === 0 && !this.lastResume) {
7818
8569
  const generation = this.generation;
@@ -7832,6 +8583,15 @@ var ChatPersistor = class {
7832
8583
  return this.adapter.setItem(this.id, state);
7833
8584
  });
7834
8585
  }
8586
+ /** Validate a raw `getItem` result. */
8587
+ normalize(raw) {
8588
+ if (Array.isArray(raw)) {
8589
+ this.legacyStored = true;
8590
+ console.error(`[TanStack AI] The stored chat for threadId "${this.id}" is in the 0.x format (a bare message array). TanStack AI 1.0 does not read this format, so the chat starts empty and the stored value is not overwritten. Clear the chat or the stored value to start saving again.`);
8591
+ return;
8592
+ }
8593
+ if (raw && Array.isArray(raw.messages)) return raw;
8594
+ }
7835
8595
  /**
7836
8596
  * Synchronously read the persisted state for constructor-time hydration.
7837
8597
  * Returns the normalized combined record, or a promise of it for async stores.
@@ -7839,8 +8599,8 @@ var ChatPersistor = class {
7839
8599
  readInitial() {
7840
8600
  try {
7841
8601
  const raw = this.adapter.getItem(this.id);
7842
- if (raw instanceof Promise) return raw.then(normalizePersistedState).catch(() => void 0);
7843
- const state = normalizePersistedState(raw);
8602
+ if (raw instanceof Promise) return raw.then((value) => this.normalize(value)).catch(() => void 0);
8603
+ const state = this.normalize(raw);
7844
8604
  if (state) {
7845
8605
  this.lastMessages = state.messages;
7846
8606
  this.lastResume = state.resume ?? null;
@@ -7892,6 +8652,7 @@ var ChatPersistor = class {
7892
8652
  }
7893
8653
  /** Remove the persisted conversation. Invalidates any queued writes. */
7894
8654
  remove() {
8655
+ this.legacyStored = false;
7895
8656
  this.lastMessages = [];
7896
8657
  this.lastResume = null;
7897
8658
  const generation = ++this.generation;
@@ -8018,7 +8779,7 @@ var ChatPersistor = class {
8018
8779
  }
8019
8780
  };
8020
8781
  //#endregion
8021
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/cleared-stream-tracker.js
8782
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/cleared-stream-tracker.js
8022
8783
  function getChunkToolCallId(chunk) {
8023
8784
  return "toolCallId" in chunk && typeof chunk.toolCallId === "string" ? chunk.toolCallId : void 0;
8024
8785
  }
@@ -8111,7 +8872,7 @@ var ClearedStreamTracker = class {
8111
8872
  }
8112
8873
  };
8113
8874
  //#endregion
8114
- //#region ../node_modules/.bun/@tanstack+ai-client@0.39.2+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
8875
+ //#region ../node_modules/.bun/@tanstack+ai-client@1.0.0+367daa2260c029d6/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
8115
8876
  var STREAM_PROCESSING_BUDGET_MS = 8;
8116
8877
  function yieldToHost() {
8117
8878
  const { scheduler } = globalThis;
@@ -8257,9 +9018,30 @@ var REJOIN_REBUILD_TRIGGERS = /* @__PURE__ */ new Set([
8257
9018
  ]);
8258
9019
  function rebuildsAssistantMessage(chunk) {
8259
9020
  if (chunk.type === "REASONING_ENCRYPTED_VALUE") return chunk.subtype === "message" && typeof chunk.encryptedValue === "string" && chunk.encryptedValue.length > 0;
8260
- if (chunk.type === "STEP_FINISHED") return "signature" in chunk && Boolean(chunk.signature);
8261
9021
  return REJOIN_REBUILD_TRIGGERS.has(chunk.type);
8262
9022
  }
9023
+ /**
9024
+ * Snapshot messages are frozen, and a host can pass them back in
9025
+ * (`setMessagesManually(snapshot.messages)`, `initialMessages`). The client
9026
+ * writes subagent handles into message parts, nested cards included, so copy
9027
+ * each frozen part down through subagent transcripts.
9028
+ */
9029
+ function thawMessages(messages) {
9030
+ return messages.map((message) => ({
9031
+ ...message,
9032
+ parts: message.parts.map((part) => {
9033
+ if (!Object.isFrozen(part)) return part;
9034
+ if (part.type !== "subagent") return { ...part };
9035
+ return {
9036
+ ...part,
9037
+ subagent: {
9038
+ ...part.subagent,
9039
+ messages: thawMessages(part.subagent.messages)
9040
+ }
9041
+ };
9042
+ })
9043
+ }));
9044
+ }
8263
9045
  /** Every subagent card in the messages, nested cards included. */
8264
9046
  function collectSubagentParts(messages) {
8265
9047
  const cards = [];
@@ -8287,11 +9069,54 @@ var ChatClient = class {
8287
9069
  subagentHandles = /* @__PURE__ */ new Map();
8288
9070
  stoppedSubagentIds = /* @__PURE__ */ new Set();
8289
9071
  connection;
8290
- uniqueId;
8291
9072
  threadId;
8292
9073
  persistor;
8293
9074
  clearedStreamTracker = new ClearedStreamTracker();
8294
- currentRunId = null;
9075
+ snapshotAtom = createAtom({
9076
+ messages: [],
9077
+ status: "ready",
9078
+ isLoading: false,
9079
+ error: void 0,
9080
+ isSubscribed: false,
9081
+ connectionStatus: "disconnected",
9082
+ sessionGenerating: false,
9083
+ queue: [],
9084
+ runId: null,
9085
+ hasOlderMessages: false,
9086
+ isHydrating: false,
9087
+ interruptState: {
9088
+ interrupts: Object.freeze([]),
9089
+ interruptErrors: Object.freeze([]),
9090
+ resuming: false
9091
+ }
9092
+ });
9093
+ get status() {
9094
+ return this.snapshotAtom.get().status;
9095
+ }
9096
+ get isLoading() {
9097
+ return this.snapshotAtom.get().isLoading;
9098
+ }
9099
+ get error() {
9100
+ return this.snapshotAtom.get().error;
9101
+ }
9102
+ get isSubscribed() {
9103
+ return this.snapshotAtom.get().isSubscribed;
9104
+ }
9105
+ get connectionStatus() {
9106
+ return this.snapshotAtom.get().connectionStatus;
9107
+ }
9108
+ get sessionGenerating() {
9109
+ return this.snapshotAtom.get().sessionGenerating;
9110
+ }
9111
+ get hasOlderMessages() {
9112
+ return this.snapshotAtom.get().hasOlderMessages;
9113
+ }
9114
+ get isHydrating() {
9115
+ return this.snapshotAtom.get().isHydrating;
9116
+ }
9117
+ get currentRunId() {
9118
+ return this.snapshotAtom.get().runId;
9119
+ }
8295
9120
  lastResume = null;
8296
9121
  runParents = /* @__PURE__ */ new Map();
8297
9122
  supersededInterruptRunIds = /* @__PURE__ */ new Set();
@@ -8305,7 +9130,6 @@ var ChatClient = class {
8305
9130
  pendingResumeItems = null;
8306
9131
  activeResumeThreadId = null;
8307
9132
  activeResumeRunId = null;
8308
- bodyOption = {};
8309
9133
  forwardedPropsOption = {};
8310
9134
  byok;
8311
9135
  byokProvider;
@@ -8336,11 +9160,6 @@ var ChatClient = class {
8336
9160
  * deliverers cannot both append a user message before only one stream runs.
8337
9161
  */
8338
9162
  deliverClaim = false;
8339
- isLoading = false;
8340
- isSubscribed = false;
8341
- error = void 0;
8342
- status = "ready";
8343
- connectionStatus = "disconnected";
8344
9163
  abortController = null;
8345
9164
  clientToolsRef;
8346
9165
  devtoolsBridge;
@@ -8373,7 +9192,6 @@ var ChatClient = class {
8373
9192
  streamContinuationGeneration = 0;
8374
9193
  continuationSkipped = false;
8375
9194
  draining = false;
8376
- sessionGenerating = false;
8377
9195
  activeRunIds = /* @__PURE__ */ new Set();
8378
9196
  /** Latched by `dispose()`; stops any late async callback starting new work. */
8379
9197
  disposed = false;
@@ -8385,8 +9203,6 @@ var ChatClient = class {
8385
9203
  hydrationInFlight;
8386
9204
  /** An async storage adapter is still reading the persisted transcript. */
8387
9205
  storeHydrating = false;
8388
- /** See {@link getIsHydrating}. */
8389
- isHydrating = false;
8390
9206
  /** Constructor inputs `attach()` needs on every re-attach, not just the first. */
8391
9207
  rejoinRunId;
8392
9208
  cachesMessages;
@@ -8395,7 +9211,6 @@ var ChatClient = class {
8395
9211
  * `persistence === true`.
8396
9212
  */
8397
9213
  historyPageSize;
8398
- hasOlderMessages = false;
8399
9214
  olderMessagesCursor;
8400
9215
  knownServerMessageIds = /* @__PURE__ */ new Set();
8401
9216
  loadOlderMessagesInFlight = false;
@@ -8404,19 +9219,16 @@ var ChatClient = class {
8404
9219
  callbacksRef;
8405
9220
  constructor(options) {
8406
9221
  assertUniqueInterruptDefinitions(options.interrupts);
8407
- this.threadId = options.threadId || "";
8408
- this.uniqueId = this.threadId;
9222
+ if (typeof options.threadId !== "string" || options.threadId === "") throw new Error("ChatClient: threadId is required (a non-empty string).");
9223
+ this.threadId = options.threadId;
8409
9224
  let cachesMessages = true;
8410
9225
  if (options.persistence === true) {
8411
- if (!options.threadId) throw new Error("[TanStack AI] persistence needs a stable `threadId` to key on. Pass a threadId from your app (for example support-42).");
8412
9226
  cachesMessages = false;
8413
9227
  this.historyPageSize = options.history?.pageSize;
8414
9228
  } else if (options.persistence) {
8415
- if (!options.threadId) throw new Error("[TanStack AI] persistence needs a stable `threadId` to key on. Pass a threadId from your app (for example support-42).");
8416
9229
  this.persistor = new ChatPersistor(options.persistence, options.threadId, (messages) => this.processor.setMessages(messages), (snapshot) => this.applyPersistedResume(snapshot));
8417
9230
  this.historyPageSize = void 0;
8418
9231
  } else this.historyPageSize = void 0;
8419
- this.bodyOption = options.body || {};
8420
9232
  this.forwardedPropsOption = options.forwardedProps || {};
8421
9233
  this.byok = options.byok;
8422
9234
  this.byokProvider = options.byokProvider;
@@ -8457,7 +9269,7 @@ var ChatClient = class {
8457
9269
  if (options.initialResumeSnapshot) this.applyResumeSnapshot(options.initialResumeSnapshot);
8458
9270
  const persistedState = this.persistor?.readInitial();
8459
9271
  const syncPersistedState = persistedState instanceof Promise ? void 0 : persistedState;
8460
- const initialMessages = syncPersistedState ? syncPersistedState.messages : options.initialMessages;
9272
+ const initialMessages = syncPersistedState ? syncPersistedState.messages : options.initialMessages && thawMessages(options.initialMessages);
8461
9273
  let rejoinRunId = null;
8462
9274
  if (syncPersistedState?.resume) {
8463
9275
  const snapshot = syncPersistedState.resume;
@@ -8475,6 +9287,7 @@ var ChatClient = class {
8475
9287
  onMessagesChange: (messages) => {
8476
9288
  this.syncSubagentHandles();
8477
9289
  this.persistor?.notifyMessagesChanged(messages);
9290
+ patchAtom(this.snapshotAtom, { messages: freezeSnapshotMessages(this.frozenMessages, messages) });
8478
9291
  this.callbacksRef.current.onMessagesChange(messages);
8479
9292
  this.queueDevtoolsSnapshot();
8480
9293
  },
@@ -8535,6 +9348,7 @@ var ChatClient = class {
8535
9348
  const context = this.activeClientTools === null ? this.context : this.activeContext;
8536
9349
  const output = await executeFunc(args.input, {
8537
9350
  toolCallId: args.toolCallId,
9351
+ threadId: this.threadId,
8538
9352
  context,
8539
9353
  emitCustomEvent: () => {}
8540
9354
  });
@@ -8583,7 +9397,7 @@ var ChatClient = class {
8583
9397
  }
8584
9398
  this.rejoinRunId = rejoinRunId;
8585
9399
  this.cachesMessages = cachesMessages;
8586
- this.isHydrating = this.storeHydrating || !cachesMessages && !!this.connection.hydrate;
9400
+ this.snapshotAtom.set(this.readSnapshot(this.storeHydrating || !cachesMessages && !!this.connection.hydrate));
8587
9401
  }
8588
9402
  /**
8589
9403
  * START TAILING: re-attach to an in-flight run so its chunks arrive here.
@@ -8602,7 +9416,6 @@ var ChatClient = class {
8602
9416
  */
8603
9417
  attach() {
8604
9418
  if (this.disposed || this.tailing) return;
8605
- this.ensureThreadId();
8606
9419
  this.tailing = true;
8607
9420
  if (this.rejoinRunId) this.maybeRejoinInFlight(this.rejoinRunId);
8608
9421
  if (!this.cachesMessages && this.connection.hydrate) this.hydrateFromServer();
@@ -8757,16 +9570,10 @@ var ChatClient = class {
8757
9570
  this.callbacksRef.current.onError(error);
8758
9571
  }
8759
9572
  mountDevtools() {
8760
- this.ensureThreadId();
8761
9573
  if (this.devtoolsMounted) return;
8762
9574
  this.devtoolsMounted = true;
8763
9575
  this.devtoolsBridge.mountWithTools(this.processor.getMessages().length);
8764
9576
  }
8765
- ensureThreadId() {
8766
- if (!this.threadId) this.threadId = this.generateUniqueId("thread");
8767
- this.uniqueId = this.threadId;
8768
- return this.threadId;
8769
- }
8770
9577
  /**
8771
9578
  * Drain a runId-less RUN_ERROR that belongs to a cleared run the client is
8772
9579
  * still tracking. The persistor owns the cleared-run bookkeeping; the client
@@ -8901,7 +9708,7 @@ var ChatClient = class {
8901
9708
  }
8902
9709
  setCurrentRunId(runId) {
8903
9710
  if (this.currentRunId === runId) return;
8904
- this.currentRunId = runId;
9711
+ patchAtom(this.snapshotAtom, { runId });
8905
9712
  this.callbacksRef.current.onRunIdChange(runId);
8906
9713
  }
8907
9714
  getInterruptState() {
@@ -8910,10 +9717,6 @@ var ChatClient = class {
8910
9717
  getInterrupts() {
8911
9718
  return this.interruptManager.getInterrupts();
8912
9719
  }
8913
- /** @deprecated Use getInterrupts(). */
8914
- getPendingInterrupts() {
8915
- return this.interruptManager.getInterrupts();
8916
- }
8917
9720
  resolveInterrupts(resolution) {
8918
9721
  if (typeof resolution === "boolean") {
8919
9722
  this.interruptManager.resolve(resolution);
@@ -8949,10 +9752,6 @@ var ChatClient = class {
8949
9752
  this.pendingResumeItems = [...resume];
8950
9753
  return this.streamResponse();
8951
9754
  }
8952
- /** @deprecated Use bound interrupt methods or resumeInterruptsUnsafe(). */
8953
- resumeInterrupts(resume, state) {
8954
- return this.resumeInterruptsUnsafe(resume, state);
8955
- }
8956
9755
  async submitInterruptBatch(submission) {
8957
9756
  const continuationGeneration = this.continuationGeneration;
8958
9757
  this.activeInterruptSubmission = submission;
@@ -8996,8 +9795,45 @@ var ChatClient = class {
8996
9795
  generateUniqueId(prefix) {
8997
9796
  return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
8998
9797
  }
9798
+ /** Frozen copies of unchanged messages and parts, keyed by the live object. */
9799
+ frozenMessages = /* @__PURE__ */ new WeakMap();
9800
+ freezeSnapshotQueue(queue) {
9801
+ return Object.freeze(queue.map((item) => {
9802
+ if (typeof item.content !== "object") return Object.freeze({ ...item });
9803
+ const content = Array.isArray(item.content.content) ? Object.freeze(item.content.content.map((part) => freezeSnapshotPart(part))) : item.content.content;
9804
+ return Object.freeze({
9805
+ ...item,
9806
+ content: Object.freeze({
9807
+ ...item.content,
9808
+ content
9809
+ })
9810
+ });
9811
+ }));
9812
+ }
9813
+ /** The atom with messages, queue, and interrupt state read fresh. */
9814
+ readSnapshot(isHydrating) {
9815
+ return Object.freeze({
9816
+ ...this.snapshotAtom.get(),
9817
+ messages: freezeSnapshotMessages(this.frozenMessages, this.processor.getMessages()),
9818
+ queue: this.freezeSnapshotQueue(this.getQueue()),
9819
+ isHydrating,
9820
+ interruptState: this.interruptManager.getState()
9821
+ });
9822
+ }
9823
+ /**
9824
+ * Subscribe to UI snapshot changes. Does not fire with the current value;
9825
+ * read {@link getSnapshot} first.
9826
+ *
9827
+ * Named separately from {@link subscribe} (the live connection loop).
9828
+ */
9829
+ subscribeSnapshot = (listener) => subscribeAtom(this.snapshotAtom, listener);
9830
+ /**
9831
+ * Current UI snapshot. The snapshot, `messages`, `queue`, and their entries
9832
+ * are frozen copies. `interruptState` is the interrupt manager's own state.
9833
+ */
9834
+ getSnapshot = () => this.snapshotAtom.get();
8999
9835
  setIsLoading(isLoading) {
9000
- this.isLoading = isLoading;
9836
+ patchAtom(this.snapshotAtom, { isLoading });
9001
9837
  this.callbacksRef.current.onLoadingChange(isLoading);
9002
9838
  this.events.loadingChanged(isLoading);
9003
9839
  if (isLoading) this.supersedeHydration();
@@ -9013,35 +9849,36 @@ var ChatClient = class {
9013
9849
  this.syncIsHydrating();
9014
9850
  }
9015
9851
  setStatus(status) {
9016
- this.status = status;
9852
+ patchAtom(this.snapshotAtom, { status });
9017
9853
  this.callbacksRef.current.onStatusChange(status);
9018
9854
  this.devtoolsBridge.emitSnapshot();
9019
9855
  }
9020
9856
  setIsSubscribed(isSubscribed) {
9021
- this.isSubscribed = isSubscribed;
9857
+ patchAtom(this.snapshotAtom, { isSubscribed });
9022
9858
  this.callbacksRef.current.onSubscriptionChange(isSubscribed);
9023
9859
  this.devtoolsBridge.emitSnapshot();
9024
9860
  }
9025
9861
  setConnectionStatus(status) {
9026
- this.connectionStatus = status;
9862
+ patchAtom(this.snapshotAtom, { connectionStatus: status });
9027
9863
  this.callbacksRef.current.onConnectionStatusChange(status);
9028
9864
  this.devtoolsBridge.emitSnapshot();
9029
9865
  }
9030
9866
  syncIsHydrating() {
9031
9867
  const isHydrating = this.hydrationInFlight !== void 0 || this.storeHydrating;
9032
9868
  if (this.isHydrating === isHydrating) return;
9033
- this.isHydrating = isHydrating;
9869
+ patchAtom(this.snapshotAtom, { isHydrating });
9034
9870
  this.callbacksRef.current.onHydratingChange(isHydrating);
9035
9871
  }
9036
9872
  setSessionGenerating(isGenerating) {
9037
9873
  if (this.sessionGenerating === isGenerating) return;
9038
- this.sessionGenerating = isGenerating;
9874
+ patchAtom(this.snapshotAtom, { sessionGenerating: isGenerating });
9039
9875
  this.callbacksRef.current.onSessionGeneratingChange(isGenerating);
9040
9876
  this.devtoolsBridge.emitSnapshot();
9041
9877
  }
9042
9878
  notifyResumeStateChange(source) {
9043
9879
  const resumeState = this.getResumeState();
9044
9880
  const interruptState = this.interruptManager.getState();
9881
+ patchAtom(this.snapshotAtom, { interruptState });
9045
9882
  this.persistResumeSnapshot(resumeState);
9046
9883
  this.callbacksRef.current.onResumeStateChange(resumeState, interruptState.interrupts);
9047
9884
  this.callbacksRef.current.onInterruptStateChange(interruptState, { source });
@@ -9068,22 +9905,15 @@ var ChatClient = class {
9068
9905
  this.setSessionGenerating(false);
9069
9906
  }
9070
9907
  setError(error) {
9071
- this.error = error;
9908
+ patchAtom(this.snapshotAtom, { error });
9072
9909
  this.callbacksRef.current.onErrorChange(error);
9073
9910
  this.events.errorChanged(error?.message || null);
9074
9911
  }
9075
9912
  buildDevtoolsBridgeOptions(devtools) {
9076
- const client = this;
9077
9913
  return {
9078
- get hookId() {
9079
- return client.uniqueId;
9080
- },
9081
- get clientId() {
9082
- return client.uniqueId;
9083
- },
9084
- get threadId() {
9085
- return client.threadId;
9086
- },
9914
+ hookId: this.threadId,
9915
+ clientId: this.threadId,
9916
+ threadId: this.threadId,
9087
9917
  metadata: {
9088
9918
  hookName: devtools?.hookName ?? "useChat",
9089
9919
  outputKind: devtools?.outputKind ?? "chat",
@@ -9357,12 +10187,13 @@ var ChatClient = class {
9357
10187
  * @param content - The message content. Can be:
9358
10188
  * - A simple string for text-only messages
9359
10189
  * - A MultimodalContent object with content array and optional custom ID
9360
- * @param body - Optional body parameters to merge with the client's base body for this request.
9361
- * Uses shallow merge with per-message body taking priority.
10190
+ * @param body - Optional body parameters to merge into this request's
10191
+ * forwardedProps, over the forwardedProps option. Uses
10192
+ * shallow merge with per-message body taking priority.
9362
10193
  * @param sendOptions - Per-call overrides. `{ whenBusy }` overrides the
9363
10194
  * queue policy for this one send. `{ body }`
9364
10195
  * shallow-merges with `body` and with the chat-level
9365
- * `body` / `forwardedProps`. `sendOptions.body` wins
10196
+ * `forwardedProps`. `sendOptions.body` wins
9366
10197
  * on key collisions. Framework hooks forward this
9367
10198
  * object as their second argument.
9368
10199
  *
@@ -9405,7 +10236,7 @@ var ChatClient = class {
9405
10236
  async sendMessage(content, body, sendOptions) {
9406
10237
  this.mountDevtools();
9407
10238
  if (typeof content === "string" && !content.trim()) return;
9408
- if (this.hasPendingInterrupts()) throw new Error("ChatClient: cannot send normal input while pending interrupts exist. Use resumeInterrupts() instead.");
10239
+ if (this.hasPendingInterrupts()) throw new Error("ChatClient: cannot send normal input while pending interrupts exist. Resolve the interrupts first.");
9409
10240
  const resolvedBody = {
9410
10241
  ...body,
9411
10242
  ...sendOptions?.body
@@ -9523,7 +10354,7 @@ var ChatClient = class {
9523
10354
  */
9524
10355
  async append(message) {
9525
10356
  this.mountDevtools();
9526
- if (this.hasPendingInterrupts()) throw new Error("ChatClient: cannot append normal input while pending interrupts exist. Use resumeInterrupts() instead.");
10357
+ if (this.hasPendingInterrupts()) throw new Error("ChatClient: cannot append normal input while pending interrupts exist. Resolve the interrupts first.");
9527
10358
  const normalizedMessage = normalizeToUIMessage(message, generateMessageId);
9528
10359
  if (normalizedMessage.role === "system") return;
9529
10360
  if (normalizedMessage.role === "activity") {
@@ -9583,7 +10414,6 @@ var ChatClient = class {
9583
10414
  await this.callbacksRef.current.onResponse();
9584
10415
  if (signal.aborted) return false;
9585
10416
  const mergedBody = {
9586
- ...this.bodyOption,
9587
10417
  ...this.forwardedPropsOption,
9588
10418
  ...this.pendingMessageBody
9589
10419
  };
@@ -9802,31 +10632,6 @@ var ChatClient = class {
9802
10632
  return validation.data;
9803
10633
  }
9804
10634
  /**
9805
- * Respond to a tool approval request
9806
- */
9807
- async addToolApprovalResponse(response) {
9808
- this.processor.addToolApprovalResponse(response.id, response.approved);
9809
- this.devtoolsBridge.emitSnapshot();
9810
- if (this.interruptManager.resolveToolApprovalDecision(response.id, response.approved)) return;
9811
- const messages = this.processor.getMessages();
9812
- let foundToolCallId;
9813
- for (const msg of messages) {
9814
- const toolCallPart = msg.parts.find((p) => p.type === "tool-call" && p.approval?.id === response.id);
9815
- if (toolCallPart) {
9816
- foundToolCallId = toolCallPart.id;
9817
- break;
9818
- }
9819
- }
9820
- if (foundToolCallId) this.events.toolApprovalResponded(response.id, foundToolCallId, response.approved);
9821
- this.processor.addToolApprovalResponse(response.id, response.approved);
9822
- this.devtoolsBridge.emitSnapshot();
9823
- if (this.isLoading) {
9824
- this.queuePostStreamAction(() => this.checkForContinuation());
9825
- return;
9826
- }
9827
- await this.checkForContinuation();
9828
- }
9829
- /**
9830
10635
  * Queue an action to be executed after the current stream ends
9831
10636
  */
9832
10637
  queuePostStreamAction(action) {
@@ -9908,6 +10713,14 @@ var ChatClient = class {
9908
10713
  });
9909
10714
  }
9910
10715
  syncSubagentHandles() {
10716
+ const fieldsOf = (subagent) => {
10717
+ const { input: _old, ...card } = subagent;
10718
+ const input = subagentInputOf(card.metadata);
10719
+ return input === void 0 ? card : {
10720
+ ...card,
10721
+ input
10722
+ };
10723
+ };
9911
10724
  const cards = collectSubagentParts(this.processor.getMessages());
9912
10725
  const present = new Set(cards.map((part) => part.subagent.id));
9913
10726
  for (const id of this.subagentHandles.keys()) if (!present.has(id)) this.subagentHandles.delete(id);
@@ -9918,12 +10731,12 @@ var ChatClient = class {
9918
10731
  if (part.subagent === existing) continue;
9919
10732
  const { stop } = existing;
9920
10733
  for (const key of Object.keys(existing)) Reflect.deleteProperty(existing, key);
9921
- Object.assign(existing, part.subagent, { stop });
10734
+ Object.assign(existing, fieldsOf(part.subagent), { stop });
9922
10735
  part.subagent = existing;
9923
10736
  continue;
9924
10737
  }
9925
10738
  const handle = {
9926
- ...part.subagent,
10739
+ ...fieldsOf(part.subagent),
9927
10740
  stop: () => {
9928
10741
  this.stopSubagent(id);
9929
10742
  }
@@ -9985,19 +10798,22 @@ var ChatClient = class {
9985
10798
  this.loadOlderMessagesInFlight = false;
9986
10799
  }
9987
10800
  }
10801
+ setHasOlderMessages(hasOlderMessages) {
10802
+ patchAtom(this.snapshotAtom, { hasOlderMessages });
10803
+ }
9988
10804
  resetHistoryPaging() {
9989
- this.hasOlderMessages = false;
10805
+ this.setHasOlderMessages(false);
9990
10806
  this.olderMessagesCursor = void 0;
9991
10807
  this.knownServerMessageIds.clear();
9992
10808
  this.historyGeneration++;
9993
10809
  }
9994
10810
  applyHydrationPage(page) {
9995
10811
  if (page?.truncated === true) {
9996
- this.hasOlderMessages = true;
10812
+ this.setHasOlderMessages(true);
9997
10813
  this.olderMessagesCursor = page.cursor;
9998
10814
  return;
9999
10815
  }
10000
- this.hasOlderMessages = false;
10816
+ this.setHasOlderMessages(false);
10001
10817
  this.olderMessagesCursor = void 0;
10002
10818
  }
10003
10819
  rememberServerMessageIds(messages) {
@@ -10085,7 +10901,9 @@ var ChatClient = class {
10085
10901
  }));
10086
10902
  }
10087
10903
  emitQueueChange() {
10088
- this.callbacksRef.current.onQueueChange(this.getQueue());
10904
+ const queue = this.getQueue();
10905
+ patchAtom(this.snapshotAtom, { queue: this.freezeSnapshotQueue(queue) });
10906
+ this.callbacksRef.current.onQueueChange(queue);
10089
10907
  this.devtoolsBridge.emitSnapshot();
10090
10908
  }
10091
10909
  /**
@@ -10159,7 +10977,7 @@ var ChatClient = class {
10159
10977
  * Manually set messages
10160
10978
  */
10161
10979
  setMessagesManually(messages) {
10162
- this.processor.setMessages(messages);
10980
+ this.processor.setMessages(thawMessages(messages));
10163
10981
  this.devtoolsBridge.emitSnapshot();
10164
10982
  }
10165
10983
  updateOptions(options) {
@@ -10181,7 +10999,6 @@ var ChatClient = class {
10181
10999
  this.connection = normalizeConnectionAdapter(transport);
10182
11000
  if (wasSubscribed) this.subscribe();
10183
11001
  }
10184
- if (options.body !== void 0) this.bodyOption = options.body;
10185
11002
  if (options.forwardedProps !== void 0) this.forwardedPropsOption = options.forwardedProps;
10186
11003
  if (options.byok !== void 0) this.byok = options.byok;
10187
11004
  if (options.byokProvider !== void 0) this.byokProvider = options.byokProvider;
@@ -10269,12 +11086,13 @@ async function validateParameters(parameters, input) {
10269
11086
  }
10270
11087
  //#endregion
10271
11088
  //#region src/core/agent-tools.ts
11089
+ const HOST_TOOL_NOT_EXECUTED = Symbol("Host tool was not executed");
10272
11090
  /** The full tool set declared to the agent; `render_widget` only when widgets are registered. */
10273
- function buildAgentTools(widgets, hostTools, renderWidget, debug) {
11091
+ function buildAgentTools(widgets, hostTools, renderWidget, debug, guardHostExecution) {
10274
11092
  return [
10275
11093
  ...Object.keys(widgets).length > 0 ? [buildRenderWidgetTool(widgets, renderWidget)] : [],
10276
11094
  buildAskQuestionnaireTool(),
10277
- ...buildHostTools(hostTools, debug)
11095
+ ...buildHostTools(hostTools, debug, guardHostExecution)
10278
11096
  ];
10279
11097
  }
10280
11098
  function buildRenderWidgetTool(widgets, render) {
@@ -10367,21 +11185,26 @@ function buildAskQuestionnaireTool() {
10367
11185
  }).client();
10368
11186
  }
10369
11187
  /** Wraps the host's mount-time tools as client tools the agent can call. */
10370
- function buildHostTools(tools, debug) {
11188
+ function buildHostTools(tools, debug, guardHostExecution) {
10371
11189
  return Object.entries(tools).map(([name, tool]) => toolDefinition({
10372
11190
  name,
10373
11191
  description: tool.description,
10374
11192
  inputSchema: toJsonSchema(tool.parameters),
10375
11193
  ...tool.metadata ? { metadata: tool.metadata } : {}
10376
- }).client(async (input) => {
10377
- debug?.("tool", `executing host tool "${name}"`, { input });
10378
- const validated = await validateParameters(tool.parameters, input ?? {});
10379
- if (validated == null) {
10380
- debug?.("error", `input for host tool "${name}" failed schema validation`, { input });
10381
- throw new Error(`Input for tool "${name}" failed schema validation`);
10382
- }
11194
+ }).client(async (input, context) => {
11195
+ let started = false;
10383
11196
  try {
10384
- const output = await tool.execute(validated);
11197
+ const resolve = guardHostExecution?.(name, tool, context?.toolCallId);
11198
+ debug?.("tool", `executing host tool "${name}"`, { input });
11199
+ const validated = await validateParameters(tool.parameters, input ?? {});
11200
+ if (validated == null) {
11201
+ debug?.("error", `input for host tool "${name}" failed schema validation`, { input });
11202
+ throw new Error(`Input for tool "${name}" failed schema validation`);
11203
+ }
11204
+ context?.abortSignal?.throwIfAborted();
11205
+ const current = resolve?.() ?? tool;
11206
+ started = true;
11207
+ const output = await current.execute(validated);
10385
11208
  try {
10386
11209
  canonicalInterruptJson(output);
10387
11210
  } catch {
@@ -10391,6 +11214,7 @@ function buildHostTools(tools, debug) {
10391
11214
  return output;
10392
11215
  } catch (error) {
10393
11216
  debug?.("error", `host tool "${name}" threw`, { error });
11217
+ if (!started && error instanceof Error) Object.assign(error, { [HOST_TOOL_NOT_EXECUTED]: true });
10394
11218
  throw error;
10395
11219
  }
10396
11220
  }));
@@ -10923,10 +11747,6 @@ function projectThreadMessages(records, pendingInteractions = [], liveToolMessag
10923
11747
  const call = calls.get(savedToolCallId(message.source_assistant_message_id, message.source_tool_part_id, message.response_target_id));
10924
11748
  if (!call) continue;
10925
11749
  call.output = part.output ?? null;
10926
- if (call.name === "sandbox_publish_artifact") {
10927
- call.artifactMessageId = message.id;
10928
- call.artifactPartId = String(part.id);
10929
- }
10930
11750
  Object.assign(call, { resultOutcome: part.outcome });
10931
11751
  call.state = part.outcome === "succeeded" ? "complete" : "error";
10932
11752
  }
@@ -10946,7 +11766,7 @@ function projectThreadMessages(records, pendingInteractions = [], liveToolMessag
10946
11766
  type: "url",
10947
11767
  value: ""
10948
11768
  },
10949
- savedAttachmentId: part.id
11769
+ fileId: "id" in source && typeof source.id === "string" ? source.id : void 0
10950
11770
  }];
10951
11771
  if (part.type !== "tool-call") return [part];
10952
11772
  if (part.executionLocation === "provider") return [part];
@@ -11090,6 +11910,7 @@ function createAstralBeamChat(options, deferStart = false) {
11090
11910
  let identity;
11091
11911
  let started = false;
11092
11912
  let selectionGeneration = 0;
11913
+ let toolExecutionGeneration = 0;
11093
11914
  let historyGeneration = 0;
11094
11915
  let hydration = Promise.resolve();
11095
11916
  let requestController = new AbortController();
@@ -11262,35 +12083,48 @@ function createAstralBeamChat(options, deferStart = false) {
11262
12083
  });
11263
12084
  }
11264
12085
  };
11265
- const buildTools = () => buildAgentTools(live.widgets ?? {}, live.tools ?? {}, renderWidget, debug).map((tool) => {
11266
- if (!tool.execute) return tool;
11267
- const execute = tool.execute;
11268
- return {
11269
- ...tool,
11270
- execute: async (input, context) => {
11271
- const toolCallId = context?.toolCallId;
11272
- if (!toolCallId || !liveToolCalls.has(toolCallId)) throw new Error("A saved tool call cannot execute again. Send a new message to request it.");
11273
- const results = toolResults;
11274
- const key = toolResultKey(toolCallId);
11275
- const resultIdentity = identity;
11276
- const apiUrl = authentication.apiUrl;
11277
- try {
11278
- const output = await execute(input, context);
11279
- if (identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
11280
- outcome: "succeeded",
11281
- output: output ?? null
11282
- });
11283
- return output;
11284
- } catch (error) {
11285
- if (identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
11286
- outcome: "unknown",
11287
- output: { error: error instanceof Error ? error.message : String(error) }
11288
- });
11289
- throw error;
12086
+ const buildTools = () => {
12087
+ const selection = selectionGeneration;
12088
+ return buildAgentTools(live.widgets ?? {}, live.tools ?? {}, renderWidget, debug, (name, declaration, toolCallId) => {
12089
+ const execution = toolExecutionGeneration;
12090
+ const executingClient = client;
12091
+ const executingIdentity = identity;
12092
+ const apiUrl = authentication.apiUrl;
12093
+ return () => {
12094
+ const current = live.tools && Object.hasOwn(live.tools, name) ? live.tools[name] : void 0;
12095
+ if (selection !== selectionGeneration || execution !== toolExecutionGeneration || executingClient !== client || executingIdentity !== identity || apiUrl !== authentication.apiUrl || state.thread?.role === "viewer" || !toolCallId || !liveToolCalls.has(toolCallId) || !current || current.parameters !== declaration.parameters) throw new DOMException("Host tool authority changed", "AbortError");
12096
+ return current;
12097
+ };
12098
+ }).map((tool) => {
12099
+ if (!tool.execute) return tool;
12100
+ const execute = tool.execute;
12101
+ return {
12102
+ ...tool,
12103
+ execute: async (input, context) => {
12104
+ const toolCallId = context?.toolCallId;
12105
+ if (!toolCallId || !liveToolCalls.has(toolCallId)) throw new Error("A saved tool call cannot execute again. Send a new message to request it.");
12106
+ const results = toolResults;
12107
+ const key = toolResultKey(toolCallId);
12108
+ const resultIdentity = identity;
12109
+ const apiUrl = authentication.apiUrl;
12110
+ try {
12111
+ const output = await execute(input, context);
12112
+ if (identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
12113
+ outcome: "succeeded",
12114
+ output: output ?? null
12115
+ });
12116
+ return output;
12117
+ } catch (error) {
12118
+ if (!(error instanceof Error && HOST_TOOL_NOT_EXECUTED in error) && identity === resultIdentity && authentication.apiUrl === apiUrl) results.set(key, {
12119
+ outcome: "unknown",
12120
+ output: { error: error instanceof Error ? error.message : String(error) }
12121
+ });
12122
+ throw error;
12123
+ }
11290
12124
  }
11291
- }
11292
- };
11293
- });
12125
+ };
12126
+ });
12127
+ };
11294
12128
  const declareTools = () => {
11295
12129
  const tools = buildTools();
11296
12130
  const agentTools = tools.map((tool) => {
@@ -11520,10 +12354,11 @@ function createAstralBeamChat(options, deferStart = false) {
11520
12354
  onMessagesChange: (messages) => {
11521
12355
  if (client !== next) return;
11522
12356
  restoreCompletedWidgets(messages);
12357
+ const savedMessages = new Map(state.messages.map((message) => [message.id, message]));
11523
12358
  for (const message of messages) {
11524
12359
  if (message.role !== "user") continue;
11525
- const saved = state.messages.find((previous) => previous.id === message.id);
11526
- if (saved?.parts.some((part) => "savedAttachmentId" in part)) message.parts = saved.parts;
12360
+ const saved = savedMessages.get(message.id);
12361
+ if (saved?.parts.some((part) => "fileId" in part)) message.parts = saved.parts;
11527
12362
  }
11528
12363
  update({
11529
12364
  messages,
@@ -11910,6 +12745,7 @@ function createAstralBeamChat(options, deferStart = false) {
11910
12745
  const start = () => {
11911
12746
  if (started) return;
11912
12747
  started = true;
12748
+ client.updateOptions({ tools: declareTools() });
11913
12749
  client.attach();
11914
12750
  if (requestController.signal.aborted) requestController = new AbortController();
11915
12751
  unsubscribeAuthentication = subscribeAuthentication(authentication, observeAuthentication);
@@ -11959,6 +12795,7 @@ function createAstralBeamChat(options, deferStart = false) {
11959
12795
  retry,
11960
12796
  addToolResult,
11961
12797
  stop: () => {
12798
+ toolExecutionGeneration++;
11962
12799
  if (submission?.phase === "submitting") endUnaccepted(submission);
11963
12800
  client.stop();
11964
12801
  },
@@ -12015,18 +12852,13 @@ function createAstralBeamChat(options, deferStart = false) {
12015
12852
  metadata: { filename }
12016
12853
  }, options);
12017
12854
  },
12018
- getFile: async (fileId) => {
12019
- const thread = state.thread;
12020
- if (!thread) throw new Error("Open a conversation before downloading files.");
12021
- return (await getChatFile({
12022
- threadId: thread.id,
12023
- fileId
12024
- }, await requestOptions())).blob();
12025
- },
12026
- getAttachment: async (messageId, partId) => {
12027
- const thread = state.thread;
12028
- if (!thread) throw new Error("Open a conversation before downloading attachments.");
12029
- return (await getChatAttachment(thread.id, messageId, partId, await requestOptions())).blob();
12855
+ getThreadAttachment: async (params, options) => {
12856
+ if (!params.threadId && !options?.preview) throw new Error("A conversation ID is required to download files.");
12857
+ return (await getThreadAttachment(params, {
12858
+ ...await requestOptions(!!params.threadId || !options?.preview),
12859
+ cache: "default",
12860
+ headers: options?.preview ? { "X-File-Preview": "true" } : {}
12861
+ })).blob();
12030
12862
  },
12031
12863
  getMcpCatalog: async () => personalMcpGetCatalog(await requestOptions(false)),
12032
12864
  manageMcpConnection: async (operation) => {