@astralbeam/sdk 0.16.0 → 0.17.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,7 +1,17 @@
1
- import { $ as listChatMessages, C as getCurrentUser, U as getResolveChatToolResultUrl, W as getRunChatUrl, _ as getChatConfig, dt as updateChatThread, f as createChatThread, g as getChatAttachment, gt as resolveApiUrl, h as deleteChatThread, ht as isAstralBeamApiError, mt as astralBeamChatFetch, tt as listChatThreads } from "./api-DzeMhfHU.js";
1
+ import { Ct as isAstralBeamApiError, O as getCurrentUser, S as getChatFile, St as astralBeamChatFetch, X as getRunChatUrl, Y as getResolveChatToolResultUrl, b as getChatAttachment, ct as listChatThreads, g as createChatThread, ot as listChatMessages, vt as updateChatThread, wt as resolveApiUrl, x as getChatConfig, xt as uploadChatFile, y as deleteChatThread } from "./api-BaIPbj-Q.js";
2
2
  import { d as JWTInvalid, h as strictDecoder, r as isObject, s as decode } from "./type_checks-C-WTHaWs.js";
3
3
  //#region \0rolldown/runtime.js
4
+ var __defProp = Object.defineProperty;
4
5
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
6
+ var __exportAll = (all, no_symbols) => {
7
+ let target = {};
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ return target;
14
+ };
5
15
  //#endregion
6
16
  //#region node_modules/.deno/jose@6.2.9/node_modules/jose/dist/webapi/util/decode_jwt.js
