@assistant-ui/core 0.2.18 → 0.2.20

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 (231) hide show
  1. package/dist/index.d.ts +4 -2
  2. package/dist/index.js +3 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/internal.d.ts +2 -1
  5. package/dist/internal.js +2 -1
  6. package/dist/model-context/interactable-composer-metadata.d.ts +105 -0
  7. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -0
  8. package/dist/model-context/interactable-composer-metadata.js +259 -0
  9. package/dist/model-context/interactable-composer-metadata.js.map +1 -0
  10. package/dist/model-context/registry.d.ts.map +1 -1
  11. package/dist/model-context/registry.js +1 -0
  12. package/dist/model-context/registry.js.map +1 -1
  13. package/dist/model-context/types.d.ts +6 -0
  14. package/dist/model-context/types.d.ts.map +1 -1
  15. package/dist/model-context/types.js +4 -0
  16. package/dist/model-context/types.js.map +1 -1
  17. package/dist/react/AssistantProvider.d.ts +1 -1
  18. package/dist/react/AssistantProvider.js +1 -1
  19. package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
  20. package/dist/react/RuntimeAdapter.js +1 -1
  21. package/dist/react/client/Interactables.d.ts +8 -2
  22. package/dist/react/client/Interactables.d.ts.map +1 -1
  23. package/dist/react/client/Interactables.js +190 -94
  24. package/dist/react/client/Interactables.js.map +1 -1
  25. package/dist/react/client/Tools.js +1 -1
  26. package/dist/react/client/interactable-model-context.d.ts +9 -6
  27. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  28. package/dist/react/client/interactable-model-context.js +154 -32
  29. package/dist/react/client/interactable-model-context.js.map +1 -1
  30. package/dist/react/index.d.ts +15 -6
  31. package/dist/react/index.js +12 -5
  32. package/dist/react/interactables-legacy/Interactables.d.ts +12 -0
  33. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -0
  34. package/dist/react/interactables-legacy/Interactables.js +264 -0
  35. package/dist/react/interactables-legacy/Interactables.js.map +1 -0
  36. package/dist/react/interactables-legacy/interactable-model-context.d.ts +12 -0
  37. package/dist/react/interactables-legacy/interactable-model-context.d.ts.map +1 -0
  38. package/dist/react/interactables-legacy/interactable-model-context.js +54 -0
  39. package/dist/react/interactables-legacy/interactable-model-context.js.map +1 -0
  40. package/dist/react/interactables-legacy/scopes.d.ts +58 -0
  41. package/dist/react/interactables-legacy/scopes.d.ts.map +1 -0
  42. package/dist/react/interactables-legacy/scopes.js +0 -0
  43. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts +31 -0
  44. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -0
  45. package/dist/react/{model-context → interactables-legacy}/useAssistantInteractable.js +6 -2
  46. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -0
  47. package/dist/react/interactables-legacy/useInteractableState.d.ts +21 -0
  48. package/dist/react/interactables-legacy/useInteractableState.d.ts.map +1 -0
  49. package/dist/react/interactables-legacy/useInteractableState.js +84 -0
  50. package/dist/react/interactables-legacy/useInteractableState.js.map +1 -0
  51. package/dist/react/model-context/interactableTool.d.ts +53 -0
  52. package/dist/react/model-context/interactableTool.d.ts.map +1 -0
  53. package/dist/react/model-context/interactableTool.js +188 -0
  54. package/dist/react/model-context/interactableTool.js.map +1 -0
  55. package/dist/react/model-context/useAssistantContext.js +1 -1
  56. package/dist/react/model-context/useAssistantDataUI.js +1 -1
  57. package/dist/react/model-context/useAssistantInstructions.js +1 -1
  58. package/dist/react/model-context/useAssistantTool.js +1 -1
  59. package/dist/react/model-context/useAssistantToolUI.js +1 -1
  60. package/dist/react/model-context/useAuiToolOverrides.js +1 -1
  61. package/dist/react/model-context/useInteractable.d.ts +73 -0
  62. package/dist/react/model-context/useInteractable.d.ts.map +1 -0
  63. package/dist/react/model-context/useInteractable.js +100 -0
  64. package/dist/react/model-context/useInteractable.js.map +1 -0
  65. package/dist/react/model-context/useInteractableState.d.ts +8 -5
  66. package/dist/react/model-context/useInteractableState.d.ts.map +1 -1
  67. package/dist/react/model-context/useInteractableState.js +48 -48
  68. package/dist/react/model-context/useInteractableState.js.map +1 -1
  69. package/dist/react/model-context/useInteractableVersions.d.ts +19 -0
  70. package/dist/react/model-context/useInteractableVersions.d.ts.map +1 -0
  71. package/dist/react/model-context/useInteractableVersions.js +51 -0
  72. package/dist/react/model-context/useInteractableVersions.js.map +1 -0
  73. package/dist/react/primitive-hooks/useThreadMessageIds.d.ts +15 -0
  74. package/dist/react/primitive-hooks/useThreadMessageIds.d.ts.map +1 -0
  75. package/dist/react/primitive-hooks/useThreadMessageIds.js +26 -0
  76. package/dist/react/primitive-hooks/useThreadMessageIds.js.map +1 -0
  77. package/dist/react/primitive-hooks/useVoice.js +1 -1
  78. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  79. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  80. package/dist/react/primitives/composer/ComposerQueue.js +1 -1
  81. package/dist/react/primitives/generativeUI/GenerativeUI.d.ts.map +1 -1
  82. package/dist/react/primitives/generativeUI/GenerativeUI.js +2 -2
  83. package/dist/react/primitives/generativeUI/GenerativeUI.js.map +1 -1
  84. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  85. package/dist/react/primitives/message/MessageGroupedParts.js +1 -1
  86. package/dist/react/primitives/message/MessageParts.js +1 -1
  87. package/dist/react/primitives/message/MessageQuote.js +1 -1
  88. package/dist/react/primitives/part/PartMessages.d.ts +5 -2
  89. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  90. package/dist/react/primitives/part/PartMessages.js +8 -8
  91. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  92. package/dist/react/primitives/thread/ThreadMessages.d.ts +31 -1
  93. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  94. package/dist/react/primitives/thread/ThreadMessages.js +64 -2
  95. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  96. package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
  97. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  98. package/dist/react/providers/MessageByIdProvider.d.ts +9 -0
  99. package/dist/react/providers/MessageByIdProvider.d.ts.map +1 -0
  100. package/dist/react/providers/MessageByIdProvider.js +57 -0
  101. package/dist/react/providers/MessageByIdProvider.js.map +1 -0
  102. package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
  103. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
  104. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +3 -0
  105. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  106. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +16 -1
  107. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  108. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +1 -1
  109. package/dist/react/runtimes/cloud/auiV0.js +1 -1
  110. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +1 -1
  111. package/dist/react/runtimes/createRuntimeExtras.d.ts +20 -0
  112. package/dist/react/runtimes/createRuntimeExtras.d.ts.map +1 -0
  113. package/dist/react/runtimes/createRuntimeExtras.js +43 -0
  114. package/dist/react/runtimes/createRuntimeExtras.js.map +1 -0
  115. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  116. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  117. package/dist/react/runtimes/useRemoteThreadListRuntime.js +6 -2
  118. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  119. package/dist/react/runtimes/useStreamingTiming.d.ts +26 -0
  120. package/dist/react/runtimes/useStreamingTiming.d.ts.map +1 -0
  121. package/dist/react/runtimes/useStreamingTiming.js +43 -0
  122. package/dist/react/runtimes/useStreamingTiming.js.map +1 -0
  123. package/dist/react/types/scopes/interactables.d.ts +40 -24
  124. package/dist/react/types/scopes/interactables.d.ts.map +1 -1
  125. package/dist/react/types/store-augmentation.d.ts +3 -1
  126. package/dist/react/types/store-augmentation.d.ts.map +1 -1
  127. package/dist/react/utils/useJSONEqual.d.ts +11 -0
  128. package/dist/react/utils/useJSONEqual.d.ts.map +1 -0
  129. package/dist/react/utils/useJSONEqual.js +30 -0
  130. package/dist/react/utils/useJSONEqual.js.map +1 -0
  131. package/dist/runtime/base/base-composer-runtime-core.d.ts +5 -0
  132. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  133. package/dist/runtime/base/base-composer-runtime-core.js +13 -0
  134. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  135. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  136. package/dist/runtime/base/default-edit-composer-runtime-core.js +6 -1
  137. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  138. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  139. package/dist/runtime/base/default-thread-composer-runtime-core.js +4 -1
  140. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  141. package/dist/runtime/utils/message-repository.d.ts +1 -0
  142. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  143. package/dist/runtime/utils/message-repository.js +6 -3
  144. package/dist/runtime/utils/message-repository.js.map +1 -1
  145. package/dist/runtime/utils/streaming-timing.d.ts +59 -0
  146. package/dist/runtime/utils/streaming-timing.d.ts.map +1 -0
  147. package/dist/runtime/utils/streaming-timing.js +76 -0
  148. package/dist/runtime/utils/streaming-timing.js.map +1 -0
  149. package/dist/runtime/utils/thread-message-like.js +2 -1
  150. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  151. package/dist/runtimes/external-store/external-store-adapter.d.ts +26 -1
  152. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  153. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +9 -0
  154. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  155. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +19 -0
  156. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  157. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  158. package/dist/runtimes/local/local-thread-runtime-core.js +1 -1
  159. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  160. package/dist/runtimes/remote-thread-list/types.d.ts +12 -0
  161. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  162. package/dist/store/clients/suggestions.js +1 -1
  163. package/dist/store/clients/thread-message-client.js +1 -1
  164. package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
  165. package/dist/store/runtime-clients/message-runtime-client.js +1 -1
  166. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  167. package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
  168. package/dist/tests/remote-thread-list-test-helpers.d.ts +1 -1
  169. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  170. package/dist/tests/remote-thread-list-test-helpers.js +3 -2
  171. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
  172. package/package.json +9 -9
  173. package/src/index.ts +17 -0
  174. package/src/internal.ts +7 -0
  175. package/src/model-context/interactable-composer-metadata.test.ts +550 -0
  176. package/src/model-context/interactable-composer-metadata.ts +395 -0
  177. package/src/model-context/registry.ts +5 -0
  178. package/src/model-context/types.ts +12 -0
  179. package/src/react/client/Interactables.test.ts +358 -0
  180. package/src/react/client/Interactables.ts +339 -86
  181. package/src/react/client/interactable-model-context.test.ts +418 -0
  182. package/src/react/client/interactable-model-context.ts +252 -58
  183. package/src/react/index.ts +72 -3
  184. package/src/react/interactables-legacy/Interactables.ts +332 -0
  185. package/src/react/interactables-legacy/interactable-model-context.test.ts +54 -0
  186. package/src/react/interactables-legacy/interactable-model-context.ts +80 -0
  187. package/src/react/interactables-legacy/scopes.ts +66 -0
  188. package/src/react/{model-context → interactables-legacy}/useAssistantInteractable.ts +10 -1
  189. package/src/react/interactables-legacy/useInteractableState.ts +67 -0
  190. package/src/react/model-context/interactableTool.tsx +175 -0
  191. package/src/react/model-context/useInteractable.ts +233 -0
  192. package/src/react/model-context/useInteractableState.ts +31 -23
  193. package/src/react/model-context/useInteractableVersions.ts +48 -0
  194. package/src/react/primitive-hooks/useThreadMessageIds.ts +27 -0
  195. package/src/react/primitives/generativeUI/GenerativeUI.tsx +5 -1
  196. package/src/react/primitives/part/PartMessages.test.tsx +17 -0
  197. package/src/react/primitives/part/PartMessages.tsx +13 -8
  198. package/src/react/primitives/thread/ThreadMessages.tsx +67 -0
  199. package/src/react/providers/MessageByIdProvider.tsx +23 -0
  200. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +21 -1
  201. package/src/react/runtimes/createRuntimeExtras.test.ts +58 -0
  202. package/src/react/runtimes/createRuntimeExtras.ts +68 -0
  203. package/src/react/runtimes/createRuntimeExtras.use.test.ts +50 -0
  204. package/src/react/runtimes/useRemoteThreadListRuntime.ts +13 -1
  205. package/src/react/runtimes/useStreamingTiming.ts +68 -0
  206. package/src/react/types/scopes/interactables.ts +45 -23
  207. package/src/react/types/store-augmentation.ts +4 -2
  208. package/src/react/utils/useJSONEqual.ts +20 -0
  209. package/src/runtime/base/base-composer-runtime-core.ts +13 -0
  210. package/src/runtime/base/default-edit-composer-runtime-core.ts +18 -1
  211. package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
  212. package/src/runtime/utils/message-repository.ts +11 -7
  213. package/src/runtime/utils/streaming-timing.test.ts +301 -0
  214. package/src/runtime/utils/streaming-timing.ts +161 -0
  215. package/src/runtime/utils/thread-message-like.ts +2 -1
  216. package/src/runtimes/external-store/external-store-adapter.ts +28 -0
  217. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +33 -1
  218. package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
  219. package/src/runtimes/remote-thread-list/types.ts +13 -0
  220. package/src/tests/MessageRepository.test.ts +2 -0
  221. package/src/tests/composer-can-send.test.ts +1 -0
  222. package/src/tests/default-edit-composer-runtime-core.test.ts +78 -1
  223. package/src/tests/default-thread-composer-runtime-core.test.ts +82 -0
  224. package/src/tests/external-store-thread-runtime-core.test.ts +337 -0
  225. package/src/tests/groupParts.test.ts +32 -0
  226. package/src/tests/remote-thread-list-reactive-threadId.test.ts +90 -0
  227. package/src/tests/remote-thread-list-test-helpers.ts +2 -1
  228. package/src/tests/thread-message-like.test.ts +50 -0
  229. package/dist/react/model-context/useAssistantInteractable.d.ts +0 -22
  230. package/dist/react/model-context/useAssistantInteractable.d.ts.map +0 -1
  231. package/dist/react/model-context/useAssistantInteractable.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRuntimeExtras.js","names":["useAuiState","AssistantClient","RuntimeExtras","provide","value","T","is","extras","tryGet","get","client","use","select","S","fallback","createRuntimeExtras","runtimeName","brand","Symbol","assert","Error","Object","defineProperty","enumerable","configurable","undefined","thread","getState","rest","hasFallback","length","s"],"sources":["../../../src/react/runtimes/createRuntimeExtras.ts"],"sourcesContent":["\"use client\";\n\nimport { useAuiState } from \"@assistant-ui/store\";\nimport type { AssistantClient } from \"@assistant-ui/store\";\n\n/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */\nexport type RuntimeExtras<T extends object> = {\n provide: (value: T) => T;\n is: (extras: unknown) => extras is T;\n tryGet: (extras: unknown) => T | undefined;\n get: (client: AssistantClient) => T;\n use: {\n (): T;\n <S>(select: (extras: T) => S): S;\n <S>(select: (extras: T) => S, fallback: S): S;\n };\n};\n\n/** @deprecated Internal API for external-store adapter authors. Not part of the public API; may change or be removed without notice. */\nexport const createRuntimeExtras = <T extends object>(\n runtimeName: string,\n): RuntimeExtras<T> => {\n const brand = Symbol(`${runtimeName} extras`);\n\n const is = (extras: unknown): extras is T =>\n typeof extras === \"object\" && extras !== null && brand in extras;\n\n const assert = (extras: unknown): T => {\n if (!is(extras))\n throw new Error(\n `The current thread is not backed by the ${runtimeName} runtime.`,\n );\n return extras;\n };\n\n const provide = (value: T): T => {\n Object.defineProperty(value, brand, {\n value: true,\n enumerable: false,\n configurable: true,\n });\n return value;\n };\n\n const tryGet = (extras: unknown): T | undefined =>\n is(extras) ? extras : undefined;\n\n const get = (client: AssistantClient): T =>\n assert(client.thread().getState().extras);\n\n function use<S>(\n select?: (extras: T) => S,\n ...rest: [fallback: S] | []\n ): S | T {\n // Detect a provided fallback by arity, not value: callers pass an explicit\n // `undefined` fallback, which must return `undefined` rather than throw.\n const hasFallback = rest.length > 0;\n const fallback = rest[0] as S;\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (is(extras)) return select ? select(extras) : extras;\n if (hasFallback) return fallback;\n return assert(extras);\n });\n }\n\n return { provide, is, tryGet, get, use: use as RuntimeExtras<T>[\"use\"] };\n};\n"],"mappings":";;;;AAmBA,MAAae,uBACXC,gBACqB;CACrB,MAAMC,QAAQC,OAAO,GAAGF,YAAW,QAAS;CAE5C,MAAMV,MAAMC,WACV,OAAOA,WAAW,YAAYA,WAAW,QAAQU,SAASV;CAE5D,MAAMY,UAAUZ,WAAuB;EACrC,IAAI,CAACD,GAAGC,MAAM,GACZ,MAAM,IAAIa,MACR,2CAA2CJ,YAAW,UACxD;EACF,OAAOT;CACT;CAEA,MAAMJ,WAAWC,UAAgB;EAC/BiB,OAAOC,eAAelB,OAAOa,OAAO;GAClCb,OAAO;GACPmB,YAAY;GACZC,cAAc;EAChB,CAAC;EACD,OAAOpB;CACT;CAEA,MAAMI,UAAUD,WACdD,GAAGC,MAAM,IAAIA,SAASkB,KAAAA;CAExB,MAAMhB,OAAOC,WACXS,OAAOT,OAAOgB,OAAO,CAAC,CAACC,SAAS,CAAC,CAACpB,MAAM;CAE1C,SAASI,IACPC,QACA,GAAGgB,MACI;EAGP,MAAMC,cAAcD,KAAKE,SAAS;EAClC,MAAMhB,WAAWc,KAAK;EACtB,OAAO5B,aAAa+B,MAAM;GACxB,MAAMxB,SAASwB,EAAEL,OAAOnB;GACxB,IAAID,GAAGC,MAAM,GAAG,OAAOK,SAASA,OAAOL,MAAM,IAAIA;GACjD,IAAIsB,aAAa,OAAOf;GACxB,OAAOK,OAAOZ,MAAM;EACtB,CAAC;CACH;CAEA,OAAO;EAAEJ;EAASG;EAAIE;EAAQC;EAAUE;CAA+B;AACzE"}
