@assistant-ui/core 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/speech.d.ts.map +1 -1
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/index.d.ts +4 -1
  5. package/dist/index.js +8 -1
  6. package/dist/index.js.map +1 -0
  7. package/dist/internal/duplicate-detection.d.ts +5 -0
  8. package/dist/internal/duplicate-detection.d.ts.map +1 -0
  9. package/dist/internal/duplicate-detection.js +11 -0
  10. package/dist/internal/duplicate-detection.js.map +1 -0
  11. package/dist/internal.d.ts +2 -2
  12. package/dist/internal.js +2 -2
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js.map +1 -1
  15. package/dist/model-context/frame/provider.d.ts.map +1 -1
  16. package/dist/model-context/frame/provider.js.map +1 -1
  17. package/dist/model-context/registry.d.ts.map +1 -1
  18. package/dist/model-context/tool.d.ts.map +1 -1
  19. package/dist/react/AssistantProvider.d.ts.map +1 -1
  20. package/dist/react/AssistantProvider.js.map +1 -1
  21. package/dist/react/client/Interactables.js.map +1 -1
  22. package/dist/react/client/Tools.d.ts.map +1 -1
  23. package/dist/react/client/Tools.js +26 -15
  24. package/dist/react/client/Tools.js.map +1 -1
  25. package/dist/react/index.d.ts +5 -4
  26. package/dist/react/index.js +2 -2
  27. package/dist/react/model-context/toolbox.d.ts +29 -2
  28. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  29. package/dist/react/model-context/toolbox.js +18 -0
  30. package/dist/react/model-context/toolbox.js.map +1 -0
  31. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  32. package/dist/react/model-context/useAssistantTool.js +6 -3
  33. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  34. package/dist/react/model-context/useAssistantToolUI.d.ts +6 -0
  35. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  36. package/dist/react/model-context/useAssistantToolUI.js +4 -2
  37. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  38. package/dist/react/model-context/useInlineRender.js.map +1 -1
  39. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  40. package/dist/react/primitives/message/MessageGroupedParts.d.ts +49 -7
  41. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  42. package/dist/react/primitives/message/MessageGroupedParts.js +28 -3
  43. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  44. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  45. package/dist/react/primitives/message/MessageParts.js +2 -7
  46. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  47. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  48. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  49. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  50. package/dist/react/runtimes/RuntimeAdapterProvider.js +6 -5
  51. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  52. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  53. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  54. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  55. package/dist/react/runtimes/external-message-converter.d.ts +1 -1
  56. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  57. package/dist/react/runtimes/external-message-converter.js +1 -0
  58. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  59. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts +7 -0
  60. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts.map +1 -0
  61. package/dist/react/runtimes/useExternalStoreSharedOptions.js +21 -0
  62. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -0
  63. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  64. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  65. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  66. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  67. package/dist/react/types/scopes/tools.d.ts +19 -2
  68. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  69. package/dist/react/utils/groupParts.d.ts +32 -11
  70. package/dist/react/utils/groupParts.d.ts.map +1 -1
  71. package/dist/react/utils/groupParts.js +13 -6
  72. package/dist/react/utils/groupParts.js.map +1 -1
  73. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  74. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  75. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  76. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  77. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  78. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  79. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  80. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  81. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  82. package/dist/runtime/base/base-assistant-runtime-core.d.ts.map +1 -1
  83. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  84. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  85. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  86. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  87. package/dist/runtime/interfaces/thread-runtime-core.d.ts +8 -0
  88. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  89. package/dist/runtime/utils/message-repository.d.ts +9 -1
  90. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  91. package/dist/runtime/utils/message-repository.js +34 -14
  92. package/dist/runtime/utils/message-repository.js.map +1 -1
  93. package/dist/runtime/utils/thread-message-like.d.ts +1 -0
  94. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  95. package/dist/runtime/utils/thread-message-like.js +2 -1
  96. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  97. package/dist/runtimes/external-store/external-store-adapter.d.ts +31 -0
  98. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  99. package/dist/runtimes/external-store/external-store-shared-options.d.ts +8 -0
  100. package/dist/runtimes/external-store/external-store-shared-options.d.ts.map +1 -0
  101. package/dist/runtimes/external-store/external-store-shared-options.js +11 -0
  102. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -0
  103. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  104. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  105. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +25 -2
  106. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  107. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +106 -26
  108. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  109. package/dist/runtimes/external-store/thread-message-converter.d.ts.map +1 -1
  110. package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
  111. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  112. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  113. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  114. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  115. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +168 -0
  116. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -0
  117. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +449 -0
  118. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -0
  119. package/dist/subscribable/subscribable.d.ts.map +1 -1
  120. package/dist/subscribable/subscribable.js.map +1 -1
  121. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  122. package/dist/types/message.d.ts +6 -0
  123. package/dist/types/message.d.ts.map +1 -1
  124. package/dist/types/message.js.map +1 -1
  125. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  126. package/dist/utils/id.d.ts +1 -3
  127. package/dist/utils/id.d.ts.map +1 -1
  128. package/dist/utils/id.js +1 -4
  129. package/dist/utils/id.js.map +1 -1
  130. package/package.json +10 -10
  131. package/src/adapters/index.ts +1 -4
  132. package/src/adapters/speech.ts +0 -1
  133. package/src/index.ts +12 -0
  134. package/src/internal/duplicate-detection.ts +26 -0
  135. package/src/internal.ts +0 -2
  136. package/src/model-context/frame/host.ts +0 -1
  137. package/src/model-context/frame/provider.ts +0 -1
  138. package/src/react/AssistantProvider.tsx +2 -3
  139. package/src/react/client/Interactables.ts +0 -1
  140. package/src/react/client/Tools.ts +50 -25
  141. package/src/react/index.ts +9 -8
  142. package/src/react/model-context/toolbox.ts +46 -1
  143. package/src/react/model-context/useAssistantTool.ts +8 -3
  144. package/src/react/model-context/useAssistantToolUI.ts +9 -2
  145. package/src/react/model-context/useInlineRender.ts +0 -1
  146. package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -2
  147. package/src/react/primitives/message/MessageAttachments.test.tsx +1 -1
  148. package/src/react/primitives/message/MessageGroupedParts.tsx +102 -13
  149. package/src/react/primitives/message/MessageParts.tsx +4 -7
  150. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
  151. package/src/react/runtimes/RuntimeAdapterProvider.tsx +12 -7
  152. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +0 -3
  153. package/src/react/runtimes/external-message-converter.ts +5 -1
  154. package/src/react/runtimes/useExternalStoreSharedOptions.ts +23 -0
  155. package/src/react/runtimes/useLocalRuntime.ts +0 -10
  156. package/src/react/runtimes/useRemoteThreadListRuntime.ts +0 -6
  157. package/src/react/types/scopes/tools.ts +20 -1
  158. package/src/react/utils/groupParts.ts +49 -18
  159. package/src/runtime/api/attachment-runtime.ts +1 -2
  160. package/src/runtime/interfaces/thread-runtime-core.ts +8 -0
  161. package/src/runtime/internal.ts +1 -4
  162. package/src/runtime/utils/message-repository.ts +57 -16
  163. package/src/runtime/utils/thread-message-like.ts +2 -0
  164. package/src/runtimes/external-store/external-store-adapter.ts +33 -0
  165. package/src/runtimes/external-store/external-store-shared-options.ts +18 -0
  166. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +1 -3
  167. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +179 -37
  168. package/src/runtimes/tool-invocations/EDGE_CASES.md +194 -0
  169. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +1054 -0
  170. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +782 -0
  171. package/src/subscribable/subscribable.ts +3 -3
  172. package/src/tests/MessageRepository.test.ts +83 -52
  173. package/src/tests/OptimisticState-delete-crash.test.ts +2 -0
  174. package/src/tests/OptimisticState-list-race.test.ts +2 -4
  175. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +5 -5
  176. package/src/tests/auiV0Encode.test.ts +1 -1
  177. package/src/tests/composer-can-send.test.ts +8 -4
  178. package/src/tests/duplicate-detection.test.ts +34 -0
  179. package/src/tests/external-store-thread-list-runtime-core.test.ts +1 -1
  180. package/src/tests/external-store-thread-runtime-core.test.ts +112 -79
  181. package/src/tests/groupParts.test.ts +70 -0
  182. package/src/tests/no-unsafe-process-env.test.ts +1 -0
  183. package/src/tests/remote-thread-list-isLoading.test.ts +2 -5
  184. package/src/tests/thread-message-like.test.ts +4 -1
  185. package/src/types/index.ts +1 -4
  186. package/src/types/message.ts +6 -0
  187. package/src/utils/id.ts +0 -4
  188. package/dist/react/runtimes/useToolInvocations.d.ts +0 -53
  189. package/dist/react/runtimes/useToolInvocations.d.ts.map +0 -1
  190. package/dist/react/runtimes/useToolInvocations.js +0 -380
  191. package/dist/react/runtimes/useToolInvocations.js.map +0 -1
  192. package/src/react/runtimes/useToolInvocations.ts +0 -694