7
17
  function decodeJwt(jwt) {
@@ -26,7 +36,7 @@ function decodeJwt(jwt) {
26
36
  return result;
27
37
  }
28
38
  //#endregion
29
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
39
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
30
40
  var UnsupportedResponseStreamError = class extends Error {
31
41
  missingFeature;
32
42
  constructor(missingFeature) {
@@ -48,14 +58,14 @@ function createResponseStreamTextDecoder() {
48
58
  return new globalThis.TextDecoder();
49
59
  }
50
60
  //#endregion
51
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/sse-utils.js
61
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/sse-utils.js
52
62
  function parseSseDataLine(line) {
53
63
  if (!line.startsWith("data:")) return line;
54
64
  const data = line.slice(5);
55
65
  return data.startsWith(" ") ? data.slice(1) : data;
56
66
  }
57
67
  //#endregion
58
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/message-date-normalizer.js
68
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/message-date-normalizer.js
59
69
  function validDate(value) {
60
70
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value;
61
71
  if (typeof value !== "string") return void 0;
@@ -87,7 +97,7 @@ function normalizeMessagesDates(messages) {
87
97
  return messages.map(normalizeMessageDates);
88
98
  }
89
99
  //#endregion
90
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-usage.js
100
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-usage.js
91
101
  function definedDetails(value) {
92
102
  return Object.keys(value).length > 0 ? value : void 0;
93
103
  }
@@ -132,7 +142,7 @@ function fromSpecTokenUsage(usage, leftover) {
132
142
  };
133
143
  }
134
144
  //#endregion
135
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/merge-metadata.js
145
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/merge-metadata.js
136
146
  function isPlainRecord$1(value) {
137
147
  return value != null && typeof value === "object" && !Array.isArray(value);
138
148
  }
@@ -211,7 +221,7 @@ let EventType = /* @__PURE__ */ function(EventType) {
211
221
  return EventType;
212
222
  }({});
213
223
  //#endregion
214
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/reasoning-encrypted-value.js
224
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/reasoning-encrypted-value.js
215
225
  /**
216
226
  * Id prefix for the reasoning message of a redacted thinking block (Anthropic
217
227
  * `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of
@@ -223,7 +233,7 @@ function isRedactedThinkingId(id) {
223
233
  return typeof id === "string" && id.startsWith("redacted_thinking-");
224
234
  }
225
235
  //#endregion
226
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-serialization.js
236
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/interrupt-serialization.js
227
237
  var SHA256_K = new Uint32Array([
228
238
  1116352408,
229
239
  1899447441,
@@ -398,7 +408,7 @@ function cloneAndDeepFreezeJson(value) {
398
408
  return clone;
399
409
  }
400
410
  //#endregion
401
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupts.js
411
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/interrupts.js
402
412
  function canonicalizeInterruptResolutions(resolutions) {
403
413
  const frozen = cloneAndDeepFreezeJson([...resolutions].sort((left, right) => left.interruptId.localeCompare(right.interruptId)));
404
414
  const canonicalResolutions = canonicalInterruptJson(frozen);
@@ -409,7 +419,7 @@ function canonicalizeInterruptResolutions(resolutions) {
409
419
  });
410
420
  }
411
421
  //#endregion
412
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/schema-converter.js
422
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/schema-converter.js
413
423
  /**
414
424
  * Build a JSONSchema object from any plain key/value source. The `JSONSchema`
415
425
  * interface's `[key: string]: any` index signature makes every property
@@ -677,7 +687,7 @@ async function validateWithStandardSchema(schema, data) {
677
687
  };
678
688
  }
679
689
  //#endregion
680
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/approval-schema.js
690
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/approval-schema.js
681
691
  var jsonSchemaKeywords = /* @__PURE__ */ new Set([
682
692
  "$schema",
683
693
  "$id",
@@ -789,7 +799,7 @@ function hashSchemaInput(schema) {
789
799
  return digestInterruptJson(canonicalInterruptJson(schemaToWire(schema).jsonSchema ?? { standardValidator: "unserialized" }));
790
800
  }
791
801
  //#endregion
792
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-resume.js
802
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/interrupt-resume.js
793
803
  /**
794
804
  * The `Interrupt.metadata` key under which this package's resume binding
795
805
  * travels.
@@ -910,7 +920,7 @@ function readInterruptBinding(descriptor) {
910
920
  };
911
921
  }
912
922
  //#endregion
913
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/interrupt-definition.js
923
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/interrupt-definition.js
914
924
  var INTERRUPT_PAYLOAD_METADATA_KEY = "tanstack:interruptPayload";
915
925
  function schemaJson(schema, name) {
916
926
  if (!isStandardJSONSchema(schema)) throw new TypeError(`${name} must be a Standard Schema with a JSON Schema converter.`);
@@ -935,7 +945,7 @@ function hashInterruptDefinitionSchema(schema) {
935
945
  return digestInterruptJson(schemaJson(schema, "Interrupt schema").canonicalJson);
936
946
  }
937
947
  //#endregion
938
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/generic-interrupt-continuation.js
948
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/generic-interrupt-continuation.js
939
949
  /**
940
950
  * `ResumeEntry.metadata` key for a first-party generic request.
941
951
  *
@@ -974,7 +984,7 @@ function genericInterruptContinuationFromDescriptor(interrupt) {
974
984
  };
975
985
  }
976
986
  //#endregion
977
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/provider-executed.js
987
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/provider-executed.js
978
988
  /**
979
989
  * Narrow a tool call's opaque `metadata` to the provider-executed convention.
980
990
  * Returns the typed metadata when the call is provider-executed, else `null`.
@@ -1004,7 +1014,7 @@ function isAssistantSegmentOf(id, parentId) {
1004
1014
  return id?.startsWith(`${parentId}-segment-`) === true;
1005
1015
  }
1006
1016
  //#endregion
1007
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/tool-result.js
1017
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/tool-result.js
1008
1018
  var CONTENT_PART_TYPES = /* @__PURE__ */ new Set([
1009
1019
  "text",
1010
1020
  "image",
@@ -1065,7 +1075,7 @@ function normalizeToolResult(result) {
1065
1075
  return JSON.stringify(result);
1066
1076
  }
1067
1077
  //#endregion
1068
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/subagent-wire.js
1078
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/subagent-wire.js
1069
1079
  function isRecord$2(value) {
1070
1080
  return typeof value === "object" && value !== null && !Array.isArray(value);
1071
1081
  }
@@ -1169,7 +1179,7 @@ function splitSubagentWire(messages) {
1169
1179
  };
1170
1180
  }
1171
1181
  //#endregion
1172
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
1182
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/messages.js
1173
1183
  function isRecord$1(value) {
1174
1184
  return typeof value === "object" && value !== null && !Array.isArray(value);
1175
1185
  }
@@ -1362,6 +1372,7 @@ function assistantMetadata(uiMessage) {
1362
1372
  */
1363
1373
  function uiMessageToModelMessages(uiMessage) {
1364
1374
  if (uiMessage.role === "system") return [];
1375
+ if (uiMessage.role === "activity") return [];
1365
1376
  if (uiMessage.role !== "assistant") return [buildUserOrToolMessage(uiMessage)];
1366
1377
  return buildAssistantMessages(uiMessage);
1367
1378
  }
@@ -1491,6 +1502,7 @@ function buildAssistantMessages(uiMessage) {
1491
1502
  }
1492
1503
  break;
1493
1504
  case "ui-resource": break;
1505
+ case "activity": break;
1494
1506
  case "subagent": {
1495
1507
  const block = part.subagent.parentToolCallId === void 0 ? subagentHistoryText(part) : "";
1496
1508
  if (block !== "") {
@@ -1707,6 +1719,15 @@ function aguiSnapshotMessageToUIMessage(message) {
1707
1719
  }] : []
1708
1720
  });
1709
1721
  }
1722
+ case "activity": return applySnapshotMetadata(message, {
1723
+ id,
1724
+ role: "activity",
1725
+ parts: [{
1726
+ type: "activity",
1727
+ activityType: message.activityType,
1728
+ content: structuredClone(message.content)
1729
+ }]
1730
+ });
1710
1731
  default: return applySnapshotMetadata(message, {
1711
1732
  id,
1712
1733
  role: "assistant",
@@ -1752,15 +1773,23 @@ function applySnapshotMetadata(source, ui) {
1752
1773
  }
1753
1774
  function snapshotStructuredOutput(value) {
1754
1775
  if (value == null || value.status !== "streaming" && value.status !== "complete" && value.status !== "error" || typeof value.raw !== "string") return;
1755
- return {
1776
+ const base = {
1756
1777
  type: "structured-output",
1757
- status: value.status,
1758
1778
  raw: value.raw,
1759
1779
  ...value.partial !== void 0 ? { partial: value.partial } : {},
1760
- ...value.data !== void 0 ? { data: value.data } : {},
1761
1780
  ...value.reasoning ? { reasoning: value.reasoning } : {},
1762
1781
  ...value.errorMessage !== void 0 ? { errorMessage: value.errorMessage } : {}
1763
1782
  };
1783
+ if (value.status !== "complete") return {
1784
+ ...base,
1785
+ status: value.status
1786
+ };
1787
+ if (value.data === void 0) return void 0;
1788
+ return {
1789
+ ...base,
1790
+ status: "complete",
1791
+ data: value.data
1792
+ };
1764
1793
  }
1765
1794
  /**
1766
1795
  * Convert AG-UI user message content into `UIMessage` parts.
@@ -1818,7 +1847,7 @@ function generateMessageId() {
1818
1847
  return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1819
1848
  }
1820
1849
  //#endregion
1821
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-wire.js
1850
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/ag-ui-wire.js
1822
1851
  function isRecord(value) {
1823
1852
  return typeof value === "object" && value !== null && !Array.isArray(value);
1824
1853
  }
@@ -1849,15 +1878,35 @@ function rebuiltToolMetadata(metadata, createdAt, id, content, anchorOwnsUiResou
1849
1878
  * on assistant messages are additionally emitted as fan-out
1850
1879
  * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI
1851
1880
  * server consumers. Set `includeSnapshotStructuredOutput` to retain complete
1852
- * structured-output metadata for UI snapshots.
1881
+ * structured-output metadata for UI snapshots. Set `includeActivity` to emit
1882
+ * AG-UI `ActivityMessage` rows (MESSAGES_SNAPSHOT only — default omit so
1883
+ * RunAgentInput never carries activity).
1853
1884
  */
1854
1885
  function uiMessagesToWire(messages, options) {
1855
1886
  const wire = [];
1856
1887
  const usedWireIds = new Set(messages.flatMap((message) => "id" in message && message.id && message.role !== "tool" ? [message.id] : []));
1857
1888
  const includeSnapshotStructuredOutput = options?.includeSnapshotStructuredOutput ?? false;
1889
+ const includeActivity = options?.includeActivity ?? false;
1858
1890
  const assistantIds = /* @__PURE__ */ new Set();
1859
1891
  for (const msg of messages) if (msg.role === "assistant" && msg.id !== void 0) assistantIds.add(msg.id);
1860
1892
  for (const msg of messages) {
1893
+ if (msg.role === "activity") {
1894
+ if (includeActivity && "parts" in msg) {
1895
+ const part = msg.parts.find((p) => p.type === "activity");
1896
+ if (part) {
1897
+ const activity = {
1898
+ id: msg.id,
1899
+ role: "activity",
1900
+ activityType: part.activityType,
1901
+ content: structuredClone(part.content),
1902
+ ...msg.metadata != null && { metadata: msg.metadata },
1903
+ ...part.subagentRunId !== void 0 && { subagentRunId: part.subagentRunId }
1904
+ };
1905
+ wire.push(activity);
1906
+ }
1907
+ }
1908
+ continue;
1909
+ }
1861
1910
  if (!("parts" in msg) && msg.role === "tool" && msg.toolCallId) {
1862
1911
  const id = uniqueToolWireId(toolWireId(msg.id, msg.toolCallId, assistantIds), usedWireIds);
1863
1912
  const metadata = rebuiltToolMetadata(msg.metadata, msg.createdAt, msg.id, msg.content);
@@ -2132,7 +2181,7 @@ function hashContent(s) {
2132
2181
  return Math.abs(h).toString(36);
2133
2182
  }
2134
2183
  //#endregion
2135
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/restore-inbound-chunk.js
2184
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/restore-inbound-chunk.js
2136
2185
  /**
2137
2186
  * Rebuild TanStack `TokenUsage` (`promptTokens`) from spec `usage[]` plus
2138
2187
  * leftover fields in `metadata.tanstack.usage`. Restore in-process aliases
@@ -2169,7 +2218,7 @@ function restoreInboundChunk(chunk) {
2169
2218
  return next;
2170
2219
  }
2171
2220
  //#endregion
2172
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
2221
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/tools/tool-definition.js
2173
2222
  /**
2174
2223
  * Create an isomorphic tool definition that can be used directly or instantiated for server/client
2175
2224
  *
@@ -2267,7 +2316,7 @@ function toolDefinition(config) {
2267
2316
  };
2268
2317
  }
2269
2318
  //#endregion
2270
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/chunk-ids.js
2319
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/chunk-ids.js
2271
2320
  function stringField(value) {
2272
2321
  return typeof value === "string" && value !== "" ? value : void 0;
2273
2322
  }
@@ -2370,7 +2419,7 @@ var require_options = /* @__PURE__ */ __commonJSMin(((exports) => {
2370
2419
  exports.default = exports.Allow;
2371
2420
  }));
2372
2421
  //#endregion
2373
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
2422
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/json-parser.js
2374
2423
  var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
2375
2424
  var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
2376
2425
  if (k2 === void 0) k2 = k;
@@ -2592,7 +2641,7 @@ function parsePartialJSON(jsonString) {
2592
2641
  return defaultJSONParser.parse(jsonString);
2593
2642
  }
2594
2643
  //#endregion
2595
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
2644
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/strategies.js
2596
2645
  /**
2597
2646
  * Immediate Strategy - emit on every chunk (default behavior)
2598
2647
  */
@@ -2602,7 +2651,7 @@ var ImmediateStrategy = class {
2602
2651
  }
2603
2652
  };
2604
2653
  //#endregion
2605
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/utilities/errors.js
2654
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/utilities/errors.js
2606
2655
  /**
2607
2656
  * Convert an AG-UI RUN_ERROR event to the Error shape exposed to consumers.
2608
2657
  * Preserves the provider code and sanitized raw event when available, while
@@ -2616,7 +2665,730 @@ function runErrorEventToError(chunk) {
2616
2665
  return error;
2617
2666
  }
2618
2667
  //#endregion
2619
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
2668
+ //#region node_modules/.deno/fast-json-patch@3.1.1/node_modules/fast-json-patch/module/helpers.mjs
2669
+ /*!
2670
+ * https://github.com/Starcounter-Jack/JSON-Patch
2671
+ * (c) 2017-2022 Joachim Wester
2672
+ * MIT licensed
2673
+ */
2674
+ var __extends = (function() {
2675
+ var extendStatics = function(d, b) {
2676
+ extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
2677
+ d.__proto__ = b;
2678
+ } || function(d, b) {
2679
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
2680
+ };
2681
+ return extendStatics(d, b);
2682
+ };
2683
+ return function(d, b) {
2684
+ extendStatics(d, b);
2685
+ function __() {
2686
+ this.constructor = d;
2687
+ }
2688
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2689
+ };
2690
+ })();
2691
+ var _hasOwnProperty = Object.prototype.hasOwnProperty;
2692
+ function hasOwnProperty(obj, key) {
2693
+ return _hasOwnProperty.call(obj, key);
2694
+ }
2695
+ function _objectKeys(obj) {
2696
+ if (Array.isArray(obj)) {
2697
+ var keys_1 = new Array(obj.length);
2698
+ for (var k = 0; k < keys_1.length; k++) keys_1[k] = "" + k;
2699
+ return keys_1;
2700
+ }
2701
+ if (Object.keys) return Object.keys(obj);
2702
+ var keys = [];
2703
+ for (var i in obj) if (hasOwnProperty(obj, i)) keys.push(i);
2704
+ return keys;
2705
+ }
2706
+ /**
2707
+ * Deeply clone the object.
2708
+ * https://jsperf.com/deep-copy-vs-json-stringify-json-parse/25 (recursiveDeepCopy)
2709
+ * @param {any} obj value to clone
2710
+ * @return {any} cloned obj
2711
+ */
2712
+ function _deepClone(obj) {
2713
+ switch (typeof obj) {
2714
+ case "object": return JSON.parse(JSON.stringify(obj));
2715
+ case "undefined": return null;
2716
+ default: return obj;
2717
+ }
2718
+ }
2719
+ function isInteger(str) {
2720
+ var i = 0;
2721
+ var len = str.length;
2722
+ var charCode;
2723
+ while (i < len) {
2724
+ charCode = str.charCodeAt(i);
2725
+ if (charCode >= 48 && charCode <= 57) {
2726
+ i++;
2727
+ continue;
2728
+ }
2729
+ return false;
2730
+ }
2731
+ return true;
2732
+ }
2733
+ /**
2734
+ * Escapes a json pointer path
2735
+ * @param path The raw pointer
2736
+ * @return the Escaped path
2737
+ */
2738
+ function escapePathComponent(path) {
2739
+ if (path.indexOf("/") === -1 && path.indexOf("~") === -1) return path;
2740
+ return path.replace(/~/g, "~0").replace(/\//g, "~1");
2741
+ }
2742
+ /**
2743
+ * Unescapes a json pointer path
2744
+ * @param path The escaped pointer
2745
+ * @return The unescaped path
2746
+ */
2747
+ function unescapePathComponent(path) {
2748
+ return path.replace(/~1/g, "/").replace(/~0/g, "~");
2749
+ }
2750
+ /**
2751
+ * Recursively checks whether an object has any undefined values inside.
2752
+ */
2753
+ function hasUndefined(obj) {
2754
+ if (obj === void 0) return true;
2755
+ if (obj) {
2756
+ if (Array.isArray(obj)) {
2757
+ for (var i_1 = 0, len = obj.length; i_1 < len; i_1++) if (hasUndefined(obj[i_1])) return true;
2758
+ } else if (typeof obj === "object") {
2759
+ var objKeys = _objectKeys(obj);
2760
+ var objKeysLength = objKeys.length;
2761
+ for (var i = 0; i < objKeysLength; i++) if (hasUndefined(obj[objKeys[i]])) return true;
2762
+ }
2763
+ }
2764
+ return false;
2765
+ }
2766
+ function patchErrorMessageFormatter(message, args) {
2767
+ var messageParts = [message];
2768
+ for (var key in args) {
2769
+ var value = typeof args[key] === "object" ? JSON.stringify(args[key], null, 2) : args[key];
2770
+ if (typeof value !== "undefined") messageParts.push(key + ": " + value);
2771
+ }
2772
+ return messageParts.join("\n");
2773
+ }
2774
+ var PatchError = function(_super) {
2775
+ __extends(PatchError, _super);
2776
+ function PatchError(message, name, index, operation, tree) {
2777
+ var _newTarget = this.constructor;
2778
+ var _this = _super.call(this, patchErrorMessageFormatter(message, {
2779
+ name,
2780
+ index,
2781
+ operation,
2782
+ tree
2783
+ })) || this;
2784
+ _this.name = name;
2785
+ _this.index = index;
2786
+ _this.operation = operation;
2787
+ _this.tree = tree;
2788
+ Object.setPrototypeOf(_this, _newTarget.prototype);
2789
+ _this.message = patchErrorMessageFormatter(message, {
2790
+ name,
2791
+ index,
2792
+ operation,
2793
+ tree
2794
+ });
2795
+ return _this;
2796
+ }
2797
+ return PatchError;
2798
+ }(Error);
2799
+ //#endregion
2800
+ //#region node_modules/.deno/fast-json-patch@3.1.1/node_modules/fast-json-patch/module/core.mjs
2801
+ var core_exports = /* @__PURE__ */ __exportAll({
2802
+ JsonPatchError: () => JsonPatchError,
2803
+ _areEquals: () => _areEquals,
2804
+ applyOperation: () => applyOperation,
2805
+ applyPatch: () => applyPatch,
2806
+ applyReducer: () => applyReducer,
2807
+ deepClone: () => deepClone,
2808
+ getValueByPointer: () => getValueByPointer,
2809
+ validate: () => validate,
2810
+ validator: () => validator
2811
+ });
2812
+ var JsonPatchError = PatchError;
2813
+ var deepClone = _deepClone;
2814
+ var objOps = {
2815
+ add: function(obj, key, document) {
2816
+ obj[key] = this.value;
2817
+ return { newDocument: document };
2818
+ },
2819
+ remove: function(obj, key, document) {
2820
+ var removed = obj[key];
2821
+ delete obj[key];
2822
+ return {
2823
+ newDocument: document,
2824
+ removed
2825
+ };
2826
+ },
2827
+ replace: function(obj, key, document) {
2828
+ var removed = obj[key];
2829
+ obj[key] = this.value;
2830
+ return {
2831
+ newDocument: document,
2832
+ removed
2833
+ };
2834
+ },
2835
+ move: function(obj, key, document) {
2836
+ var removed = getValueByPointer(document, this.path);
2837
+ if (removed) removed = _deepClone(removed);
2838
+ var originalValue = applyOperation(document, {
2839
+ op: "remove",
2840
+ path: this.from
2841
+ }).removed;
2842
+ applyOperation(document, {
2843
+ op: "add",
2844
+ path: this.path,
2845
+ value: originalValue
2846
+ });
2847
+ return {
2848
+ newDocument: document,
2849
+ removed
2850
+ };
2851
+ },
2852
+ copy: function(obj, key, document) {
2853
+ var valueToCopy = getValueByPointer(document, this.from);
2854
+ applyOperation(document, {
2855
+ op: "add",
2856
+ path: this.path,
2857
+ value: _deepClone(valueToCopy)
2858
+ });
2859
+ return { newDocument: document };
2860
+ },
2861
+ test: function(obj, key, document) {
2862
+ return {
2863
+ newDocument: document,
2864
+ test: _areEquals(obj[key], this.value)
2865
+ };
2866
+ },
2867
+ _get: function(obj, key, document) {
2868
+ this.value = obj[key];
2869
+ return { newDocument: document };
2870
+ }
2871
+ };
2872
+ var arrOps = {
2873
+ add: function(arr, i, document) {
2874
+ if (isInteger(i)) arr.splice(i, 0, this.value);
2875
+ else arr[i] = this.value;
2876
+ return {
2877
+ newDocument: document,
2878
+ index: i
2879
+ };
2880
+ },
2881
+ remove: function(arr, i, document) {
2882
+ return {
2883
+ newDocument: document,
2884
+ removed: arr.splice(i, 1)[0]
2885
+ };
2886
+ },
2887
+ replace: function(arr, i, document) {
2888
+ var removed = arr[i];
2889
+ arr[i] = this.value;
2890
+ return {
2891
+ newDocument: document,
2892
+ removed
2893
+ };
2894
+ },
2895
+ move: objOps.move,
2896
+ copy: objOps.copy,
2897
+ test: objOps.test,
2898
+ _get: objOps._get
2899
+ };
2900
+ /**
2901
+ * Retrieves a value from a JSON document by a JSON pointer.
2902
+ * Returns the value.
2903
+ *
2904
+ * @param document The document to get the value from
2905
+ * @param pointer an escaped JSON pointer
2906
+ * @return The retrieved value
2907
+ */
2908
+ function getValueByPointer(document, pointer) {
2909
+ if (pointer == "") return document;
2910
+ var getOriginalDestination = {
2911
+ op: "_get",
2912
+ path: pointer
2913
+ };
2914
+ applyOperation(document, getOriginalDestination);
2915
+ return getOriginalDestination.value;
2916
+ }
2917
+ /**
2918
+ * Apply a single JSON Patch Operation on a JSON document.
2919
+ * Returns the {newDocument, result} of the operation.
2920
+ * It modifies the `document` and `operation` objects - it gets the values by reference.
2921
+ * If you would like to avoid touching your values, clone them:
2922
+ * `jsonpatch.applyOperation(document, jsonpatch._deepClone(operation))`.
2923
+ *
2924
+ * @param document The document to patch
2925
+ * @param operation The operation to apply
2926
+ * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation.
2927
+ * @param mutateDocument Whether to mutate the original document or clone it before applying
2928
+ * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`.
2929
+ * @return `{newDocument, result}` after the operation
2930
+ */
2931
+ function applyOperation(document, operation, validateOperation, mutateDocument, banPrototypeModifications, index) {
2932
+ if (validateOperation === void 0) validateOperation = false;
2933
+ if (mutateDocument === void 0) mutateDocument = true;
2934
+ if (banPrototypeModifications === void 0) banPrototypeModifications = true;
2935
+ if (index === void 0) index = 0;
2936
+ if (validateOperation) if (typeof validateOperation == "function") validateOperation(operation, 0, document, operation.path);
2937
+ else validator(operation, 0);
2938
+ if (operation.path === "") {
2939
+ var returnValue = { newDocument: document };
2940
+ if (operation.op === "add") {
2941
+ returnValue.newDocument = operation.value;
2942
+ return returnValue;
2943
+ } else if (operation.op === "replace") {
2944
+ returnValue.newDocument = operation.value;
2945
+ returnValue.removed = document;
2946
+ return returnValue;
2947
+ } else if (operation.op === "move" || operation.op === "copy") {
2948
+ returnValue.newDocument = getValueByPointer(document, operation.from);
2949
+ if (operation.op === "move") returnValue.removed = document;
2950
+ return returnValue;
2951
+ } else if (operation.op === "test") {
2952
+ returnValue.test = _areEquals(document, operation.value);
2953
+ if (returnValue.test === false) throw new JsonPatchError("Test operation failed", "TEST_OPERATION_FAILED", index, operation, document);
2954
+ returnValue.newDocument = document;
2955
+ return returnValue;
2956
+ } else if (operation.op === "remove") {
2957
+ returnValue.removed = document;
2958
+ returnValue.newDocument = null;
2959
+ return returnValue;
2960
+ } else if (operation.op === "_get") {
2961
+ operation.value = document;
2962
+ return returnValue;
2963
+ } else if (validateOperation) throw new JsonPatchError("Operation `op` property is not one of operations defined in RFC-6902", "OPERATION_OP_INVALID", index, operation, document);
2964
+ else return returnValue;
2965
+ } else {
2966
+ if (!mutateDocument) document = _deepClone(document);
2967
+ var keys = (operation.path || "").split("/");
2968
+ var obj = document;
2969
+ var t = 1;
2970
+ var len = keys.length;
2971
+ var existingPathFragment = void 0;
2972
+ var key = void 0;
2973
+ var validateFunction = void 0;
2974
+ if (typeof validateOperation == "function") validateFunction = validateOperation;
2975
+ else validateFunction = validator;
2976
+ while (true) {
2977
+ key = keys[t];
2978
+ if (key && key.indexOf("~") != -1) key = unescapePathComponent(key);
2979
+ if (banPrototypeModifications && (key == "__proto__" || key == "prototype" && t > 0 && keys[t - 1] == "constructor")) throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");
2980
+ if (validateOperation) {
2981
+ if (existingPathFragment === void 0) {
2982
+ if (obj[key] === void 0) existingPathFragment = keys.slice(0, t).join("/");
2983
+ else if (t == len - 1) existingPathFragment = operation.path;
2984
+ if (existingPathFragment !== void 0) validateFunction(operation, 0, document, existingPathFragment);
2985
+ }
2986
+ }
2987
+ t++;
2988
+ if (Array.isArray(obj)) {
2989
+ if (key === "-") key = obj.length;
2990
+ else if (validateOperation && !isInteger(key)) throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", index, operation, document);
2991
+ else if (isInteger(key)) key = ~~key;
2992
+ if (t >= len) {
2993
+ if (validateOperation && operation.op === "add" && key > obj.length) throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document);
2994
+ var returnValue = arrOps[operation.op].call(operation, obj, key, document);
2995
+ if (returnValue.test === false) throw new JsonPatchError("Test operation failed", "TEST_OPERATION_FAILED", index, operation, document);
2996
+ return returnValue;
2997
+ }
2998
+ } else if (t >= len) {
2999
+ var returnValue = objOps[operation.op].call(operation, obj, key, document);
3000
+ if (returnValue.test === false) throw new JsonPatchError("Test operation failed", "TEST_OPERATION_FAILED", index, operation, document);
3001
+ return returnValue;
3002
+ }
3003
+ obj = obj[key];
3004
+ if (validateOperation && t < len && (!obj || typeof obj !== "object")) throw new JsonPatchError("Cannot perform operation at the desired path", "OPERATION_PATH_UNRESOLVABLE", index, operation, document);
3005
+ }
3006
+ }
3007
+ }
3008
+ /**
3009
+ * Apply a full JSON Patch array on a JSON document.
3010
+ * Returns the {newDocument, result} of the patch.
3011
+ * It modifies the `document` object and `patch` - it gets the values by reference.
3012
+ * If you would like to avoid touching your values, clone them:
3013
+ * `jsonpatch.applyPatch(document, jsonpatch._deepClone(patch))`.
3014
+ *
3015
+ * @param document The document to patch
3016
+ * @param patch The patch to apply
3017
+ * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation.
3018
+ * @param mutateDocument Whether to mutate the original document or clone it before applying
3019
+ * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`.
3020
+ * @return An array of `{newDocument, result}` after the patch
3021
+ */
3022
+ function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) {
3023
+ if (mutateDocument === void 0) mutateDocument = true;
3024
+ if (banPrototypeModifications === void 0) banPrototypeModifications = true;
3025
+ if (validateOperation) {
3026
+ if (!Array.isArray(patch)) throw new JsonPatchError("Patch sequence must be an array", "SEQUENCE_NOT_AN_ARRAY");
3027
+ }
3028
+ if (!mutateDocument) document = _deepClone(document);
3029
+ var results = new Array(patch.length);
3030
+ for (var i = 0, length_1 = patch.length; i < length_1; i++) {
3031
+ results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i);
3032
+ document = results[i].newDocument;
3033
+ }
3034
+ results.newDocument = document;
3035
+ return results;
3036
+ }
3037
+ /**
3038
+ * Apply a single JSON Patch Operation on a JSON document.
3039
+ * Returns the updated document.
3040
+ * Suitable as a reducer.
3041
+ *
3042
+ * @param document The document to patch
3043
+ * @param operation The operation to apply
3044
+ * @return The updated document
3045
+ */
3046
+ function applyReducer(document, operation, index) {
3047
+ var operationResult = applyOperation(document, operation);
3048
+ if (operationResult.test === false) throw new JsonPatchError("Test operation failed", "TEST_OPERATION_FAILED", index, operation, document);
3049
+ return operationResult.newDocument;
3050
+ }
3051
+ /**
3052
+ * Validates a single operation. Called from `jsonpatch.validate`. Throws `JsonPatchError` in case of an error.
3053
+ * @param {object} operation - operation object (patch)
3054
+ * @param {number} index - index of operation in the sequence
3055
+ * @param {object} [document] - object where the operation is supposed to be applied
3056
+ * @param {string} [existingPathFragment] - comes along with `document`
3057
+ */
3058
+ function validator(operation, index, document, existingPathFragment) {
3059
+ if (typeof operation !== "object" || operation === null || Array.isArray(operation)) throw new JsonPatchError("Operation is not an object", "OPERATION_NOT_AN_OBJECT", index, operation, document);
3060
+ else if (!objOps[operation.op]) throw new JsonPatchError("Operation `op` property is not one of operations defined in RFC-6902", "OPERATION_OP_INVALID", index, operation, document);
3061
+ else if (typeof operation.path !== "string") throw new JsonPatchError("Operation `path` property is not a string", "OPERATION_PATH_INVALID", index, operation, document);
3062
+ else if (operation.path.indexOf("/") !== 0 && operation.path.length > 0) throw new JsonPatchError("Operation `path` property must start with \"/\"", "OPERATION_PATH_INVALID", index, operation, document);
3063
+ else if ((operation.op === "move" || operation.op === "copy") && typeof operation.from !== "string") throw new JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)", "OPERATION_FROM_REQUIRED", index, operation, document);
3064
+ else if ((operation.op === "add" || operation.op === "replace" || operation.op === "test") && operation.value === void 0) throw new JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)", "OPERATION_VALUE_REQUIRED", index, operation, document);
3065
+ else if ((operation.op === "add" || operation.op === "replace" || operation.op === "test") && hasUndefined(operation.value)) throw new JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)", "OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED", index, operation, document);
3066
+ else if (document) {
3067
+ if (operation.op == "add") {
3068
+ var pathLen = operation.path.split("/").length;
3069
+ var existingPathLen = existingPathFragment.split("/").length;
3070
+ if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) throw new JsonPatchError("Cannot perform an `add` operation at the desired path", "OPERATION_PATH_CANNOT_ADD", index, operation, document);
3071
+ } else if (operation.op === "replace" || operation.op === "remove" || operation.op === "_get") {
3072
+ if (operation.path !== existingPathFragment) throw new JsonPatchError("Cannot perform the operation at a path that does not exist", "OPERATION_PATH_UNRESOLVABLE", index, operation, document);
3073
+ } else if (operation.op === "move" || operation.op === "copy") {
3074
+ var error = validate([{
3075
+ op: "_get",
3076
+ path: operation.from,
3077
+ value: void 0
3078
+ }], document);
3079
+ if (error && error.name === "OPERATION_PATH_UNRESOLVABLE") throw new JsonPatchError("Cannot perform the operation from a path that does not exist", "OPERATION_FROM_UNRESOLVABLE", index, operation, document);
3080
+ }
3081
+ }
3082
+ }
3083
+ /**
3084
+ * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document.
3085
+ * If error is encountered, returns a JsonPatchError object
3086
+ * @param sequence
3087
+ * @param document
3088
+ * @returns {JsonPatchError|undefined}
3089
+ */
3090
+ function validate(sequence, document, externalValidator) {
3091
+ try {
3092
+ if (!Array.isArray(sequence)) throw new JsonPatchError("Patch sequence must be an array", "SEQUENCE_NOT_AN_ARRAY");
3093
+ if (document) applyPatch(_deepClone(document), _deepClone(sequence), externalValidator || true);
3094
+ else {
3095
+ externalValidator = externalValidator || validator;
3096
+ for (var i = 0; i < sequence.length; i++) externalValidator(sequence[i], i, document, void 0);
3097
+ }
3098
+ } catch (e) {
3099
+ if (e instanceof JsonPatchError) return e;
3100
+ else throw e;
3101
+ }
3102
+ }
3103
+ function _areEquals(a, b) {
3104
+ if (a === b) return true;
3105
+ if (a && b && typeof a == "object" && typeof b == "object") {
3106
+ var arrA = Array.isArray(a), arrB = Array.isArray(b), i, length, key;
3107
+ if (arrA && arrB) {
3108
+ length = a.length;
3109
+ if (length != b.length) return false;
3110
+ for (i = length; i-- !== 0;) if (!_areEquals(a[i], b[i])) return false;
3111
+ return true;
3112
+ }
3113
+ if (arrA != arrB) return false;
3114
+ var keys = Object.keys(a);
3115
+ length = keys.length;
3116
+ if (length !== Object.keys(b).length) return false;
3117
+ for (i = length; i-- !== 0;) if (!b.hasOwnProperty(keys[i])) return false;
3118
+ for (i = length; i-- !== 0;) {
3119
+ key = keys[i];
3120
+ if (!_areEquals(a[key], b[key])) return false;
3121
+ }
3122
+ return true;
3123
+ }
3124
+ return a !== a && b !== b;
3125
+ }
3126
+ //#endregion
3127
+ //#region node_modules/.deno/fast-json-patch@3.1.1/node_modules/fast-json-patch/module/duplex.mjs
3128
+ /*!
3129
+ * https://github.com/Starcounter-Jack/JSON-Patch
3130
+ * (c) 2017-2021 Joachim Wester
3131
+ * MIT license
3132
+ */
3133
+ var duplex_exports = /* @__PURE__ */ __exportAll({
3134
+ compare: () => compare,
3135
+ generate: () => generate,
3136
+ observe: () => observe,
3137
+ unobserve: () => unobserve
3138
+ });
3139
+ var beforeDict = /* @__PURE__ */ new WeakMap();
3140
+ var Mirror = function() {
3141
+ function Mirror(obj) {
3142
+ this.observers = /* @__PURE__ */ new Map();
3143
+ this.obj = obj;
3144
+ }
3145
+ return Mirror;
3146
+ }();
3147
+ var ObserverInfo = function() {
3148
+ function ObserverInfo(callback, observer) {
3149
+ this.callback = callback;
3150
+ this.observer = observer;
3151
+ }
3152
+ return ObserverInfo;
3153
+ }();
3154
+ function getMirror(obj) {
3155
+ return beforeDict.get(obj);
3156
+ }
3157
+ function getObserverFromMirror(mirror, callback) {
3158
+ return mirror.observers.get(callback);
3159
+ }
3160
+ function removeObserverFromMirror(mirror, observer) {
3161
+ mirror.observers.delete(observer.callback);
3162
+ }
3163
+ /**
3164
+ * Detach an observer from an object
3165
+ */
3166
+ function unobserve(root, observer) {
3167
+ observer.unobserve();
3168
+ }
3169
+ /**
3170
+ * Observes changes made to an object, which can then be retrieved using generate
3171
+ */
3172
+ function observe(obj, callback) {
3173
+ var patches = [];
3174
+ var observer;
3175
+ var mirror = getMirror(obj);
3176
+ if (!mirror) {
3177
+ mirror = new Mirror(obj);
3178
+ beforeDict.set(obj, mirror);
3179
+ } else {
3180
+ var observerInfo = getObserverFromMirror(mirror, callback);
3181
+ observer = observerInfo && observerInfo.observer;
3182
+ }
3183
+ if (observer) return observer;
3184
+ observer = {};
3185
+ mirror.value = _deepClone(obj);
3186
+ if (callback) {
3187
+ observer.callback = callback;
3188
+ observer.next = null;
3189
+ var dirtyCheck = function() {
3190
+ generate(observer);
3191
+ };
3192
+ var fastCheck = function() {
3193
+ clearTimeout(observer.next);
3194
+ observer.next = setTimeout(dirtyCheck);
3195
+ };
3196
+ if (typeof window !== "undefined") {
3197
+ window.addEventListener("mouseup", fastCheck);
3198
+ window.addEventListener("keyup", fastCheck);
3199
+ window.addEventListener("mousedown", fastCheck);
3200
+ window.addEventListener("keydown", fastCheck);
3201
+ window.addEventListener("change", fastCheck);
3202
+ }
3203
+ }
3204
+ observer.patches = patches;
3205
+ observer.object = obj;
3206
+ observer.unobserve = function() {
3207
+ generate(observer);
3208
+ clearTimeout(observer.next);
3209
+ removeObserverFromMirror(mirror, observer);
3210
+ if (typeof window !== "undefined") {
3211
+ window.removeEventListener("mouseup", fastCheck);
3212
+ window.removeEventListener("keyup", fastCheck);
3213
+ window.removeEventListener("mousedown", fastCheck);
3214
+ window.removeEventListener("keydown", fastCheck);
3215
+ window.removeEventListener("change", fastCheck);
3216
+ }
3217
+ };
3218
+ mirror.observers.set(callback, new ObserverInfo(callback, observer));
3219
+ return observer;
3220
+ }
3221
+ /**
3222
+ * Generate an array of patches from an observer
3223
+ */
3224
+ function generate(observer, invertible) {
3225
+ if (invertible === void 0) invertible = false;
3226
+ var mirror = beforeDict.get(observer.object);
3227
+ _generate(mirror.value, observer.object, observer.patches, "", invertible);
3228
+ if (observer.patches.length) applyPatch(mirror.value, observer.patches);
3229
+ var temp = observer.patches;
3230
+ if (temp.length > 0) {
3231
+ observer.patches = [];
3232
+ if (observer.callback) observer.callback(temp);
3233
+ }
3234
+ return temp;
3235
+ }
3236
+ function _generate(mirror, obj, patches, path, invertible) {
3237
+ if (obj === mirror) return;
3238
+ if (typeof obj.toJSON === "function") obj = obj.toJSON();
3239
+ var newKeys = _objectKeys(obj);
3240
+ var oldKeys = _objectKeys(mirror);
3241
+ var deleted = false;
3242
+ for (var t = oldKeys.length - 1; t >= 0; t--) {
3243
+ var key = oldKeys[t];
3244
+ var oldVal = mirror[key];
3245
+ if (hasOwnProperty(obj, key) && !(obj[key] === void 0 && oldVal !== void 0 && Array.isArray(obj) === false)) {
3246
+ var newVal = obj[key];
3247
+ if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null && Array.isArray(oldVal) === Array.isArray(newVal)) _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key), invertible);
3248
+ else if (oldVal !== newVal) {
3249
+ if (invertible) patches.push({
3250
+ op: "test",
3251
+ path: path + "/" + escapePathComponent(key),
3252
+ value: _deepClone(oldVal)
3253
+ });
3254
+ patches.push({
3255
+ op: "replace",
3256
+ path: path + "/" + escapePathComponent(key),
3257
+ value: _deepClone(newVal)
3258
+ });
3259
+ }
3260
+ } else if (Array.isArray(mirror) === Array.isArray(obj)) {
3261
+ if (invertible) patches.push({
3262
+ op: "test",
3263
+ path: path + "/" + escapePathComponent(key),
3264
+ value: _deepClone(oldVal)
3265
+ });
3266
+ patches.push({
3267
+ op: "remove",
3268
+ path: path + "/" + escapePathComponent(key)
3269
+ });
3270
+ deleted = true;
3271
+ } else {
3272
+ if (invertible) patches.push({
3273
+ op: "test",
3274
+ path,
3275
+ value: mirror
3276
+ });
3277
+ patches.push({
3278
+ op: "replace",
3279
+ path,
3280
+ value: obj
3281
+ });
3282
+ }
3283
+ }
3284
+ if (!deleted && newKeys.length == oldKeys.length) return;
3285
+ for (var t = 0; t < newKeys.length; t++) {
3286
+ var key = newKeys[t];
3287
+ if (!hasOwnProperty(mirror, key) && obj[key] !== void 0) patches.push({
3288
+ op: "add",
3289
+ path: path + "/" + escapePathComponent(key),
3290
+ value: _deepClone(obj[key])
3291
+ });
3292
+ }
3293
+ }
3294
+ /**
3295
+ * Create an array of patches from the differences in two objects
3296
+ */
3297
+ function compare(tree1, tree2, invertible) {
3298
+ if (invertible === void 0) invertible = false;
3299
+ var patches = [];
3300
+ _generate(tree1, tree2, patches, "", invertible);
3301
+ return patches;
3302
+ }
3303
+ //#endregion
3304
+ //#region node_modules/.deno/fast-json-patch@3.1.1/node_modules/fast-json-patch/index.mjs
3305
+ /**
3306
+ * Default export for backwards compat
3307
+ */
3308
+ var fast_json_patch_default = Object.assign({}, core_exports, duplex_exports, {
3309
+ JsonPatchError: PatchError,
3310
+ deepClone: _deepClone,
3311
+ escapePathComponent,
3312
+ unescapePathComponent
3313
+ });
3314
+ //#endregion
3315
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/activity-records.js
3316
+ function isActivityPart(part) {
3317
+ return part.type === "activity";
3318
+ }
3319
+ function isActivityContent(value) {
3320
+ return value != null && typeof value === "object" && !Array.isArray(value);
3321
+ }
3322
+ function applyActivitySnapshotToUIMessages(messages, chunk) {
3323
+ const { messageId, activityType, content } = chunk;
3324
+ const replace = chunk.replace ?? true;
3325
+ const existingIndex = messages.findIndex((m) => m.id === messageId);
3326
+ const existing = existingIndex >= 0 ? messages[existingIndex] : void 0;
3327
+ if (existing && existing.role !== "activity") {
3328
+ console.warn(`ACTIVITY_SNAPSHOT: Message '${messageId}' is not an activity message`);
3329
+ return messages;
3330
+ }
3331
+ if (existing && !replace) return messages;
3332
+ const metadata = mergeMetadata(existing?.role === "activity" ? existing.metadata : void 0, chunk.metadata);
3333
+ const next = {
3334
+ id: messageId,
3335
+ role: "activity",
3336
+ parts: [{
3337
+ type: "activity",
3338
+ activityType,
3339
+ content: structuredClone(content ?? {})
3340
+ }],
3341
+ ...metadata != null ? { metadata } : {},
3342
+ ...existing?.role === "activity" && existing.createdAt != null ? { createdAt: existing.createdAt } : {},
3343
+ ...existing?.role === "activity" && existing.name != null ? { name: existing.name } : {}
3344
+ };
3345
+ if (existingIndex === -1) return [...messages, next];
3346
+ return messages.map((msg, index) => index === existingIndex ? next : msg);
3347
+ }
3348
+ function applyActivityDeltaToUIMessages(messages, chunk) {
3349
+ const { messageId, activityType, patch } = chunk;
3350
+ const existingIndex = messages.findIndex((m) => m.id === messageId);
3351
+ if (existingIndex === -1) {
3352
+ console.warn(`ACTIVITY_DELTA: No activity message '${messageId}'`);
3353
+ return messages;
3354
+ }
3355
+ const existing = messages[existingIndex];
3356
+ if (existing == null || existing.role !== "activity") {
3357
+ console.warn(`ACTIVITY_DELTA: Message '${messageId}' is not an activity message`);
3358
+ return messages;
3359
+ }
3360
+ const activityPart = existing.parts.find(isActivityPart);
3361
+ if (activityPart && activityPart.activityType !== activityType) {
3362
+ console.warn(`ACTIVITY_DELTA: activityType '${activityType}' does not match '${activityPart.activityType}' for '${messageId}'`);
3363
+ return messages;
3364
+ }
3365
+ const baseContent = structuredClone(activityPart?.content ?? {});
3366
+ try {
3367
+ const result = fast_json_patch_default.applyPatch(baseContent, patch ?? [], true, false);
3368
+ if (!isActivityContent(result.newDocument)) {
3369
+ console.warn(`ACTIVITY_DELTA: patched content for '${messageId}' is not an object`);
3370
+ return messages;
3371
+ }
3372
+ const nextPart = {
3373
+ type: "activity",
3374
+ activityType,
3375
+ content: structuredClone(result.newDocument)
3376
+ };
3377
+ const parts = activityPart ? existing.parts.map((part) => part.type === "activity" ? nextPart : part) : [nextPart];
3378
+ const metadata = mergeMetadata(existing.metadata, chunk.metadata);
3379
+ return messages.map((msg, index) => index === existingIndex ? {
3380
+ ...msg,
3381
+ parts,
3382
+ ...metadata != null ? { metadata } : {}
3383
+ } : msg);
3384
+ } catch (error) {
3385
+ const errorMessage = error instanceof Error ? error.message : String(error);
3386
+ console.warn(`Failed to apply activity patch for '${messageId}': ${errorMessage}`);
3387
+ return messages;
3388
+ }
3389
+ }
3390
+ //#endregion
3391
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/message-updaters.js
2620
3392
  /**
2621
3393
  * Message Updaters (Internal)
2622
3394
  *
@@ -2918,7 +3690,7 @@ function updateThinkingPart(messages, messageId, stepId, content, signature) {
2918
3690
  });
2919
3691
  }
2920
3692
  //#endregion
2921
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
3693
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/activities/chat/stream/processor.js
2922
3694
  /**
2923
3695
  * Unified Stream Processor
2924
3696
  *
@@ -2939,6 +3711,28 @@ function updateThinkingPart(messages, messageId, stepId, content, signature) {
2939
3711
  * adapter contract, single-shot flows, and expected UIMessage output.
2940
3712
  */