@@ -3,8 +3,8 @@ import { LocalRuntimeCore } from "../../runtimes/local/local-runtime-core.js";
3
3
  import { useRuntimeAdapters } from "./RuntimeAdapterProvider.js";
4
4
  import { useRemoteThreadListRuntime } from "./useRemoteThreadListRuntime.js";
5
5
  import { useCloudThreadListAdapter } from "./cloud/useCloudThreadListAdapter.js";
6
- import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
7
6
  import { useAuiState } from "@assistant-ui/store";
7
+ import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
8
8
  //#region src/react/runtimes/useLocalRuntime.ts
9
9
  const useLocalThreadRuntime = (chatModel, { initialMessages, ...options }) => {
10
10
  const { modelContext, ...threadListAdapters } = useRuntimeAdapters() ?? {};
@@ -1 +1 @@
1
- {"version":3,"file":"useRemoteThreadListRuntime.d.ts","names":[],"sources":["../../../src/react/runtimes/useRemoteThreadListRuntime.ts"],"mappings":";;;;cAwCa,0BAAA,GACX,OAAA,EAAS,uBAAA,KACR,gBAmDF"}
1
+ {"version":3,"file":"useRemoteThreadListRuntime.d.ts","names":[],"sources":["../../../src/react/runtimes/useRemoteThreadListRuntime.ts"],"mappings":";;;;cA+Ca,0BAAA,GACX,OAAA,EAAS,uBAAA,KACR,gBAwDF"}
@@ -1,8 +1,8 @@
1
1
  import { BaseAssistantRuntimeCore } from "../../runtime/base/base-assistant-runtime-core.js";
2
2
  import { AssistantRuntimeImpl } from "../../runtime/api/assistant-runtime.js";
3
3
  import { RemoteThreadListThreadListRuntimeCore } from "./RemoteThreadListThreadListRuntimeCore.js";
4
- import { useCallback, useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
5
4
  import { useAui } from "@assistant-ui/store";
5
+ import { useCallback, useEffect, useEffectEvent, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
6
6
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
7
7
  //#region src/react/runtimes/useRemoteThreadListRuntime.ts
8
8
  var RemoteThreadListRuntimeCore = class extends BaseAssistantRuntimeCore {
@@ -57,11 +57,15 @@ const useRemoteThreadListRuntime = (options) => {
57
57
  const stableRuntimeHook = useCallback(() => {
58
58
  return runtimeHookRef.current();
59
59
  }, []);
60
+ const onThreadIdChange = useEffectEvent((threadId) => {
61
+ options.onThreadIdChange?.(threadId);
62
+ });
60
63
  const stableOptions = useMemo(() => ({
61
64
  adapter: options.adapter,
62
65
  allowNesting: options.allowNesting,
63
66
  initialThreadId: startThreadIdRef.current,
64
- runtimeHook: stableRuntimeHook
67
+ runtimeHook: stableRuntimeHook,
68
+ onThreadIdChange
65
69
  }), [
66
70
  options.adapter,
67
71
  options.allowNesting,
@@ -1 +1 @@
1
- {"version":3,"file":"useRemoteThreadListRuntime.js","names":["useState","useEffect","useMemo","useRef","useCallback","BaseAssistantRuntimeCore","AssistantRuntimeImpl","RemoteThreadListOptions","AssistantRuntimeCore","AssistantRuntime","RemoteThreadListThreadListRuntimeCore","useAui","RemoteThreadListRuntimeCore","threads","constructor","options","_contextProvider","RenderComponent","__internal_RenderComponent","useRemoteThreadListRuntimeImpl","$","_c","t0","runtime","t1","__internal_setOptions","__internal_load","t2","t3","useRemoteThreadListRuntime","runtimeHookRef","runtimeHook","current","startThreadIdRef","threadId","initialThreadId","stableRuntimeHook","stableOptions","adapter","allowNesting","aui","isNested","threadListItem","source","Error","prevThreadIdRef","switchToThread","catch","switchToNewThread"],"sources":["../../../src/react/runtimes/useRemoteThreadListRuntime.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { BaseAssistantRuntimeCore } from \"../../runtime/base/base-assistant-runtime-core\";\nimport { AssistantRuntimeImpl } from \"../../runtime/api/assistant-runtime\";\nimport type { RemoteThreadListOptions } from \"../../runtimes/remote-thread-list/types\";\nimport type { AssistantRuntimeCore } from \"../../runtime/interfaces/assistant-runtime-core\";\nimport type { AssistantRuntime } from \"../../runtime/api/assistant-runtime\";\nimport { RemoteThreadListThreadListRuntimeCore } from \"./RemoteThreadListThreadListRuntimeCore\";\nimport { useAui } from \"@assistant-ui/store\";\n\nclass RemoteThreadListRuntimeCore\n extends BaseAssistantRuntimeCore\n implements AssistantRuntimeCore\n{\n public readonly threads;\n\n constructor(options: RemoteThreadListOptions) {\n super();\n this.threads = new RemoteThreadListThreadListRuntimeCore(\n options,\n this._contextProvider,\n );\n }\n\n public get RenderComponent() {\n return this.threads.__internal_RenderComponent;\n }\n}\n\nconst useRemoteThreadListRuntimeImpl = (\n options: RemoteThreadListOptions,\n): AssistantRuntime => {\n const [runtime] = useState(() => new RemoteThreadListRuntimeCore(options));\n useEffect(() => {\n runtime.threads.__internal_setOptions(options);\n runtime.threads.__internal_load();\n }, [runtime, options]);\n\n return useMemo(() => new AssistantRuntimeImpl(runtime), [runtime]);\n};\n\nexport const useRemoteThreadListRuntime = (\n options: RemoteThreadListOptions,\n): AssistantRuntime => {\n const runtimeHookRef = useRef(options.runtimeHook);\n runtimeHookRef.current = options.runtimeHook;\n\n // threadId/initialThreadId only affect the constructor; capture once via ref\n const startThreadIdRef = useRef(options.threadId ?? options.initialThreadId);\n\n const stableRuntimeHook = useCallback(() => {\n return runtimeHookRef.current();\n }, []);\n\n const stableOptions = useMemo<RemoteThreadListOptions>(\n () => ({\n adapter: options.adapter,\n allowNesting: options.allowNesting,\n initialThreadId: startThreadIdRef.current,\n runtimeHook: stableRuntimeHook,\n }),\n [options.adapter, options.allowNesting, stableRuntimeHook],\n );\n\n const aui = useAui();\n const isNested = aui.threadListItem.source !== null;\n\n if (isNested) {\n if (!stableOptions.allowNesting) {\n throw new Error(\n \"useRemoteThreadListRuntime cannot be nested inside another RemoteThreadListRuntime. \" +\n \"Set allowNesting: true to allow nesting (the inner runtime will become a no-op).\",\n );\n }\n\n // If allowNesting is true and already inside a thread list context,\n // just call the runtimeHook directly (no-op behavior)\n return stableRuntimeHook();\n }\n\n const runtime = useRemoteThreadListRuntimeImpl(stableOptions);\n\n const prevThreadIdRef = useRef(options.threadId);\n useEffect(() => {\n if (options.threadId === prevThreadIdRef.current) return;\n prevThreadIdRef.current = options.threadId;\n if (options.threadId) {\n runtime.threads.switchToThread(options.threadId).catch(() => {});\n } else {\n runtime.threads.switchToNewThread().catch(() => {});\n }\n }, [runtime, options.threadId]);\n\n return runtime;\n};\n"],"mappings":";;;;;;;AASA,IAAMY,8BAAN,cACUP,yBAEV;CACE;CAEAS,YAAYC,SAAkC;EAC5C,MAAM;EACN,KAAKF,UAAU,IAAIH,sCACjBK,SACA,KAAKC,gBACP;CACF;CAEA,IAAWC,kBAAkB;EAC3B,OAAO,KAAKJ,QAAQK;CACtB;AACF;AAEA,MAAMC,kCAAiCJ,YAAA;CAAA,MAAAK,IAAAC,EAAA,EAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAL,SAAA;EAGVO,WAAM,IAAIV,4BAA4BG,OAAO;EAACK,EAAA,KAAAL;EAAAK,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAzE,MAAA,CAAAG,WAAkBvB,SAASsB,EAA8C;CAAE,IAAAE;CAAA,IAAAJ,EAAA,OAAAL,WAAAK,EAAA,OAAAG,QAAAV,SAAA;EACjEW,WAAA;GACRD,QAAOV,QAAQY,sBAAuBV,OAAO;GAC7CQ,QAAOV,QAAQa,gBAAiB;EAAC;EAClCN,EAAA,KAAAL;EAAAK,EAAA,KAAAG,QAAAV;EAAAO,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,IAAAO;CAAA,IAAAP,EAAA,OAAAL,WAAAK,EAAA,OAAAG,SAAA;EAAEI,KAAA,CAACJ,SAASR,OAAO;EAACK,EAAA,KAAAL;EAAAK,EAAA,KAAAG;EAAAH,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAHrBnB,UAAUuB,IAGPG,EAAkB;CAAC,IAAAC;CAAA,IAAAR,EAAA,OAAAG,SAAA;EAEDK,KAAA,IAAItB,qBAAqBiB,OAAO;EAACH,EAAA,KAAAG;EAAAH,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAAjCQ;AAAiC;AAGxD,MAAaC,8BACXd,YACqB;CACrB,MAAMe,iBAAiB3B,OAAOY,QAAQgB,WAAW;CACjDD,eAAeE,UAAUjB,QAAQgB;CAGjC,MAAME,mBAAmB9B,OAAOY,QAAQmB,YAAYnB,QAAQoB,eAAe;CAE3E,MAAMC,oBAAoBhC,kBAAkB;EAC1C,OAAO0B,eAAeE,QAAQ;CAChC,GAAG,CAAA,CAAE;CAEL,MAAMK,gBAAgBnC,eACb;EACLoC,SAASvB,QAAQuB;EACjBC,cAAcxB,QAAQwB;EACtBJ,iBAAiBF,iBAAiBD;EAClCD,aAAaK;CACf,IACA;EAACrB,QAAQuB;EAASvB,QAAQwB;EAAcH;CAAiB,CAC3D;CAKA,IAHYzB,OACK6B,CAAG,CAACE,eAAeC,WAAW,MAEjC;EACZ,IAAI,CAACN,cAAcE,cACjB,MAAM,IAAIK,MACR,sKAEF;EAKF,OAAOR,kBAAkB;CAC3B;CAEA,MAAMb,UAAUJ,+BAA+BkB,aAAa;CAE5D,MAAMQ,kBAAkB1C,OAAOY,QAAQmB,QAAQ;CAC/CjC,gBAAgB;EACd,IAAIc,QAAQmB,aAAaW,gBAAgBb,SAAS;EAClDa,gBAAgBb,UAAUjB,QAAQmB;EAClC,IAAInB,QAAQmB,UACVX,QAAQV,QAAQiC,eAAe/B,QAAQmB,QAAQ,CAAC,CAACa,YAAY,CAAC,CAAC;OAE/DxB,QAAQV,QAAQmC,kBAAkB,CAAC,CAACD,YAAY,CAAC,CAAC;CAEtD,GAAG,CAACxB,SAASR,QAAQmB,QAAQ,CAAC;CAE9B,OAAOX;AACT"}
1
+ {"version":3,"file":"useRemoteThreadListRuntime.js","names":["useState","useEffect","useMemo","useRef","useCallback","useEffectEvent","BaseAssistantRuntimeCore","AssistantRuntimeImpl","RemoteThreadListOptions","AssistantRuntimeCore","AssistantRuntime","RemoteThreadListThreadListRuntimeCore","useAui","RemoteThreadListRuntimeCore","threads","constructor","options","_contextProvider","RenderComponent","__internal_RenderComponent","useRemoteThreadListRuntimeImpl","$","_c","t0","runtime","t1","__internal_setOptions","__internal_load","t2","t3","useRemoteThreadListRuntime","runtimeHookRef","runtimeHook","current","startThreadIdRef","threadId","initialThreadId","stableRuntimeHook","onThreadIdChange","stableOptions","adapter","allowNesting","aui","isNested","threadListItem","source","Error","prevThreadIdRef","switchToThread","catch","switchToNewThread"],"sources":["../../../src/react/runtimes/useRemoteThreadListRuntime.ts"],"sourcesContent":["import {\n useState,\n useEffect,\n useMemo,\n useRef,\n useCallback,\n useEffectEvent,\n} from \"react\";\nimport { BaseAssistantRuntimeCore } from \"../../runtime/base/base-assistant-runtime-core\";\nimport { AssistantRuntimeImpl } from \"../../runtime/api/assistant-runtime\";\nimport type { RemoteThreadListOptions } from \"../../runtimes/remote-thread-list/types\";\nimport type { AssistantRuntimeCore } from \"../../runtime/interfaces/assistant-runtime-core\";\nimport type { AssistantRuntime } from \"../../runtime/api/assistant-runtime\";\nimport { RemoteThreadListThreadListRuntimeCore } from \"./RemoteThreadListThreadListRuntimeCore\";\nimport { useAui } from \"@assistant-ui/store\";\n\nclass RemoteThreadListRuntimeCore\n extends BaseAssistantRuntimeCore\n implements AssistantRuntimeCore\n{\n public readonly threads;\n\n constructor(options: RemoteThreadListOptions) {\n super();\n this.threads = new RemoteThreadListThreadListRuntimeCore(\n options,\n this._contextProvider,\n );\n }\n\n public get RenderComponent() {\n return this.threads.__internal_RenderComponent;\n }\n}\n\nconst useRemoteThreadListRuntimeImpl = (\n options: RemoteThreadListOptions,\n): AssistantRuntime => {\n const [runtime] = useState(() => new RemoteThreadListRuntimeCore(options));\n useEffect(() => {\n runtime.threads.__internal_setOptions(options);\n runtime.threads.__internal_load();\n }, [runtime, options]);\n\n return useMemo(() => new AssistantRuntimeImpl(runtime), [runtime]);\n};\n\nexport const useRemoteThreadListRuntime = (\n options: RemoteThreadListOptions,\n): AssistantRuntime => {\n const runtimeHookRef = useRef(options.runtimeHook);\n runtimeHookRef.current = options.runtimeHook;\n\n // threadId/initialThreadId only affect the constructor; capture once via ref\n const startThreadIdRef = useRef(options.threadId ?? options.initialThreadId);\n\n const stableRuntimeHook = useCallback(() => {\n return runtimeHookRef.current();\n }, []);\n\n const onThreadIdChange = useEffectEvent((threadId: string | undefined) => {\n options.onThreadIdChange?.(threadId);\n });\n\n const stableOptions = useMemo<RemoteThreadListOptions>(\n () => ({\n adapter: options.adapter,\n allowNesting: options.allowNesting,\n initialThreadId: startThreadIdRef.current,\n runtimeHook: stableRuntimeHook,\n onThreadIdChange,\n }),\n [options.adapter, options.allowNesting, stableRuntimeHook],\n );\n\n const aui = useAui();\n const isNested = aui.threadListItem.source !== null;\n\n if (isNested) {\n if (!stableOptions.allowNesting) {\n throw new Error(\n \"useRemoteThreadListRuntime cannot be nested inside another RemoteThreadListRuntime. \" +\n \"Set allowNesting: true to allow nesting (the inner runtime will become a no-op).\",\n );\n }\n\n // If allowNesting is true and already inside a thread list context,\n // just call the runtimeHook directly (no-op behavior)\n return stableRuntimeHook();\n }\n\n const runtime = useRemoteThreadListRuntimeImpl(stableOptions);\n\n const prevThreadIdRef = useRef(options.threadId);\n useEffect(() => {\n if (options.threadId === prevThreadIdRef.current) return;\n prevThreadIdRef.current = options.threadId;\n if (options.threadId) {\n runtime.threads.switchToThread(options.threadId).catch(() => {});\n } else {\n runtime.threads.switchToNewThread().catch(() => {});\n }\n }, [runtime, options.threadId]);\n\n return runtime;\n};\n"],"mappings":";;;;;;;AAgBA,IAAMa,8BAAN,cACUP,yBAEV;CACE;CAEAS,YAAYC,SAAkC;EAC5C,MAAM;EACN,KAAKF,UAAU,IAAIH,sCACjBK,SACA,KAAKC,gBACP;CACF;CAEA,IAAWC,kBAAkB;EAC3B,OAAO,KAAKJ,QAAQK;CACtB;AACF;AAEA,MAAMC,kCAAiCJ,YAAA;CAAA,MAAAK,IAAAC,EAAA,EAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAL,SAAA;EAGVO,WAAM,IAAIV,4BAA4BG,OAAO;EAACK,EAAA,KAAAL;EAAAK,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAzE,MAAA,CAAAG,WAAkBxB,SAASuB,EAA8C;CAAE,IAAAE;CAAA,IAAAJ,EAAA,OAAAL,WAAAK,EAAA,OAAAG,QAAAV,SAAA;EACjEW,WAAA;GACRD,QAAOV,QAAQY,sBAAuBV,OAAO;GAC7CQ,QAAOV,QAAQa,gBAAiB;EAAC;EAClCN,EAAA,KAAAL;EAAAK,EAAA,KAAAG,QAAAV;EAAAO,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,IAAAO;CAAA,IAAAP,EAAA,OAAAL,WAAAK,EAAA,OAAAG,SAAA;EAAEI,KAAA,CAACJ,SAASR,OAAO;EAACK,EAAA,KAAAL;EAAAK,EAAA,KAAAG;EAAAH,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAHrBpB,UAAUwB,IAGPG,EAAkB;CAAC,IAAAC;CAAA,IAAAR,EAAA,OAAAG,SAAA;EAEDK,KAAA,IAAItB,qBAAqBiB,OAAO;EAACH,EAAA,KAAAG;EAAAH,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAAjCQ;AAAiC;AAGxD,MAAaC,8BACXd,YACqB;CACrB,MAAMe,iBAAiB5B,OAAOa,QAAQgB,WAAW;CACjDD,eAAeE,UAAUjB,QAAQgB;CAGjC,MAAME,mBAAmB/B,OAAOa,QAAQmB,YAAYnB,QAAQoB,eAAe;CAE3E,MAAMC,oBAAoBjC,kBAAkB;EAC1C,OAAO2B,eAAeE,QAAQ;CAChC,GAAG,CAAA,CAAE;CAEL,MAAMK,mBAAmBjC,gBAAgB8B,aAAiC;EACxEnB,QAAQsB,mBAAmBH,QAAQ;CACrC,CAAC;CAED,MAAMI,gBAAgBrC,eACb;EACLsC,SAASxB,QAAQwB;EACjBC,cAAczB,QAAQyB;EACtBL,iBAAiBF,iBAAiBD;EAClCD,aAAaK;EACbC;CACF,IACA;EAACtB,QAAQwB;EAASxB,QAAQyB;EAAcJ;CAAiB,CAC3D;CAKA,IAHYzB,OACK8B,CAAG,CAACE,eAAeC,WAAW,MAEjC;EACZ,IAAI,CAACN,cAAcE,cACjB,MAAM,IAAIK,MACR,sKAEF;EAKF,OAAOT,kBAAkB;CAC3B;CAEA,MAAMb,UAAUJ,+BAA+BmB,aAAa;CAE5D,MAAMQ,kBAAkB5C,OAAOa,QAAQmB,QAAQ;CAC/ClC,gBAAgB;EACd,IAAIe,QAAQmB,aAAaY,gBAAgBd,SAAS;EAClDc,gBAAgBd,UAAUjB,QAAQmB;EAClC,IAAInB,QAAQmB,UACVX,QAAQV,QAAQkC,eAAehC,QAAQmB,QAAQ,CAAC,CAACc,YAAY,CAAC,CAAC;OAE/DzB,QAAQV,QAAQoC,kBAAkB,CAAC,CAACD,YAAY,CAAC,CAAC;CAEtD,GAAG,CAACzB,SAASR,QAAQmB,QAAQ,CAAC;CAE9B,OAAOX;AACT"}
@@ -0,0 +1,26 @@
1
+ import { MessageTiming } from "../../types/message.js";
2
+ import { StreamingTimingAccessors, StreamingTimingOptions, StreamingTimingState } from "../../runtime/utils/streaming-timing.js";
3
+
4
+ //#region src/react/runtimes/useStreamingTiming.d.ts
5
+ /**
6
+ * Tracks per-message streaming timing client-side and returns finalized
7
+ * `MessageTiming` keyed by message id.
8
+ *
9
+ * Observes `isRunning` transitions and content growth through the provided
10
+ * `accessors`, which adapt the hook to a runtime's message shape. Timing is
11
+ * finalized when streaming ends; adapters thread the result into
12
+ * `useExternalMessageConverter` metadata as `messageTiming`.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const messageTiming = useStreamingTiming(messages, isRunning, {
17
+ * getAssistantMessageId: (msgs) => msgs.findLast((m) => m.role === "assistant")?.id,
18
+ * getTextLength: (msgs, id) => msgs.find((m) => m.id === id)?.content?.length ?? 0,
19
+ * getToolCallCount: (msgs, id) => msgs.find((m) => m.id === id)?.tool_calls?.length ?? 0,
20
+ * });
21
+ * ```
22
+ */
23
+ declare const useStreamingTiming: <TMessage>(messages: readonly TMessage[], isRunning: boolean, accessors: StreamingTimingAccessors<TMessage>, options?: StreamingTimingOptions) => Record<string, MessageTiming>;
24
+ //#endregion
25
+ export { type StreamingTimingAccessors, type StreamingTimingOptions, type StreamingTimingState, useStreamingTiming };
26
+ //# sourceMappingURL=useStreamingTiming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStreamingTiming.d.ts","names":[],"sources":["../../../src/react/runtimes/useStreamingTiming.ts"],"mappings":";;;;;AAmCA;;;;;;;;;;;;;;;;;cAAa,kBAAA,aACX,QAAA,WAAmB,QAAA,IACnB,SAAA,WACA,SAAA,EAAW,wBAAA,CAAyB,QAAA,GACpC,OAAA,GAAU,sBAAA,KACT,MAAA,SAAe,aAAA"}
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { stepStreamingTiming } from "../../runtime/utils/streaming-timing.js";
3
+ import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
4
+ //#region src/react/runtimes/useStreamingTiming.ts
5
+ /**
6
+ * Tracks per-message streaming timing client-side and returns finalized
7
+ * `MessageTiming` keyed by message id.
8
+ *
9
+ * Observes `isRunning` transitions and content growth through the provided
10
+ * `accessors`, which adapt the hook to a runtime's message shape. Timing is
11
+ * finalized when streaming ends; adapters thread the result into
12
+ * `useExternalMessageConverter` metadata as `messageTiming`.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const messageTiming = useStreamingTiming(messages, isRunning, {
17
+ * getAssistantMessageId: (msgs) => msgs.findLast((m) => m.role === "assistant")?.id,
18
+ * getTextLength: (msgs, id) => msgs.find((m) => m.id === id)?.content?.length ?? 0,
19
+ * getToolCallCount: (msgs, id) => msgs.find((m) => m.id === id)?.tool_calls?.length ?? 0,
20
+ * });
21
+ * ```
22
+ */
23
+ const useStreamingTiming = (messages, isRunning, accessors, options) => {
24
+ const [timings, setTimings] = useState({});
25
+ const stateRef = useRef(null);
26
+ const accessorsRef = useRef(accessors);
27
+ accessorsRef.current = accessors;
28
+ const optionsRef = useRef(options);
29
+ optionsRef.current = options;
30
+ useEffect(() => {
31
+ const result = stepStreamingTiming(stateRef.current, messages, isRunning, accessorsRef.current, optionsRef.current);
32
+ stateRef.current = result.state;
33
+ if (Object.keys(result.timings).length > 0) setTimings((prev) => ({
34
+ ...prev,
35
+ ...result.timings
36
+ }));
37
+ }, [messages, isRunning]);
38
+ return timings;
39
+ };
40
+ //#endregion
41
+ export { useStreamingTiming };
42
+
43
+ //# sourceMappingURL=useStreamingTiming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStreamingTiming.js","names":["useEffect","useRef","useState","MessageTiming","stepStreamingTiming","StreamingTimingAccessors","StreamingTimingOptions","StreamingTimingState","useStreamingTiming","messages","TMessage","isRunning","accessors","options","Record","timings","setTimings","stateRef","accessorsRef","current","optionsRef","result","state","Object","keys","length","prev"],"sources":["../../../src/react/runtimes/useStreamingTiming.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { MessageTiming } from \"../../types/message\";\nimport {\n stepStreamingTiming,\n type StreamingTimingAccessors,\n type StreamingTimingOptions,\n type StreamingTimingState,\n} from \"../../runtime/utils/streaming-timing\";\n\nexport type {\n StreamingTimingAccessors,\n StreamingTimingOptions,\n StreamingTimingState,\n};\n\n/**\n * Tracks per-message streaming timing client-side and returns finalized\n * `MessageTiming` keyed by message id.\n *\n * Observes `isRunning` transitions and content growth through the provided\n * `accessors`, which adapt the hook to a runtime's message shape. Timing is\n * finalized when streaming ends; adapters thread the result into\n * `useExternalMessageConverter` metadata as `messageTiming`.\n *\n * @example\n * ```ts\n * const messageTiming = useStreamingTiming(messages, isRunning, {\n * getAssistantMessageId: (msgs) => msgs.findLast((m) => m.role === \"assistant\")?.id,\n * getTextLength: (msgs, id) => msgs.find((m) => m.id === id)?.content?.length ?? 0,\n * getToolCallCount: (msgs, id) => msgs.find((m) => m.id === id)?.tool_calls?.length ?? 0,\n * });\n * ```\n */\nexport const useStreamingTiming = <TMessage>(\n messages: readonly TMessage[],\n isRunning: boolean,\n accessors: StreamingTimingAccessors<TMessage>,\n options?: StreamingTimingOptions,\n): Record<string, MessageTiming> => {\n const [timings, setTimings] = useState<Record<string, MessageTiming>>({});\n const stateRef = useRef<StreamingTimingState | null>(null);\n // Read the latest accessors/options from refs so the effect keeps the\n // original `[messages, isRunning]` reactivity of the adapter hooks this\n // replaces (a stable timings object while streaming, a single new reference\n // at finalize).\n const accessorsRef = useRef(accessors);\n accessorsRef.current = accessors;\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const result = stepStreamingTiming(\n stateRef.current,\n messages,\n isRunning,\n accessorsRef.current,\n optionsRef.current,\n );\n stateRef.current = result.state;\n if (Object.keys(result.timings).length > 0) {\n setTimings((prev) => ({ ...prev, ...result.timings }));\n }\n }, [messages, isRunning]);\n\n return timings;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAaQ,sBACXC,UACAE,WACAC,WACAC,YACkC;CAClC,MAAM,CAACE,SAASC,cAAcd,SAAwC,CAAC,CAAC;CACxE,MAAMe,WAAWhB,OAAoC,IAAI;CAKzD,MAAMiB,eAAejB,OAAOW,SAAS;CACrCM,aAAaC,UAAUP;CACvB,MAAMQ,aAAanB,OAAOY,OAAO;CACjCO,WAAWD,UAAUN;CAErBb,gBAAgB;EACd,MAAMqB,SAASjB,oBACba,SAASE,SACTV,UACAE,WACAO,aAAaC,SACbC,WAAWD,OACb;EACAF,SAASE,UAAUE,OAAOC;EAC1B,IAAIC,OAAOC,KAAKH,OAAON,OAAO,CAAC,CAACU,SAAS,GACvCT,YAAYU,UAAU;GAAE,GAAGA;GAAM,GAAGL,OAAON;EAAQ,EAAE;CAEzD,GAAG,CAACN,UAAUE,SAAS,CAAC;CAExB,OAAOI;AACT"}
@@ -1,4 +1,5 @@
1
1
  import { Unsubscribe } from "../../../types/unsubscribe.js";
2
+ import { ToolCallMessagePartComponent } from "../MessagePartComponentTypes.js";
2
3
  import { Tool } from "assistant-stream";
3
4
 
4
5
  //#region src/react/types/scopes/interactables.d.ts
@@ -6,53 +7,68 @@ import { Tool } from "assistant-stream";
6
7
  * Schema type matching Tool["parameters"] from assistant-stream.
7
8
  * Accepts both StandardSchemaV1 and JSONSchema7.
8
9
  */
9
- type InteractableStateSchema = NonNullable<Extract<Tool, {
10
+ type Unstable_InteractableStateSchema = NonNullable<Extract<Tool, {
10
11
  parameters: unknown;
11
12
  }>["parameters"]>;
12
- type InteractableDefinition = {
13
+ type InteractableScope = "app" | "thread";
14
+ type Unstable_InteractableDefinition = {
13
15
  id: string;
14
16
  name: string;
15
17
  description: string;
16
- stateSchema: InteractableStateSchema;
18
+ stateSchema: Unstable_InteractableStateSchema;
17
19
  state: unknown;
18
- selected?: boolean | undefined;
20
+ initialState: unknown;
21
+ scope?: InteractableScope | undefined;
19
22
  };
20
- type InteractableRegistration = {
23
+ type Unstable_InteractableRegistration = {
21
24
  id: string;
22
25
  name: string;
23
26
  description: string;
24
- stateSchema: InteractableStateSchema;
27
+ stateSchema: Unstable_InteractableStateSchema;
25
28
  initialState: unknown;
26
- selected?: boolean | undefined;
29
+ /**
30
+ * Component installed as the tool UI for this interactable's `update_{name}`
31
+ * tool calls, so a model edit re-renders the interactable at the message
32
+ * that made it. Registered once per name; requires the `tools` scope.
33
+ */
34
+ updateRender?: ToolCallMessagePartComponent | undefined;
27
35
  };
28
- type InteractablePersistenceStatus = {
36
+ type Unstable_InteractablePersistenceStatus = {
29
37
  isPending: boolean;
30
38
  error: unknown;
31
39
  };
32
- type InteractablesState = {
33
- /** Keyed by instance id */definitions: Record<string, InteractableDefinition>; /** Per-id persistence sync status */
34
- persistence: Record<string, InteractablePersistenceStatus>;
40
+ type Unstable_InteractablesState = {
41
+ /** Keyed by instance id */definitions: Record<string, Unstable_InteractableDefinition>; /** Per-id persistence sync status */
42
+ persistence: Record<string, Unstable_InteractablePersistenceStatus>;
35
43
  };
36
- type InteractablePersistedState = Record<string, {
44
+ type Unstable_InteractablePersistedState = Record<string, {
37
45
  name: string;
38
46
  state: unknown;
39
47
  }>;
40
- type InteractablePersistenceAdapter = {
41
- save(state: InteractablePersistedState): void | Promise<void>;
48
+ type Unstable_InteractablePersistenceAdapter = {
49
+ save(state: Unstable_InteractablePersistedState): void | Promise<void>;
50
+ /**
51
+ * Restores previously saved state. Called when the adapter is attached;
52
+ * loaded state seeds app-scoped interactables that have not been locally
53
+ * edited yet (a local edit always wins over a slow load).
54
+ */
55
+ load?(): Unstable_InteractablePersistedState | null | undefined | Promise<Unstable_InteractablePersistedState | null | undefined>;
56
+ };
57
+ type Unstable_InteractablesConfig = {
58
+ persistence?: Unstable_InteractablePersistenceAdapter | undefined;
42
59
  };
43
- type InteractablesMethods = {
44
- getState(): InteractablesState;
45
- register(def: InteractableRegistration): Unsubscribe;
60
+ type Unstable_InteractablesMethods = {
61
+ getState(): Unstable_InteractablesState;
62
+ register(def: Unstable_InteractableRegistration): Unsubscribe;
46
63
  setState(id: string, updater: (prev: unknown) => unknown): void;
47
- setSelected(id: string, selected: boolean): void;
48
- exportState(): InteractablePersistedState;
49
- importState(saved: InteractablePersistedState): void;
50
- setPersistenceAdapter(adapter: InteractablePersistenceAdapter | undefined): void;
64
+ exportState(): Unstable_InteractablePersistedState;
65
+ importState(saved: Unstable_InteractablePersistedState): void;
66
+ setPersistenceAdapter(adapter: Unstable_InteractablePersistenceAdapter | undefined): void;
51
67
  flush(): Promise<void>;
52
68
  };
53
- type InteractablesClientSchema = {
54
- methods: InteractablesMethods;
69
+ type Unstable_InteractablesClientSchema = {
70
+ methods: Unstable_InteractablesMethods;
55
71
  };
56
72
  //#endregion
57
- export { InteractableDefinition, InteractablePersistedState, InteractablePersistenceAdapter, InteractablePersistenceStatus, InteractableRegistration, InteractableStateSchema, InteractablesClientSchema, InteractablesMethods, InteractablesState };
73
+ export { Unstable_InteractableDefinition, Unstable_InteractablePersistedState, Unstable_InteractablePersistenceAdapter, Unstable_InteractablePersistenceStatus, Unstable_InteractableRegistration, Unstable_InteractableStateSchema, Unstable_InteractablesClientSchema, Unstable_InteractablesConfig, Unstable_InteractablesMethods, Unstable_InteractablesState };
58
74
  //# sourceMappingURL=interactables.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactables.d.ts","names":[],"sources":["../../../../src/react/types/scopes/interactables.ts"],"mappings":";;;;;;;AAOA;KAAY,uBAAA,GAA0B,WAAA,CACpC,OAAA,CAAQ,IAAA;EAAQ,UAAA;AAAA;AAAA,KAGN,sBAAA;EACV,EAAA;EACA,IAAA;EACA,WAAA;EACA,WAAA,EAAa,uBAAuB;EACpC,KAAA;EACA,QAAA;AAAA;AAAA,KAGU,wBAAA;EACV,EAAA;EACA,IAAA;EACA,WAAA;EACA,WAAA,EAAa,uBAAuB;EACpC,YAAA;EACA,QAAA;AAAA;AAAA,KAGU,6BAAA;EACV,SAAA;EACA,KAAK;AAAA;AAAA,KAGK,kBAAA;EAjBF,2BAmBR,WAAA,EAAa,MAAA,SAAe,sBAAA,GAhBlB;EAkBV,WAAA,EAAa,MAAA,SAAe,6BAAA;AAAA;AAAA,KAGlB,0BAAA,GAA6B,MAAM;EAE3C,IAAA;EAAc,KAAA;AAAA;AAAA,KAGN,8BAAA;EACV,IAAA,CAAK,KAAA,EAAO,0BAAA,UAAoC,OAAO;AAAA;AAAA,KAG7C,oBAAA;EACV,QAAA,IAAY,kBAAA;EACZ,QAAA,CAAS,GAAA,EAAK,wBAAA,GAA2B,WAAA;EACzC,QAAA,CAAS,EAAA,UAAY,OAAA,GAAU,IAAA;EAC/B,WAAA,CAAY,EAAA,UAAY,QAAA;EACxB,WAAA,IAAe,0BAAA;EACf,WAAA,CAAY,KAAA,EAAO,0BAAA;EACnB,qBAAA,CACE,OAAA,EAAS,8BAAA;EAEX,KAAA,IAAS,OAAA;AAAA;AAAA,KAGC,yBAAA;EACV,OAAA,EAAS,oBAAoB;AAAA"}
1
+ {"version":3,"file":"interactables.d.ts","names":[],"sources":["../../../../src/react/types/scopes/interactables.ts"],"mappings":";;;;;;;;AAQA;KAAY,gCAAA,GAAmC,WAAA,CAC7C,OAAA,CAAQ,IAAA;EAAQ,UAAA;AAAA;AAAA,KAGb,iBAAA;AAAA,KAEO,+BAAA;EACV,EAAA;EACA,IAAA;EACA,WAAA;EACA,WAAA,EAAa,gCAAA;EACb,KAAA;EACA,YAAA;EACA,KAAA,GAAQ,iBAAiB;AAAA;AAAA,KAGf,iCAAA;EACV,EAAA;EACA,IAAA;EACA,WAAA;EACA,WAAA,EAAa,gCAAA;EACb,YAAA;EAfyC;;;;;EAqBzC,YAAA,GAAe,4BAA4B;AAAA;AAAA,KAGjC,sCAAA;EACV,SAAA;EACA,KAAK;AAAA;AAAA,KAGK,2BAAA;EAtBe,2BAwBzB,WAAA,EAAa,MAAA,SAAe,+BAAA,GArBlB;EAuBV,WAAA,EAAa,MAAA,SAAe,sCAAA;AAAA;AAAA,KAGlB,mCAAA,GAAsC,MAAM;EAEpD,IAAA;EAAc,KAAA;AAAA;AAAA,KAGN,uCAAA;EACV,IAAA,CAAK,KAAA,EAAO,mCAAA,UAA6C,OAAA;EA3BzD;;;;AAM2C;EA2B3C,IAAA,KACI,mCAAA,sBAGA,OAAA,CAAQ,mCAAA;AAAA;AAAA,KAGF,4BAAA;EACV,WAAA,GAAc,uCAAuC;AAAA;AAAA,KAG3C,6BAAA;EACV,QAAA,IAAY,2BAAA;EACZ,QAAA,CAAS,GAAA,EAAK,iCAAA,GAAoC,WAAA;EAClD,QAAA,CAAS,EAAA,UAAY,OAAA,GAAU,IAAA;EAC/B,WAAA,IAAe,mCAAA;EACf,WAAA,CAAY,KAAA,EAAO,mCAAA;EACnB,qBAAA,CACE,OAAA,EAAS,uCAAA;EAEX,KAAA,IAAS,OAAA;AAAA;AAAA,KAGC,kCAAA;EACV,OAAA,EAAS,6BAA6B;AAAA"}
@@ -1,5 +1,6 @@
1
+ import { Unstable_InteractablesClientSchema } from "./scopes/interactables.js";
1
2
  import { ToolsClientSchema } from "./scopes/tools.js";
2
- import { InteractablesClientSchema } from "./scopes/interactables.js";
3
+ import { InteractablesClientSchema } from "../interactables-legacy/scopes.js";
3
4
  import { DataRenderersClientSchema } from "./scopes/dataRenderers.js";
4
5
 
5
6
  //#region src/react/types/store-augmentation.d.ts
@@ -8,6 +9,7 @@ declare module "@assistant-ui/store" {
8
9
  tools: ToolsClientSchema;
9
10
  dataRenderers: DataRenderersClientSchema;
10
11
  interactables: InteractablesClientSchema;
12
+ unstable_interactables: Unstable_InteractablesClientSchema;
11
13
  }
12
14
  } //# sourceMappingURL=store-augmentation.d.ts.map
13
15
  //# sourceMappingURL=store-augmentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store-augmentation.d.ts","names":[],"sources":["../../../src/react/types/store-augmentation.ts"],"mappings":";;;;;;YAKY,aAAA;IACR,KAAA,EAAO,iBAAA;IACP,aAAA,EAAe,yBAAA;IACf,aAAA,EAAe,yBAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"store-augmentation.d.ts","names":[],"sources":["../../../src/react/types/store-augmentation.ts"],"mappings":";;;;;;;YAMY,aAAA;IACR,KAAA,EAAO,iBAAA;IACP,aAAA,EAAe,yBAAA;IACf,aAAA,EAAe,yBAAA;IACf,sBAAA,EAAwB,kCAAA;EAAA;AAAA"}
@@ -0,0 +1,11 @@
1
+ //#region src/react/utils/useJSONEqual.d.ts
2
+ /**
3
+ * Like `useShallow`, but with JSON deep-equality. Use when a selector derives an
4
+ * equal-but-fresh value on every store update — e.g. folding over
5
+ * `thread.messages`, whose identity changes on every streaming token — where a
6
+ * shallow compare would re-render regardless.
7
+ */
8
+ declare function useJSONEqual<S, U>(selector: (state: S) => U): (state: S) => U;
9
+ //#endregion
10
+ export { useJSONEqual };
11
+ //# sourceMappingURL=useJSONEqual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useJSONEqual.d.ts","names":[],"sources":["../../../src/react/utils/useJSONEqual.ts"],"mappings":";;AASA;;;;;iBAAgB,YAAA,OAAmB,QAAA,GAAW,KAAA,EAAO,CAAA,KAAM,CAAA,IAAK,KAAA,EAAO,CAAA,KAAM,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { isJSONValueEqual } from "../../utils/json/is-json-equal.js";
2
+ import { useRef } from "@assistant-ui/tap/react-shim";
3
+ import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
4
+ //#region src/react/utils/useJSONEqual.ts
5
+ /**
6
+ * Like `useShallow`, but with JSON deep-equality. Use when a selector derives an
7
+ * equal-but-fresh value on every store update — e.g. folding over
8
+ * `thread.messages`, whose identity changes on every streaming token — where a
9
+ * shallow compare would re-render regardless.
10
+ */
11
+ function useJSONEqual(selector) {
12
+ const $ = c(2);
13
+ const prev = useRef(void 0);
14
+ let t0;
15
+ if ($[0] !== selector) {
16
+ t0 = (state) => {
17
+ const next = selector(state);
18
+ if (prev.current !== void 0 && isJSONValueEqual(prev.current, next)) return prev.current;
19
+ prev.current = next;
20
+ return next;
21
+ };
22
+ $[0] = selector;
23
+ $[1] = t0;
24
+ } else t0 = $[1];
25
+ return t0;
26
+ }
27
+ //#endregion
28
+ export { useJSONEqual };
29
+
30
+ //# sourceMappingURL=useJSONEqual.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useJSONEqual.js","names":["useRef","isJSONValueEqual","useJSONEqual","selector","$","_c","prev","undefined","t0","state","next","current"],"sources":["../../../src/react/utils/useJSONEqual.ts"],"sourcesContent":["import { useRef } from \"react\";\nimport { isJSONValueEqual } from \"../../utils/json/is-json-equal\";\n\n/**\n * Like `useShallow`, but with JSON deep-equality. Use when a selector derives an\n * equal-but-fresh value on every store update — e.g. folding over\n * `thread.messages`, whose identity changes on every streaming token — where a\n * shallow compare would re-render regardless.\n */\nexport function useJSONEqual<S, U>(selector: (state: S) => U): (state: S) => U {\n const prev = useRef<U | undefined>(undefined);\n return (state) => {\n const next = selector(state);\n if (prev.current !== undefined && isJSONValueEqual(prev.current, next)) {\n return prev.current;\n }\n prev.current = next;\n return next;\n };\n}\n"],"mappings":";;;;;;;;;;AASA,SAAOE,aAAAC,UAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CACL,MAAAC,OAAaN,OAAsBO,KAAAA,CAAS;CAAE,IAAAC;CAAA,IAAAJ,EAAA,OAAAD,UAAA;EACvCK,MAAAC,UAAA;GACL,MAAAC,OAAaP,SAASM,KAAK;GAC3B,IAAIH,KAAIK,YAAaJ,KAAAA,KAAaN,iBAAiBK,KAAIK,SAAUD,IAAI,GAAC,OAC7DJ,KAAIK;GAEbL,KAAIK,UAAWD;GAAH,OACLA;EAAI;EACZN,EAAA,KAAAD;EAAAC,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAPMI;AAON"}
@@ -12,6 +12,11 @@ declare abstract class BaseComposerRuntimeCore extends BaseSubscribable implemen
12
12
  readonly isEditing = true;
13
13
  protected abstract getAttachmentAdapter(): AttachmentAdapter | undefined;
14
14
  protected abstract getDictationAdapter(): DictationAdapter | undefined;
15
+ protected enrichWithComposerMetadata<T extends {
16
+ metadata?: {
17
+ custom?: Record<string, unknown>;
18
+ };
19
+ }>(message: T, composerMetadata: Record<string, unknown> | undefined): T;
15
20
  get attachmentAccept(): string;
16
21
  private _attachments;
17
22
  get attachments(): readonly Attachment[];
@@ -1 +1 @@
1
- {"version":3,"file":"base-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"mappings":";;;;;;;;;;uBAkCsB,uBAAA,SACZ,gBAAA,YACG,mBAAA;EAAA,SAEK,SAAA;EAAA,mBAEG,oBAAA,IAAwB,iBAAA;EAAA,mBACxB,mBAAA,IAAuB,gBAAA;EAAA,IAE/B,gBAAA;EAAA,QAIH,YAAA;EAAA,IACG,WAAA,aAAW,UAAA;EAAA,UAIZ,cAAA,CAAe,KAAA,WAAgB,UAAA;EAAA,aAKrB,SAAA;EAAA,aACA,OAAA;EAAA,IAET,OAAA;EAAA,QAIH,KAAA;EAAA,IAEJ,IAAA;EAAA,QAII,KAAA;EAAA,IAEJ,IAAA;EAAA,QAII,UAAA;EAAA,IAEJ,SAAA,IAAS,SAAA;EAAA,QAIL,MAAA;EAAA,IAEJ,KAAA,IAAK,SAAA;EAIF,QAAA,CAAS,KAAA,EAAO,SAAA;EAOhB,OAAA,CAAQ,KAAA;EAaR,OAAA,CAAQ,IAAA,EAAM,WAAA;EAOd,YAAA,CAAa,SAAA,EAAW,SAAA;EAAA,QAOvB,wBAAA;EAAA,QAMM,mBAAA;EAQD,KAAA,IAAK,OAAA;EAoBL,gBAAA,IAAgB,OAAA;EAOhB,IAAA,CAAK,OAAA,GAAU,WAAA,GAAW,OAAA;EAuChC,MAAA;EAAA,IAII,KAAA,aAAkB,cAAA;EAItB,cAAA,CAAe,YAAA;EACf,eAAA,CAAgB,YAAA;EAAA,mBAEJ,UAAA,CACjB,OAAA,EAAS,IAAA,CAAK,aAAA,4BACd,OAAA,GAAU,WAAA;EAAA,mBAEO,YAAA;EAEb,aAAA,CAAc,gBAAA,EAAkB,IAAA,GAAO,gBAAA,GAAgB,OAAA;EAAA,QAqHrD,2BAAA;EAqBF,gBAAA,CAAiB,YAAA,WAAoB,OAAA;EAAA,QAenC,UAAA;EAAA,QACA,iBAAA;EAAA,QACA,sBAAA;EAAA,QACA,kBAAA;EAAA,QACA,mBAAA;EAAA,QACA,0BAAA;EAAA,QACA,yBAAA;EAAA,QACA,oBAAA;EAAA,IAEG,SAAA,IAAa,cAAA;EAAA,QAIhB,gBAAA;EAUD,cAAA;EA6FA,aAAA;EAAA,QAUC,iBAAA;EAAA,QAuBA,iBAAA;EAAA,UAKE,uBAAA,WAAkC,wBAAA,EAC1C,KAAA,EAAO,CAAA,EACP,OAAA,EAAS,2BAAA,CAA4B,CAAA;EAQhC,WAAA,WAAsB,wBAAA,EAC3B,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,4BAAA,CAA6B,CAAA;AAAA"}
1
+ {"version":3,"file":"base-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"mappings":";;;;;;;;;;uBAkCsB,uBAAA,SACZ,gBAAA,YACG,mBAAA;EAAA,SAEK,SAAA;EAAA,mBAEG,oBAAA,IAAwB,iBAAA;EAAA,mBACxB,mBAAA,IAAuB,gBAAA;EAAA,UAEhC,0BAAA;IACI,QAAA;MAAa,MAAA,GAAS,MAAA;IAAA;EAAA,GAClC,OAAA,EAAS,CAAA,EAAG,gBAAA,EAAkB,MAAA,gCAAsC,CAAA;EAAA,IAW3D,gBAAA;EAAA,QAIH,YAAA;EAAA,IACG,WAAA,aAAW,UAAA;EAAA,UAIZ,cAAA,CAAe,KAAA,WAAgB,UAAA;EAAA,aAKrB,SAAA;EAAA,aACA,OAAA;EAAA,IAET,OAAA;EAAA,QAIH,KAAA;EAAA,IAEJ,IAAA;EAAA,QAII,KAAA;EAAA,IAEJ,IAAA;EAAA,QAII,UAAA;EAAA,IAEJ,SAAA,IAAS,SAAA;EAAA,QAIL,MAAA;EAAA,IAEJ,KAAA,IAAK,SAAA;EAIF,QAAA,CAAS,KAAA,EAAO,SAAA;EAOhB,OAAA,CAAQ,KAAA;EAaR,OAAA,CAAQ,IAAA,EAAM,WAAA;EAOd,YAAA,CAAa,SAAA,EAAW,SAAA;EAAA,QAOvB,wBAAA;EAAA,QAMM,mBAAA;EAQD,KAAA,IAAK,OAAA;EAoBL,gBAAA,IAAgB,OAAA;EAOhB,IAAA,CAAK,OAAA,GAAU,WAAA,GAAW,OAAA;EAuChC,MAAA;EAAA,IAII,KAAA,aAAkB,cAAA;EAItB,cAAA,CAAe,YAAA;EACf,eAAA,CAAgB,YAAA;EAAA,mBAEJ,UAAA,CACjB,OAAA,EAAS,IAAA,CAAK,aAAA,4BACd,OAAA,GAAU,WAAA;EAAA,mBAEO,YAAA;EAEb,aAAA,CAAc,gBAAA,EAAkB,IAAA,GAAO,gBAAA,GAAgB,OAAA;EAAA,QAqHrD,2BAAA;EAqBF,gBAAA,CAAiB,YAAA,WAAoB,OAAA;EAAA,QAenC,UAAA;EAAA,QACA,iBAAA;EAAA,QACA,sBAAA;EAAA,QACA,kBAAA;EAAA,QACA,mBAAA;EAAA,QACA,0BAAA;EAAA,QACA,yBAAA;EAAA,QACA,oBAAA;EAAA,IAEG,SAAA,IAAa,cAAA;EAAA,QAIhB,gBAAA;EAUD,cAAA;EA6FA,aAAA;EAAA,QAUC,iBAAA;EAAA,QAuBA,iBAAA;EAAA,UAKE,uBAAA,WAAkC,wBAAA,EAC1C,KAAA,EAAO,CAAA,EACP,OAAA,EAAS,2BAAA,CAA4B,CAAA;EAQhC,WAAA,WAAsB,wBAAA,EAC3B,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,4BAAA,CAA6B,CAAA;AAAA"}
@@ -6,6 +6,19 @@ import { BaseSubscribable } from "../../subscribable/subscribable.js";
6
6
  const isAttachmentComplete = (a) => a.status.type === "complete";
7
7
  var BaseComposerRuntimeCore = class extends BaseSubscribable {
8
8
  isEditing = true;
9
+ enrichWithComposerMetadata(message, composerMetadata) {
10
+ if (!composerMetadata) return message;
11
+ return {
12
+ ...message,
13
+ metadata: {
14
+ ...message.metadata,
15
+ custom: {
16
+ ...message.metadata?.custom,
17
+ ...composerMetadata
18
+ }
19
+ }
20
+ };
21
+ }
9
22
  get attachmentAccept() {
10
23
  return this.getAttachmentAdapter()?.accept ?? "*";
11
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base-composer-runtime-core.js","names":["Attachment","CompleteAttachment","CreateAttachment","PendingAttachment","MessageRole","AppendMessage","QuoteInfo","Unsubscribe","RunConfig","BaseSubscribable","AttachmentAdapter","fileMatchesAccept","AttachmentAddErrorReason","ComposerRuntimeCore","ComposerRuntimeEventCallback","ComposerRuntimeEventPayload","ComposerRuntimeEventType","DictationState","SendOptions","DictationAdapter","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","isAttachmentComplete","a","status","type","BaseComposerRuntimeCore","isEditing","getAttachmentAdapter","getDictationAdapter","attachmentAccept","accept","_attachments","attachments","setAttachments","value","_notifySubscribers","canCancel","canSend","isEmpty","text","trim","length","_text","_role","role","_runConfig","runConfig","_quote","undefined","quote","setQuote","setText","_dictation","_dictationBaseText","_currentInterimText","inputDisabled","setRole","setRunConfig","_emptyTextAndAttachments","_onClearAttachments","adapter","pending","filter","Promise","all","map","remove","reset","Object","keys","task","clearAttachments","send","options","_dictationSession","cancel","_cleanupDictation","Error","result","message","Omit","createdAt","Date","content","metadata","custom","handleSend","_notifyEventSubscribers","handleCancel","queue","steerQueueItem","_queueItemId","removeQueueItem","addAttachment","fileOrAttachment","File","name","contentType","err","_safeEmitAttachmentAddError","id","upsertAttachment","idx","findIndex","attachment","slice","lastAttachment","promiseOrGenerator","add","file","Symbol","asyncIterator","r","e","reason","String","hasError","attachmentId","error","subscriberError","console","removeAttachment","index","Session","_dictationUnsubscribes","_dictationSessionIdCounter","_activeDictationSessionId","_isCleaningDictation","dictation","_isActiveSession","sessionId","session","startDictation","unsub","oldSession","stop","catch","disableInputDuringDictation","listen","unsubSpeech","onSpeech","isFinal","needsSeparator","endsWith","transcript","separator","_","rest","push","unsubStart","onSpeechStart","unsubEnd","onSpeechEnd","statusInterval","setInterval","clearInterval","stopDictation","finally","isStaleSession","_eventSubscribers","Map","Set","payload","event","E","subscribers","get","callback","unstable_on","wrapped","set","delete"],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"sourcesContent":["import type {\n Attachment,\n CompleteAttachment,\n CreateAttachment,\n PendingAttachment,\n} from \"../../types/attachment\";\nimport type { MessageRole, AppendMessage } from \"../../types/message\";\nimport type { QuoteInfo } from \"../../types/quote\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { RunConfig } from \"../../types/message\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\nimport {\n type AttachmentAdapter,\n fileMatchesAccept,\n} from \"../../adapters/attachment\";\nimport type {\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n SendOptions,\n} from \"../interfaces/composer-runtime-core\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\n\nconst isAttachmentComplete = (a: Attachment): a is CompleteAttachment =>\n a.status.type === \"complete\";\n\nexport abstract class BaseComposerRuntimeCore\n extends BaseSubscribable\n implements ComposerRuntimeCore\n{\n public readonly isEditing = true;\n\n protected abstract getAttachmentAdapter(): AttachmentAdapter | undefined;\n protected abstract getDictationAdapter(): DictationAdapter | undefined;\n\n public get attachmentAccept(): string {\n return this.getAttachmentAdapter()?.accept ?? \"*\";\n }\n\n private _attachments: readonly Attachment[] = [];\n public get attachments() {\n return this._attachments;\n }\n\n protected setAttachments(value: readonly Attachment[]) {\n this._attachments = value;\n this._notifySubscribers();\n }\n\n public abstract get canCancel(): boolean;\n public abstract get canSend(): boolean;\n\n public get isEmpty() {\n return !this.text.trim() && !this.attachments.length;\n }\n\n private _text = \"\";\n\n get text() {\n return this._text;\n }\n\n private _role: MessageRole = \"user\";\n\n get role() {\n return this._role;\n }\n\n private _runConfig: RunConfig = {};\n\n get runConfig() {\n return this._runConfig;\n }\n\n private _quote: QuoteInfo | undefined = undefined;\n\n get quote() {\n return this._quote;\n }\n\n public setQuote(quote: QuoteInfo | undefined) {\n if (this._quote === quote) return;\n\n this._quote = quote;\n this._notifySubscribers();\n }\n\n public setText(value: string) {\n if (this._text === value) return;\n\n this._text = value;\n if (this._dictation) {\n this._dictationBaseText = value;\n this._currentInterimText = \"\";\n const { status, inputDisabled } = this._dictation;\n this._dictation = inputDisabled ? { status, inputDisabled } : { status };\n }\n this._notifySubscribers();\n }\n\n public setRole(role: MessageRole) {\n if (this._role === role) return;\n\n this._role = role;\n this._notifySubscribers();\n }\n\n public setRunConfig(runConfig: RunConfig) {\n if (this._runConfig === runConfig) return;\n\n this._runConfig = runConfig;\n this._notifySubscribers();\n }\n\n private _emptyTextAndAttachments() {\n this._attachments = [];\n this._text = \"\";\n this._notifySubscribers();\n }\n\n private async _onClearAttachments() {\n const adapter = this.getAttachmentAdapter();\n if (adapter) {\n const pending = this._attachments.filter((a) => !isAttachmentComplete(a));\n await Promise.all(pending.map((a) => adapter.remove(a)));\n }\n }\n\n public async reset() {\n if (\n this._attachments.length === 0 &&\n this._text === \"\" &&\n this._role === \"user\" &&\n Object.keys(this._runConfig).length === 0 &&\n this._quote === undefined\n ) {\n return;\n }\n\n this._role = \"user\";\n this._runConfig = {};\n this._quote = undefined;\n\n const task = this._onClearAttachments();\n this._emptyTextAndAttachments();\n await task;\n }\n\n public async clearAttachments() {\n const task = this._onClearAttachments();\n this.setAttachments([]);\n\n await task;\n }\n\n public async send(options?: SendOptions) {\n if (!this.canSend) return;\n\n if (this._dictationSession) {\n this._dictationSession.cancel();\n this._cleanupDictation();\n }\n\n const adapter = this.getAttachmentAdapter();\n const attachments =\n this.attachments.length > 0\n ? Promise.all(\n this.attachments.map(async (a) => {\n if (isAttachmentComplete(a)) return a;\n if (!adapter) throw new Error(\"Attachments are not supported\");\n const result = await adapter.send(a);\n return result as CompleteAttachment;\n }),\n )\n : [];\n\n const text = this.text;\n const quote = this._quote;\n this._quote = undefined;\n this._emptyTextAndAttachments();\n\n const message: Omit<AppendMessage, \"parentId\" | \"sourceId\"> = {\n createdAt: new Date(),\n role: this.role,\n content: text ? [{ type: \"text\", text }] : [],\n attachments: await attachments,\n runConfig: this.runConfig,\n metadata: { custom: { ...(quote ? { quote } : {}) } },\n };\n\n this.handleSend(message, options);\n this._notifyEventSubscribers(\"send\", {});\n }\n\n public cancel() {\n this.handleCancel();\n }\n\n public get queue(): readonly QueueItemState[] {\n return EMPTY_QUEUE_ITEMS;\n }\n\n public steerQueueItem(_queueItemId: string): void {}\n public removeQueueItem(_queueItemId: string): void {}\n\n protected abstract handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ): void;\n protected abstract handleCancel(): void;\n\n async addAttachment(fileOrAttachment: File | CreateAttachment) {\n if (!(fileOrAttachment instanceof File)) {\n const adapter = this.getAttachmentAdapter();\n if (\n adapter &&\n !fileMatchesAccept(\n {\n name: fileOrAttachment.name,\n type: fileOrAttachment.contentType ?? \"\",\n },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.contentType || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"not-accepted\",\n message,\n undefined,\n err,\n );\n throw err;\n }\n\n const a: CompleteAttachment = {\n id: fileOrAttachment.id ?? generateId(),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n this._attachments = [...this._attachments, a];\n this._notifySubscribers();\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n return;\n }\n\n const upsertAttachment = (a: PendingAttachment) => {\n const idx = this._attachments.findIndex(\n (attachment) => attachment.id === a.id,\n );\n if (idx !== -1)\n this._attachments = [\n ...this._attachments.slice(0, idx),\n a,\n ...this._attachments.slice(idx + 1),\n ];\n else {\n this._attachments = [...this._attachments, a];\n }\n\n this._notifySubscribers();\n };\n\n const adapter = this.getAttachmentAdapter();\n if (!adapter) {\n const message = \"Attachments are not supported\";\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"no-adapter\", message, undefined, err);\n throw err;\n }\n\n if (\n !fileMatchesAccept(\n { name: fileOrAttachment.name, type: fileOrAttachment.type },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.type || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"not-accepted\", message, undefined, err);\n throw err;\n }\n\n let lastAttachment: PendingAttachment | undefined;\n try {\n const promiseOrGenerator = adapter.add({ file: fileOrAttachment });\n if (Symbol.asyncIterator in promiseOrGenerator) {\n for await (const r of promiseOrGenerator) {\n lastAttachment = r;\n upsertAttachment(r);\n }\n } else {\n lastAttachment = await promiseOrGenerator;\n upsertAttachment(lastAttachment);\n }\n } catch (e) {\n if (lastAttachment) {\n upsertAttachment({\n ...lastAttachment,\n status: { type: \"incomplete\", reason: \"error\" },\n });\n }\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n e instanceof Error ? e.message : String(e),\n lastAttachment?.id,\n e instanceof Error ? e : undefined,\n );\n throw e;\n }\n\n const hasError =\n lastAttachment?.status.type === \"incomplete\" &&\n lastAttachment.status.reason === \"error\";\n if (hasError) {\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n \"Attachment upload did not complete successfully.\",\n lastAttachment?.id,\n );\n } else {\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n }\n }\n\n private _safeEmitAttachmentAddError(\n reason: AttachmentAddErrorReason,\n message: string,\n attachmentId?: string,\n error?: Error,\n ) {\n try {\n this._notifyEventSubscribers(\"attachmentAddError\", {\n reason,\n message,\n ...(attachmentId !== undefined && { attachmentId }),\n ...(error !== undefined && { error }),\n });\n } catch (subscriberError) {\n console.error(\n \"[assistant-ui] attachmentAddError subscriber threw:\",\n subscriberError,\n );\n }\n }\n\n async removeAttachment(attachmentId: string) {\n const index = this._attachments.findIndex((a) => a.id === attachmentId);\n if (index === -1) throw new Error(\"Attachment not found\");\n const attachment = this._attachments[index]!;\n\n if (!isAttachmentComplete(attachment)) {\n const adapter = this.getAttachmentAdapter();\n if (!adapter) throw new Error(\"Attachments are not supported\");\n await adapter.remove(attachment);\n }\n\n this._attachments = this._attachments.filter((a) => a.id !== attachmentId);\n this._notifySubscribers();\n }\n\n private _dictation: DictationState | undefined;\n private _dictationSession: DictationAdapter.Session | undefined;\n private _dictationUnsubscribes: Unsubscribe[] = [];\n private _dictationBaseText = \"\";\n private _currentInterimText = \"\";\n private _dictationSessionIdCounter = 0;\n private _activeDictationSessionId: number | undefined;\n private _isCleaningDictation = false;\n\n public get dictation(): DictationState | undefined {\n return this._dictation;\n }\n\n private _isActiveSession(\n sessionId: number,\n session: DictationAdapter.Session,\n ): boolean {\n return (\n this._activeDictationSessionId === sessionId &&\n this._dictationSession === session\n );\n }\n\n public startDictation(): void {\n const adapter = this.getDictationAdapter();\n if (!adapter) {\n throw new Error(\"Dictation adapter not configured\");\n }\n\n if (this._dictationSession) {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n const oldSession = this._dictationSession;\n oldSession.stop().catch(() => {});\n this._dictationSession = undefined;\n }\n\n const inputDisabled = adapter.disableInputDuringDictation ?? false;\n\n this._dictationBaseText = this._text;\n this._currentInterimText = \"\";\n\n const session = adapter.listen();\n this._dictationSession = session;\n const sessionId = ++this._dictationSessionIdCounter;\n this._activeDictationSessionId = sessionId;\n this._dictation = { status: session.status, inputDisabled };\n this._notifySubscribers();\n\n const unsubSpeech = session.onSpeech((result) => {\n if (!this._isActiveSession(sessionId, session)) return;\n const isFinal = result.isFinal !== false;\n\n const needsSeparator =\n this._dictationBaseText &&\n !this._dictationBaseText.endsWith(\" \") &&\n result.transcript;\n const separator = needsSeparator ? \" \" : \"\";\n\n if (isFinal) {\n this._dictationBaseText =\n this._dictationBaseText + separator + result.transcript;\n this._currentInterimText = \"\";\n this._text = this._dictationBaseText;\n\n if (this._dictation) {\n const { transcript: _, ...rest } = this._dictation;\n this._dictation = rest;\n }\n this._notifySubscribers();\n } else {\n this._currentInterimText = separator + result.transcript;\n this._text = this._dictationBaseText + this._currentInterimText;\n\n if (this._dictation) {\n this._dictation = {\n ...this._dictation,\n transcript: result.transcript,\n };\n }\n this._notifySubscribers();\n }\n });\n this._dictationUnsubscribes.push(unsubSpeech);\n\n const unsubStart = session.onSpeechStart(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n this._dictation = {\n status: { type: \"running\" },\n inputDisabled,\n ...(this._dictation?.transcript && {\n transcript: this._dictation.transcript,\n }),\n };\n this._notifySubscribers();\n });\n this._dictationUnsubscribes.push(unsubStart);\n\n const unsubEnd = session.onSpeechEnd(() => {\n this._cleanupDictation({ sessionId });\n });\n this._dictationUnsubscribes.push(unsubEnd);\n\n const statusInterval = setInterval(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n if (session.status.type === \"ended\") {\n this._cleanupDictation({ sessionId });\n }\n }, 100);\n this._dictationUnsubscribes.push(() => clearInterval(statusInterval));\n }\n\n public stopDictation(): void {\n if (!this._dictationSession) return;\n\n const session = this._dictationSession;\n const sessionId = this._activeDictationSessionId;\n session.stop().finally(() => {\n this._cleanupDictation({ sessionId });\n });\n }\n\n private _cleanupDictation(options?: { sessionId: number | undefined }): void {\n const isStaleSession =\n options?.sessionId !== undefined &&\n options.sessionId !== this._activeDictationSessionId;\n if (isStaleSession || this._isCleaningDictation) return;\n\n this._isCleaningDictation = true;\n try {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n this._dictationSession = undefined;\n this._activeDictationSessionId = undefined;\n this._dictation = undefined;\n this._dictationBaseText = \"\";\n this._currentInterimText = \"\";\n this._notifySubscribers();\n } finally {\n this._isCleaningDictation = false;\n }\n }\n\n private _eventSubscribers = new Map<\n ComposerRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n protected _notifyEventSubscribers<E extends ComposerRuntimeEventType>(\n event: E,\n payload: ComposerRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n for (const callback of subscribers) callback(payload);\n }\n\n public unstable_on<E extends ComposerRuntimeEventType>(\n event: E,\n callback: ComposerRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base-composer-runtime-core.js","names":["Attachment","CompleteAttachment","CreateAttachment","PendingAttachment","MessageRole","AppendMessage","QuoteInfo","Unsubscribe","RunConfig","BaseSubscribable","AttachmentAdapter","fileMatchesAccept","AttachmentAddErrorReason","ComposerRuntimeCore","ComposerRuntimeEventCallback","ComposerRuntimeEventPayload","ComposerRuntimeEventType","DictationState","SendOptions","DictationAdapter","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","isAttachmentComplete","a","status","type","BaseComposerRuntimeCore","isEditing","getAttachmentAdapter","getDictationAdapter","enrichWithComposerMetadata","metadata","custom","Record","message","T","composerMetadata","attachmentAccept","accept","_attachments","attachments","setAttachments","value","_notifySubscribers","canCancel","canSend","isEmpty","text","trim","length","_text","_role","role","_runConfig","runConfig","_quote","undefined","quote","setQuote","setText","_dictation","_dictationBaseText","_currentInterimText","inputDisabled","setRole","setRunConfig","_emptyTextAndAttachments","_onClearAttachments","adapter","pending","filter","Promise","all","map","remove","reset","Object","keys","task","clearAttachments","send","options","_dictationSession","cancel","_cleanupDictation","Error","result","Omit","createdAt","Date","content","handleSend","_notifyEventSubscribers","handleCancel","queue","steerQueueItem","_queueItemId","removeQueueItem","addAttachment","fileOrAttachment","File","name","contentType","err","_safeEmitAttachmentAddError","id","upsertAttachment","idx","findIndex","attachment","slice","lastAttachment","promiseOrGenerator","add","file","Symbol","asyncIterator","r","e","reason","String","hasError","attachmentId","error","subscriberError","console","removeAttachment","index","Session","_dictationUnsubscribes","_dictationSessionIdCounter","_activeDictationSessionId","_isCleaningDictation","dictation","_isActiveSession","sessionId","session","startDictation","unsub","oldSession","stop","catch","disableInputDuringDictation","listen","unsubSpeech","onSpeech","isFinal","needsSeparator","endsWith","transcript","separator","_","rest","push","unsubStart","onSpeechStart","unsubEnd","onSpeechEnd","statusInterval","setInterval","clearInterval","stopDictation","finally","isStaleSession","_eventSubscribers","Map","Set","payload","event","E","subscribers","get","callback","unstable_on","wrapped","set","delete"],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"sourcesContent":["import type {\n Attachment,\n CompleteAttachment,\n CreateAttachment,\n PendingAttachment,\n} from \"../../types/attachment\";\nimport type { MessageRole, AppendMessage } from \"../../types/message\";\nimport type { QuoteInfo } from \"../../types/quote\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { RunConfig } from \"../../types/message\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\nimport {\n type AttachmentAdapter,\n fileMatchesAccept,\n} from \"../../adapters/attachment\";\nimport type {\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n SendOptions,\n} from \"../interfaces/composer-runtime-core\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\n\nconst isAttachmentComplete = (a: Attachment): a is CompleteAttachment =>\n a.status.type === \"complete\";\n\nexport abstract class BaseComposerRuntimeCore\n extends BaseSubscribable\n implements ComposerRuntimeCore\n{\n public readonly isEditing = true;\n\n protected abstract getAttachmentAdapter(): AttachmentAdapter | undefined;\n protected abstract getDictationAdapter(): DictationAdapter | undefined;\n\n protected enrichWithComposerMetadata<\n T extends { metadata?: { custom?: Record<string, unknown> } },\n >(message: T, composerMetadata: Record<string, unknown> | undefined): T {\n if (!composerMetadata) return message;\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom: { ...message.metadata?.custom, ...composerMetadata },\n },\n } as T;\n }\n\n public get attachmentAccept(): string {\n return this.getAttachmentAdapter()?.accept ?? \"*\";\n }\n\n private _attachments: readonly Attachment[] = [];\n public get attachments() {\n return this._attachments;\n }\n\n protected setAttachments(value: readonly Attachment[]) {\n this._attachments = value;\n this._notifySubscribers();\n }\n\n public abstract get canCancel(): boolean;\n public abstract get canSend(): boolean;\n\n public get isEmpty() {\n return !this.text.trim() && !this.attachments.length;\n }\n\n private _text = \"\";\n\n get text() {\n return this._text;\n }\n\n private _role: MessageRole = \"user\";\n\n get role() {\n return this._role;\n }\n\n private _runConfig: RunConfig = {};\n\n get runConfig() {\n return this._runConfig;\n }\n\n private _quote: QuoteInfo | undefined = undefined;\n\n get quote() {\n return this._quote;\n }\n\n public setQuote(quote: QuoteInfo | undefined) {\n if (this._quote === quote) return;\n\n this._quote = quote;\n this._notifySubscribers();\n }\n\n public setText(value: string) {\n if (this._text === value) return;\n\n this._text = value;\n if (this._dictation) {\n this._dictationBaseText = value;\n this._currentInterimText = \"\";\n const { status, inputDisabled } = this._dictation;\n this._dictation = inputDisabled ? { status, inputDisabled } : { status };\n }\n this._notifySubscribers();\n }\n\n public setRole(role: MessageRole) {\n if (this._role === role) return;\n\n this._role = role;\n this._notifySubscribers();\n }\n\n public setRunConfig(runConfig: RunConfig) {\n if (this._runConfig === runConfig) return;\n\n this._runConfig = runConfig;\n this._notifySubscribers();\n }\n\n private _emptyTextAndAttachments() {\n this._attachments = [];\n this._text = \"\";\n this._notifySubscribers();\n }\n\n private async _onClearAttachments() {\n const adapter = this.getAttachmentAdapter();\n if (adapter) {\n const pending = this._attachments.filter((a) => !isAttachmentComplete(a));\n await Promise.all(pending.map((a) => adapter.remove(a)));\n }\n }\n\n public async reset() {\n if (\n this._attachments.length === 0 &&\n this._text === \"\" &&\n this._role === \"user\" &&\n Object.keys(this._runConfig).length === 0 &&\n this._quote === undefined\n ) {\n return;\n }\n\n this._role = \"user\";\n this._runConfig = {};\n this._quote = undefined;\n\n const task = this._onClearAttachments();\n this._emptyTextAndAttachments();\n await task;\n }\n\n public async clearAttachments() {\n const task = this._onClearAttachments();\n this.setAttachments([]);\n\n await task;\n }\n\n public async send(options?: SendOptions) {\n if (!this.canSend) return;\n\n if (this._dictationSession) {\n this._dictationSession.cancel();\n this._cleanupDictation();\n }\n\n const adapter = this.getAttachmentAdapter();\n const attachments =\n this.attachments.length > 0\n ? Promise.all(\n this.attachments.map(async (a) => {\n if (isAttachmentComplete(a)) return a;\n if (!adapter) throw new Error(\"Attachments are not supported\");\n const result = await adapter.send(a);\n return result as CompleteAttachment;\n }),\n )\n : [];\n\n const text = this.text;\n const quote = this._quote;\n this._quote = undefined;\n this._emptyTextAndAttachments();\n\n const message: Omit<AppendMessage, \"parentId\" | \"sourceId\"> = {\n createdAt: new Date(),\n role: this.role,\n content: text ? [{ type: \"text\", text }] : [],\n attachments: await attachments,\n runConfig: this.runConfig,\n metadata: { custom: { ...(quote ? { quote } : {}) } },\n };\n\n this.handleSend(message, options);\n this._notifyEventSubscribers(\"send\", {});\n }\n\n public cancel() {\n this.handleCancel();\n }\n\n public get queue(): readonly QueueItemState[] {\n return EMPTY_QUEUE_ITEMS;\n }\n\n public steerQueueItem(_queueItemId: string): void {}\n public removeQueueItem(_queueItemId: string): void {}\n\n protected abstract handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ): void;\n protected abstract handleCancel(): void;\n\n async addAttachment(fileOrAttachment: File | CreateAttachment) {\n if (!(fileOrAttachment instanceof File)) {\n const adapter = this.getAttachmentAdapter();\n if (\n adapter &&\n !fileMatchesAccept(\n {\n name: fileOrAttachment.name,\n type: fileOrAttachment.contentType ?? \"\",\n },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.contentType || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"not-accepted\",\n message,\n undefined,\n err,\n );\n throw err;\n }\n\n const a: CompleteAttachment = {\n id: fileOrAttachment.id ?? generateId(),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n this._attachments = [...this._attachments, a];\n this._notifySubscribers();\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n return;\n }\n\n const upsertAttachment = (a: PendingAttachment) => {\n const idx = this._attachments.findIndex(\n (attachment) => attachment.id === a.id,\n );\n if (idx !== -1)\n this._attachments = [\n ...this._attachments.slice(0, idx),\n a,\n ...this._attachments.slice(idx + 1),\n ];\n else {\n this._attachments = [...this._attachments, a];\n }\n\n this._notifySubscribers();\n };\n\n const adapter = this.getAttachmentAdapter();\n if (!adapter) {\n const message = \"Attachments are not supported\";\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"no-adapter\", message, undefined, err);\n throw err;\n }\n\n if (\n !fileMatchesAccept(\n { name: fileOrAttachment.name, type: fileOrAttachment.type },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.type || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"not-accepted\", message, undefined, err);\n throw err;\n }\n\n let lastAttachment: PendingAttachment | undefined;\n try {\n const promiseOrGenerator = adapter.add({ file: fileOrAttachment });\n if (Symbol.asyncIterator in promiseOrGenerator) {\n for await (const r of promiseOrGenerator) {\n lastAttachment = r;\n upsertAttachment(r);\n }\n } else {\n lastAttachment = await promiseOrGenerator;\n upsertAttachment(lastAttachment);\n }\n } catch (e) {\n if (lastAttachment) {\n upsertAttachment({\n ...lastAttachment,\n status: { type: \"incomplete\", reason: \"error\" },\n });\n }\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n e instanceof Error ? e.message : String(e),\n lastAttachment?.id,\n e instanceof Error ? e : undefined,\n );\n throw e;\n }\n\n const hasError =\n lastAttachment?.status.type === \"incomplete\" &&\n lastAttachment.status.reason === \"error\";\n if (hasError) {\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n \"Attachment upload did not complete successfully.\",\n lastAttachment?.id,\n );\n } else {\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n }\n }\n\n private _safeEmitAttachmentAddError(\n reason: AttachmentAddErrorReason,\n message: string,\n attachmentId?: string,\n error?: Error,\n ) {\n try {\n this._notifyEventSubscribers(\"attachmentAddError\", {\n reason,\n message,\n ...(attachmentId !== undefined && { attachmentId }),\n ...(error !== undefined && { error }),\n });\n } catch (subscriberError) {\n console.error(\n \"[assistant-ui] attachmentAddError subscriber threw:\",\n subscriberError,\n );\n }\n }\n\n async removeAttachment(attachmentId: string) {\n const index = this._attachments.findIndex((a) => a.id === attachmentId);\n if (index === -1) throw new Error(\"Attachment not found\");\n const attachment = this._attachments[index]!;\n\n if (!isAttachmentComplete(attachment)) {\n const adapter = this.getAttachmentAdapter();\n if (!adapter) throw new Error(\"Attachments are not supported\");\n await adapter.remove(attachment);\n }\n\n this._attachments = this._attachments.filter((a) => a.id !== attachmentId);\n this._notifySubscribers();\n }\n\n private _dictation: DictationState | undefined;\n private _dictationSession: DictationAdapter.Session | undefined;\n private _dictationUnsubscribes: Unsubscribe[] = [];\n private _dictationBaseText = \"\";\n private _currentInterimText = \"\";\n private _dictationSessionIdCounter = 0;\n private _activeDictationSessionId: number | undefined;\n private _isCleaningDictation = false;\n\n public get dictation(): DictationState | undefined {\n return this._dictation;\n }\n\n private _isActiveSession(\n sessionId: number,\n session: DictationAdapter.Session,\n ): boolean {\n return (\n this._activeDictationSessionId === sessionId &&\n this._dictationSession === session\n );\n }\n\n public startDictation(): void {\n const adapter = this.getDictationAdapter();\n if (!adapter) {\n throw new Error(\"Dictation adapter not configured\");\n }\n\n if (this._dictationSession) {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n const oldSession = this._dictationSession;\n oldSession.stop().catch(() => {});\n this._dictationSession = undefined;\n }\n\n const inputDisabled = adapter.disableInputDuringDictation ?? false;\n\n this._dictationBaseText = this._text;\n this._currentInterimText = \"\";\n\n const session = adapter.listen();\n this._dictationSession = session;\n const sessionId = ++this._dictationSessionIdCounter;\n this._activeDictationSessionId = sessionId;\n this._dictation = { status: session.status, inputDisabled };\n this._notifySubscribers();\n\n const unsubSpeech = session.onSpeech((result) => {\n if (!this._isActiveSession(sessionId, session)) return;\n const isFinal = result.isFinal !== false;\n\n const needsSeparator =\n this._dictationBaseText &&\n !this._dictationBaseText.endsWith(\" \") &&\n result.transcript;\n const separator = needsSeparator ? \" \" : \"\";\n\n if (isFinal) {\n this._dictationBaseText =\n this._dictationBaseText + separator + result.transcript;\n this._currentInterimText = \"\";\n this._text = this._dictationBaseText;\n\n if (this._dictation) {\n const { transcript: _, ...rest } = this._dictation;\n this._dictation = rest;\n }\n this._notifySubscribers();\n } else {\n this._currentInterimText = separator + result.transcript;\n this._text = this._dictationBaseText + this._currentInterimText;\n\n if (this._dictation) {\n this._dictation = {\n ...this._dictation,\n transcript: result.transcript,\n };\n }\n this._notifySubscribers();\n }\n });\n this._dictationUnsubscribes.push(unsubSpeech);\n\n const unsubStart = session.onSpeechStart(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n this._dictation = {\n status: { type: \"running\" },\n inputDisabled,\n ...(this._dictation?.transcript && {\n transcript: this._dictation.transcript,\n }),\n };\n this._notifySubscribers();\n });\n this._dictationUnsubscribes.push(unsubStart);\n\n const unsubEnd = session.onSpeechEnd(() => {\n this._cleanupDictation({ sessionId });\n });\n this._dictationUnsubscribes.push(unsubEnd);\n\n const statusInterval = setInterval(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n if (session.status.type === \"ended\") {\n this._cleanupDictation({ sessionId });\n }\n }, 100);\n this._dictationUnsubscribes.push(() => clearInterval(statusInterval));\n }\n\n public stopDictation(): void {\n if (!this._dictationSession) return;\n\n const session = this._dictationSession;\n const sessionId = this._activeDictationSessionId;\n session.stop().finally(() => {\n this._cleanupDictation({ sessionId });\n });\n }\n\n private _cleanupDictation(options?: { sessionId: number | undefined }): void {\n const isStaleSession =\n options?.sessionId !== undefined &&\n options.sessionId !== this._activeDictationSessionId;\n if (isStaleSession || this._isCleaningDictation) return;\n\n this._isCleaningDictation = true;\n try {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n this._dictationSession = undefined;\n this._activeDictationSessionId = undefined;\n this._dictation = undefined;\n this._dictationBaseText = \"\";\n this._currentInterimText = \"\";\n this._notifySubscribers();\n } finally {\n this._isCleaningDictation = false;\n }\n }\n\n private _eventSubscribers = new Map<\n ComposerRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n protected _notifyEventSubscribers<E extends ComposerRuntimeEventType>(\n event: E,\n payload: ComposerRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n for (const callback of subscribers) callback(payload);\n }\n\n public unstable_on<E extends ComposerRuntimeEventType>(\n event: E,\n callback: ComposerRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"default-edit-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"mappings":";;;;;;;;cAUa,8BAAA,SAAuC,uBAAA;EAAA,QAuBxC,OAAA;EAAA,QAQA,eAAA;EAAA,IA9BC,SAAA;EAAA,IAIA,OAAA;EAAA,UAID,oBAAA,IAAoB,iBAAA;EAAA,UAIpB,mBAAA,IAAmB,gBAAA;EAAA,QAIrB,aAAA;EAAA,QACA,oBAAA;EAAA,QACA,mBAAA;EAAA,QACA,SAAA;EAAA,QACA,SAAA;cAEE,OAAA,EAAS,iBAAA;IACf,QAAA;MAEM,WAAA,GAAc,iBAAA;MACd,SAAA,GAAY,gBAAA;IAAA;EAAA,GAIZ,eAAA;IACN,QAAA;IAAU;EAAA;IAAa,QAAA;IAAyB,OAAA,EAAS,aAAA;EAAA;EAAA,IA2BlD,QAAA;EAAA,IAIA,QAAA;EAIE,UAAA,CACX,OAAA,EAAS,IAAA,CAAK,aAAA,4BACd,OAAA,GAAU,WAAA,GAAW,OAAA;EAgChB,YAAA;AAAA"}
1
+ {"version":3,"file":"default-edit-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"mappings":";;;;;;;;cAWa,8BAAA,SAAuC,uBAAA;EAAA,QAuBxC,OAAA;EAAA,QAQA,eAAA;EAAA,IA9BC,SAAA;EAAA,IAIA,OAAA;EAAA,UAID,oBAAA,IAAoB,iBAAA;EAAA,UAIpB,mBAAA,IAAmB,gBAAA;EAAA,QAIrB,aAAA;EAAA,QACA,oBAAA;EAAA,QACA,mBAAA;EAAA,QACA,SAAA;EAAA,QACA,SAAA;cAEE,OAAA,EAAS,iBAAA;IACf,QAAA;MAEM,WAAA,GAAc,iBAAA;MACd,SAAA,GAAY,gBAAA;IAAA;EAAA,GAIZ,eAAA;IACN,QAAA;IAAU;EAAA;IAAa,QAAA;IAAyB,OAAA,EAAS,aAAA;EAAA;EAAA,IA2BlD,QAAA;EAAA,IAIA,QAAA;EAIE,UAAA,CACX,OAAA,EAAS,IAAA,CAAK,aAAA,4BACd,OAAA,GAAU,WAAA,GAAW,OAAA;EAgDhB,YAAA;AAAA"}
@@ -1,3 +1,4 @@
1
+ import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata.js";
1
2
  import { attachmentsEqual, liftNonTextParts } from "../../adapters/attachment.js";
2
3
  import { getThreadMessageText } from "../../utils/text.js";
3
4
  import { BaseComposerRuntimeCore } from "./base-composer-runtime-core.js";
@@ -52,8 +53,12 @@ var DefaultEditComposerRuntimeCore = class extends BaseComposerRuntimeCore {
52
53
  const attachmentsChanged = !attachmentsEqual(message.attachments ?? [], this._previousAttachments);
53
54
  if (text !== this._previousText || attachmentsChanged || options?.startRun) {
54
55
  const content = this._nonTextPassthrough.length > 0 ? [...message.content, ...this._nonTextPassthrough] : message.content;
56
+ const messages = this.runtime.messages;
57
+ const parentIndex = this._parentId === null ? -1 : messages.findIndex((m) => m.id === this._parentId);
58
+ const composerMetadata = gateInteractableComposerMetadata(this.runtime.getModelContext().unstable_composerMetadata, messages.slice(0, parentIndex + 1));
59
+ const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
55
60
  this.runtime.append({
56
- ...message,
61
+ ...enriched,
57
62
  content,
58
63
  parentId: this._parentId,
59
64
  sourceId: this._sourceId,