@@ -1,4 +1,4 @@
1
- import { generateId, generateOptimisticId } from "../../utils/id.js";
1
+ import { generateId } from "../../utils/id.js";
2
2
  import { getAutoStatus } from "./auto-status.js";
3
3
  import { fromThreadMessageLike } from "./thread-message-like.js";
4
4
  //#region src/runtime/utils/message-repository.ts
@@ -126,14 +126,6 @@ var MessageRepository = class {
126
126
  index: message.level
127
127
  };
128
128
  }
129
- appendOptimisticMessage(parentId, message) {
130
- let optimisticId;
131
- do
132
- optimisticId = generateOptimisticId();
133
- while (this.messages.has(optimisticId));
134
- this.addOrUpdateMessage(parentId, fromThreadMessageLike(message, optimisticId, { type: "running" }));
135
- return optimisticId;
136
- }
137
129
  deleteMessage(messageId, replacementId) {
138
130
  const message = this.messages.get(messageId);
139
131
  if (!message) throw new Error("MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.");
@@ -155,12 +147,33 @@ var MessageRepository = class {
155
147
  const { children } = message.prev ?? this.root;
156
148
  return children;
157
149
  }
150
+ /**
151
+ * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved
152
+ * away from. Since eviction runs on every head move, the only optimistic
153
+ * messages in the repository live on the branch the head previously pointed
154
+ * at — so we walk just that branch rather than the whole repository. Keeps a
155
+ * client→server id swap from leaving a phantom sibling, and drops off-branch
156
+ * placeholders.
157
+ */
158
+ evictOffBranchOptimisticMessages(previousHead, currentHead) {
159
+ if (!previousHead) return;
160
+ const onHeadBranch = /* @__PURE__ */ new Set();
161
+ for (let current = currentHead; current; current = current.prev) onHeadBranch.add(current.current.id);
162
+ const stale = [];
163
+ for (let current = previousHead; current; current = current.prev) {
164
+ if (onHeadBranch.has(current.current.id)) break;
165
+ if (current.current.metadata?.isOptimistic) stale.push(current.current.id);
166
+ }
167
+ for (const id of stale) if (this.messages.has(id)) this.deleteMessage(id);
168
+ }
158
169
  switchToBranch(messageId) {
159
170
  const message = this.messages.get(messageId);
160
171
  if (!message) throw new Error("MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.");
172
+ const previousHead = this.head;
161
173
  const prevOrRoot = message.prev ?? this.root;
162
174
  prevOrRoot.next = message;
163
175
  this.head = findHead(message);
176
+ this.evictOffBranchOptimisticMessages(previousHead, this.head);
164
177
  this._messages.dirty();
165
178
  }
166
179
  resetHead(messageId) {
@@ -170,6 +183,7 @@ var MessageRepository = class {
170
183
  }
171
184
  const message = this.messages.get(messageId);
172
185
  if (!message) throw new Error("MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.");
186
+ const previousHead = this.head;
173
187
  if (message.children.length > 0) {
174
188
  const deleteDescendants = (msg) => {
175
189
  for (const childId of msg.children) {
@@ -187,6 +201,7 @@ var MessageRepository = class {
187
201
  this.head = message;
188
202
  for (let current = message; current; current = current.prev) if (current.prev) current.prev.next = current;
189
203
  else this.root.next = current;
204
+ this.evictOffBranchOptimisticMessages(previousHead, this.head);
190
205
  this._messages.dirty();
191
206
  }
192
207
  clear() {
@@ -200,12 +215,17 @@ var MessageRepository = class {
200
215
  }
201
216
  export() {
202
217
  const exportItems = [];
203
- for (const [, message] of this.messages) exportItems.push({
204
- message: message.current,
205
- parentId: message.prev?.current.id ?? null
206
- });
218
+ for (const [, message] of this.messages) {
219
+ if (message.current.metadata?.isOptimistic) continue;
220
+ exportItems.push({
221
+ message: message.current,
222
+ parentId: message.prev?.current.id ?? null
223
+ });
224
+ }
225
+ let head = this.head;
226
+ while (head?.current.metadata?.isOptimistic) head = head.prev;
207
227
  return {
208
- headId: this.head?.current.id ?? null,
228
+ headId: head?.current.id ?? null,
209
229
  messages: exportItems
210
230
  };
211
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"message-repository.js","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId, generateOptimisticId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getAutoStatus(false, false, false, false, undefined),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n const fallbackStatus = getAutoStatus(false, false, false, false, undefined);\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(message, message.id, fallbackStatus),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n if (message.next) return findHead(message.next);\n if (\"current\" in message) return message;\n return null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n constructor(private func: () => T) {}\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n message.level = newLevel;\n for (const childId of message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n this.updateLevels(childMessage, newLevel + 1);\n }\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n appendOptimisticMessage(parentId: string | null, message: ThreadMessageLike) {\n let optimisticId: string;\n do {\n optimisticId = generateOptimisticId();\n } while (this.messages.has(optimisticId));\n\n this.addOrUpdateMessage(\n parentId,\n fromThreadMessageLike(message, optimisticId, { type: \"running\" }),\n );\n\n return optimisticId;\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (message.children.length > 0) {\n const deleteDescendants = (msg: RepositoryMessage) => {\n for (const childId of msg.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n deleteDescendants(childMessage);\n this.messages.delete(childId);\n }\n }\n };\n deleteDescendants(message);\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n } else {\n this.root.next = current;\n }\n }\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n for (const [, message] of this.messages) {\n exportItems.push({\n message: message.current,\n parentId: message.prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.head?.current.id ?? null,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"message-repository.js","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getAutoStatus(false, false, false, false, undefined),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n const fallbackStatus = getAutoStatus(false, false, false, false, undefined);\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(message, message.id, fallbackStatus),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n if (message.next) return findHead(message.next);\n if (\"current\" in message) return message;\n return null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n constructor(private func: () => T) {}\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n message.level = newLevel;\n for (const childId of message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n this.updateLevels(childMessage, newLevel + 1);\n }\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved\n * away from. Since eviction runs on every head move, the only optimistic\n * messages in the repository live on the branch the head previously pointed\n * at — so we walk just that branch rather than the whole repository. Keeps a\n * client→server id swap from leaving a phantom sibling, and drops off-branch\n * placeholders.\n */\n private evictOffBranchOptimisticMessages(\n previousHead: RepositoryMessage | null,\n currentHead: RepositoryMessage | null,\n ) {\n if (!previousHead) return;\n\n const onHeadBranch = new Set<string>();\n for (let current = currentHead; current; current = current.prev) {\n onHeadBranch.add(current.current.id);\n }\n\n const stale: string[] = [];\n for (\n let current: RepositoryMessage | null = previousHead;\n current;\n current = current.prev\n ) {\n // Stop at the first node shared with the current head branch: every\n // ancestor above it is shared too, so nothing further can be off-branch.\n if (onHeadBranch.has(current.current.id)) break;\n if (current.current.metadata?.isOptimistic) {\n stale.push(current.current.id);\n }\n }\n\n for (const id of stale) {\n // A prior deletion may have already removed this node.\n if (this.messages.has(id)) this.deleteMessage(id);\n }\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n\n if (message.children.length > 0) {\n const deleteDescendants = (msg: RepositoryMessage) => {\n for (const childId of msg.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n deleteDescendants(childMessage);\n this.messages.delete(childId);\n }\n }\n };\n deleteDescendants(message);\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n } else {\n this.root.next = current;\n }\n }\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // Optimistic messages are ephemeral and never persisted. They're always\n // leaf nodes, so skipping them can't orphan a persisted child.\n for (const [, message] of this.messages) {\n if (message.current.metadata?.isOptimistic) continue;\n exportItems.push({\n message: message.current,\n parentId: message.prev?.current.id ?? null,\n });\n }\n\n // The head may itself be optimistic; walk up to the nearest persisted ancestor.\n let head = this.head;\n while (head?.current.metadata?.isOptimistic) {\n head = head.prev;\n }\n\n return {\n headId: head?.current.id ?? null,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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"}
@@ -46,6 +46,7 @@ type ThreadMessageLike = {
46
46
  readonly submittedFeedback?: {
47
47
  readonly type: "positive" | "negative";
48
48
  };
49
+ readonly isOptimistic?: boolean | undefined;
49
50
  readonly custom?: Record<string, unknown> | undefined;
50
51
  } | undefined;
51
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;;KA0BK,gBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAI;AAAA;AAAA,KAGH,iBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,qBAGD,eAAA,GACA,oBAAA,GACA,iBAAA,GACA,gBAAA,GACA,eAAA,GACA,eAAA,GACA,uBAAA,GACA,yBAAA,GACA,gBAAA;IAAA,SAEW,IAAA;IAAA,SACA,UAAA;IAAA,SACA,QAAA;IAAA,SACA,IAAA,GAAO,kBAAA;IAAA,SACP,QAAA;IAAA,SACA,QAAA;IAAA,SACA,MAAA;IAAA,SACA,OAAA;IAAA,SACA,QAAA;IAAA,SACA,QAAA,YAAoB,aAAA;IAAA,SACpB,SAAA;MAAc,IAAA;MAAe,OAAA;IAAA;IAAA,SAC7B,QAAA;MAAA,SACE,EAAA;MAAA,SACA,QAAA;MAAA,SACA,MAAA;MAAA,SACA,WAAA;IAAA;EAAA;EAAA,SAIZ,EAAA;EAAA,SACA,SAAA,GAAY,IAAA;EAAA,SACZ,MAAA,GAAS,aAAA;EAAA,SACT,WAAA,aACK,IAAA,CAAK,kBAAA;IAAA,SACJ,OAAA,YAAmB,qBAAA,GAAwB,gBAAA;EAAA;EAAA,SAGjD,QAAA;IAAA,SAEM,cAAA,GAAiB,iBAAA;IAAA,SACjB,oBAAA,YACI,iBAAA;IAAA,SAEJ,aAAA,YAAyB,iBAAA;IAAA,SACzB,KAAA,YAAiB,UAAA;IAAA,SACjB,MAAA,GAAS,aAAA;IAAA,SACT,iBAAA;MAAA,SAA+B,IAAA;IAAA;IAAA,SAC/B,MAAA,GAAS,MAAA;EAAA;AAAA;AAAA,cAab,qBAAA,GACX,IAAA,EAAM,iBAAA,EACN,UAAA,UACA,cAAA,EAAgB,aAAA,KACf,aAAA"}
1
+ {"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;;KA0BK,gBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAI;AAAA;AAAA,KAGH,iBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,qBAGD,eAAA,GACA,oBAAA,GACA,iBAAA,GACA,gBAAA,GACA,eAAA,GACA,eAAA,GACA,uBAAA,GACA,yBAAA,GACA,gBAAA;IAAA,SAEW,IAAA;IAAA,SACA,UAAA;IAAA,SACA,QAAA;IAAA,SACA,IAAA,GAAO,kBAAA;IAAA,SACP,QAAA;IAAA,SACA,QAAA;IAAA,SACA,MAAA;IAAA,SACA,OAAA;IAAA,SACA,QAAA;IAAA,SACA,QAAA,YAAoB,aAAA;IAAA,SACpB,SAAA;MAAc,IAAA;MAAe,OAAA;IAAA;IAAA,SAC7B,QAAA;MAAA,SACE,EAAA;MAAA,SACA,QAAA;MAAA,SACA,MAAA;MAAA,SACA,WAAA;IAAA;EAAA;EAAA,SAIZ,EAAA;EAAA,SACA,SAAA,GAAY,IAAA;EAAA,SACZ,MAAA,GAAS,aAAA;EAAA,SACT,WAAA,aACK,IAAA,CAAK,kBAAA;IAAA,SACJ,OAAA,YAAmB,qBAAA,GAAwB,gBAAA;EAAA;EAAA,SAGjD,QAAA;IAAA,SAEM,cAAA,GAAiB,iBAAA;IAAA,SACjB,oBAAA,YACI,iBAAA;IAAA,SAEJ,aAAA,YAAyB,iBAAA;IAAA,SACzB,KAAA,YAAiB,UAAA;IAAA,SACjB,MAAA,GAAS,aAAA;IAAA,SACT,iBAAA;MAAA,SAA+B,IAAA;IAAA;IAAA,SAC/B,YAAA;IAAA,SACA,MAAA,GAAS,MAAA;EAAA;AAAA;AAAA,cAab,qBAAA,GACX,IAAA,EAAM,iBAAA,EACN,UAAA,UACA,cAAA,EAAgB,aAAA,KACf,aAAA"}
@@ -84,7 +84,8 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
84
84
  custom: metadata?.custom ?? {},
85
85
  steps: metadata?.steps ?? [],
86
86
  ...metadata?.timing && { timing: metadata.timing },
87
- ...metadata?.submittedFeedback && { submittedFeedback: metadata.submittedFeedback }
87
+ ...metadata?.submittedFeedback && { submittedFeedback: metadata.submittedFeedback },
88
+ ...metadata?.isOptimistic && { isOptimistic: true }
88
89
  }
89
90
  };
90
91
  case "user": return {
@@ -1 +1 @@
1
- {"version":3,"file":"thread-message-like.js","names":["unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type { MessageTiming, TextMessagePart } from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n };\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n const dataUri = image.match(\n /^data:image\\/(png|jpeg|jpg|gif|webp|svg\\+xml);base64,(.*)$/,\n );\n if (dataUri) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"reasoning\":\n if (part.text.trim().length === 0) return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-message-like.js","names":["unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type { MessageTiming, TextMessagePart } from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n };\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly isOptimistic?: boolean | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n const dataUri = image.match(\n /^data:image\\/(png|jpeg|jpg|gif|webp|svg\\+xml);base64,(.*)$/,\n );\n if (dataUri) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"reasoning\":\n if (part.text.trim().length === 0) return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { RealtimeVoiceAdapter } from "../../adapters/voice.js";
6
6
  import { ThreadMessageLike } from "../../runtime/utils/thread-message-like.js";
7
7
  import { ExportedMessageRepository } from "../../runtime/utils/message-repository.js";
8
8
  import { AddToolResultOptions, RespondToToolApprovalOptions, ResumeRunConfig, StartRunConfig, ThreadSuggestion } from "../../runtime/interfaces/thread-runtime-core.js";
9
+ import { ToolExecutionStatus } from "../tool-invocations/ToolInvocationTracker.js";
9
10
  import { ReadonlyJSONValue } from "assistant-stream/utils";
10
11
 
11
12
  //#region src/runtimes/external-store/external-store-adapter.d.ts
@@ -103,6 +104,36 @@ type ExternalStoreAdapterBase<T> = {
103
104
  unstable_capabilities?: {
104
105
  copy?: boolean | undefined;
105
106
  } | undefined;
107
+ /**
108
+ * Opt in to the built-in client-side tool-invocations pipeline
109
+ * (`streamCall` / `execute` / tool-status tracking) for this thread.
110
+ *
111
+ * Defaults to `false` — the runtime does *not* drive client-side tool
112
+ * callbacks on its own. Set to `true` to have the runtime construct a
113
+ * `ToolInvocationTracker` and feed every snapshot through it, so tool
114
+ * callbacks fire automatically for tool-call parts in `messages`.
115
+ *
116
+ * Opt-in by default because most external-store runtimes either run
117
+ * tools entirely server-side, or already wire their own client-side
118
+ * dispatch path. Enabling the embedded tracker on top of an existing
119
+ * dispatch path would cause tool callbacks to run twice.
120
+ *
121
+ * When enabled, client-side tool results (from `execute()` returning,
122
+ * or from `streamCall` resolving) flow back through
123
+ * `adapter.onAddToolResult` like any other tool result, with
124
+ * `modelContent` populated when present.
125
+ */
126
+ unstable_enableToolInvocations?: boolean | undefined;
127
+ /**
128
+ * Receives the current per-tool-call execution status map whenever it
129
+ * changes. Only invoked when `unstable_enableToolInvocations` is `true`
130
+ * — the runtime maintains the map via the embedded tracker.
131
+ *
132
+ * Wire this into local React state and feed it into the converter's
133
+ * `metadata.toolStatuses` so the UI can render `executing` spinners
134
+ * and human-input prompts.
135
+ */
136
+ setToolStatuses?: ((statuses: Record<string, ToolExecutionStatus>) => void) | undefined;
106
137
  };
107
138
  type ExternalStoreAdapter<T = ThreadMessage> = ExternalStoreAdapterBase<T> & (T extends ThreadMessage ? object : ExternalStoreMessageConverterAdapter<T>);
108
139
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-adapter.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-adapter.ts"],"mappings":";;;;;;;;;;;KAmBY,uBAAA;EACV,MAAA,EAAQ,MAAM;EACd,EAAA;EACA,QAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,KAGU,8BAAA;EAPF;;;EAWR,QAAA;EACA,SAAA;EACA,OAAA,YAAmB,uBAAA;EACnB,eAAA,YAA2B,uBAAA;EAPjB;;;EAWV,mBAAA,UAA6B,OAAA;EAJF;;;EAQ3B,gBAAA,KAAqB,QAAA,aAAqB,OAAA;EAC1C,QAAA,IACE,QAAA,UACA,QAAA,cACI,OAAA;EACN,SAAA,KAAc,QAAA,aAAqB,OAAA;EACnC,WAAA,KAAgB,QAAA,aAAqB,OAAA;EACrC,QAAA,KAAa,QAAA,aAAqB,OAAA;AAAA;AAAA,KAGxB,6BAAA,OACV,OAAA,EAAS,CAAA,EACT,GAAA,aACG,iBAAiB;AAAA,KAEjB,oCAAA;EACH,cAAA,EAAgB,6BAA6B,CAAC,CAAA;AAAA;AAAA,KAG3C,wBAAA;EA3BwB;;;;;;EAkC3B,UAAA;EAxBE;;;;;;;;EAiCF,cAAA;EA5BA;;;;AAAyC;AAG3C;;;EAkCE,SAAA;EACA,SAAA;EACA,QAAA,YAAoB,CAAA;EACpB,iBAAA,GAAoB,yBAAA;EACpB,WAAA,YAAuB,gBAAA;EACvB,KAAA,GAAQ,iBAAA;EACR,MAAA;EAEA,WAAA,KAAgB,QAAA,WAAmB,CAAA;EACnC,QAAA,KAAa,QAAA,WAAmB,aAAA;EAChC,qBAAA;EACA,mBAAA,KAAwB,KAAA;EACxB,KAAA,GAAQ,OAAA,EAAS,aAAA,KAAkB,OAAA;EACnC,MAAA,KAAW,OAAA,EAAS,aAAA,KAAkB,OAAA;EACtC,QAAA,KACM,QAAA,iBAAyB,MAAA,EAAQ,cAAA,KAAmB,OAAA;EAE1D,QAAA,KAAa,MAAA,EAAQ,eAAA,KAAoB,OAAA;EACzC,QAAA,UAAkB,OAAA;EAClB,eAAA,KACM,OAAA,EAAS,oBAAA,KAAyB,OAAA;EAExC,gBAAA,KACM,OAAA;IAAW,UAAA;IAAoB,OAAA;EAAA;EAErC,uBAAA,KACM,OAAA,EAAS,4BAAA,KAAiC,OAAA;EAEhD,cAAA,GAAiB,6BAAA,CAA8B,CAAA;EAC/C,QAAA;IAEM,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,SAAA,GAAY,gBAAA;IACZ,KAAA,GAAQ,oBAAA;IACR,QAAA,GAAW,eAAA;IAtBG;;;IA0Bd,UAAA,GAAa,8BAAA;EAAA;EAGnB,qBAAA;IAEM,IAAA;EAAA;AAAA;AAAA,KAKI,oBAAA,KAAyB,aAAA,IACnC,wBAAA,CAAyB,CAAA,KACtB,CAAA,SAAU,aAAA,YAEP,oCAAA,CAAqC,CAAA"}
1
+ {"version":3,"file":"external-store-adapter.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-adapter.ts"],"mappings":";;;;;;;;;;;;KAoBY,uBAAA;EACV,MAAA,EAAQ,MAAM;EACd,EAAA;EACA,QAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,KAGU,8BAAA;EAPF;;;EAWR,QAAA;EACA,SAAA;EACA,OAAA,YAAmB,uBAAA;EACnB,eAAA,YAA2B,uBAAA;EAPjB;;;EAWV,mBAAA,UAA6B,OAAA;EAJF;;;EAQ3B,gBAAA,KAAqB,QAAA,aAAqB,OAAA;EAC1C,QAAA,IACE,QAAA,UACA,QAAA,cACI,OAAA;EACN,SAAA,KAAc,QAAA,aAAqB,OAAA;EACnC,WAAA,KAAgB,QAAA,aAAqB,OAAA;EACrC,QAAA,KAAa,QAAA,aAAqB,OAAA;AAAA;AAAA,KAGxB,6BAAA,OACV,OAAA,EAAS,CAAA,EACT,GAAA,aACG,iBAAiB;AAAA,KAEjB,oCAAA;EACH,cAAA,EAAgB,6BAA6B,CAAC,CAAA;AAAA;AAAA,KAG3C,wBAAA;EA3BwB;;;;;;EAkC3B,UAAA;EAxBE;;;;;;;;EAiCF,cAAA;EA5BA;;;;AAAyC;AAG3C;;;EAkCE,SAAA;EACA,SAAA;EACA,QAAA,YAAoB,CAAA;EACpB,iBAAA,GAAoB,yBAAA;EACpB,WAAA,YAAuB,gBAAA;EACvB,KAAA,GAAQ,iBAAA;EACR,MAAA;EAEA,WAAA,KAAgB,QAAA,WAAmB,CAAA;EACnC,QAAA,KAAa,QAAA,WAAmB,aAAA;EAChC,qBAAA;EACA,mBAAA,KAAwB,KAAA;EACxB,KAAA,GAAQ,OAAA,EAAS,aAAA,KAAkB,OAAA;EACnC,MAAA,KAAW,OAAA,EAAS,aAAA,KAAkB,OAAA;EACtC,QAAA,KACM,QAAA,iBAAyB,MAAA,EAAQ,cAAA,KAAmB,OAAA;EAE1D,QAAA,KAAa,MAAA,EAAQ,eAAA,KAAoB,OAAA;EACzC,QAAA,UAAkB,OAAA;EAClB,eAAA,KACM,OAAA,EAAS,oBAAA,KAAyB,OAAA;EAExC,gBAAA,KACM,OAAA;IAAW,UAAA;IAAoB,OAAA;EAAA;EAErC,uBAAA,KACM,OAAA,EAAS,4BAAA,KAAiC,OAAA;EAEhD,cAAA,GAAiB,6BAAA,CAA8B,CAAA;EAC/C,QAAA;IAEM,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,SAAA,GAAY,gBAAA;IACZ,KAAA,GAAQ,oBAAA;IACR,QAAA,GAAW,eAAA;IAtBG;;;IA0Bd,UAAA,GAAa,8BAAA;EAAA;EAGnB,qBAAA;IAEM,IAAA;EAAA;EAxBkC;;;;;;;;;;;;;;;;;;;EA8CxC,8BAAA;EAhEA;;;;;;;;;EA0EA,eAAA,KACM,QAAA,EAAU,MAAA,SAAe,mBAAA;AAAA;AAAA,KAIrB,oBAAA,KAAyB,aAAA,IACnC,wBAAA,CAAyB,CAAA,KACtB,CAAA,SAAU,aAAA,YAEP,oCAAA,CAAqC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { ExternalStoreAdapter } from "./external-store-adapter.js";
2
+
3
+ //#region src/runtimes/external-store/external-store-shared-options.d.ts
4
+ type ExternalStoreSharedOptions = Pick<ExternalStoreAdapter, "isDisabled" | "isSendDisabled" | "unstable_capabilities" | "suggestions">;
5
+ declare const pickExternalStoreSharedOptions: (options: ExternalStoreSharedOptions) => ExternalStoreSharedOptions;
6
+ //#endregion
7
+ export { ExternalStoreSharedOptions, pickExternalStoreSharedOptions };
8
+ //# sourceMappingURL=external-store-shared-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-store-shared-options.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-shared-options.ts"],"mappings":";;;KAEY,0BAAA,GAA6B,IAAI,CAC3C,oBAAA;AAAA,cAIW,8BAAA,GACX,OAAA,EAAS,0BAAA,KACR,0BAQA"}
@@ -0,0 +1,11 @@
1
+ //#region src/runtimes/external-store/external-store-shared-options.ts
2
+ const pickExternalStoreSharedOptions = (options) => ({
3
+ isDisabled: options.isDisabled,
4
+ isSendDisabled: options.isSendDisabled,
5
+ unstable_capabilities: options.unstable_capabilities,
6
+ suggestions: options.suggestions
7
+ });
8
+ //#endregion
9
+ export { pickExternalStoreSharedOptions };
10
+
11
+ //# sourceMappingURL=external-store-shared-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-store-shared-options.js","names":[],"sources":["../../../src/runtimes/external-store/external-store-shared-options.ts"],"sourcesContent":["import type { ExternalStoreAdapter } from \"./external-store-adapter\";\n\nexport type ExternalStoreSharedOptions = Pick<\n ExternalStoreAdapter,\n \"isDisabled\" | \"isSendDisabled\" | \"unstable_capabilities\" | \"suggestions\"\n>;\n\nexport const pickExternalStoreSharedOptions = (\n options: ExternalStoreSharedOptions,\n): ExternalStoreSharedOptions =>\n ({\n isDisabled: options.isDisabled,\n isSendDisabled: options.isSendDisabled,\n unstable_capabilities: options.unstable_capabilities,\n suggestions: options.suggestions,\n }) satisfies {\n [K in keyof Required<ExternalStoreSharedOptions>]: ExternalStoreSharedOptions[K];\n };\n"],"mappings":";AAOA,MAAa,kCACX,aAEC;CACC,YAAY,QAAQ;CACpB,gBAAgB,QAAQ;CACxB,uBAAuB,QAAQ;CAC/B,aAAa,QAAQ;AACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-list-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"mappings":";;;;;;KAQY,0BAAA,SAAmC,8BAA8B;AAAA,cAgBhE,kCAAA,YACA,qBAAA;EAAA,QAyCD,aAAA;EAAA,QAvCF,aAAA;EAAA,QACA,QAAA;EAAA,QACA,gBAAA;EAAA,QACA,WAAA;EAAA,QAEA,OAAA;EAAA,IAEG,SAAA,CAAA;EAAA,IAIA,WAAA,CAAA;EAAA,IAIA,SAAA,CAAA;EAAA,IAIA,iBAAA,CAAA;EAAA,IAIA,WAAA,CAAA,GAAW,QAAA,CAAA,MAAA,SAAA,uBAAA;EAIf,qBAAA,CAAA,GAAqB,OAAA;EAAA,QAIpB,WAAA;EAAA,IAEG,YAAA,CAAA;cAKT,OAAA,EAAS,8BAAA,cACD,aAAA,EAAe,0BAAA;EAKlB,wBAAA,CAAA,GAAwB,8BAAA;EAIxB,oBAAA,CAAA;EAIA,WAAA,CAAY,QAAA,WAAgB,uBAAA;EAI5B,qBAAA,CACL,OAAA,EAAS,8BAAA,EACT,WAAA;EAqFW,cAAA,CACX,QAAA,UACA,QAAA;IAAa,SAAA;EAAA,IACZ,OAAA;EAUU,iBAAA,CAAA,GAAqB,OAAA;EAUrB,MAAA,CAAO,QAAA,UAAkB,QAAA,WAAmB,OAAA;EAQ5C,MAAA,CAAA,GAAU,OAAA;EAIV,OAAA,CAAQ,QAAA,WAAmB,OAAA;EAQ3B,SAAA,CAAU,QAAA,WAAmB,OAAA;EAQ7B,MAAA,CAAO,QAAA,WAAmB,OAAA;EAQhC,UAAA,CACL,QAAA,WACC,OAAA;IAAU,QAAA;IAAkB,UAAA;EAAA;EAIxB,aAAA,CAAA;EAAA,QAIC,cAAA;EAED,SAAA,CAAU,QAAA,eAAuB,WAAA;EAAA,QAKhC,kBAAA;AAAA"}
1
+ {"version":3,"file":"external-store-thread-list-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"mappings":";;;;;;KAQY,0BAAA,SAAmC,8BAA8B;AAAA,cAgBhE,kCAAA,YAA8C,qBAAA;EAAA,QAwC/C,aAAA;EAAA,QAvCF,aAAA;EAAA,QACA,QAAA;EAAA,QACA,gBAAA;EAAA,QACA,WAAA;EAAA,QAEA,OAAA;EAAA,IAEG,SAAA;EAAA,IAIA,WAAA;EAAA,IAIA,SAAA;EAAA,IAIA,iBAAA;EAAA,IAIA,WAAA,IAAW,QAAA,CAAA,MAAA,SAAA,uBAAA;EAIf,qBAAA,IAAqB,OAAA;EAAA,QAIpB,WAAA;EAAA,IAEG,YAAA;cAKT,OAAA,EAAS,8BAAA,cACD,aAAA,EAAe,0BAAA;EAKlB,wBAAA,IAAwB,8BAAA;EAIxB,oBAAA;EAIA,WAAA,CAAY,QAAA,WAAgB,uBAAA;EAI5B,qBAAA,CACL,OAAA,EAAS,8BAAA,EACT,WAAA;EAqFW,cAAA,CACX,QAAA,UACA,QAAA;IAAa,SAAA;EAAA,IACZ,OAAA;EAUU,iBAAA,IAAqB,OAAA;EAUrB,MAAA,CAAO,QAAA,UAAkB,QAAA,WAAmB,OAAA;EAQ5C,MAAA,IAAU,OAAA;EAIV,OAAA,CAAQ,QAAA,WAAmB,OAAA;EAQ3B,SAAA,CAAU,QAAA,WAAmB,OAAA;EAQ7B,MAAA,CAAO,QAAA,WAAmB,OAAA;EAQhC,UAAA,CACL,QAAA,WACC,OAAA;IAAU,QAAA;IAAkB,UAAA;EAAA;EAIxB,aAAA;EAAA,QAIC,cAAA;EAED,SAAA,CAAU,QAAA,eAAuB,WAAA;EAAA,QAKhC,kBAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-list-runtime-core.js","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ExternalStoreThreadRuntimeCore } from \"./external-store-thread-runtime-core\";\nimport type {\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"../../runtime/interfaces/thread-list-runtime-core\";\nimport type { ExternalStoreThreadListAdapter } from \"./external-store-adapter\";\n\nexport type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;\n\nconst EMPTY_ARRAY = Object.freeze([]);\nconst DEFAULT_THREAD_ID = \"DEFAULT_THREAD_ID\";\nconst DEFAULT_THREADS = Object.freeze([DEFAULT_THREAD_ID]);\nconst DEFAULT_THREAD = Object.freeze({\n id: DEFAULT_THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n});\nconst RESOLVED_PROMISE = Promise.resolve();\nconst DEFAULT_THREAD_DATA = Object.freeze({\n [DEFAULT_THREAD_ID]: DEFAULT_THREAD,\n});\n\nexport class ExternalStoreThreadListRuntimeCore\n implements ThreadListRuntimeCore\n{\n private _mainThreadId: string = DEFAULT_THREAD_ID;\n private _threads: readonly string[] = DEFAULT_THREADS;\n private _archivedThreads: readonly string[] = EMPTY_ARRAY;\n private _threadData: Readonly<Record<string, ThreadListItemCoreState>> =\n DEFAULT_THREAD_DATA;\n private adapter: ExternalStoreThreadListAdapter = {};\n\n public get isLoading() {\n return this.adapter.isLoading ?? false;\n }\n\n public get newThreadId() {\n return undefined;\n }\n\n public get threadIds() {\n return this._threads;\n }\n\n public get archivedThreadIds() {\n return this._archivedThreads;\n }\n\n public get threadItems() {\n return this._threadData;\n }\n\n public getLoadThreadsPromise() {\n return RESOLVED_PROMISE;\n }\n\n private _mainThread!: ExternalStoreThreadRuntimeCore;\n\n public get mainThreadId() {\n return this._mainThreadId;\n }\n\n constructor(\n adapter: ExternalStoreThreadListAdapter = {},\n private threadFactory: ExternalStoreThreadFactory,\n ) {\n this.__internal_setAdapter(adapter, true);\n }\n\n public getMainThreadRuntimeCore() {\n return this._mainThread;\n }\n\n public getThreadRuntimeCore(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n public getItemById(threadId: string) {\n return this._threadData[threadId];\n }\n\n public __internal_setAdapter(\n adapter: ExternalStoreThreadListAdapter,\n initialLoad = false,\n ) {\n const previousAdapter = this.adapter;\n this.adapter = adapter;\n\n const newThreadId = adapter.threadId ?? DEFAULT_THREAD_ID;\n const newThreads = adapter.threads ?? EMPTY_ARRAY;\n const newArchivedThreads = adapter.archivedThreads ?? EMPTY_ARRAY;\n\n const previousThreadId = previousAdapter.threadId ?? DEFAULT_THREAD_ID;\n const previousThreads = previousAdapter.threads ?? EMPTY_ARRAY;\n const previousArchivedThreads =\n previousAdapter.archivedThreads ?? EMPTY_ARRAY;\n\n if (\n !initialLoad &&\n previousThreadId === newThreadId &&\n previousThreads === newThreads &&\n previousArchivedThreads === newArchivedThreads\n ) {\n return;\n }\n\n if (\n previousThreads !== newThreads ||\n previousArchivedThreads !== newArchivedThreads ||\n previousThreadId !== newThreadId\n ) {\n this._threadData = {\n ...DEFAULT_THREAD_DATA,\n ...Object.fromEntries(\n adapter.threads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"regular\",\n },\n ]) ?? [],\n ),\n ...Object.fromEntries(\n adapter.archivedThreads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"archived\",\n },\n ]) ?? [],\n ),\n };\n }\n\n if (previousThreads !== newThreads) {\n this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n if (previousArchivedThreads !== newArchivedThreads) {\n this._archivedThreads =\n this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n // `initialLoad ||`: `_mainThread!` must be assigned on construction.\n if (initialLoad || previousThreadId !== newThreadId) {\n this._mainThreadId = newThreadId;\n this._mainThread = this.threadFactory();\n }\n\n if (!this._threadData[this._mainThreadId]) {\n this._threadData = {\n ...this._threadData,\n [this._mainThreadId]: {\n id: this._mainThreadId,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n },\n };\n }\n\n this._notifySubscribers();\n }\n\n public async switchToThread(\n threadId: string,\n _options?: { unarchive?: boolean },\n ): Promise<void> {\n if (this._mainThreadId === threadId) return;\n const onSwitchToThread = this.adapter.onSwitchToThread;\n if (!onSwitchToThread)\n throw new Error(\n \"External store adapter does not support switching to thread\",\n );\n await onSwitchToThread(threadId);\n }\n\n public async switchToNewThread(): Promise<void> {\n const onSwitchToNewThread = this.adapter.onSwitchToNewThread;\n if (!onSwitchToNewThread)\n throw new Error(\n \"External store adapter does not support switching to new thread\",\n );\n\n await onSwitchToNewThread();\n }\n\n public async rename(threadId: string, newTitle: string): Promise<void> {\n const onRename = this.adapter.onRename;\n if (!onRename)\n throw new Error(\"External store adapter does not support renaming\");\n\n await onRename(threadId, newTitle);\n }\n\n public async detach(): Promise<void> {\n // no-op\n }\n\n public async archive(threadId: string): Promise<void> {\n const onArchive = this.adapter.onArchive;\n if (!onArchive)\n throw new Error(\"External store adapter does not support archiving\");\n\n await onArchive(threadId);\n }\n\n public async unarchive(threadId: string): Promise<void> {\n const onUnarchive = this.adapter.onUnarchive;\n if (!onUnarchive)\n throw new Error(\"External store adapter does not support unarchiving\");\n\n await onUnarchive(threadId);\n }\n\n public async delete(threadId: string): Promise<void> {\n const onDelete = this.adapter.onDelete;\n if (!onDelete)\n throw new Error(\"External store adapter does not support deleting\");\n\n await onDelete(threadId);\n }\n\n public initialize(\n threadId: string,\n ): Promise<{ remoteId: string; externalId: string | undefined }> {\n return Promise.resolve({ remoteId: threadId, externalId: undefined });\n }\n\n public generateTitle(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n private _subscriptions = new Set<() => void>();\n\n public subscribe(callback: () => void): Unsubscribe {\n this._subscriptions.add(callback);\n return () => this._subscriptions.delete(callback);\n }\n\n private _notifySubscribers() {\n for (const callback of this._subscriptions) callback();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"external-store-thread-list-runtime-core.js","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ExternalStoreThreadRuntimeCore } from \"./external-store-thread-runtime-core\";\nimport type {\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"../../runtime/interfaces/thread-list-runtime-core\";\nimport type { ExternalStoreThreadListAdapter } from \"./external-store-adapter\";\n\nexport type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;\n\nconst EMPTY_ARRAY = Object.freeze([]);\nconst DEFAULT_THREAD_ID = \"DEFAULT_THREAD_ID\";\nconst DEFAULT_THREADS = Object.freeze([DEFAULT_THREAD_ID]);\nconst DEFAULT_THREAD = Object.freeze({\n id: DEFAULT_THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n});\nconst RESOLVED_PROMISE = Promise.resolve();\nconst DEFAULT_THREAD_DATA = Object.freeze({\n [DEFAULT_THREAD_ID]: DEFAULT_THREAD,\n});\n\nexport class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore {\n private _mainThreadId: string = DEFAULT_THREAD_ID;\n private _threads: readonly string[] = DEFAULT_THREADS;\n private _archivedThreads: readonly string[] = EMPTY_ARRAY;\n private _threadData: Readonly<Record<string, ThreadListItemCoreState>> =\n DEFAULT_THREAD_DATA;\n private adapter: ExternalStoreThreadListAdapter = {};\n\n public get isLoading() {\n return this.adapter.isLoading ?? false;\n }\n\n public get newThreadId() {\n return undefined;\n }\n\n public get threadIds() {\n return this._threads;\n }\n\n public get archivedThreadIds() {\n return this._archivedThreads;\n }\n\n public get threadItems() {\n return this._threadData;\n }\n\n public getLoadThreadsPromise() {\n return RESOLVED_PROMISE;\n }\n\n private _mainThread!: ExternalStoreThreadRuntimeCore;\n\n public get mainThreadId() {\n return this._mainThreadId;\n }\n\n constructor(\n adapter: ExternalStoreThreadListAdapter = {},\n private threadFactory: ExternalStoreThreadFactory,\n ) {\n this.__internal_setAdapter(adapter, true);\n }\n\n public getMainThreadRuntimeCore() {\n return this._mainThread;\n }\n\n public getThreadRuntimeCore(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n public getItemById(threadId: string) {\n return this._threadData[threadId];\n }\n\n public __internal_setAdapter(\n adapter: ExternalStoreThreadListAdapter,\n initialLoad = false,\n ) {\n const previousAdapter = this.adapter;\n this.adapter = adapter;\n\n const newThreadId = adapter.threadId ?? DEFAULT_THREAD_ID;\n const newThreads = adapter.threads ?? EMPTY_ARRAY;\n const newArchivedThreads = adapter.archivedThreads ?? EMPTY_ARRAY;\n\n const previousThreadId = previousAdapter.threadId ?? DEFAULT_THREAD_ID;\n const previousThreads = previousAdapter.threads ?? EMPTY_ARRAY;\n const previousArchivedThreads =\n previousAdapter.archivedThreads ?? EMPTY_ARRAY;\n\n if (\n !initialLoad &&\n previousThreadId === newThreadId &&\n previousThreads === newThreads &&\n previousArchivedThreads === newArchivedThreads\n ) {\n return;\n }\n\n if (\n previousThreads !== newThreads ||\n previousArchivedThreads !== newArchivedThreads ||\n previousThreadId !== newThreadId\n ) {\n this._threadData = {\n ...DEFAULT_THREAD_DATA,\n ...Object.fromEntries(\n adapter.threads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"regular\",\n },\n ]) ?? [],\n ),\n ...Object.fromEntries(\n adapter.archivedThreads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"archived\",\n },\n ]) ?? [],\n ),\n };\n }\n\n if (previousThreads !== newThreads) {\n this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n if (previousArchivedThreads !== newArchivedThreads) {\n this._archivedThreads =\n this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n // `initialLoad ||`: `_mainThread!` must be assigned on construction.\n if (initialLoad || previousThreadId !== newThreadId) {\n this._mainThreadId = newThreadId;\n this._mainThread = this.threadFactory();\n }\n\n if (!this._threadData[this._mainThreadId]) {\n this._threadData = {\n ...this._threadData,\n [this._mainThreadId]: {\n id: this._mainThreadId,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n },\n };\n }\n\n this._notifySubscribers();\n }\n\n public async switchToThread(\n threadId: string,\n _options?: { unarchive?: boolean },\n ): Promise<void> {\n if (this._mainThreadId === threadId) return;\n const onSwitchToThread = this.adapter.onSwitchToThread;\n if (!onSwitchToThread)\n throw new Error(\n \"External store adapter does not support switching to thread\",\n );\n await onSwitchToThread(threadId);\n }\n\n public async switchToNewThread(): Promise<void> {\n const onSwitchToNewThread = this.adapter.onSwitchToNewThread;\n if (!onSwitchToNewThread)\n throw new Error(\n \"External store adapter does not support switching to new thread\",\n );\n\n await onSwitchToNewThread();\n }\n\n public async rename(threadId: string, newTitle: string): Promise<void> {\n const onRename = this.adapter.onRename;\n if (!onRename)\n throw new Error(\"External store adapter does not support renaming\");\n\n await onRename(threadId, newTitle);\n }\n\n public async detach(): Promise<void> {\n // no-op\n }\n\n public async archive(threadId: string): Promise<void> {\n const onArchive = this.adapter.onArchive;\n if (!onArchive)\n throw new Error(\"External store adapter does not support archiving\");\n\n await onArchive(threadId);\n }\n\n public async unarchive(threadId: string): Promise<void> {\n const onUnarchive = this.adapter.onUnarchive;\n if (!onUnarchive)\n throw new Error(\"External store adapter does not support unarchiving\");\n\n await onUnarchive(threadId);\n }\n\n public async delete(threadId: string): Promise<void> {\n const onDelete = this.adapter.onDelete;\n if (!onDelete)\n throw new Error(\"External store adapter does not support deleting\");\n\n await onDelete(threadId);\n }\n\n public initialize(\n threadId: string,\n ): Promise<{ remoteId: string; externalId: string | undefined }> {\n return Promise.resolve({ remoteId: threadId, externalId: undefined });\n }\n\n public generateTitle(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n private _subscriptions = new Set<() => void>();\n\n public subscribe(callback: () => void): Unsubscribe {\n this._subscriptions.add(callback);\n return () => this._subscriptions.delete(callback);\n }\n\n private _notifySubscribers() {\n for (const callback of this._subscriptions) callback();\n }\n}\n"],"mappings":"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"}
@@ -12,8 +12,6 @@ import { ExternalStoreAdapter, ExternalStoreThreadListAdapter } from "./external
12
12
  //#region src/runtimes/external-store/external-store-thread-runtime-core.d.ts
13
13
  declare const hasUpcomingMessage: (isRunning: boolean, messages: readonly ThreadMessage[]) => boolean;
14
14
  declare class ExternalStoreThreadRuntimeCore extends BaseThreadRuntimeCore implements ThreadRuntimeCore {
15
- private _assistantOptimisticId;
16
- private _lastSyncedMessageIds;
17
15
  private _capabilities;
18
16
  get capabilities(): RuntimeCapabilities;
19
17
  private _messages;
@@ -35,9 +33,34 @@ declare class ExternalStoreThreadRuntimeCore extends BaseThreadRuntimeCore imple
35
33
  extras: unknown;
36
34
  private _converter;
37
35
  private _store;
36
+ /**
37
+ * Client-side tool-invocations pipeline. Constructed lazily on first
38
+ * snapshot — only when `adapter.unstable_enableToolInvocations === true`.
39
+ */
40
+ private _toolInvocations;
38
41
  beginEdit(messageId: string): void;
39
42
  constructor(contextProvider: ModelContextProvider, store: ExternalStoreAdapter<any>);
40
43
  __internal_setAdapter(store: ExternalStoreAdapter<any>): void;
44
+ /**
45
+ * Feed the current message snapshot into the tool-invocations tracker.
46
+ * Opt-in via `adapter.unstable_enableToolInvocations: true`. The tracker
47
+ * itself is fail-silent — see ToolInvocationTracker for the
48
+ * state-transition contract.
49
+ */
50
+ private _driveToolInvocations;
51
+ /**
52
+ * Lookup table from `toolCallId` to the owning assistant message's `id`,
53
+ * rebuilt lazily when `_messages` changes (see `_messagesForToolCallIndex`).
54
+ */
55
+ private _toolCallToMessageId;
56
+ private _messagesForToolCallIndex;
57
+ /**
58
+ * Look up the assistant message that owns a tool-call part. Lazily builds
59
+ * (and caches) a `toolCallId → messageId` map keyed off the current
60
+ * `_messages` reference, so onResult dispatches stay O(1) instead of
61
+ * walking the full thread on every result.
62
+ */
63
+ private _findMessageIdForToolCall;
41
64
  switchToBranch(branchId: string): void;
42
65
  append(message: AppendMessage): Promise<void>;
43
66
  startRun(config: StartRunConfig): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;cA4Ca,kBAAA,GACX,SAAA,WACA,QAAA,WAAmB,aAAa;AAAA,cAKrB,8BAAA,SACH,qBAAA,YACG,iBAAA;EAAA,QAEH,sBAAA;EAAA,QACA,qBAAA;EAAA,QAEA,aAAA;EAAA,IAeG,YAAA,CAAA,GAAY,mBAAA;EAAA,QAIf,SAAA;EACD,UAAA;EACA,cAAA;EAAA,IACI,SAAA,CAAA;EAAA,IAIA,SAAA,CAAA;EAAA,UAIQ,gBAAA,CAAA,YAA6B,aAAA;EAAA,IAI5B,KAAA,CAAA,gEAAK,kBAAA,oCAAA,iBAAA;EAAA,IAId,QAAA,CAAA;kBARkD,iBAAA;;;;;;;EAYtD,WAAA,WAAsB,gBAAA;EACtB,MAAA;EAAA,QAEC,UAAA;EAAA,QAEA,MAAA;EAEQ,SAAA,CAAU,SAAA;cAQxB,eAAA,EAAiB,oBAAA,EACjB,KAAA,EAAO,oBAAA;EAMF,qBAAA,CAAsB,KAAA,EAAO,oBAAA;EA4JpB,cAAA,CAAe,QAAA;EAalB,MAAA,CAAO,OAAA,EAAS,aAAA,GAAgB,OAAA;EAUhC,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA;EAOlC,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA;EAO1C,mBAAA,CAAA;EAOA,mBAAA,CAAoB,KAAA;EAOpB,SAAA,CAAA;EAkCA,aAAA,CAAc,OAAA,EAAS,oBAAA;EAMvB,cAAA,CAAe,OAAA,EAAS,qBAAA;EAMxB,qBAAA,CAAsB,OAAA,EAAS,4BAAA;EAMtB,KAAA,CAAM,eAAA,YAA2B,iBAAA;EAOjC,MAAA,CAAO,IAAA,EAAM,yBAAA;EAAA,QAWrB,cAAA;AAAA"}
1
+ {"version":3,"file":"external-store-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;cA8Ca,kBAAA,GACX,SAAA,WACA,QAAA,WAAmB,aAAa;AAAA,cAKrB,8BAAA,SACH,qBAAA,YACG,iBAAA;EAAA,QAEH,aAAA;EAAA,IAeG,YAAA,IAAY,mBAAA;EAAA,QAIf,SAAA;EACD,UAAA;EACA,cAAA;EAAA,IACI,SAAA;EAAA,IAIA,SAAA;EAAA,UAIQ,gBAAA,aAA6B,aAAA;EAAA,IAI5B,KAAA,iEAAK,kBAAA,oCAAA,iBAAA;EAAA,IAId,QAAA;kBARkD,iBAAA;;;;;;;EAYtD,WAAA,WAAsB,gBAAA;EACtB,MAAA;EAAA,QAEC,UAAA;EAAA,QAEA,MAAA;;;;;UAMA,gBAAA;EAEQ,SAAA,CAAU,SAAA;cAQxB,eAAA,EAAiB,oBAAA,EACjB,KAAA,EAAO,oBAAA;EAMF,qBAAA,CAAsB,KAAA,EAAO,oBAAA;EAuQS;;;;;;EAAA,QA5GrC,qBAAA;EA+O8B;;;;EAAA,QA5K9B,oBAAA;EAAA,QACA,yBAAA;EAvSoB;;;;;;EAAA,QA+SpB,yBAAA;EAmBQ,cAAA,CAAe,QAAA;EAalB,MAAA,CAAO,OAAA,EAAS,aAAA,GAAgB,OAAA;EAoBhC,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA;EAYlC,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA;EAO1C,mBAAA;EAOA,mBAAA,CAAoB,KAAA;EAmBpB,SAAA;EAwCA,aAAA,CAAc,OAAA,EAAS,oBAAA;EAMvB,cAAA,CAAe,OAAA,EAAS,qBAAA;EAoBxB,qBAAA,CAAsB,OAAA,EAAS,4BAAA;EAMtB,KAAA,CAAM,eAAA,YAA2B,iBAAA;EAMjC,MAAA,CAAO,IAAA,EAAM,yBAAA;EAAA,QAQrB,cAAA;AAAA"}