2941
3713
  var STRUCTURED_OUTPUT_UPDATE_BATCH_SIZE = 12;
3714
+ /**
3715
+ * Events that leave this processor's open *_CHUNK stream open.
3716
+ * RAW, activity events, and REASONING_ENCRYPTED_VALUE match the AG-UI client.
3717
+ * Subagent lifecycle events stay here too: the child processor owns that
3718
+ * lane, and SUBAGENT_FINISHED or SUBAGENT_ERROR finalizes the child.
3719
+ */
3720
+ var CHUNK_PASS_THROUGH = /* @__PURE__ */ new Set([
3721
+ "RAW",
3722
+ "ACTIVITY_SNAPSHOT",
3723
+ "ACTIVITY_DELTA",
3724
+ "REASONING_ENCRYPTED_VALUE",
3725
+ "SUBAGENT_STARTED",
3726
+ "SUBAGENT_FINISHED",
3727
+ "SUBAGENT_ERROR"
3728
+ ]);
3729
+ /** A run-level event closes every open shorthand lane, including children. */
3730
+ var RUN_LEVEL_CLOSES_LANES = /* @__PURE__ */ new Set([
3731
+ "RUN_STARTED",
3732
+ "RUN_FINISHED",
3733
+ "RUN_ERROR",
3734
+ "MESSAGES_SNAPSHOT"
3735
+ ]);
2942
3736
  function interruptBatchHasGeneric(interrupts) {
2943
3737
  return interrupts.some((interrupt) => {
2944
3738
  const metadata = interrupt.metadata;
@@ -2964,6 +3758,19 @@ function serializeToolInput(input) {
2964
3758
  }
2965
3759
  }
2966
3760
  /**
3761
+ * The input of a tool call from its raw arguments: `{}` for an empty string,
3762
+ * `undefined` when the arguments are not complete JSON (for example cut off)
3763
+ * or are `null`.
3764
+ */
3765
+ function parseToolArguments(args) {
3766
+ if (args.trim() === "") return {};
3767
+ try {
3768
+ return JSON.parse(args) ?? void 0;
3769
+ } catch {
3770
+ return;
3771
+ }
3772
+ }
3773
+ /**
2967
3774
  * StreamProcessor - State machine for processing AI response streams
2968
3775
  *
2969
3776
  * Manages the full UIMessage[] conversation and emits events on changes.
@@ -2990,9 +3797,12 @@ var StreamProcessor = class StreamProcessor {
2990
3797
  toolCallToMessage = /* @__PURE__ */ new Map();
2991
3798
  pendingManualMessageId = null;
2992
3799
  pendingThinkingStepId = null;
3800
+ openChunk = null;
2993
3801
  structuredMessageIds = /* @__PURE__ */ new Set();
2994
3802
  structuredOutputUpdateBatches = /* @__PURE__ */ new Map();
2995
3803
  activeRuns = /* @__PURE__ */ new Set();
3804
+ runToolCallIds = [];
3805
+ toolCallsSentToClient = /* @__PURE__ */ new Set();
2996
3806
  childProcessors = /* @__PURE__ */ new Map();
2997
3807
  childToolCalls = /* @__PURE__ */ new Map();
2998
3808
  finishReason = null;
@@ -3199,6 +4009,7 @@ var StreamProcessor = class StreamProcessor {
3199
4009
  this.structuredMessageIds.clear();
3200
4010
  this.structuredOutputUpdateBatches.clear();
3201
4011
  this.pendingManualMessageId = null;
4012
+ this.openChunk = null;
3202
4013
  this.childProcessors.clear();
3203
4014
  this.childToolCalls.clear();
3204
4015
  this.emitMessagesChange();
@@ -3219,7 +4030,7 @@ var StreamProcessor = class StreamProcessor {
3219
4030
  *
3220
4031
  * Central dispatch for all AG-UI events. Each event type maps to a specific
3221
4032
  * handler. Events not listed in the switch are intentionally ignored
3222
- * (STEP_STARTED, STATE_SNAPSHOT, STATE_DELTA).
4033
+ * (STATE_SNAPSHOT, STATE_DELTA).
3223
4034
  *
3224
4035
  * @see docs/chat-architecture.md#adapter-contract — Expected event types and ordering
3225
4036
  */
@@ -3230,6 +4041,10 @@ var StreamProcessor = class StreamProcessor {
3230
4041
  index: this.recording.chunks.length
3231
4042
  });
3232
4043
  if (this.routeToChild(chunk)) return;
4044
+ for (const event of this.expandChunk(chunk)) this.dispatchChunk(event);
4045
+ }
4046
+ /** Send one event, after expandChunk(), to its handler. */
4047
+ dispatchChunk(chunk) {
3233
4048
  switch (chunk.type) {
3234
4049
  case "SUBAGENT_STARTED":
3235
4050
  this.handleSubagentStartedEvent(chunk);
@@ -3289,7 +4104,178 @@ var StreamProcessor = class StreamProcessor {
3289
4104
  case "TOOL_CALL_RESULT":
3290
4105
  this.handleToolCallResultEvent(chunk);
3291
4106
  break;
3292
- case "STEP_STARTED": this.handleStepStartedEvent(chunk);
4107
+ case "STEP_STARTED":
4108
+ this.handleStepStartedEvent(chunk);
4109
+ break;
4110
+ case "ACTIVITY_SNAPSHOT":
4111
+ this.handleActivitySnapshotEvent(chunk);
4112
+ break;
4113
+ case "ACTIVITY_DELTA": this.handleActivityDeltaEvent(chunk);
4114
+ }
4115
+ }
4116
+ /**
4117
+ * AG-UI lets a producer send one TEXT_MESSAGE_CHUNK, TOOL_CALL_CHUNK or
4118
+ * REASONING_MESSAGE_CHUNK in place of the START / CONTENT (ARGS) / END
4119
+ * events. A chunk with a new id opens a stream. A chunk with the same id or
4120
+ * no id continues it. Any other event closes it, except the ones in
4121
+ * CHUNK_PASS_THROUGH. Expand the shorthand into the START / CONTENT (ARGS)
4122
+ * / END events, so both forms build the same message.
4123
+ */
4124
+ expandChunk(chunk) {
4125
+ const open = this.openChunk;
4126
+ const timestamp = chunk.timestamp;
4127
+ switch (chunk.type) {
4128
+ case "TEXT_MESSAGE_CHUNK": {
4129
+ const id = this.chunkStreamId("TEXT_MESSAGE", chunk.messageId, chunk.type);
4130
+ if (id === void 0) return this.closeChunk();
4131
+ const events = [];
4132
+ if (open?.family !== "TEXT_MESSAGE" || open.id !== id) {
4133
+ events.push(...this.closeChunk(), {
4134
+ type: EventType.TEXT_MESSAGE_START,
4135
+ messageId: id,
4136
+ role: chunk.role ?? "assistant",
4137
+ ...chunk.name !== void 0 ? { name: chunk.name } : {},
4138
+ timestamp
4139
+ });
4140
+ this.openChunk = {
4141
+ family: "TEXT_MESSAGE",
4142
+ id
4143
+ };
4144
+ }
4145
+ if (chunk.delta !== void 0 || chunk.metadata !== void 0) events.push({
4146
+ type: EventType.TEXT_MESSAGE_CONTENT,
4147
+ messageId: id,
4148
+ delta: chunk.delta ?? "",
4149
+ metadata: chunk.metadata,
4150
+ timestamp
4151
+ });
4152
+ return events;
4153
+ }
4154
+ case "TOOL_CALL_CHUNK": {
4155
+ const id = this.chunkStreamId("TOOL_CALL", chunk.toolCallId, chunk.type);
4156
+ if (id === void 0) return this.closeChunk();
4157
+ const events = [];
4158
+ if (open?.family !== "TOOL_CALL" || open.id !== id) {
4159
+ if (chunk.toolCallName === void 0) {
4160
+ console.warn(`[StreamProcessor] Dropped TOOL_CALL_CHUNK ${id}: the first chunk of a tool call needs a toolCallName`);
4161
+ return this.closeChunk();
4162
+ }
4163
+ events.push(...this.closeChunk(), {
4164
+ type: EventType.TOOL_CALL_START,
4165
+ toolCallId: id,
4166
+ toolCallName: chunk.toolCallName,
4167
+ parentMessageId: chunk.parentMessageId,
4168
+ metadata: chunk.metadata,
4169
+ timestamp
4170
+ });
4171
+ this.openChunk = {
4172
+ family: "TOOL_CALL",
4173
+ id
4174
+ };
4175
+ }
4176
+ if (chunk.delta !== void 0 || chunk.metadata !== void 0) events.push({
4177
+ type: EventType.TOOL_CALL_ARGS,
4178
+ toolCallId: id,
4179
+ delta: chunk.delta ?? "",
4180
+ ...chunk.metadata !== void 0 ? { metadata: chunk.metadata } : {},
4181
+ timestamp
4182
+ });
4183
+ return events;
4184
+ }
4185
+ case "REASONING_MESSAGE_CHUNK": {
4186
+ const id = this.chunkStreamId("REASONING_MESSAGE", chunk.messageId, chunk.type);
4187
+ if (id === void 0) return this.closeChunk();
4188
+ const events = [];
4189
+ if (open?.family !== "REASONING_MESSAGE" || open.id !== id) {
4190
+ events.push(...this.closeChunk(), {
4191
+ type: EventType.REASONING_MESSAGE_START,
4192
+ messageId: id,
4193
+ role: "reasoning",
4194
+ timestamp
4195
+ });
4196
+ this.openChunk = {
4197
+ family: "REASONING_MESSAGE",
4198
+ id
4199
+ };
4200
+ }
4201
+ if (chunk.delta !== void 0 || chunk.metadata !== void 0) events.push({
4202
+ type: EventType.REASONING_MESSAGE_CONTENT,
4203
+ messageId: id,
4204
+ delta: chunk.delta ?? "",
4205
+ ...chunk.metadata !== void 0 ? { metadata: chunk.metadata } : {},
4206
+ timestamp
4207
+ });
4208
+ return events;
4209
+ }
4210
+ default: {
4211
+ const events = open && !CHUNK_PASS_THROUGH.has(chunk.type) ? this.closeChunk() : [];
4212
+ if (RUN_LEVEL_CLOSES_LANES.has(chunk.type)) this.closeChildChunkLanes();
4213
+ return [...events, chunk];
4214
+ }
4215
+ }
4216
+ }
4217
+ /** Synthesize *_END on every nested shorthand lane and apply those events there. */
4218
+ closeChildChunkLanes() {
4219
+ for (const child of this.childProcessors.values()) {
4220
+ for (const event of child.closeChunk()) child.dispatchChunk(event);
4221
+ child.closeChildChunkLanes();
4222
+ }
4223
+ }
4224
+ /**
4225
+ * The child an untagged chunk with no id continues: the only child whose
4226
+ * subtree has an open chunk stream of its kind, when this processor has
4227
+ * none. The AG-UI client resolves a chunk that tags only its opener the
4228
+ * same way.
4229
+ */
4230
+ childContinuing(chunk) {
4231
+ let family;
4232
+ if (chunk.type === "TEXT_MESSAGE_CHUNK" && chunk.messageId === void 0) family = "TEXT_MESSAGE";
4233
+ else if (chunk.type === "REASONING_MESSAGE_CHUNK" && chunk.messageId === void 0) family = "REASONING_MESSAGE";
4234
+ else if (chunk.type === "TOOL_CALL_CHUNK" && chunk.toolCallId === void 0) family = "TOOL_CALL";
4235
+ else return;
4236
+ if (this.openChunkCount(family) !== 1) return void 0;
4237
+ for (const [id, child] of this.childProcessors) if (child.openChunkCount(family) === 1) return id;
4238
+ }
4239
+ /**
4240
+ * How many open chunk streams of a kind this processor and all its nested
4241
+ * children hold.
4242
+ */
4243
+ openChunkCount(family) {
4244
+ let count = this.openChunk?.family === family ? 1 : 0;
4245
+ for (const child of this.childProcessors.values()) count += child.openChunkCount(family);
4246
+ return count;
4247
+ }
4248
+ /**
4249
+ * The id a chunk opens or continues. A chunk with no id continues. If it
4250
+ * continues nothing, the caller drops it and closes the open stream, so a
4251
+ * later chunk with no id cannot continue that stream either.
4252
+ */
4253
+ chunkStreamId(family, id, type) {
4254
+ if (id !== void 0) return id;
4255
+ if (this.openChunk?.family === family) return this.openChunk.id;
4256
+ console.warn(`[StreamProcessor] Dropped ${type}: it has no id and continues nothing`);
4257
+ }
4258
+ closeChunk() {
4259
+ const open = this.openChunk;
4260
+ if (!open) return [];
4261
+ this.openChunk = null;
4262
+ const timestamp = Date.now();
4263
+ switch (open.family) {
4264
+ case "TEXT_MESSAGE": return [{
4265
+ type: EventType.TEXT_MESSAGE_END,
4266
+ messageId: open.id,
4267
+ timestamp
4268
+ }];
4269
+ case "TOOL_CALL": return [{
4270
+ type: EventType.TOOL_CALL_END,
4271
+ toolCallId: open.id,
4272
+ timestamp
4273
+ }];
4274
+ case "REASONING_MESSAGE": return [{
4275
+ type: EventType.REASONING_MESSAGE_END,
4276
+ messageId: open.id,
4277
+ timestamp
4278
+ }];
3293
4279
  }
3294
4280
  }
3295
4281
  /**
@@ -3366,7 +4352,7 @@ var StreamProcessor = class StreamProcessor {
3366
4352
  * MESSAGES_SNAPSHOT) but whose transient state was cleared. In that case we
3367
4353
  * hydrate state from the existing message rather than creating a duplicate.
3368
4354
  */
3369
- ensureAssistantMessage(preferredId) {
4355
+ ensureAssistantMessage(preferredId, fallbackToActive = true) {
3370
4356
  if (preferredId) {
3371
4357
  const state = this.getMessageState(preferredId);
3372
4358
  if (state) {
@@ -3377,7 +4363,7 @@ var StreamProcessor = class StreamProcessor {
3377
4363
  };
3378
4364
  }
3379
4365
  }
3380
- const activeId = this.getActiveAssistantMessageId();
4366
+ const activeId = fallbackToActive ? this.getActiveAssistantMessageId() : null;
3381
4367
  if (activeId) {
3382
4368
  const state = this.getMessageState(activeId);
3383
4369
  if (state) {
@@ -3390,7 +4376,8 @@ var StreamProcessor = class StreamProcessor {
3390
4376
  }
3391
4377
  if (preferredId) {
3392
4378
  const existingMsg = this.messages.find((m) => m.id === preferredId);
3393
- if (existingMsg) {
4379
+ if (existingMsg?.role === "activity") preferredId = void 0;
4380
+ else if (existingMsg) {
3394
4381
  const state = this.createMessageState(preferredId, existingMsg.role);
3395
4382
  this.activeMessageIds.add(preferredId);
3396
4383
  const lastPart = existingMsg.parts.length > 0 ? existingMsg.parts[existingMsg.parts.length - 1] : null;
@@ -3415,7 +4402,7 @@ var StreamProcessor = class StreamProcessor {
3415
4402
  this.messages = [...this.messages, assistantMessage];
3416
4403
  const state = this.createMessageState(id, "assistant");
3417
4404
  this.activeMessageIds.add(id);
3418
- this.pendingManualMessageId = id;
4405
+ if (!preferredId) this.pendingManualMessageId = id;
3419
4406
  this.events.onStreamStart?.();
3420
4407
  this.emitMessagesChange();
3421
4408
  return {
@@ -3585,7 +4572,9 @@ var StreamProcessor = class StreamProcessor {
3585
4572
  /**
3586
4573
  * Send a child's chunk to that child's processor, so the card keeps text,
3587
4574
  * reasoning, tool calls, results, and nested children. A tool event without
3588
- * `subagentRunId` follows its `TOOL_CALL_START`.
4575
+ * `subagentRunId` follows its `TOOL_CALL_START` or `TOOL_CALL_CHUNK`. An
4576
+ * untagged chunk with no id follows a child's open chunk stream (see
4577
+ * childContinuing()).
3589
4578
  */
3590
4579
  routeToChild(chunk) {
3591
4580
  let id;
@@ -3595,6 +4584,7 @@ var StreamProcessor = class StreamProcessor {
3595
4584
  id = chunk.subagentRunId;
3596
4585
  } else if ("subagentRunId" in chunk && chunk.subagentRunId) id = chunk.subagentRunId;
3597
4586
  else if ("toolCallId" in chunk && typeof chunk.toolCallId === "string") id = this.childToolCalls.get(chunk.toolCallId);
4587
+ else id = this.childContinuing(chunk);
3598
4588
  if (id === void 0) return false;
3599
4589
  const owner = this.childOwning(id);
3600
4590
  if (owner === void 0) {
@@ -3603,34 +4593,45 @@ var StreamProcessor = class StreamProcessor {
3603
4593
  return true;
3604
4594
  }
3605
4595
  if (this.findSubagentPart(owner)?.part.subagent.status === "error") return true;
3606
- if (chunk.type === "TOOL_CALL_START") this.childToolCalls.set(chunk.toolCallId, owner);
4596
+ if ((chunk.type === "TOOL_CALL_START" || chunk.type === "TOOL_CALL_CHUNK") && chunk.toolCallId !== void 0) this.childToolCalls.set(chunk.toolCallId, owner);
3607
4597
  this.updateChild(owner, (child) => child.processChunk(chunk));
3608
4598
  return true;
3609
4599
  }
4600
+ renameMessage(fromId, toId) {
4601
+ this.messages = this.messages.map((msg) => msg.id === fromId ? {
4602
+ ...msg,
4603
+ id: toId
4604
+ } : msg);
4605
+ const existingState = this.messageStates.get(fromId);
4606
+ if (existingState) {
4607
+ existingState.id = toId;
4608
+ this.messageStates.delete(fromId);
4609
+ this.messageStates.set(toId, existingState);
4610
+ }
4611
+ this.activeMessageIds.delete(fromId);
4612
+ this.activeMessageIds.add(toId);
4613
+ for (const [toolCallId, mappedMessageId] of this.toolCallToMessage) if (mappedMessageId === fromId) this.toolCallToMessage.set(toolCallId, toId);
4614
+ if (this.structuredMessageIds.delete(fromId)) this.structuredMessageIds.add(toId);
4615
+ const batch = this.structuredOutputUpdateBatches.get(fromId);
4616
+ if (batch) {
4617
+ this.structuredOutputUpdateBatches.delete(fromId);
4618
+ this.structuredOutputUpdateBatches.set(toId, batch);
4619
+ }
4620
+ }
3610
4621
  /**
3611
4622
  * Handle TEXT_MESSAGE_START event
3612
4623
  */
3613
4624
  handleTextMessageStartEvent(chunk) {
3614
4625
  const { messageId, role } = chunk;
4626
+ if (this.messages.some((m) => m.id === messageId && m.role === "activity")) {
4627
+ console.warn(`TEXT_MESSAGE_START: Dropped text for '${messageId}', the id of an activity message`);
4628
+ return;
4629
+ }
3615
4630
  const uiRole = role === "user" || role === "system" ? role : "assistant";
3616
4631
  if (this.pendingManualMessageId) {
3617
4632
  const pendingId = this.pendingManualMessageId;
3618
4633
  this.pendingManualMessageId = null;
3619
- if (pendingId !== messageId) {
3620
- this.messages = this.messages.map((msg) => msg.id === pendingId ? {
3621
- ...msg,
3622
- id: messageId
3623
- } : msg);
3624
- const existingState = this.messageStates.get(pendingId);
3625
- if (existingState) {
3626
- existingState.id = messageId;
3627
- this.messageStates.delete(pendingId);
3628
- this.messageStates.set(messageId, existingState);
3629
- }
3630
- this.activeMessageIds.delete(pendingId);
3631
- this.activeMessageIds.add(messageId);
3632
- for (const [toolCallId, mappedMessageId] of this.toolCallToMessage) if (mappedMessageId === pendingId) this.toolCallToMessage.set(toolCallId, messageId);
3633
- }
4634
+ if (pendingId !== messageId) this.renameMessage(pendingId, messageId);
3634
4635
  let pendingState = this.messageStates.get(messageId);
3635
4636
  if (!pendingState) {
3636
4637
  pendingState = this.createMessageState(messageId, uiRole);
@@ -3641,6 +4642,7 @@ var StreamProcessor = class StreamProcessor {
3641
4642
  pendingState.lastEmittedText = "";
3642
4643
  pendingState.hasToolCallsSinceTextStart = false;
3643
4644
  }
4645
+ this.applySenderName(messageId, chunk.name);
3644
4646
  this.mergeMessageMetadata(messageId, chunk.metadata);
3645
4647
  this.emitMessagesChange();
3646
4648
  return;
@@ -3655,6 +4657,7 @@ var StreamProcessor = class StreamProcessor {
3655
4657
  existingState.lastEmittedText = "";
3656
4658
  existingState.hasToolCallsSinceTextStart = false;
3657
4659
  }
4660
+ this.applySenderName(messageId, chunk.name);
3658
4661
  this.mergeMessageMetadata(messageId, chunk.metadata);
3659
4662
  return;
3660
4663
  }
@@ -3667,10 +4670,18 @@ var StreamProcessor = class StreamProcessor {
3667
4670
  this.messages = [...this.messages, newMessage];
3668
4671
  this.createMessageState(messageId, uiRole);
3669
4672
  this.activeMessageIds.add(messageId);
4673
+ this.applySenderName(messageId, chunk.name);
3670
4674
  this.mergeMessageMetadata(messageId, chunk.metadata);
3671
4675
  this.events.onStreamStart?.();
3672
4676
  this.emitMessagesChange();
3673
4677
  }
4678
+ applySenderName(messageId, name) {
4679
+ if (name === void 0) return;
4680
+ this.messages = this.messages.map((msg) => msg.id === messageId ? {
4681
+ ...msg,
4682
+ name
4683
+ } : msg);
4684
+ }
3674
4685
  /**
3675
4686
  * Handle TEXT_MESSAGE_END event
3676
4687
  */
@@ -3700,10 +4711,31 @@ var StreamProcessor = class StreamProcessor {
3700
4711
  metadata: prev.metadata
3701
4712
  };
3702
4713
  });
3703
- this.messages = this.attachSnapshotSubagents(reconciled, top, groups, prevMessages);
4714
+ this.messages = this.mergeOmittedActivity(prevMessages, this.attachSnapshotSubagents(reconciled, top, groups, prevMessages));
3704
4715
  this.emitMessagesChange();
3705
4716
  }
3706
4717
  /**
4718
+ * Snapshot is authoritative for user/assistant/system. Activity omitted
4719
+ * from the snapshot (TanStack chat() still builds snapshots from
4720
+ * ModelMessage[]) stays in the transcript so persist/reconnect cannot
4721
+ * wipe it. Snapshot activity rows win when the id is present.
4722
+ *
4723
+ * Keep every snapshot row, including two assistants that share an id
4724
+ * (agent-loop retry reuses `currentMessageId`). A Map keyed by id would
4725
+ * drop the earlier error tool-call (#1192).
4726
+ */
4727
+ mergeOmittedActivity(prevMessages, snapshot) {
4728
+ const snapshotIds = new Set(snapshot.map((msg) => msg.id));
4729
+ const omitted = prevMessages.filter((msg) => msg.role === "activity" && !snapshotIds.has(msg.id));
4730
+ if (omitted.length === 0) return snapshot;
4731
+ const out = [...snapshot];
4732
+ for (const activity of omitted) {
4733
+ const prevIndex = prevMessages.findIndex((msg) => msg.id === activity.id);
4734
+ out.splice(Math.min(Math.max(prevIndex, 0), out.length), 0, activity);
4735
+ }
4736
+ return out;
4737
+ }
4738
+ /**
3707
4739
  * Put subagent cards back on a snapshot. Child wire messages (tagged with
3708
4740
  * `subagentRunId`) become a card on the nearest assistant message before
3709
4741
  * them, or a new assistant message when there is none. A card that the
@@ -3923,6 +4955,10 @@ var StreamProcessor = class StreamProcessor {
3923
4955
  * @see docs/chat-architecture.md#uimessage-part-ordering-invariants — Replace vs. push logic
3924
4956
  */
3925
4957
  handleTextMessageContentEvent(chunk) {
4958
+ if (this.messages.some((m) => m.id === chunk.messageId && m.role === "activity")) {
4959
+ console.warn(`TEXT_MESSAGE_CONTENT: Dropped text for '${chunk.messageId}', the id of an activity message`);
4960
+ return;
4961
+ }
3926
4962
  const { messageId, state } = this.ensureAssistantMessage(chunk.messageId);
3927
4963
  this.mergeMessageMetadata(messageId, chunk.metadata);
3928
4964
  if (this.structuredMessageIds.has(messageId)) {
@@ -3966,8 +5002,25 @@ var StreamProcessor = class StreamProcessor {
3966
5002
  * @see docs/chat-architecture.md#adapter-contract — Ordering requirements
3967
5003
  */
3968
5004
  handleToolCallStartEvent(chunk) {
5005
+ const pendingId = this.pendingManualMessageId;
5006
+ const parentId = chunk.parentMessageId;
5007
+ if (pendingId && parentId && parentId !== pendingId) {
5008
+ const parent = this.messages.find((m) => m.id === parentId);
5009
+ const placeholder = this.messages.find((m) => m.id === pendingId);
5010
+ if (!parent) {
5011
+ this.pendingManualMessageId = null;
5012
+ this.renameMessage(pendingId, parentId);
5013
+ } else if (parent.role === "assistant" && placeholder) {
5014
+ this.pendingManualMessageId = null;
5015
+ this.messages = this.messages.filter((m) => m.id !== pendingId).map((m) => m.id === parentId ? {
5016
+ ...m,
5017
+ parts: [...m.parts, ...placeholder.parts]
5018
+ } : m);
5019
+ this.renameMessage(pendingId, parentId);
5020
+ }
5021
+ }
3969
5022
  const targetMessageId = chunk.parentMessageId ?? this.getActiveAssistantMessageId();
3970
- const { messageId, state } = this.ensureAssistantMessage(targetMessageId ?? void 0);
5023
+ const { messageId, state } = this.ensureAssistantMessage(targetMessageId ?? void 0, chunk.parentMessageId === void 0);
3971
5024
  state.hasToolCallsSinceTextStart = true;
3972
5025
  const toolCallId = chunk.toolCallId;
3973
5026
  if (!state.toolCalls.get(toolCallId)) {
@@ -3985,6 +5038,7 @@ var StreamProcessor = class StreamProcessor {
3985
5038
  };
3986
5039
  state.toolCalls.set(toolCallId, newToolCall);
3987
5040
  state.toolCallOrder.push(toolCallId);
5041
+ this.runToolCallIds.push(toolCallId);
3988
5042
  this.toolCallToMessage.set(toolCallId, messageId);
3989
5043
  this.messages = updateToolCallPart(this.messages, messageId, {
3990
5044
  id: chunk.toolCallId,
@@ -4018,6 +5072,7 @@ var StreamProcessor = class StreamProcessor {
4018
5072
  const existingToolCall = state.toolCalls.get(toolCallId);
4019
5073
  if (!existingToolCall) return;
4020
5074
  const wasAwaitingInput = existingToolCall.state === "awaiting-input";
5075
+ if (chunk.metadata !== void 0) existingToolCall.metadata = mergeMetadata(existingToolCall.metadata, chunk.metadata);
4021
5076
  existingToolCall.arguments += chunk.delta || "";
4022
5077
  if (wasAwaitingInput && chunk.delta) existingToolCall.state = "input-streaming";
4023
5078
  existingToolCall.parsedArguments = this.jsonParser.parse(existingToolCall.arguments);
@@ -4025,7 +5080,8 @@ var StreamProcessor = class StreamProcessor {
4025
5080
  id: existingToolCall.id,
4026
5081
  name: existingToolCall.name,
4027
5082
  arguments: existingToolCall.arguments,
4028
- state: existingToolCall.state
5083
+ state: existingToolCall.state,
5084
+ ...existingToolCall.metadata !== void 0 && { metadata: existingToolCall.metadata }
4029
5085
  });
4030
5086
  this.emitMessagesChange();
4031
5087
  this.events.onToolCallStateChange?.(messageId, existingToolCall.id, existingToolCall.state, existingToolCall.arguments);
@@ -4102,6 +5158,10 @@ var StreamProcessor = class StreamProcessor {
4102
5158
  * runs are still active before finalizing.
4103
5159
  */
4104
5160
  handleRunStartedEvent(chunk) {
5161
+ if (this.activeRuns.size === 0) {
5162
+ this.runToolCallIds = [];
5163
+ this.toolCallsSentToClient.clear();
5164
+ }
4105
5165
  this.activeRuns.add(chunk.runId);
4106
5166
  }
4107
5167
  /**
@@ -4122,11 +5182,39 @@ var StreamProcessor = class StreamProcessor {
4122
5182
  if (this.activeRuns.size === 0) {
4123
5183
  this.completeAllToolCalls();
4124
5184
  if (this.finishReason === "tool_calls" && chunk.outcome?.type !== "interrupt") return;
5185
+ if (!chunk.outcome || chunk.outcome.type === "success") this.handlePendingToolCalls(chunk.outcome?.pendingToolCallIds);
4125
5186
  this.isDone = true;
4126
5187
  this.finalizeStream();
4127
5188
  }
4128
5189
  }
4129
5190
  /**
5191
+ * AG-UI ends a run that calls a frontend tool with a success outcome and
5192
+ * leaves the call unanswered. The pending calls are the ones named in
5193
+ * `pendingToolCallIds` that this run started, or else every call this run
5194
+ * started that has no result. Fire onToolCall once for each, so the client
5195
+ * runs it and continues.
5196
+ */
5197
+ handlePendingToolCalls(pendingToolCallIds) {
5198
+ const ids = pendingToolCallIds?.length ? pendingToolCallIds.filter((id) => this.runToolCallIds.includes(id)) : this.runToolCallIds;
5199
+ const parts = this.messages.flatMap((msg) => msg.parts ?? []);
5200
+ for (const toolCallId of ids) {
5201
+ if (this.toolCallsSentToClient.has(toolCallId)) continue;
5202
+ const part = parts.find((p) => p.type === "tool-call" && p.id === toolCallId);
5203
+ 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;
5204
+ const input = part.input ?? parseToolArguments(part.arguments);
5205
+ if (input === void 0) {
5206
+ console.warn(`[StreamProcessor] Did not run tool call ${toolCallId}: the arguments of ${part.name} are not complete JSON`);
5207
+ continue;
5208
+ }
5209
+ this.toolCallsSentToClient.add(toolCallId);
5210
+ this.events.onToolCall?.({
5211
+ toolCallId,
5212
+ toolName: part.name,
5213
+ input
5214
+ });
5215
+ }
5216
+ }
5217
+ /**
4130
5218
  * Apply interrupt state to tool-call parts, then fire the client events.
4131
5219
  * A child's interrupt updates the child's card. `emit` is false there, so
4132
5220
  * the events fire once, from the top processor.
@@ -4168,6 +5256,7 @@ var StreamProcessor = class StreamProcessor {
4168
5256
  }
4169
5257
  if (kind === "client_tool" || interrupt.reason === "client_tool_input") {
4170
5258
  if (hasGeneric || !emit) continue;
5259
+ this.toolCallsSentToClient.add(toolCallId);
4171
5260
  this.events.onToolCall?.({
4172
5261
  toolCallId,
4173
5262
  toolName,
@@ -4228,6 +5317,24 @@ var StreamProcessor = class StreamProcessor {
4228
5317
  this.pendingThinkingStepId = stepId;
4229
5318
  }
4230
5319
  /**
5320
+ * Handle ACTIVITY_SNAPSHOT. Creates or replaces a frontend-only activity
5321
+ * message. Does not create MessageStreamState (that path feeds
5322
+ * ProcessorResult.content).
5323
+ */
5324
+ handleActivitySnapshotEvent(chunk) {
5325
+ this.messages = applyActivitySnapshotToUIMessages(this.messages, chunk);
5326
+ this.emitMessagesChange();
5327
+ }
5328
+ /**
5329
+ * Handle ACTIVITY_DELTA. Applies RFC 6902 patches to an existing activity
5330
+ * `content`. Missing or non-activity ids are no-ops. Patch failure leaves
5331
+ * the previous content in place.
5332
+ */
5333
+ handleActivityDeltaEvent(chunk) {
5334
+ this.messages = applyActivityDeltaToUIMessages(this.messages, chunk);
5335
+ this.emitMessagesChange();
5336
+ }
5337
+ /**
4231
5338
  * Handle STEP_FINISHED event.
4232
5339
  *
4233
5340
  * Thinking *content* comes from REASONING_MESSAGE_CONTENT, not STEP_FINISHED.
@@ -4256,6 +5363,7 @@ var StreamProcessor = class StreamProcessor {
4256
5363
  */
4257
5364
  handleReasoningMessageContentEvent(chunk) {
4258
5365
  const { messageId, state } = this.ensureAssistantMessage(this.getActiveAssistantMessageId() ?? void 0);
5366
+ this.mergeMessageMetadata(messageId, chunk.metadata);
4259
5367
  state.hasSeenReasoningEvents = true;
4260
5368
  const delta = chunk.delta || "";
4261
5369
  this.consumePendingThinkingStep(state);
@@ -4368,6 +5476,7 @@ var StreamProcessor = class StreamProcessor {
4368
5476
  }
4369
5477
  if (chunk.name === "tool-input-available" && chunk.value) {
4370
5478
  const { toolCallId, toolName, input } = chunk.value;
5479
+ this.toolCallsSentToClient.add(toolCallId);
4371
5480
  this.events.onToolCall?.({
4372
5481
  toolCallId,
4373
5482
  toolName,
@@ -4546,6 +5655,8 @@ var StreamProcessor = class StreamProcessor {
4546
5655
  */
4547
5656
  finalizeStream() {
4548
5657
  this.isDone = true;
5658
+ for (const event of this.closeChunk()) this.dispatchChunk(event);
5659
+ this.closeChildChunkLanes();
4549
5660
  let lastAssistantMessage;
4550
5661
  for (const messageId of this.activeMessageIds) {
4551
5662
  const state = this.getMessageState(messageId);
@@ -4663,6 +5774,7 @@ var StreamProcessor = class StreamProcessor {
4663
5774
  this.structuredOutputUpdateBatches.clear();
4664
5775
  this.pendingManualMessageId = null;
4665
5776
  this.pendingThinkingStepId = null;
5777
+ this.openChunk = null;
4666
5778
  this.finishReason = null;
4667
5779
  this.hasError = false;
4668
5780
  this.isDone = false;
@@ -4702,14 +5814,14 @@ function createReplayStream(recording) {
4702
5814
  } };
4703
5815
  }
4704
5816
  //#endregion
4705
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/providers.js
5817
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/byok/providers.js
4706
5818
  /** `[a-z][a-z0-9-]{0,63}` — lowercase, no underscores, max 64 chars. */
4707
5819
  var BYOK_PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
4708
5820
  function isProviderId(value) {
4709
5821
  return typeof value === "string" && BYOK_PROVIDER_ID_PATTERN.test(value);
4710
5822
  }
4711
5823
  //#endregion
4712
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/missing.js
5824
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/byok/missing.js
4713
5825
  function isByokMissingBody(value) {
4714
5826
  if (typeof value !== "object" || value === null) return false;
4715
5827
  if (!("error" in value)) return false;
@@ -4722,7 +5834,7 @@ function isByokMissingBody(value) {
4722
5834
  return true;
4723
5835
  }
4724
5836
  //#endregion
4725
- //#region node_modules/.deno/@tanstack+ai@0.64.0/node_modules/@tanstack/ai/dist/esm/byok/errors.js
5837
+ //#region node_modules/.deno/@tanstack+ai@0.68.0/node_modules/@tanstack/ai/dist/esm/byok/errors.js
4726
5838
  var ByokMissingError = class extends Error {
4727
5839
  provider;
4728
5840
  constructor(provider) {
@@ -4748,7 +5860,7 @@ var ByokUnresolvedProviderError = class extends Error {
4748
5860
  }
4749
5861
  };
4750
5862
  //#endregion
4751
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
5863
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/connection-adapters.js
4752
5864
  /**
4753
5865
  * Associates connect-wrapped chunks with the run they were produced under.
4754
5866
  * Content events (TEXT_MESSAGE_CONTENT, TOOL_CALL_*, …) carry no `runId` of
@@ -4941,6 +6053,9 @@ async function* readStreamLines(reader, abortSignal) {
4941
6053
  buffer += decoder.decode();
4942
6054
  if (buffer.trim() && !abortSignal?.aborted) throw new StreamTruncatedError();
4943
6055
  } finally {
6056
+ try {
6057
+ reader.cancel().catch(() => {});
6058
+ } catch {}
4944
6059
  reader.releaseLock();
4945
6060
  }
4946
6061
  }
@@ -5443,7 +6558,7 @@ async function* abortableIterable(iterable, signal) {
5443
6558
  }
5444
6559
  }
5445
6560
  //#endregion
5446
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/interrupt-manager.js
6561
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/interrupt-manager.js
5447
6562
  function isClientOwnedInterrupt(item) {
5448
6563
  return item.resumable;
5449
6564
  }
@@ -6385,7 +7500,7 @@ var InterruptManager = class {
6385
7500
  }
6386
7501
  };
6387
7502
  //#endregion
6388
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/byok/client.js
7503
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/byok/client.js
6389
7504
  var registeredProviderIds = /* @__PURE__ */ new WeakMap();
6390
7505
  /**
6391
7506
  * Provider to stamp when the caller did not pass a slug.
@@ -6398,7 +7513,7 @@ function byokFallbackProviderId(byok) {
6398
7513
  if (registered.length === 1) return registered[0];
6399
7514
  }
6400
7515
  //#endregion
6401
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/byok/resolve.js
7516
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/byok/resolve.js
6402
7517
  function resolveByokProviderId(byokProvider, ...candidates) {
6403
7518
  const fromFn = byokProvider?.();
6404
7519
  if (isProviderId(fromFn)) return fromFn;
@@ -6414,7 +7529,7 @@ async function prepareResolvedByokHeaders(byok, provider) {
6414
7529
  return byok.headers(provider);
6415
7530
  }
6416
7531
  //#endregion
6417
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/events.js
7532
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/events.js
6418
7533
  /**
6419
7534
  * Abstract base class for ChatClient event emission
6420
7535
  */
@@ -6588,7 +7703,7 @@ var ChatClientEventEmitter = class {
6588
7703
  }
6589
7704
  };
6590
7705
  //#endregion
6591
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/devtools-noop.js
7706
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/devtools-noop.js
6592
7707
  var NoOpChatClientEventEmitter = class extends ChatClientEventEmitter {
6593
7708
  emitEvent() {}
6594
7709
  };
@@ -6633,7 +7748,7 @@ var NoOpChatDevtoolsBridge = class {
6633
7748
  };
6634
7749
  var createNoOpChatDevtoolsBridge = (options) => new NoOpChatDevtoolsBridge(options);
6635
7750
  //#endregion
6636
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/client-persistor.js
7751
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/client-persistor.js
6637
7752
  /** Normalize a raw `getItem` result (legacy bare array or combined record). */
6638
7753
  function normalizePersistedState(raw) {
6639
7754
  if (Array.isArray(raw)) return { messages: raw };
@@ -6732,12 +7847,13 @@ var ChatPersistor = class {
6732
7847
  }
6733
7848
  /**
6734
7849
  * Apply state from an async `getItem` once it resolves, unless the message
6735
- * list has already changed since hydration began.
7850
+ * list has already changed since hydration began. Returns a promise that
7851
+ * settles (never rejects) when it is done, or `undefined` for sync state.
6736
7852
  */
6737
7853
  hydrateAsync(persistedState) {
6738
7854
  if (!(persistedState instanceof Promise)) return;
6739
7855
  const hydrationGeneration = this.messagesGeneration;
6740
- persistedState.then((state) => {
7856
+ return persistedState.then((state) => {
6741
7857
  if (!state || this.messagesGeneration !== hydrationGeneration) return;
6742
7858
  this.lastResume = state.resume ?? null;
6743
7859
  this.lastMessages = state.messages;
@@ -6893,11 +8009,11 @@ var ChatPersistor = class {
6893
8009
  isRunlessChunkFromIgnoredRun(chunk) {
6894
8010
  if (getChunkRunId$1(chunk) || !this.currentRunlessRunId) return false;
6895
8011
  if (!this.ignoredActiveRunIds.has(this.currentRunlessRunId) && !this.clearedRunIds.has(this.currentRunlessRunId)) return false;
6896
- return chunk.type === "TEXT_MESSAGE_START" || chunk.type === "TEXT_MESSAGE_CONTENT" || chunk.type === "TOOL_CALL_START" || chunk.type === "TOOL_CALL_ARGS" || chunk.type === "TOOL_CALL_END" || chunk.type === "TOOL_CALL_RESULT" || chunk.type === "MESSAGES_SNAPSHOT" || chunk.type === "RUN_ERROR";
8012
+ return chunk.type === "TEXT_MESSAGE_START" || chunk.type === "TEXT_MESSAGE_CONTENT" || chunk.type === "TEXT_MESSAGE_CHUNK" || chunk.type === "TOOL_CALL_START" || chunk.type === "TOOL_CALL_ARGS" || chunk.type === "TOOL_CALL_END" || chunk.type === "TOOL_CALL_RESULT" || chunk.type === "TOOL_CALL_CHUNK" || chunk.type === "MESSAGES_SNAPSHOT" || chunk.type === "RUN_ERROR";
6897
8013
  }
6898
8014
  };
6899
8015
  //#endregion
6900
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/cleared-stream-tracker.js
8016
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/cleared-stream-tracker.js
6901
8017
  function getChunkToolCallId(chunk) {
6902
8018
  return "toolCallId" in chunk && typeof chunk.toolCallId === "string" ? chunk.toolCallId : void 0;
6903
8019
  }
@@ -6986,11 +8102,11 @@ var ClearedStreamTracker = class {
6986
8102
  isRunlessChunkFromIgnoredRun(chunk) {
6987
8103
  if (getChunkRunId$1(chunk) || !this.currentRunlessRunId) return false;
6988
8104
  if (!this.ignoredActiveRunIds.has(this.currentRunlessRunId) && !this.clearedRunIds.has(this.currentRunlessRunId)) return false;
6989
- return chunk.type === "TEXT_MESSAGE_START" || chunk.type === "TEXT_MESSAGE_CONTENT" || chunk.type === "TOOL_CALL_START" || chunk.type === "TOOL_CALL_ARGS" || chunk.type === "TOOL_CALL_END" || chunk.type === "TOOL_CALL_RESULT" || chunk.type === "MESSAGES_SNAPSHOT" || chunk.type === "RUN_ERROR";
8105
+ return chunk.type === "TEXT_MESSAGE_START" || chunk.type === "TEXT_MESSAGE_CONTENT" || chunk.type === "TEXT_MESSAGE_CHUNK" || chunk.type === "TOOL_CALL_START" || chunk.type === "TOOL_CALL_ARGS" || chunk.type === "TOOL_CALL_END" || chunk.type === "TOOL_CALL_RESULT" || chunk.type === "TOOL_CALL_CHUNK" || chunk.type === "MESSAGES_SNAPSHOT" || chunk.type === "RUN_ERROR";
6990
8106
  }
6991
8107
  };
6992
8108
  //#endregion
6993
- //#region node_modules/.deno/@tanstack+ai-client@0.36.1/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
8109
+ //#region node_modules/.deno/@tanstack+ai-client@0.39.2/node_modules/@tanstack/ai-client/dist/esm/chat-client.js
6994
8110
  var STREAM_PROCESSING_BUDGET_MS = 8;
6995
8111
  function yieldToHost() {
6996
8112
  const { scheduler } = globalThis;
@@ -7126,8 +8242,11 @@ var REJOIN_CONNECT_DEADLINE_MS = 2e3;
7126
8242
  var REJOIN_REBUILD_TRIGGERS = /* @__PURE__ */ new Set([
7127
8243
  "TEXT_MESSAGE_START",
7128
8244
  "TEXT_MESSAGE_CONTENT",
8245
+ "TEXT_MESSAGE_CHUNK",
7129
8246
  "REASONING_MESSAGE_CONTENT",
8247
+ "REASONING_MESSAGE_CHUNK",
7130
8248
  "TOOL_CALL_START",
8249
+ "TOOL_CALL_CHUNK",
7131
8250
  "MESSAGES_SNAPSHOT",
7132
8251
  "SUBAGENT_STARTED"
7133
8252
  ]);
@@ -7231,6 +8350,7 @@ var ChatClient = class {
7231
8350
  currentMessageId = null;
7232
8351
  postStreamActions = [];
7233
8352
  pendingToolExecutions = /* @__PURE__ */ new Map();
8353
+ handingOverPendingToolCalls = false;
7234
8354
  activeClientTools = null;
7235
8355
  activeContext = void 0;
7236
8356
  continuationPending = false;
@@ -7256,6 +8376,12 @@ var ChatClient = class {
7256
8376
  hydrationError;
7257
8377
  /** Whether a view is currently watching. See `attach` / `detach`. */
7258
8378
  tailing = false;
8379
+ /** `historyGeneration` of the mount hydration GET still in flight, if any. */
8380
+ hydrationInFlight;
8381
+ /** An async storage adapter is still reading the persisted transcript. */
8382
+ storeHydrating = false;
8383
+ /** See {@link getIsHydrating}. */
8384
+ isHydrating = false;
7259
8385
  /** Constructor inputs `attach()` needs on every re-attach, not just the first. */
7260
8386
  rejoinRunId;
7261
8387
  cachesMessages;
@@ -7310,6 +8436,7 @@ var ChatClient = class {
7310
8436
  onSubscriptionChange: options.onSubscriptionChange || (() => {}),
7311
8437
  onConnectionStatusChange: options.onConnectionStatusChange || (() => {}),
7312
8438
  onSessionGeneratingChange: options.onSessionGeneratingChange || (() => {}),
8439
+ onHydratingChange: options.onHydratingChange || (() => {}),
7313
8440
  onQueueChange: options.onQueueChange || (() => {}),
7314
8441
  onResumeStateChange: options.onResumeStateChange || (() => {}),
7315
8442
  onRunIdChange: options.onRunIdChange || (() => {}),
@@ -7391,6 +8518,10 @@ var ChatClient = class {
7391
8518
  onToolCall: (args) => {
7392
8519
  const clientTool = (this.activeClientTools ?? this.clientToolsRef.current).get(args.toolName);
7393
8520
  const executeFunc = clientTool?.execute;
8521
+ if (this.handingOverPendingToolCalls && clientTool?.needsApproval === true) {
8522
+ console.warn(`[ChatClient] Did not run tool call ${args.toolCallId}: ${args.toolName} needs approval, and the server did not ask for it`);
8523
+ return;
8524
+ }
7394
8525
  if (executeFunc) {
7395
8526
  const continuationGeneration = this.continuationGeneration;
7396
8527
  const runEventContext = this.devtoolsBridge.getCurrentRunEventContext();
@@ -7437,9 +8568,17 @@ var ChatClient = class {
7437
8568
  }
7438
8569
  });
7439
8570
  this.syncSubagentHandles();
7440
- this.persistor?.hydrateAsync(persistedState);
8571
+ const storeHydration = this.persistor?.hydrateAsync(persistedState);
8572
+ if (storeHydration) {
8573
+ this.storeHydrating = true;
8574
+ storeHydration.finally(() => {
8575
+ this.storeHydrating = false;
8576
+ this.syncIsHydrating();
8577
+ });
8578
+ }
7441
8579
  this.rejoinRunId = rejoinRunId;
7442
8580
  this.cachesMessages = cachesMessages;
8581
+ this.isHydrating = this.storeHydrating || !cachesMessages && !!this.connection.hydrate;
7443
8582
  }
7444
8583
  /**
7445
8584
  * START TAILING: re-attach to an in-flight run so its chunks arrive here.
@@ -7542,21 +8681,30 @@ var ChatClient = class {
7542
8681
  */
7543
8682
  hydrateFromServer() {
7544
8683
  const hydrate = this.connection.hydrate;
7545
- if (!hydrate) return;
7546
- if (this.isLoading || this.abortController) return;
7547
- if (this.disposed) return;
8684
+ if (!hydrate || this.isLoading || this.abortController || this.disposed) {
8685
+ this.syncIsHydrating();
8686
+ return;
8687
+ }
8688
+ if (this.hydrationInFlight === this.historyGeneration) return;
7548
8689
  const pageSize = this.historyPageSize;
7549
8690
  const hydrateOptions = pageSize === void 0 ? void 0 : { limit: pageSize };
7550
8691
  (async () => {
7551
8692
  let result;
7552
8693
  const generation = this.historyGeneration;
8694
+ this.hydrationInFlight = generation;
8695
+ this.syncIsHydrating();
8696
+ const isCurrent = () => this.hydrationInFlight === generation && generation === this.historyGeneration;
8697
+ let current;
7553
8698
  try {
7554
8699
  result = await hydrate(this.threadId, hydrateOptions);
7555
8700
  } catch (cause) {
7556
- if (generation === this.historyGeneration) this.failHydration(cause);
8701
+ if (isCurrent()) this.failHydration(cause);
7557
8702
  return;
8703
+ } finally {
8704
+ current = isCurrent();
8705
+ if (this.hydrationInFlight === generation) this.hydrationInFlight = void 0;
7558
8706
  }
7559
- if (generation !== this.historyGeneration) return;
8707
+ if (!current) return;
7560
8708
  if (this.disposed || !this.tailing) return;
7561
8709
  if (this.isLoading || this.abortController) return;
7562
8710
  if (this.hydrationError && this.error === this.hydrationError) {
@@ -7578,7 +8726,7 @@ var ChatClient = class {
7578
8726
  pendingInterrupts: result.interrupts.pending
7579
8727
  });
7580
8728
  else if (result.activeRun?.runId) this.maybeRejoinInFlight(result.activeRun.runId);
7581
- })();
8729
+ })().finally(() => this.syncIsHydrating());
7582
8730
  }
7583
8731
  /**
7584
8732
  * Surface a mount-hydration failure (`persistence: true`) on the observable
@@ -7847,6 +8995,17 @@ var ChatClient = class {
7847
8995
  this.isLoading = isLoading;
7848
8996
  this.callbacksRef.current.onLoadingChange(isLoading);
7849
8997
  this.events.loadingChanged(isLoading);
8998
+ if (isLoading) this.supersedeHydration();
8999
+ }
9000
+ /**
9001
+ * A send or a clear now owns the transcript. A load that is still pending can
9002
+ * no longer paint it (the generation guards drop its result), so it no longer
9003
+ * counts as hydrating.
9004
+ */
9005
+ supersedeHydration() {
9006
+ this.hydrationInFlight = void 0;
9007
+ this.storeHydrating = false;
9008
+ this.syncIsHydrating();
7850
9009
  }
7851
9010
  setStatus(status) {
7852
9011
  this.status = status;
@@ -7863,6 +9022,12 @@ var ChatClient = class {
7863
9022
  this.callbacksRef.current.onConnectionStatusChange(status);
7864
9023
  this.devtoolsBridge.emitSnapshot();
7865
9024
  }
9025
+ syncIsHydrating() {
9026
+ const isHydrating = this.hydrationInFlight !== void 0 || this.storeHydrating;
9027
+ if (this.isHydrating === isHydrating) return;
9028
+ this.isHydrating = isHydrating;
9029
+ this.callbacksRef.current.onHydratingChange(isHydrating);
9030
+ }
7866
9031
  setSessionGenerating(isGenerating) {
7867
9032
  if (this.sessionGenerating === isGenerating) return;
7868
9033
  this.sessionGenerating = isGenerating;
@@ -8128,7 +9293,12 @@ var ChatClient = class {
8128
9293
  this.resolveJoinedRun(chunk);
8129
9294
  return;
8130
9295
  }
8131
- this.processor.processChunk(chunk);
9296
+ this.handingOverPendingToolCalls = chunk.type === "RUN_FINISHED" && chunk.outcome?.type !== "interrupt";
9297
+ try {
9298
+ this.processor.processChunk(chunk);
9299
+ } finally {
9300
+ this.handingOverPendingToolCalls = false;
9301
+ }
8132
9302
  this.syncSubagentHandles();
8133
9303
  this.updateRunLifecycle(chunk);
8134
9304
  this.observeInterruptState(chunk);
@@ -8351,6 +9521,14 @@ var ChatClient = class {
8351
9521
  if (this.hasPendingInterrupts()) throw new Error("ChatClient: cannot append normal input while pending interrupts exist. Use resumeInterrupts() instead.");
8352
9522
  const normalizedMessage = normalizeToUIMessage(message, generateMessageId);
8353
9523
  if (normalizedMessage.role === "system") return;
9524
+ if (normalizedMessage.role === "activity") {
9525
+ const uiMessage = normalizedMessage;
9526
+ this.events.messageAppended(uiMessage);
9527
+ const messages = this.processor.getMessages();
9528
+ this.processor.setMessages([...messages, uiMessage]);
9529
+ this.devtoolsBridge.emitSnapshot();
9530
+ return;
9531
+ }
8354
9532
  const uiMessage = normalizedMessage;
8355
9533
  this.events.messageAppended(uiMessage);
8356
9534
  const messages = this.processor.getMessages();
@@ -8567,6 +9745,7 @@ var ChatClient = class {
8567
9745
  this.persistor?.beginClear();
8568
9746
  this.processor.clearMessages();
8569
9747
  this.resetHistoryPaging();
9748
+ this.supersedeHydration();
8570
9749
  this.discardPendingSends();
8571
9750
  this.persistor?.remove();
8572
9751
  this.stoppedSubagentIds.clear();
@@ -8825,16 +10004,17 @@ var ChatClient = class {
8825
10004
  this.rememberServerMessageIds(this.processor.getMessages());
8826
10005
  }
8827
10006
  messagesForSend(messages) {
8828
- if (this.historyPageSize === void 0) return messages;
10007
+ const forModel = messages.filter((message) => message.role !== "activity");
10008
+ if (this.historyPageSize === void 0) return forModel;
8829
10009
  const unknownMessages = [];
8830
- for (const message of messages) {
10010
+ for (const message of forModel) {
8831
10011
  if (this.knownServerMessageIds.has(message.id)) continue;
8832
10012
  unknownMessages.push(message);
8833
10013
  }
8834
10014
  if (unknownMessages.length > 0) return unknownMessages;
8835
- const lastUserIndex = messages.findLastIndex((message) => message.role === "user");
10015
+ const lastUserIndex = forModel.findLastIndex((message) => message.role === "user");
8836
10016
  if (lastUserIndex === -1) return [];
8837
- return messages.slice(lastUserIndex);
10017
+ return forModel.slice(lastUserIndex);
8838
10018
  }
8839
10019
  /**
8840
10020
  * True when an interrupt (or another direct send) claimed the client during
@@ -8956,6 +10136,15 @@ var ChatClient = class {
8956
10136
  return this.sessionGenerating;
8957
10137
  }
8958
10138
  /**
10139
+ * Whether the client is rebuilding the chat from persistence: the server
10140
+ * hydrate (`persistence: true`) or an async storage adapter. Turns false once
10141
+ * the transcript is applied and any in-flight run is re-joined (from then on
10142
+ * `isLoading` covers the stream), or when the load fails.
10143
+ */
10144
+ getIsHydrating() {
10145
+ return this.isHydrating;
10146
+ }
10147
+ /**
8959
10148
  * Get current error
8960
10149
  */
8961
10150
  getError() {
@@ -9006,6 +10195,7 @@ var ChatClient = class {
9006
10195
  if (options.onSubscriptionChange !== void 0) this.callbacksRef.current.onSubscriptionChange = options.onSubscriptionChange;
9007
10196
  if (options.onConnectionStatusChange !== void 0) this.callbacksRef.current.onConnectionStatusChange = options.onConnectionStatusChange;
9008
10197
  if (options.onSessionGeneratingChange !== void 0) this.callbacksRef.current.onSessionGeneratingChange = options.onSessionGeneratingChange;
10198
+ if (options.onHydratingChange !== void 0) this.callbacksRef.current.onHydratingChange = options.onHydratingChange;
9009
10199
  if (options.onQueueChange !== void 0) this.callbacksRef.current.onQueueChange = options.onQueueChange;
9010
10200
  if (options.onResumeStateChange !== void 0) this.callbacksRef.current.onResumeStateChange = options.onResumeStateChange;
9011
10201
  if (options.onRunIdChange !== void 0) this.callbacksRef.current.onRunIdChange = options.onRunIdChange;
@@ -9332,6 +10522,7 @@ async function loadChatAuthToken(options) {
9332
10522
  } catch (cause) {
9333
10523
  signal.throwIfAborted();
9334
10524
  const error = cause instanceof Error ? cause : /* @__PURE__ */ new Error("Authentication failed");
10525
+ if (isAstralBeamApiError(error) && error.status === 401) error.message = "AstralBeam rejected the chat token after renewal. Check that apiUrl matches the deployment that issued your API key. If the key was revoked or expired, create a replacement in API Keys and update your server's secret.";
9335
10526
  session.cached = void 0;
9336
10527
  publishAuthentication(options, {
9337
10528
  status: "error",
@@ -9463,6 +10654,11 @@ function hasPendingToolRun(messages, toolNames) {
9463
10654
  return messages.some((message) => message.parts.some((part) => part.type === "tool-call" && !isSettledToolCall(part) && part.name !== "ask_questionnaire" && toolNames.has(part.name)));
9464
10655
  }
9465
10656
  //#endregion
10657
+ //#region src/core/web.ts
10658
+ function webPartMetadata(part) {
10659
+ return part.metadata ?? {};
10660
+ }
10661
+ //#endregion
9466
10662
  //#region src/core/sandbox.ts
9467
10663
  const SANDBOX_TOOLS = [
9468
10664
  SANDBOX_WRITE_FILE_TOOL,
@@ -9513,19 +10709,19 @@ function sandboxPathLabel(part) {
9513
10709
  if (relative !== void 0 && relative !== ".") return relative;
9514
10710
  return text(part.output, "path") ?? text(part.input, "path");
9515
10711
  }
9516
- /** A `sandbox_publish_artifact` call whose output carries the download ticket. */
10712
+ /** A `sandbox_publish_artifact` call whose output carries a durable file reference. */
9517
10713
  function readSandboxArtifact(part) {
9518
10714
  if (part.name !== "sandbox_publish_artifact") return void 0;
9519
10715
  const path = text(part.output, "path") ?? text(part.input, "path");
9520
- const ticket = text(part.output, "ticket");
10716
+ const fileId = text(part.output, "fileId");
9521
10717
  return {
9522
10718
  toolCallId: part.id,
9523
10719
  path: path ?? "",
9524
10720
  label: sandboxPathLabel(part) ?? path ?? "",
9525
10721
  mimeType: text(part.output, "mimeType"),
9526
10722
  size: count(part.output, "size"),
9527
- ticket,
9528
- published: ticket !== void 0 && sandboxRefusal(part) === void 0
10723
+ fileId,
10724
+ published: fileId !== void 0 && sandboxRefusal(part) === void 0
9529
10725
  };
9530
10726
  }
9531
10727
  /** A `sandbox_run_command` call. `stdout` holds combined output on providers with no stderr. */
@@ -9627,6 +10823,10 @@ function projectThreadMessages(records, pendingInteractions = [], liveToolMessag
9627
10823
  const call = calls.get(savedToolCallId(message.source_assistant_message_id, message.source_tool_part_id, message.response_target_id));
9628
10824
  if (!call) continue;
9629
10825
  call.output = part.output ?? null;
10826
+ if (call.name === "sandbox_publish_artifact") {
10827
+ call.artifactMessageId = message.id;
10828
+ call.artifactPartId = String(part.id);
10829
+ }
9630
10830
  Object.assign(call, { resultOutcome: part.outcome });
9631
10831
  call.state = part.outcome === "succeeded" ? "complete" : "error";
9632
10832
  }
@@ -9634,7 +10834,12 @@ function projectThreadMessages(records, pendingInteractions = [], liveToolMessag
9634
10834
  }
9635
10835
  const parts = message.parts.flatMap((part) => {
9636
10836
  const source = part.source;
9637
- if ((part.type === "image" || part.type === "document") && source && typeof source === "object" && !Array.isArray(source) && "type" in source && source.type === "attachment") return [{
10837
+ if (typeof part.type === "string" && [
10838
+ "image",
10839
+ "document",
10840
+ "audio",
10841
+ "video"
10842
+ ].includes(part.type) && source && typeof source === "object" && !Array.isArray(source) && "type" in source && source.type === "attachment") return [{
9638
10843
  ...part,
9639
10844
  source: {
9640
10845
  ...source,
@@ -9644,6 +10849,7 @@ function projectThreadMessages(records, pendingInteractions = [], liveToolMessag
9644
10849
  savedAttachmentId: part.id
9645
10850
  }];
9646
10851
  if (part.type !== "tool-call") return [part];
10852
+ if (part.executionLocation === "provider") return [part];
9647
10853
  const toolCallId = String(part.toolCallId);
9648
10854
  const targets = Array.isArray(part.targets) ? part.targets.flatMap((target) => target && typeof target === "object" && !Array.isArray(target) && "id" in target && typeof target.id === "string" ? [target.id] : []) : pendingInteractions.filter((pending) => pending.sourceMessageId === message.id && pending.sourcePartId === part.id).map((pending) => pending.responseTargetId);
9649
10855
  return (targets.length ? targets : [void 0]).map((responseTargetId) => {
@@ -9714,6 +10920,7 @@ function createAstralBeamChat(options, deferStart = false) {
9714
10920
  capabilities: { attachments: true },
9715
10921
  agentTools: [],
9716
10922
  sandboxStatus: void 0,
10923
+ usageLimitReached: void 0,
9717
10924
  sandbox: {
9718
10925
  files: [],
9719
10926
  commands: []
@@ -9764,6 +10971,14 @@ function createAstralBeamChat(options, deferStart = false) {
9764
10971
  } });
9765
10972
  pendingSend.callbacks?.onAccepted?.();
9766
10973
  };
10974
+ const replaceAcceptedMessage = (record) => {
10975
+ const messages = [...client.getMessages()];
10976
+ const index = messages.findLastIndex((message) => message.role === "user");
10977
+ if (index !== -1) {
10978
+ messages[index] = projectThreadMessages([record])[0];
10979
+ client.setMessagesManually(messages);
10980
+ }
10981
+ };
9767
10982
  const liveToolCalls = /* @__PURE__ */ new Set();
9768
10983
  const liveToolMessageIds = /* @__PURE__ */ new Map();
9769
10984
  const historicalToolIds = /* @__PURE__ */ new Map();
@@ -9793,17 +11008,19 @@ function createAstralBeamChat(options, deferStart = false) {
9793
11008
  error: failure,
9794
11009
  status: "error"
9795
11010
  });
9796
- live.streamCallbacks?.onError?.(failure);
11011
+ if (state.auth.status !== "error" || state.auth.error !== failure) live.streamCallbacks?.onError?.(failure);
9797
11012
  };
9798
- const requestOptions = async () => {
11013
+ const requestOptions = async (conversation = true) => {
9799
11014
  const generation = selectionGeneration;
11015
+ const authSignal = authentication.session.abortController.signal;
9800
11016
  const token = await getValidChatAuthToken(authentication);
9801
- if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
11017
+ authSignal.throwIfAborted();
11018
+ if (conversation && generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
9802
11019
  return {
9803
11020
  apiUrl: authentication.apiUrl,
9804
11021
  astralBeamToken: token,
9805
11022
  cache: "no-store",
9806
- signal: AbortSignal.any([requestController.signal, authentication.session.abortController.signal]),
11023
+ signal: conversation ? AbortSignal.any([requestController.signal, authSignal]) : authSignal,
9807
11024
  fetchClient: (input, init) => fetchAuthenticatedChat({
9808
11025
  ...authentication,
9809
11026
  input,
@@ -10007,6 +11224,11 @@ function createAstralBeamChat(options, deferStart = false) {
10007
11224
  headers,
10008
11225
  body: JSON.stringify(payload)
10009
11226
  }).catch((error) => {
11227
+ const limit = isAstralBeamApiError(error) ? error.body?.usage_limit : void 0;
11228
+ if (limit) update({ usageLimitReached: {
11229
+ name: limit.name,
11230
+ resetsAt: limit.resets_at
11231
+ } });
10010
11232
  if (submission && !previouslyAttempted && isAstralBeamApiError(error) && (error.status === 400 || error.status === 413 || error.status === 429)) delete submission.tools;
10011
11233
  throw error;
10012
11234
  });
@@ -10014,11 +11236,23 @@ function createAstralBeamChat(options, deferStart = false) {
10014
11236
  if (response.headers.get("Content-Type")?.includes("application/json")) {
10015
11237
  const receipt = await response.json();
10016
11238
  if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
10017
- update({ thread: {
10018
- ...state.thread,
10019
- version: receipt.thread_version
10020
- } });
10021
- if (submission) acceptPendingSend();
11239
+ update({
11240
+ thread: {
11241
+ ...state.thread,
11242
+ version: receipt.thread_version
11243
+ },
11244
+ ...receipt.usage_limit ? { usageLimitReached: {
11245
+ name: receipt.usage_limit.name,
11246
+ resetsAt: receipt.usage_limit.resets_at
11247
+ } } : {}
11248
+ });
11249
+ if (submission) {
11250
+ const history = await loadThreadMessages(thread.id, auth, void 0, liveToolMessageIds);
11251
+ if (generation !== selectionGeneration) throw new DOMException("Conversation changed", "AbortError");
11252
+ const accepted = history.messages.find((message) => message.id === receipt.accepted_message_id);
11253
+ if (accepted) replaceAcceptedMessage(accepted);
11254
+ acceptPendingSend();
11255
+ }
10022
11256
  return new Response("", { headers: { "Content-Type": "text/event-stream" } });
10023
11257
  }
10024
11258
  return response;
@@ -10143,6 +11377,11 @@ function createAstralBeamChat(options, deferStart = false) {
10143
11377
  onMessagesChange: (messages) => {
10144
11378
  if (client !== next || generation !== selectionGeneration) return;
10145
11379
  restoreCompletedWidgets(messages);
11380
+ for (const message of messages) {
11381
+ if (message.role !== "user") continue;
11382
+ const saved = state.messages.find((previous) => previous.id === message.id);
11383
+ if (saved?.parts.some((part) => "savedAttachmentId" in part)) message.parts = saved.parts;
11384
+ }
10146
11385
  update({
10147
11386
  messages,
10148
11387
  sandbox: collectSandboxActivity(messages),
@@ -10152,7 +11391,8 @@ function createAstralBeamChat(options, deferStart = false) {
10152
11391
  onStatusChange: (status) => {
10153
11392
  if (client === next && generation === selectionGeneration) update({
10154
11393
  status,
10155
- error: next.getError()
11394
+ error: next.getError(),
11395
+ ...status === "submitted" ? { usageLimitReached: void 0 } : {}
10156
11396
  });
10157
11397
  },
10158
11398
  onInterruptStateChange: (interrupts) => {
@@ -10163,6 +11403,7 @@ function createAstralBeamChat(options, deferStart = false) {
10163
11403
  if (eventType === "astralbeam_thread") {
10164
11404
  const event = data;
10165
11405
  if (state.thread?.id === event.threadId) {
11406
+ if (event.acceptedMessage && pendingSend && !pendingSend.accepted) replaceAcceptedMessage(event.acceptedMessage);
10166
11407
  if (event.acceptedMessageId) acceptPendingSend();
10167
11408
  if (event.saved) for (const id of event.executableToolCallIds ?? []) {
10168
11409
  if (!liveToolCalls.has(id)) toolResults.delete(toolResultKey(id));
@@ -10179,6 +11420,14 @@ function createAstralBeamChat(options, deferStart = false) {
10179
11420
  }
10180
11421
  return;
10181
11422
  }
11423
+ const limit = data;
11424
+ if (eventType === "astralbeam.usage_limit.reached" && typeof limit?.name === "string" && typeof limit.resetsAt === "string") {
11425
+ update({ usageLimitReached: {
11426
+ name: limit.name,
11427
+ resetsAt: limit.resetsAt
11428
+ } });
11429
+ return;
11430
+ }
10182
11431
  const value = data?.state;
10183
11432
  if (eventType === "astralbeam.sandbox.status" && (value === "starting" || value === "ready" || value === "error")) {
10184
11433
  debug?.("sandbox", `sandbox ${value}`);
@@ -10198,7 +11447,7 @@ function createAstralBeamChat(options, deferStart = false) {
10198
11447
  if (client === next) live.streamCallbacks?.onFinish?.(message);
10199
11448
  },
10200
11449
  onError: (error) => {
10201
- if (client === next) live.streamCallbacks?.onError?.(error);
11450
+ if (client === next && (state.auth.status !== "error" || state.auth.error !== error)) live.streamCallbacks?.onError?.(error);
10202
11451
  }
10203
11452
  });
10204
11453
  return next;
@@ -10220,7 +11469,7 @@ function createAstralBeamChat(options, deferStart = false) {
10220
11469
  client.setMessagesManually(state.messages.map((message) => {
10221
11470
  const aliases = /* @__PURE__ */ new Map();
10222
11471
  const parts = message.parts.map((part) => {
10223
- if (part.type !== "tool-call") return part;
11472
+ if (part.type !== "tool-call" || webPartMetadata(part).providerExecuted) return part;
10224
11473
  const stored = part;
10225
11474
  const upstreamToolCallId = stored.upstreamToolCallId ?? part.id;
10226
11475
  if (liveToolMessageIds.get(upstreamToolCallId) === message.id && !isSettledToolCall(part)) return part;
@@ -10268,6 +11517,7 @@ function createAstralBeamChat(options, deferStart = false) {
10268
11517
  commands: []
10269
11518
  },
10270
11519
  sandboxStatus: void 0,
11520
+ usageLimitReached: void 0,
10271
11521
  pendingInteractions: [],
10272
11522
  threadLoadFailed: false,
10273
11523
  messagesCursor: void 0,
@@ -10434,7 +11684,7 @@ function createAstralBeamChat(options, deferStart = false) {
10434
11684
  });
10435
11685
  }
10436
11686
  scopeCompletedToolCalls();
10437
- if (pending && (!("tool" in result) || result.toolCallId === savedToolCallId(pending.sourceMessageId, pending.sourcePartId, pending.responseTargetId))) {
11687
+ if (pending) {
10438
11688
  replaceClient();
10439
11689
  await hydration;
10440
11690
  if (generation !== selectionGeneration) return;
@@ -10528,6 +11778,7 @@ function createAstralBeamChat(options, deferStart = false) {
10528
11778
  };
10529
11779
  const observeAuthentication = () => {
10530
11780
  const auth = authenticationState(authentication);
11781
+ const previous = state.auth;
10531
11782
  if (auth.status === "ready") {
10532
11783
  const nextIdentity = authenticationIdentity(auth.currentUser);
10533
11784
  if (identity !== void 0 && identity !== nextIdentity) {
@@ -10553,6 +11804,7 @@ function createAstralBeamChat(options, deferStart = false) {
10553
11804
  }
10554
11805
  }
10555
11806
  update({ auth });
11807
+ if (auth.status === "error" && (previous.status !== "error" || previous.error !== auth.error)) live.streamCallbacks?.onError?.(auth.error);
10556
11808
  };
10557
11809
  const start = () => {
10558
11810
  if (started) return;
@@ -10646,6 +11898,28 @@ function createAstralBeamChat(options, deferStart = false) {
10646
11898
  deleteThread,
10647
11899
  refreshThread,
10648
11900
  loadOlderMessages,
11901
+ uploadAttachment: async ({ data, filename, mimeType }) => {
11902
+ const agentId = state.thread ? state.thread.agentId : live.agentId;
11903
+ const [encoded, options] = await Promise.all([data, requestOptions(false)]);
11904
+ return uploadChatFile({
11905
+ ...agentId ? { agentId } : {},
11906
+ type: mimeType.startsWith("image/") ? "image" : "document",
11907
+ source: {
11908
+ type: "data",
11909
+ value: encoded,
11910
+ mimeType
11911
+ },
11912
+ metadata: { filename }
11913
+ }, options);
11914
+ },
11915
+ getFile: async (fileId) => {
11916
+ const thread = state.thread;
11917
+ if (!thread) throw new Error("Open a conversation before downloading files.");
11918
+ return (await getChatFile({
11919
+ threadId: thread.id,
11920
+ fileId
11921
+ }, await requestOptions())).blob();
11922
+ },
10649
11923
  getAttachment: async (messageId, partId) => {
10650
11924
  const thread = state.thread;
10651
11925
  if (!thread) throw new Error("Open a conversation before downloading attachments.");