@assistant-ui/react 0.14.14 → 0.14.15

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 (207) hide show
  1. package/README.md +5 -1
  2. package/dist/client/ExternalThread.d.ts +2 -12
  3. package/dist/client/ExternalThread.d.ts.map +1 -1
  4. package/dist/client/ExternalThread.js +30 -29
  5. package/dist/client/ExternalThread.js.map +1 -1
  6. package/dist/client/InMemoryThreadList.d.ts.map +1 -1
  7. package/dist/client/InMemoryThreadList.js +11 -10
  8. package/dist/client/InMemoryThreadList.js.map +1 -1
  9. package/dist/client/SingleThreadList.d.ts.map +1 -1
  10. package/dist/client/SingleThreadList.js +9 -8
  11. package/dist/client/SingleThreadList.js.map +1 -1
  12. package/dist/context/providers/ThreadViewportProvider.js +1 -1
  13. package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
  14. package/dist/context/react/ThreadViewportContext.js +1 -1
  15. package/dist/context/react/utils/createContextHook.js +1 -1
  16. package/dist/context/react/utils/ensureBinding.js.map +1 -1
  17. package/dist/context/react/utils/useRuntimeState.js +1 -1
  18. package/dist/context/stores/ThreadViewport.js.map +1 -1
  19. package/dist/devtools/DevToolsHooks.js.map +1 -1
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +3 -3
  22. package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -1
  23. package/dist/legacy-runtime/cloud/auiV0.js +1 -1
  24. package/dist/legacy-runtime/hooks/AssistantContext.js.map +1 -1
  25. package/dist/legacy-runtime/hooks/AttachmentContext.js.map +1 -1
  26. package/dist/legacy-runtime/hooks/ComposerContext.js.map +1 -1
  27. package/dist/legacy-runtime/hooks/MessageContext.js.map +1 -1
  28. package/dist/legacy-runtime/hooks/MessagePartContext.js.map +1 -1
  29. package/dist/legacy-runtime/hooks/ThreadContext.js +1 -1
  30. package/dist/legacy-runtime/hooks/ThreadContext.js.map +1 -1
  31. package/dist/legacy-runtime/hooks/ThreadListItemContext.js.map +1 -1
  32. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js +1 -1
  33. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +1 -1
  34. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +1 -1
  35. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +1 -1
  36. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  37. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +1 -1
  38. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js +1 -1
  39. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  40. package/dist/mcp-apps/McpAppRenderer.js +7 -7
  41. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  42. package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
  43. package/dist/mcp-apps/McpAppsRemoteHost.js +5 -4
  44. package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
  45. package/dist/mcp-apps/app-frame.d.ts +1 -1
  46. package/dist/mcp-apps/app-frame.d.ts.map +1 -1
  47. package/dist/mcp-apps/app-frame.js +82 -104
  48. package/dist/mcp-apps/app-frame.js.map +1 -1
  49. package/dist/mcp-apps/bridge.d.ts +3 -3
  50. package/dist/mcp-apps/bridge.d.ts.map +1 -1
  51. package/dist/mcp-apps/bridge.js +35 -10
  52. package/dist/mcp-apps/bridge.js.map +1 -1
  53. package/dist/mcp-apps/types.d.ts +2 -12
  54. package/dist/mcp-apps/types.d.ts.map +1 -1
  55. package/dist/mcp-apps/types.js.map +1 -1
  56. package/dist/model-context/frame/useAssistantFrameHost.js +1 -1
  57. package/dist/model-context/makeAssistantVisible.js +1 -1
  58. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  59. package/dist/primitives/actionBar/ActionBarCopy.js +1 -1
  60. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -1
  61. package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
  62. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -1
  63. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -1
  64. package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -1
  65. package/dist/primitives/actionBar/ActionBarRoot.js +1 -1
  66. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -1
  67. package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -1
  68. package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -1
  69. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -1
  70. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -1
  71. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -1
  72. package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -1
  73. package/dist/primitives/assistantModal/AssistantModalContent.js +1 -1
  74. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -1
  75. package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -1
  76. package/dist/primitives/attachment/AttachmentRemove.js +1 -1
  77. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  78. package/dist/primitives/attachment/AttachmentRoot.js +1 -1
  79. package/dist/primitives/attachment/AttachmentThumb.js +1 -1
  80. package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -1
  81. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -1
  82. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  83. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -1
  84. package/dist/primitives/composer/ComposerAddAttachment.js +1 -1
  85. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  86. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -1
  87. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  88. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -1
  89. package/dist/primitives/composer/ComposerInput.js +1 -1
  90. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  91. package/dist/primitives/composer/ComposerInputPluginContext.js +1 -1
  92. package/dist/primitives/composer/ComposerQuote.js +1 -1
  93. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  94. package/dist/primitives/composer/ComposerRoot.js +1 -1
  95. package/dist/primitives/composer/ComposerSend.js +1 -1
  96. package/dist/primitives/composer/ComposerStopDictation.js +1 -1
  97. package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
  98. package/dist/primitives/composer/trigger/TriggerPopover.js +2 -2
  99. package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
  100. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -1
  101. package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -1
  102. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -1
  103. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -1
  104. package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -1
  105. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
  106. package/dist/primitives/composer/trigger/TriggerPopoverResource.js +8 -7
  107. package/dist/primitives/composer/trigger/TriggerPopoverResource.js.map +1 -1
  108. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -1
  109. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
  110. package/dist/primitives/composer/trigger/triggerDetectionResource.js +5 -4
  111. package/dist/primitives/composer/trigger/triggerDetectionResource.js.map +1 -1
  112. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  113. package/dist/primitives/composer/trigger/triggerKeyboardResource.js +8 -7
  114. package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
  115. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  116. package/dist/primitives/composer/trigger/triggerNavigationResource.js +13 -12
  117. package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
  118. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  119. package/dist/primitives/composer/trigger/triggerSelectionResource.js +7 -6
  120. package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
  121. package/dist/primitives/error/ErrorMessage.js +1 -1
  122. package/dist/primitives/error/ErrorRoot.js +1 -1
  123. package/dist/primitives/message/MessagePartsGrouped.js +1 -1
  124. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  125. package/dist/primitives/message/MessageRoot.js +1 -1
  126. package/dist/primitives/message/MessageRoot.js.map +1 -1
  127. package/dist/primitives/messagePart/MessagePartImage.js +1 -1
  128. package/dist/primitives/messagePart/MessagePartText.js +1 -1
  129. package/dist/primitives/queueItem/QueueItemRemove.js +1 -1
  130. package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
  131. package/dist/primitives/queueItem/QueueItemSteer.js +1 -1
  132. package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
  133. package/dist/primitives/queueItem/QueueItemText.js +1 -1
  134. package/dist/primitives/reasoning/useScrollLock.js +1 -1
  135. package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
  136. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -1
  137. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
  138. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -1
  139. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
  140. package/dist/primitives/suggestion/SuggestionDescription.js +1 -1
  141. package/dist/primitives/suggestion/SuggestionTitle.js +1 -1
  142. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -1
  143. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  144. package/dist/primitives/thread/ThreadRoot.js +1 -1
  145. package/dist/primitives/thread/ThreadScrollToBottom.js +1 -1
  146. package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
  147. package/dist/primitives/thread/ThreadViewport.js +1 -1
  148. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  149. package/dist/primitives/thread/ThreadViewportFooter.js +1 -1
  150. package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
  151. package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
  152. package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -1
  153. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -1
  154. package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -1
  155. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  156. package/dist/primitives/threadList/ThreadListNew.js +1 -1
  157. package/dist/primitives/threadList/ThreadListRoot.js +1 -1
  158. package/dist/primitives/threadListItem/ThreadListItemRoot.js +1 -1
  159. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -1
  160. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -1
  161. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -1
  162. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -1
  163. package/dist/sandbox-host/SandboxHost.d.ts +50 -0
  164. package/dist/sandbox-host/SandboxHost.d.ts.map +1 -0
  165. package/dist/sandbox-host/SandboxHost.js +85 -0
  166. package/dist/sandbox-host/SandboxHost.js.map +1 -0
  167. package/dist/unstable/useMentionAdapter.js +1 -1
  168. package/dist/unstable/useMentionAdapter.js.map +1 -1
  169. package/dist/unstable/useSlashCommandAdapter.js +1 -1
  170. package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
  171. package/dist/utils/Primitive.js +1 -1
  172. package/dist/utils/createActionButton.js +1 -1
  173. package/dist/utils/createActionButton.js.map +1 -1
  174. package/dist/utils/hooks/useManagedRef.js +1 -1
  175. package/dist/utils/hooks/useMediaQuery.js +1 -1
  176. package/dist/utils/hooks/useMediaQuery.js.map +1 -1
  177. package/dist/utils/hooks/useOnResizeContent.js +1 -1
  178. package/dist/utils/hooks/useOnScrollToBottom.js +1 -1
  179. package/dist/utils/hooks/useSizeHandle.js +1 -1
  180. package/dist/utils/json/is-json.js.map +1 -1
  181. package/dist/utils/smooth/SmoothContext.js +1 -1
  182. package/dist/utils/smooth/SmoothContext.js.map +1 -1
  183. package/dist/utils/smooth/useSmooth.js +1 -1
  184. package/dist/utils/smooth/useSmooth.js.map +1 -1
  185. package/dist/utils/useToolArgsFieldStatus.d.ts +2 -2
  186. package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
  187. package/package.json +21 -20
  188. package/src/client/ExternalThread.ts +484 -515
  189. package/src/client/InMemoryThreadList.ts +153 -162
  190. package/src/client/SingleThreadList.ts +87 -84
  191. package/src/context/providers/ThreadViewportProvider.tsx +2 -2
  192. package/src/index.ts +8 -1
  193. package/src/mcp-apps/McpAppRenderer.tsx +28 -35
  194. package/src/mcp-apps/McpAppsRemoteHost.ts +25 -24
  195. package/src/mcp-apps/app-frame.tsx +100 -141
  196. package/src/mcp-apps/bridge.test.ts +100 -60
  197. package/src/mcp-apps/bridge.ts +43 -21
  198. package/src/mcp-apps/types.ts +2 -12
  199. package/src/primitives/composer/trigger/TriggerPopover.tsx +1 -1
  200. package/src/primitives/composer/trigger/TriggerPopoverResource.ts +75 -76
  201. package/src/primitives/composer/trigger/triggerDetectionResource.ts +6 -5
  202. package/src/primitives/composer/trigger/triggerKeyboardResource.ts +9 -13
  203. package/src/primitives/composer/trigger/triggerNavigationResource.ts +14 -19
  204. package/src/primitives/composer/trigger/triggerSelectionResource.ts +8 -7
  205. package/src/sandbox-host/SandboxHost.test.tsx +231 -0
  206. package/src/sandbox-host/SandboxHost.tsx +185 -0
  207. package/src/tests/local-runtime-queue.test.tsx +305 -0
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  <a href="https://www.assistant-ui.com">
2
- <img src="https://raw.githubusercontent.com/assistant-ui/assistant-ui/main/.github/assets/header.svg" alt="assistant-ui Header" width="100%" />
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/assistant-ui/assistant-ui/main/.github/assets/header-dark.svg" />
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/assistant-ui/assistant-ui/main/.github/assets/header.svg" />
5
+ <img src="https://raw.githubusercontent.com/assistant-ui/assistant-ui/main/.github/assets/header.svg" alt="assistant-ui Header" width="100%" />
6
+ </picture>
3
7
  </a>
4
8
 
5
9
  <p align="center">
@@ -1,20 +1,10 @@
1
1
  import { ClientOutput } from "@assistant-ui/store";
2
- import { AppendMessage, ThreadMessage } from "@assistant-ui/core";
3
- import { QueueItemState } from "@assistant-ui/core/store";
2
+ import { AppendMessage, ExternalThreadQueueAdapter, ThreadMessage } from "@assistant-ui/core";
4
3
 
5
4
  //#region src/client/ExternalThread.d.ts
6
5
  type ExternalThreadMessage = ThreadMessage & {
7
6
  id: string;
8
7
  };
9
- type ExternalThreadQueueAdapter = {
10
- /** The current queue items. */items: readonly QueueItemState[]; /** Called when a message is submitted via the composer. Receives the steer preference. */
11
- enqueue: (message: AppendMessage, opts: {
12
- steer: boolean;
13
- }) => void; /** Called to promote an existing queue item (cancel current run, run this immediately). */
14
- steer: (queueItemId: string) => void; /** Called to remove an item from the queue. */
15
- remove: (queueItemId: string) => void; /** Called to clear all pending queue items, with the reason for clearing. */
16
- clear: (reason: "edit" | "reload" | "cancel-run") => void;
17
- };
18
8
  type ExternalThreadProps = {
19
9
  messages: readonly ExternalThreadMessage[];
20
10
  isRunning?: boolean;
@@ -38,5 +28,5 @@ type ExternalThreadProps = {
38
28
  };
39
29
  declare const ExternalThread: (props: ExternalThreadProps) => import("@assistant-ui/tap").ResourceElement<ClientOutput<"thread">, ExternalThreadProps>;
40
30
  //#endregion
41
- export { ExternalThread, ExternalThreadMessage, ExternalThreadProps, ExternalThreadQueueAdapter };
31
+ export { ExternalThread, ExternalThreadMessage, ExternalThreadProps };
42
32
  //# sourceMappingURL=ExternalThread.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalThread.d.ts","names":[],"sources":["../../src/client/ExternalThread.ts"],"mappings":";;;;;KAgCY,qBAAA,GAAwB,aAAa;EAC/C,EAAE;AAAA;AAAA,KAGQ,0BAAA;iCAEV,KAAA,WAAgB,cAAA,IALd;EAOF,OAAA,GAAU,OAAA,EAAS,aAAa,EAAE,IAAA;IAAQ,KAAA;EAAA,YAAV;EAEhC,KAAA,GAAQ,WAAA,mBAJQ;EAMhB,MAAA,GAAS,WAAA,mBAJU;EAMnB,KAAA,GAAQ,MAAA;AAAA;AAAA,KAGE,mBAAA;EACV,QAAA,WAAmB,qBAAA;EACnB,SAAA;EAPA;;;;;AAEgD;EAYhD,cAAA;EAT6B;;;;EAc7B,KAAA,IAAS,OAAA,EAAS,aAAA;EAClB,MAAA,IAAU,OAAA,EAAS,aAAA;EACnB,QAAA,IAAY,QAAA;EACZ,UAAA;EACA,QAAA,eAjBmB;EAmBnB,KAAA,GAAQ,0BAAA;AAAA;AAAA,cAiZG,cAAA,GAAc,KAAA,EAAA,mBAAA,iCAAA,eAAA,CAAA,YAAA,YAAA,mBAAA"}
1
+ {"version":3,"file":"ExternalThread.d.ts","names":[],"sources":["../../src/client/ExternalThread.ts"],"mappings":";;;;KA4BY,qBAAA,GAAwB,aAAa;EAC/C,EAAE;AAAA;AAAA,KAGQ,mBAAA;EACV,QAAA,WAAmB,qBAAA;EACnB,SAAA;EALE;AAGJ;;;;;EASE,cAAA;EAWQ;;;;EANR,KAAA,IAAS,OAAA,EAAS,aAAA;EAClB,MAAA,IAAU,OAAA,EAAS,aAAA;EACnB,QAAA,IAAY,QAAA;EACZ,UAAA;EACA,QAAA,eAJS;EAMT,KAAA,GAAQ,0BAAA;AAAA;AAAA,cAqYG,cAAA,GAAc,KAAA,EAAA,mBAAA,iCAAA,eAAA,CAAA,YAAA,YAAA,mBAAA"}
@@ -1,16 +1,17 @@
1
1
  import { SingleThreadList } from "./SingleThreadList.js";
2
- import { Derived, attachTransformScopes, tapClientLookup, tapClientResource } from "@assistant-ui/store";
2
+ import { Derived, attachTransformScopes, useClientLookup, useClientResource } from "@assistant-ui/store";
3
3
  import { DataRenderers, Tools } from "@assistant-ui/core/react";
4
+ import { useEffect, useEffectEvent, useMemo, useState } from "@assistant-ui/tap/react-shim";
4
5
  import { ModelContext, Suggestions } from "@assistant-ui/core/store";
5
- import { resource, tapEffect, tapEffectEvent, tapMemo, tapState, withKey } from "@assistant-ui/tap";
6
+ import { resource, withKey } from "@assistant-ui/tap";
6
7
  //#region src/client/ExternalThread.ts
7
8
  const EMPTY_QUEUE_ITEMS = [];
8
- const MessageClient = resource(({ message, index, onEdit, onReload, queue }) => {
9
- const [isCopied, setIsCopied] = tapState(false);
10
- const [isHovering, setIsHovering] = tapState(false);
11
- const [isEditing, setIsEditing] = tapState(false);
12
- const partClients = tapClientLookup(() => message.content.map((part, idx) => withKey(idx, PartResource({ part }))), [message.content]);
13
- const attachmentClients = tapClientLookup(() => (message.attachments ?? []).map((attachment) => withKey(attachment.id, AttachmentResource({
9
+ const MessageClient = resource(function MessageClient({ message, index, onEdit, onReload, queue }) {
10
+ const [isCopied, setIsCopied] = useState(false);
11
+ const [isHovering, setIsHovering] = useState(false);
12
+ const [isEditing, setIsEditing] = useState(false);
13
+ const partClients = useClientLookup(() => message.content.map((part, idx) => withKey(idx, PartResource({ part }))), [message.content]);
14
+ const attachmentClients = useClientLookup(() => (message.attachments ?? []).map((attachment) => withKey(attachment.id, AttachmentResource({
14
15
  attachment,
15
16
  onRemove: () => {}
16
17
  }))), [message.attachments]);
@@ -29,7 +30,7 @@ const MessageClient = resource(({ message, index, onEdit, onReload, queue }) =>
29
30
  });
30
31
  setIsEditing(false);
31
32
  };
32
- const composerClient = tapClientResource(ComposerClientResource({
33
+ const composerClient = useClientResource(ComposerClientResource({
33
34
  type: "edit",
34
35
  isEditing,
35
36
  canCancel: true,
@@ -39,7 +40,7 @@ const MessageClient = resource(({ message, index, onEdit, onReload, queue }) =>
39
40
  message,
40
41
  queue
41
42
  }));
42
- const state = tapMemo(() => {
43
+ const state = useMemo(() => {
43
44
  return {
44
45
  ...message,
45
46
  attachments: message.attachments ?? [],
@@ -86,8 +87,8 @@ const MessageClient = resource(({ message, index, onEdit, onReload, queue }) =>
86
87
  setIsHovering
87
88
  };
88
89
  });
89
- const PartResource = resource(({ part }) => {
90
- const state = tapMemo(() => ({
90
+ const PartResource = resource(function PartResource({ part }) {
91
+ const state = useMemo(() => ({
91
92
  ...part,
92
93
  status: { type: "complete" }
93
94
  }), [part]);
@@ -98,7 +99,7 @@ const PartResource = resource(({ part }) => {
98
99
  respondToToolApproval: () => {}
99
100
  };
100
101
  });
101
- const AttachmentResource = resource(({ attachment, onRemove }) => {
102
+ const AttachmentResource = resource(function AttachmentResource({ attachment, onRemove }) {
102
103
  return {
103
104
  getState: () => attachment,
104
105
  remove: async () => {
@@ -106,42 +107,42 @@ const AttachmentResource = resource(({ attachment, onRemove }) => {
106
107
  }
107
108
  };
108
109
  });
109
- const QueueItemClient = resource(({ item, onSteer, onRemove }) => {
110
+ const QueueItemClient = resource(function QueueItemClient({ item, onSteer, onRemove }) {
110
111
  return {
111
112
  getState: () => item,
112
113
  steer: onSteer,
113
114
  remove: onRemove
114
115
  };
115
116
  });
116
- const ComposerClientResource = resource(({ type, isEditing, canCancel, isSendDisabled = false, onCancel, onBeginEdit, onSend, message, queue }) => {
117
- const [text, setText] = tapState("");
118
- const [role, setRole] = tapState("user");
119
- const [runConfig, setRunConfig] = tapState({});
120
- const [attachments, setAttachments] = tapState([]);
121
- const [quote, setQuote] = tapState(void 0);
122
- const updateFromMessage = tapEffectEvent(() => {
117
+ const ComposerClientResource = resource(function ComposerClientResource({ type, isEditing, canCancel, isSendDisabled = false, onCancel, onBeginEdit, onSend, message, queue }) {
118
+ const [text, setText] = useState("");
119
+ const [role, setRole] = useState("user");
120
+ const [runConfig, setRunConfig] = useState({});
121
+ const [attachments, setAttachments] = useState([]);
122
+ const [quote, setQuote] = useState(void 0);
123
+ const updateFromMessage = useEffectEvent(() => {
123
124
  if (message) {
124
125
  setText(message.content.filter((part) => part.type === "text").map((part) => "text" in part ? part.text : "").join("\n\n"));
125
126
  setRole(message.role);
126
127
  setAttachments(message.attachments ?? []);
127
128
  }
128
129
  });
129
- tapEffect(() => {
130
+ useEffect(() => {
130
131
  if (isEditing) updateFromMessage();
131
132
  }, [isEditing]);
132
- const attachmentClients = tapClientLookup(() => attachments.map((attachment, idx) => withKey(attachment.id, AttachmentResource({
133
+ const attachmentClients = useClientLookup(() => attachments.map((attachment, idx) => withKey(attachment.id, AttachmentResource({
133
134
  attachment,
134
135
  onRemove: () => {
135
136
  setAttachments(attachments.filter((_, i) => i !== idx));
136
137
  }
137
138
  }))), [attachments]);
138
139
  const queueItems = queue?.items ?? EMPTY_QUEUE_ITEMS;
139
- const queueItemClients = tapClientLookup(() => queueItems.map((item) => withKey(item.id, QueueItemClient({
140
+ const queueItemClients = useClientLookup(() => queueItems.map((item) => withKey(item.id, QueueItemClient({
140
141
  item,
141
142
  onSteer: () => queue?.steer(item.id),
142
143
  onRemove: () => queue?.remove(item.id)
143
144
  }))), [queueItems]);
144
- const state = tapMemo(() => {
145
+ const state = useMemo(() => {
145
146
  const isEmpty = !text.trim() && !attachments.length;
146
147
  return {
147
148
  text,
@@ -249,7 +250,7 @@ const ComposerClientResource = resource(({ type, isEditing, canCancel, isSendDis
249
250
  }
250
251
  };
251
252
  });
252
- const ExternalThread = resource(({ messages, isRunning = false, isSendDisabled = false, onNew, onEdit, onReload, onStartRun, onCancel, queue }) => {
253
+ const ExternalThread = resource(function ExternalThread({ messages, isRunning = false, isSendDisabled = false, onNew, onEdit, onReload, onStartRun, onCancel, queue }) {
253
254
  const handleReload = (messageId) => {
254
255
  const messageIndex = messages.findIndex((m) => m.id === messageId);
255
256
  if (messageIndex === -1) return;
@@ -257,7 +258,7 @@ const ExternalThread = resource(({ messages, isRunning = false, isSendDisabled =
257
258
  queue?.clear("reload");
258
259
  onReload?.(parentId);
259
260
  };
260
- const messageClients = tapClientLookup(() => messages.map((msg, index) => {
261
+ const messageClients = useClientLookup(() => messages.map((msg, index) => {
261
262
  const props = {
262
263
  message: msg,
263
264
  index,
@@ -278,7 +279,7 @@ const ExternalThread = resource(({ messages, isRunning = false, isSendDisabled =
278
279
  const handleSendNew = (message) => {
279
280
  onNew?.(message);
280
281
  };
281
- const composerClient = tapClientResource(ComposerClientResource({
282
+ const composerClient = useClientResource(ComposerClientResource({
282
283
  type: "thread",
283
284
  isEditing: true,
284
285
  canCancel: isRunning,
@@ -288,7 +289,7 @@ const ExternalThread = resource(({ messages, isRunning = false, isSendDisabled =
288
289
  queue
289
290
  }));
290
291
  const hasQueue = !!queue;
291
- const state = tapMemo(() => {
292
+ const state = useMemo(() => {
292
293
  const messageStates = messageClients.state.map((s, idx, arr) => ({
293
294
  ...s,
294
295
  isLast: idx === arr.length - 1
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalThread.js","names":[],"sources":["../../src/client/ExternalThread.ts"],"sourcesContent":["import {\n resource,\n tapState,\n tapMemo,\n tapEffect,\n tapEffectEvent,\n} from \"@assistant-ui/tap\";\nimport {\n type ClientElement,\n type ClientOutput,\n tapClientLookup,\n attachTransformScopes,\n tapClientResource,\n Derived,\n} from \"@assistant-ui/store\";\nimport { withKey } from \"@assistant-ui/tap\";\nimport type {\n AppendMessage,\n Attachment,\n CreateAttachment,\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { QueueItemState } from \"@assistant-ui/core/store\";\nimport type { ComposerSendOptions } from \"@assistant-ui/core/store\";\nimport { ModelContext, Suggestions } from \"@assistant-ui/core/store\";\nimport { Tools, DataRenderers } from \"@assistant-ui/core/react\";\nimport { SingleThreadList } from \"./SingleThreadList\";\n\nconst EMPTY_QUEUE_ITEMS: readonly QueueItemState[] = [];\n\nexport type ExternalThreadMessage = ThreadMessage & {\n id: string;\n};\n\nexport type ExternalThreadQueueAdapter = {\n /** The current queue items. */\n items: readonly QueueItemState[];\n /** Called when a message is submitted via the composer. Receives the steer preference. */\n enqueue: (message: AppendMessage, opts: { steer: boolean }) => void;\n /** Called to promote an existing queue item (cancel current run, run this immediately). */\n steer: (queueItemId: string) => void;\n /** Called to remove an item from the queue. */\n remove: (queueItemId: string) => void;\n /** Called to clear all pending queue items, with the reason for clearing. */\n clear: (reason: \"edit\" | \"reload\" | \"cancel-run\") => void;\n};\n\nexport type ExternalThreadProps = {\n messages: readonly ExternalThreadMessage[];\n isRunning?: boolean;\n /**\n * Whether sending new messages is currently disabled. When `true`, the\n * thread composer's input remains usable but `send()` is a no-op and\n * `composer.canSend` is `false`. Edit composers (saving message edits)\n * intentionally ignore this flag.\n */\n isSendDisabled?: boolean;\n /**\n * Callback for new messages (non-queue runtimes).\n * @note Unused when `queue` is provided — new messages are routed through `queue.enqueue` instead.\n */\n onNew?: (message: AppendMessage) => void;\n onEdit?: (message: AppendMessage) => void;\n onReload?: (parentId: string | null) => void;\n onStartRun?: () => void;\n onCancel?: () => void;\n /** Queue adapter for runtimes that support message queuing and steering. */\n queue?: ExternalThreadQueueAdapter;\n};\n\ntype MessageClientProps = {\n message: ExternalThreadMessage;\n index: number;\n onEdit?: (message: AppendMessage) => void;\n onReload?: () => void;\n queue?: ExternalThreadQueueAdapter | undefined;\n};\n\n// Message Client - minimal implementation\nconst MessageClient = resource(\n ({\n message,\n index,\n onEdit,\n onReload,\n queue,\n }: MessageClientProps): ClientOutput<\"message\"> => {\n const [isCopied, setIsCopied] = tapState(false);\n const [isHovering, setIsHovering] = tapState(false);\n const [isEditing, setIsEditing] = tapState(false);\n\n const partClients = tapClientLookup(\n () =>\n message.content.map((part, idx) =>\n withKey(idx, PartResource({ part })),\n ),\n [message.content],\n );\n\n const attachmentClients = tapClientLookup(\n () =>\n (message.attachments ?? []).map((attachment) =>\n withKey(\n attachment.id,\n AttachmentResource({\n attachment,\n onRemove: () => {},\n }),\n ),\n ),\n [message.attachments],\n );\n\n const handleBeginEdit = () => {\n setIsEditing(true);\n };\n\n const handleCancelEdit = () => {\n setIsEditing(false);\n };\n\n const handleSendEdit = (msg: AppendMessage) => {\n queue?.clear(\"edit\");\n onEdit?.({\n ...msg,\n parentId: message.id,\n sourceId: message.id,\n });\n setIsEditing(false);\n };\n\n const composerClient = tapClientResource(\n ComposerClientResource({\n type: \"edit\",\n isEditing,\n canCancel: true,\n onCancel: handleCancelEdit,\n onBeginEdit: handleBeginEdit,\n onSend: handleSendEdit,\n message,\n queue,\n }),\n );\n\n const state = tapMemo(() => {\n return {\n ...message,\n attachments: message.attachments ?? [],\n parentId: null,\n isLast: false, // Will be set by thread\n branchNumber: 1,\n branchCount: 1,\n speech: undefined,\n parts: partClients.state,\n isCopied,\n isHovering,\n index,\n composer: composerClient.state,\n };\n }, [\n message,\n isCopied,\n isHovering,\n index,\n composerClient.state,\n partClients.state,\n ]);\n\n return {\n getState: () => state,\n composer: () => composerClient.methods,\n reload: () => {\n onReload?.();\n },\n speak: () => {},\n stopSpeaking: () => {},\n submitFeedback: () => {},\n switchToBranch: () => {},\n getCopyText: () =>\n message.content.map((c) => (\"text\" in c ? c.text : \"\")).join(\"\"),\n part: (selector) => {\n if (\"index\" in selector) {\n return partClients.get(selector);\n }\n const partIndex = state.parts.findIndex(\n (p) => p.type === \"tool-call\" && p.toolCallId === selector.toolCallId,\n );\n return partClients.get({ index: partIndex });\n },\n attachment: (selector) => {\n if (\"id\" in selector) {\n return attachmentClients.get({ key: selector.id });\n }\n return attachmentClients.get(selector);\n },\n setIsCopied,\n setIsHovering,\n };\n },\n);\n\ntype PartResourceProps = {\n part: ThreadAssistantMessagePart | ThreadUserMessagePart;\n};\n\n// Part Client - minimal implementation\nconst PartResource = resource(\n ({ part }: PartResourceProps): ClientOutput<\"part\"> => {\n const state = tapMemo(\n () => ({\n ...part,\n status: { type: \"complete\" as const },\n }),\n [part],\n );\n\n return {\n getState: () => state,\n addToolResult: () => {},\n resumeToolCall: () => {},\n respondToToolApproval: () => {},\n };\n },\n);\n\ntype AttachmentResourceProps = {\n attachment: Attachment;\n onRemove?: () => void;\n};\n\n// Attachment Client - minimal implementation\nconst AttachmentResource = resource(\n ({\n attachment,\n onRemove,\n }: AttachmentResourceProps): ClientOutput<\"attachment\"> => {\n return {\n getState: () => attachment,\n remove: async () => {\n onRemove?.();\n },\n };\n },\n);\n\ntype ComposerClientResourceProps = {\n type: \"thread\" | \"edit\";\n isEditing: boolean;\n canCancel: boolean;\n isSendDisabled?: boolean;\n onCancel: () => void;\n onBeginEdit?: () => void;\n onSend?: (message: AppendMessage) => void;\n message?: ExternalThreadMessage;\n queue?: ExternalThreadQueueAdapter | undefined;\n};\n\nconst QueueItemClient = resource(\n ({\n item,\n onSteer,\n onRemove,\n }: {\n item: QueueItemState;\n onSteer: () => void;\n onRemove: () => void;\n }): ClientOutput<\"queueItem\"> => {\n return {\n getState: () => item,\n steer: onSteer,\n remove: onRemove,\n };\n },\n);\n\n// Composer Client - minimal implementation\nconst ComposerClientResource = resource(\n ({\n type,\n isEditing,\n canCancel,\n isSendDisabled = false,\n onCancel,\n onBeginEdit,\n onSend,\n message,\n queue,\n }: ComposerClientResourceProps): ClientOutput<\"composer\"> => {\n const [text, setText] = tapState(\"\");\n const [role, setRole] = tapState<\"user\" | \"assistant\" | \"system\">(\"user\");\n const [runConfig, setRunConfig] = tapState<Record<string, unknown>>({});\n const [attachments, setAttachments] = tapState<readonly Attachment[]>([]);\n const [quote, setQuote] = tapState<\n { readonly text: string; readonly messageId: string } | undefined\n >(undefined);\n\n // Update composer values when editing begins\n const updateFromMessage = tapEffectEvent(() => {\n if (message) {\n // Extract text from message content (text parts only)\n const textParts = message.content.filter(\n (part) => part.type === \"text\",\n );\n const messageText = textParts\n .map((part) => (\"text\" in part ? part.text : \"\"))\n .join(\"\\n\\n\");\n\n setText(messageText);\n setRole(message.role);\n setAttachments(message.attachments ?? []);\n }\n });\n\n tapEffect(() => {\n if (isEditing) {\n updateFromMessage();\n }\n }, [isEditing]);\n\n const attachmentClients = tapClientLookup(\n () =>\n attachments.map((attachment, idx) =>\n withKey(\n attachment.id,\n AttachmentResource({\n attachment,\n onRemove: () => {\n setAttachments(attachments.filter((_, i) => i !== idx));\n },\n }),\n ),\n ),\n [attachments],\n );\n\n const queueItems = queue?.items ?? EMPTY_QUEUE_ITEMS;\n const queueItemClients = tapClientLookup(\n () =>\n queueItems.map((item) =>\n withKey(\n item.id,\n QueueItemClient({\n item,\n onSteer: () => queue?.steer(item.id),\n onRemove: () => queue?.remove(item.id),\n }),\n ),\n ),\n [queueItems],\n );\n\n const state = tapMemo(() => {\n const isEmpty = !text.trim() && !attachments.length;\n return {\n text,\n role,\n attachments: attachmentClients.state,\n runConfig,\n isEditing,\n canCancel,\n canSend: isEditing && !isEmpty && !isSendDisabled,\n attachmentAccept: \"*\",\n isEmpty,\n type,\n dictation: undefined,\n quote,\n queue: queueItems,\n };\n }, [\n text,\n role,\n attachmentClients.state,\n runConfig,\n isEditing,\n canCancel,\n isSendDisabled,\n type,\n attachments.length,\n quote,\n queueItems,\n ]);\n\n return {\n getState: () => state,\n setText,\n setRole,\n setRunConfig,\n addAttachment: async (fileOrAttachment: File | CreateAttachment) => {\n if (fileOrAttachment instanceof File) {\n const newAttachment: Attachment = {\n id: Math.random().toString(36).substring(7),\n type: \"file\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.type,\n file: fileOrAttachment,\n status: { type: \"complete\" },\n content: [],\n };\n setAttachments([...attachments, newAttachment]);\n } else {\n const newAttachment: Attachment = {\n id: fileOrAttachment.id ?? Math.random().toString(36).substring(7),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n setAttachments([...attachments, newAttachment]);\n }\n },\n clearAttachments: async () => {\n setAttachments([]);\n },\n attachment: (selector) => {\n if (\"id\" in selector) {\n return attachmentClients.get({ key: selector.id });\n }\n return attachmentClients.get(selector);\n },\n reset: async () => {\n setText(\"\");\n setRole(\"user\");\n setRunConfig({});\n setAttachments([]);\n setQuote(undefined);\n },\n send: (opts?: ComposerSendOptions) => {\n if (!state.canSend) return;\n\n const currentQuote = quote;\n const composedMessage: AppendMessage = {\n role,\n content: text ? [{ type: \"text\" as const, text }] : [],\n attachments: attachments as any,\n createdAt: new Date(),\n parentId: null,\n sourceId: null,\n runConfig,\n startRun: opts?.startRun,\n metadata: {\n custom: { ...(currentQuote ? { quote: currentQuote } : {}) },\n },\n };\n if (queue) {\n queue.enqueue(composedMessage, { steer: opts?.steer ?? false });\n } else {\n onSend?.(composedMessage);\n }\n setText(\"\");\n setAttachments([]);\n setQuote(undefined);\n },\n cancel: onCancel,\n beginEdit: () => {\n onBeginEdit?.();\n },\n startDictation: () => {},\n stopDictation: () => {},\n setQuote,\n queueItem: (selector: { index: number }) => {\n return queueItemClients.get(selector);\n },\n };\n },\n);\n\n// External Thread Client\nexport const ExternalThread = resource(\n ({\n messages,\n isRunning = false,\n isSendDisabled = false,\n onNew,\n onEdit,\n onReload,\n onStartRun,\n onCancel,\n queue,\n }: ExternalThreadProps): ClientOutput<\"thread\"> => {\n const handleReload = (messageId: string) => {\n const messageIndex = messages.findIndex((m) => m.id === messageId);\n if (messageIndex === -1) return;\n\n const parentId = messageIndex > 0 ? messages[messageIndex - 1]!.id : null;\n queue?.clear(\"reload\");\n onReload?.(parentId);\n };\n\n const messageClients = tapClientLookup(\n () =>\n messages.map((msg, index) => {\n const props: MessageClientProps = {\n message: msg,\n index,\n onReload: () => handleReload(msg.id),\n queue,\n };\n if (onEdit) props.onEdit = onEdit;\n return withKey(msg.id, MessageClient(props));\n }),\n [messages, onEdit, queue],\n );\n\n const handleCancelRun = () => {\n queue?.clear(\"cancel-run\");\n onCancel?.();\n };\n\n const handleSendNew = (message: AppendMessage) => {\n onNew?.(message);\n };\n\n const composerClient = tapClientResource(\n ComposerClientResource({\n type: \"thread\",\n isEditing: true,\n canCancel: isRunning,\n isSendDisabled,\n onCancel: handleCancelRun,\n onSend: handleSendNew,\n queue,\n }),\n );\n\n const hasQueue = !!queue;\n const state = tapMemo(() => {\n const messageStates = messageClients.state.map((s, idx, arr) => ({\n ...s,\n isLast: idx === arr.length - 1,\n }));\n\n return {\n isEmpty: messages.length === 0,\n isDisabled: false,\n isLoading: false,\n isRunning,\n capabilities: {\n edit: false,\n reload: false,\n cancel: isRunning,\n speech: false,\n attachments: false,\n feedback: false,\n voice: false,\n switchToBranch: false,\n switchBranchDuringRun: false,\n unstable_copy: false,\n dictation: false,\n queue: hasQueue,\n },\n messages: messageStates,\n state: {},\n suggestions: [],\n extras: undefined,\n speech: undefined,\n voice: undefined,\n composer: composerClient.state,\n };\n }, [\n messages,\n isRunning,\n hasQueue,\n messageClients.state,\n composerClient.state,\n ]);\n\n return {\n getState: () => state,\n composer: () => composerClient.methods,\n append: (message) => {\n const appendMessage: AppendMessage =\n typeof message === \"string\"\n ? {\n createdAt: new Date(),\n parentId: messages.at(-1)?.id ?? null,\n sourceId: null,\n runConfig: {},\n role: \"user\",\n content: [{ type: \"text\", text: message }],\n attachments: [],\n metadata: { custom: {} },\n }\n : {\n createdAt: message.createdAt ?? new Date(),\n parentId: message.parentId ?? messages.at(-1)?.id ?? null,\n sourceId: message.sourceId ?? null,\n role: message.role ?? \"user\",\n content: message.content,\n attachments: message.attachments ?? [],\n metadata: message.metadata ?? { custom: {} },\n runConfig: message.runConfig ?? {},\n startRun: message.startRun,\n };\n if (queue) {\n queue.enqueue(appendMessage, { steer: false });\n } else {\n onNew?.(appendMessage);\n }\n },\n startRun: () => {\n onStartRun?.();\n },\n resumeRun: () => {},\n cancelRun: handleCancelRun,\n getModelContext: () => ({ tools: {}, config: {} }),\n export: () => ({ messages: [] }),\n import: () => {},\n reset: () => {},\n message: (selector) => {\n if (\"id\" in selector) {\n return messageClients.get({ key: selector.id });\n }\n return messageClients.get(selector);\n },\n stopSpeaking: () => {},\n connectVoice: () => {},\n disconnectVoice: () => {},\n getVoiceVolume: () => 0,\n subscribeVoiceVolume: () => () => {},\n muteVoice: () => {},\n unmuteVoice: () => {},\n };\n },\n);\n\nattachTransformScopes(ExternalThread, (scopes, parent) => {\n if (!scopes.threads && parent.threads.source === null) {\n const threadElement = scopes.thread as ClientElement<\"thread\">;\n scopes.threads = SingleThreadList({ thread: threadElement });\n scopes.thread = Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().thread(\"main\"),\n });\n }\n\n if (!scopes.threadListItem && parent.threadListItem.source === null) {\n scopes.threadListItem = Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().item(\"main\"),\n });\n }\n\n scopes.composer ??= Derived({\n source: \"thread\",\n query: {},\n get: (aui) => aui.thread().composer(),\n });\n\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n if (!scopes.tools && parent.tools.source === null) {\n scopes.tools = Tools({});\n }\n if (!scopes.dataRenderers && parent.dataRenderers.source === null) {\n scopes.dataRenderers = DataRenderers();\n }\n if (!scopes.suggestions && parent.suggestions.source === null) {\n scopes.suggestions = Suggestions();\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"ExternalThread.js","names":[],"sources":["../../src/client/ExternalThread.ts"],"sourcesContent":["import { useState, useMemo, useEffect, useEffectEvent } from \"react\";\nimport { resource, withKey } from \"@assistant-ui/tap\";\nimport {\n type ClientElement,\n type ClientOutput,\n useClientLookup,\n attachTransformScopes,\n useClientResource,\n Derived,\n} from \"@assistant-ui/store\";\n\nimport type {\n AppendMessage,\n Attachment,\n CreateAttachment,\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n ThreadMessage,\n ExternalThreadQueueAdapter,\n} from \"@assistant-ui/core\";\nimport type { QueueItemState } from \"@assistant-ui/core/store\";\nimport type { ComposerSendOptions } from \"@assistant-ui/core/store\";\nimport { ModelContext, Suggestions } from \"@assistant-ui/core/store\";\nimport { Tools, DataRenderers } from \"@assistant-ui/core/react\";\nimport { SingleThreadList } from \"./SingleThreadList\";\n\nconst EMPTY_QUEUE_ITEMS: readonly QueueItemState[] = [];\n\nexport type ExternalThreadMessage = ThreadMessage & {\n id: string;\n};\n\nexport type ExternalThreadProps = {\n messages: readonly ExternalThreadMessage[];\n isRunning?: boolean;\n /**\n * Whether sending new messages is currently disabled. When `true`, the\n * thread composer's input remains usable but `send()` is a no-op and\n * `composer.canSend` is `false`. Edit composers (saving message edits)\n * intentionally ignore this flag.\n */\n isSendDisabled?: boolean;\n /**\n * Callback for new messages (non-queue runtimes).\n * @note Unused when `queue` is provided — new messages are routed through `queue.enqueue` instead.\n */\n onNew?: (message: AppendMessage) => void;\n onEdit?: (message: AppendMessage) => void;\n onReload?: (parentId: string | null) => void;\n onStartRun?: () => void;\n onCancel?: () => void;\n /** Queue adapter for runtimes that support message queuing and steering. */\n queue?: ExternalThreadQueueAdapter;\n};\n\ntype MessageClientProps = {\n message: ExternalThreadMessage;\n index: number;\n onEdit?: (message: AppendMessage) => void;\n onReload?: () => void;\n queue?: ExternalThreadQueueAdapter | undefined;\n};\n\n// Message Client - minimal implementation\nconst MessageClient = resource(function MessageClient({\n message,\n index,\n onEdit,\n onReload,\n queue,\n}: MessageClientProps): ClientOutput<\"message\"> {\n const [isCopied, setIsCopied] = useState(false);\n const [isHovering, setIsHovering] = useState(false);\n const [isEditing, setIsEditing] = useState(false);\n\n const partClients = useClientLookup(\n () =>\n message.content.map((part, idx) => withKey(idx, PartResource({ part }))),\n [message.content],\n );\n\n const attachmentClients = useClientLookup(\n () =>\n (message.attachments ?? []).map((attachment) =>\n withKey(\n attachment.id,\n AttachmentResource({\n attachment,\n onRemove: () => {},\n }),\n ),\n ),\n [message.attachments],\n );\n\n const handleBeginEdit = () => {\n setIsEditing(true);\n };\n\n const handleCancelEdit = () => {\n setIsEditing(false);\n };\n\n const handleSendEdit = (msg: AppendMessage) => {\n queue?.clear(\"edit\");\n onEdit?.({\n ...msg,\n parentId: message.id,\n sourceId: message.id,\n });\n setIsEditing(false);\n };\n\n const composerClient = useClientResource(\n ComposerClientResource({\n type: \"edit\",\n isEditing,\n canCancel: true,\n onCancel: handleCancelEdit,\n onBeginEdit: handleBeginEdit,\n onSend: handleSendEdit,\n message,\n queue,\n }),\n );\n\n const state = useMemo(() => {\n return {\n ...message,\n attachments: message.attachments ?? [],\n parentId: null,\n isLast: false, // Will be set by thread\n branchNumber: 1,\n branchCount: 1,\n speech: undefined,\n parts: partClients.state,\n isCopied,\n isHovering,\n index,\n composer: composerClient.state,\n };\n }, [\n message,\n isCopied,\n isHovering,\n index,\n composerClient.state,\n partClients.state,\n ]);\n\n return {\n getState: () => state,\n composer: () => composerClient.methods,\n reload: () => {\n onReload?.();\n },\n speak: () => {},\n stopSpeaking: () => {},\n submitFeedback: () => {},\n switchToBranch: () => {},\n getCopyText: () =>\n message.content.map((c) => (\"text\" in c ? c.text : \"\")).join(\"\"),\n part: (selector) => {\n if (\"index\" in selector) {\n return partClients.get(selector);\n }\n const partIndex = state.parts.findIndex(\n (p) => p.type === \"tool-call\" && p.toolCallId === selector.toolCallId,\n );\n return partClients.get({ index: partIndex });\n },\n attachment: (selector) => {\n if (\"id\" in selector) {\n return attachmentClients.get({ key: selector.id });\n }\n return attachmentClients.get(selector);\n },\n setIsCopied,\n setIsHovering,\n };\n});\n\ntype PartResourceProps = {\n part: ThreadAssistantMessagePart | ThreadUserMessagePart;\n};\n\n// Part Client - minimal implementation\nconst PartResource = resource(function PartResource({\n part,\n}: PartResourceProps): ClientOutput<\"part\"> {\n const state = useMemo(\n () => ({\n ...part,\n status: { type: \"complete\" as const },\n }),\n [part],\n );\n\n return {\n getState: () => state,\n addToolResult: () => {},\n resumeToolCall: () => {},\n respondToToolApproval: () => {},\n };\n});\n\ntype AttachmentResourceProps = {\n attachment: Attachment;\n onRemove?: () => void;\n};\n\n// Attachment Client - minimal implementation\nconst AttachmentResource = resource(function AttachmentResource({\n attachment,\n onRemove,\n}: AttachmentResourceProps): ClientOutput<\"attachment\"> {\n return {\n getState: () => attachment,\n remove: async () => {\n onRemove?.();\n },\n };\n});\n\ntype ComposerClientResourceProps = {\n type: \"thread\" | \"edit\";\n isEditing: boolean;\n canCancel: boolean;\n isSendDisabled?: boolean;\n onCancel: () => void;\n onBeginEdit?: () => void;\n onSend?: (message: AppendMessage) => void;\n message?: ExternalThreadMessage;\n queue?: ExternalThreadQueueAdapter | undefined;\n};\n\nconst QueueItemClient = resource(function QueueItemClient({\n item,\n onSteer,\n onRemove,\n}: {\n item: QueueItemState;\n onSteer: () => void;\n onRemove: () => void;\n}): ClientOutput<\"queueItem\"> {\n return {\n getState: () => item,\n steer: onSteer,\n remove: onRemove,\n };\n});\n\n// Composer Client - minimal implementation\nconst ComposerClientResource = resource(function ComposerClientResource({\n type,\n isEditing,\n canCancel,\n isSendDisabled = false,\n onCancel,\n onBeginEdit,\n onSend,\n message,\n queue,\n}: ComposerClientResourceProps): ClientOutput<\"composer\"> {\n const [text, setText] = useState(\"\");\n const [role, setRole] = useState<\"user\" | \"assistant\" | \"system\">(\"user\");\n const [runConfig, setRunConfig] = useState<Record<string, unknown>>({});\n const [attachments, setAttachments] = useState<readonly Attachment[]>([]);\n const [quote, setQuote] = useState<\n { readonly text: string; readonly messageId: string } | undefined\n >(undefined);\n\n // Update composer values when editing begins\n const updateFromMessage = useEffectEvent(() => {\n if (message) {\n // Extract text from message content (text parts only)\n const textParts = message.content.filter((part) => part.type === \"text\");\n const messageText = textParts\n .map((part) => (\"text\" in part ? part.text : \"\"))\n .join(\"\\n\\n\");\n\n setText(messageText);\n setRole(message.role);\n setAttachments(message.attachments ?? []);\n }\n });\n\n useEffect(() => {\n if (isEditing) {\n updateFromMessage();\n }\n }, [isEditing]);\n\n const attachmentClients = useClientLookup(\n () =>\n attachments.map((attachment, idx) =>\n withKey(\n attachment.id,\n AttachmentResource({\n attachment,\n onRemove: () => {\n setAttachments(attachments.filter((_, i) => i !== idx));\n },\n }),\n ),\n ),\n [attachments],\n );\n\n const queueItems = queue?.items ?? EMPTY_QUEUE_ITEMS;\n const queueItemClients = useClientLookup(\n () =>\n queueItems.map((item) =>\n withKey(\n item.id,\n QueueItemClient({\n item,\n onSteer: () => queue?.steer(item.id),\n onRemove: () => queue?.remove(item.id),\n }),\n ),\n ),\n [queueItems],\n );\n\n const state = useMemo(() => {\n const isEmpty = !text.trim() && !attachments.length;\n return {\n text,\n role,\n attachments: attachmentClients.state,\n runConfig,\n isEditing,\n canCancel,\n canSend: isEditing && !isEmpty && !isSendDisabled,\n attachmentAccept: \"*\",\n isEmpty,\n type,\n dictation: undefined,\n quote,\n queue: queueItems,\n };\n }, [\n text,\n role,\n attachmentClients.state,\n runConfig,\n isEditing,\n canCancel,\n isSendDisabled,\n type,\n attachments.length,\n quote,\n queueItems,\n ]);\n\n return {\n getState: () => state,\n setText,\n setRole,\n setRunConfig,\n addAttachment: async (fileOrAttachment: File | CreateAttachment) => {\n if (fileOrAttachment instanceof File) {\n const newAttachment: Attachment = {\n id: Math.random().toString(36).substring(7),\n type: \"file\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.type,\n file: fileOrAttachment,\n status: { type: \"complete\" },\n content: [],\n };\n setAttachments([...attachments, newAttachment]);\n } else {\n const newAttachment: Attachment = {\n id: fileOrAttachment.id ?? Math.random().toString(36).substring(7),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n setAttachments([...attachments, newAttachment]);\n }\n },\n clearAttachments: async () => {\n setAttachments([]);\n },\n attachment: (selector) => {\n if (\"id\" in selector) {\n return attachmentClients.get({ key: selector.id });\n }\n return attachmentClients.get(selector);\n },\n reset: async () => {\n setText(\"\");\n setRole(\"user\");\n setRunConfig({});\n setAttachments([]);\n setQuote(undefined);\n },\n send: (opts?: ComposerSendOptions) => {\n if (!state.canSend) return;\n\n const currentQuote = quote;\n const composedMessage: AppendMessage = {\n role,\n content: text ? [{ type: \"text\" as const, text }] : [],\n attachments: attachments as any,\n createdAt: new Date(),\n parentId: null,\n sourceId: null,\n runConfig,\n startRun: opts?.startRun,\n metadata: {\n custom: { ...(currentQuote ? { quote: currentQuote } : {}) },\n },\n };\n if (queue) {\n queue.enqueue(composedMessage, { steer: opts?.steer ?? false });\n } else {\n onSend?.(composedMessage);\n }\n setText(\"\");\n setAttachments([]);\n setQuote(undefined);\n },\n cancel: onCancel,\n beginEdit: () => {\n onBeginEdit?.();\n },\n startDictation: () => {},\n stopDictation: () => {},\n setQuote,\n queueItem: (selector: { index: number }) => {\n return queueItemClients.get(selector);\n },\n };\n});\n\n// External Thread Client\nexport const ExternalThread = resource(function ExternalThread({\n messages,\n isRunning = false,\n isSendDisabled = false,\n onNew,\n onEdit,\n onReload,\n onStartRun,\n onCancel,\n queue,\n}: ExternalThreadProps): ClientOutput<\"thread\"> {\n const handleReload = (messageId: string) => {\n const messageIndex = messages.findIndex((m) => m.id === messageId);\n if (messageIndex === -1) return;\n\n const parentId = messageIndex > 0 ? messages[messageIndex - 1]!.id : null;\n queue?.clear(\"reload\");\n onReload?.(parentId);\n };\n\n const messageClients = useClientLookup(\n () =>\n messages.map((msg, index) => {\n const props: MessageClientProps = {\n message: msg,\n index,\n onReload: () => handleReload(msg.id),\n queue,\n };\n if (onEdit) props.onEdit = onEdit;\n return withKey(msg.id, MessageClient(props));\n }),\n [messages, onEdit, queue],\n );\n\n const handleCancelRun = () => {\n queue?.clear(\"cancel-run\");\n onCancel?.();\n };\n\n const handleSendNew = (message: AppendMessage) => {\n onNew?.(message);\n };\n\n const composerClient = useClientResource(\n ComposerClientResource({\n type: \"thread\",\n isEditing: true,\n canCancel: isRunning,\n isSendDisabled,\n onCancel: handleCancelRun,\n onSend: handleSendNew,\n queue,\n }),\n );\n\n const hasQueue = !!queue;\n const state = useMemo(() => {\n const messageStates = messageClients.state.map((s, idx, arr) => ({\n ...s,\n isLast: idx === arr.length - 1,\n }));\n\n return {\n isEmpty: messages.length === 0,\n isDisabled: false,\n isLoading: false,\n isRunning,\n capabilities: {\n edit: false,\n reload: false,\n cancel: isRunning,\n speech: false,\n attachments: false,\n feedback: false,\n voice: false,\n switchToBranch: false,\n switchBranchDuringRun: false,\n unstable_copy: false,\n dictation: false,\n queue: hasQueue,\n },\n messages: messageStates,\n state: {},\n suggestions: [],\n extras: undefined,\n speech: undefined,\n voice: undefined,\n composer: composerClient.state,\n };\n }, [\n messages,\n isRunning,\n hasQueue,\n messageClients.state,\n composerClient.state,\n ]);\n\n return {\n getState: () => state,\n composer: () => composerClient.methods,\n append: (message) => {\n const appendMessage: AppendMessage =\n typeof message === \"string\"\n ? {\n createdAt: new Date(),\n parentId: messages.at(-1)?.id ?? null,\n sourceId: null,\n runConfig: {},\n role: \"user\",\n content: [{ type: \"text\", text: message }],\n attachments: [],\n metadata: { custom: {} },\n }\n : {\n createdAt: message.createdAt ?? new Date(),\n parentId: message.parentId ?? messages.at(-1)?.id ?? null,\n sourceId: message.sourceId ?? null,\n role: message.role ?? \"user\",\n content: message.content,\n attachments: message.attachments ?? [],\n metadata: message.metadata ?? { custom: {} },\n runConfig: message.runConfig ?? {},\n startRun: message.startRun,\n };\n if (queue) {\n queue.enqueue(appendMessage, { steer: false });\n } else {\n onNew?.(appendMessage);\n }\n },\n startRun: () => {\n onStartRun?.();\n },\n resumeRun: () => {},\n cancelRun: handleCancelRun,\n getModelContext: () => ({ tools: {}, config: {} }),\n export: () => ({ messages: [] }),\n import: () => {},\n reset: () => {},\n message: (selector) => {\n if (\"id\" in selector) {\n return messageClients.get({ key: selector.id });\n }\n return messageClients.get(selector);\n },\n stopSpeaking: () => {},\n connectVoice: () => {},\n disconnectVoice: () => {},\n getVoiceVolume: () => 0,\n subscribeVoiceVolume: () => () => {},\n muteVoice: () => {},\n unmuteVoice: () => {},\n };\n});\n\nattachTransformScopes(ExternalThread, (scopes, parent) => {\n if (!scopes.threads && parent.threads.source === null) {\n const threadElement = scopes.thread as ClientElement<\"thread\">;\n scopes.threads = SingleThreadList({ thread: threadElement });\n scopes.thread = Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().thread(\"main\"),\n });\n }\n\n if (!scopes.threadListItem && parent.threadListItem.source === null) {\n scopes.threadListItem = Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().item(\"main\"),\n });\n }\n\n scopes.composer ??= Derived({\n source: \"thread\",\n query: {},\n get: (aui) => aui.thread().composer(),\n });\n\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n if (!scopes.tools && parent.tools.source === null) {\n scopes.tools = Tools({});\n }\n if (!scopes.dataRenderers && parent.dataRenderers.source === null) {\n scopes.dataRenderers = DataRenderers();\n }\n if (!scopes.suggestions && parent.suggestions.source === null) {\n scopes.suggestions = Suggestions();\n }\n});\n"],"mappings":";;;;;;;AA0BA,MAAM,oBAA+C,CAAC;AAsCtD,MAAM,gBAAgB,SAAS,SAAS,cAAc,EACpD,SACA,OACA,QACA,UACA,SAC8C;CAC9C,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAEhD,MAAM,cAAc,sBAEhB,QAAQ,QAAQ,KAAK,MAAM,QAAQ,QAAQ,KAAK,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,GACzE,CAAC,QAAQ,OAAO,CAClB;CAEA,MAAM,oBAAoB,uBAErB,QAAQ,eAAe,CAAC,EAAA,CAAG,KAAK,eAC/B,QACE,WAAW,IACX,mBAAmB;EACjB;EACA,gBAAgB,CAAC;CACnB,CAAC,CACH,CACF,GACF,CAAC,QAAQ,WAAW,CACtB;CAEA,MAAM,wBAAwB;EAC5B,aAAa,IAAI;CACnB;CAEA,MAAM,yBAAyB;EAC7B,aAAa,KAAK;CACpB;CAEA,MAAM,kBAAkB,QAAuB;EAC7C,OAAO,MAAM,MAAM;EACnB,SAAS;GACP,GAAG;GACH,UAAU,QAAQ;GAClB,UAAU,QAAQ;EACpB,CAAC;EACD,aAAa,KAAK;CACpB;CAEA,MAAM,iBAAiB,kBACrB,uBAAuB;EACrB,MAAM;EACN;EACA,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR;EACA;CACF,CAAC,CACH;CAEA,MAAM,QAAQ,cAAc;EAC1B,OAAO;GACL,GAAG;GACH,aAAa,QAAQ,eAAe,CAAC;GACrC,UAAU;GACV,QAAQ;GACR,cAAc;GACd,aAAa;GACb,QAAQ,KAAA;GACR,OAAO,YAAY;GACnB;GACA;GACA;GACA,UAAU,eAAe;EAC3B;CACF,GAAG;EACD;EACA;EACA;EACA;EACA,eAAe;EACf,YAAY;CACd,CAAC;CAED,OAAO;EACL,gBAAgB;EAChB,gBAAgB,eAAe;EAC/B,cAAc;GACZ,WAAW;EACb;EACA,aAAa,CAAC;EACd,oBAAoB,CAAC;EACrB,sBAAsB,CAAC;EACvB,sBAAsB,CAAC;EACvB,mBACE,QAAQ,QAAQ,KAAK,MAAO,UAAU,IAAI,EAAE,OAAO,EAAG,CAAC,CAAC,KAAK,EAAE;EACjE,OAAO,aAAa;GAClB,IAAI,WAAW,UACb,OAAO,YAAY,IAAI,QAAQ;GAEjC,MAAM,YAAY,MAAM,MAAM,WAC3B,MAAM,EAAE,SAAS,eAAe,EAAE,eAAe,SAAS,UAC7D;GACA,OAAO,YAAY,IAAI,EAAE,OAAO,UAAU,CAAC;EAC7C;EACA,aAAa,aAAa;GACxB,IAAI,QAAQ,UACV,OAAO,kBAAkB,IAAI,EAAE,KAAK,SAAS,GAAG,CAAC;GAEnD,OAAO,kBAAkB,IAAI,QAAQ;EACvC;EACA;EACA;CACF;AACF,CAAC;AAOD,MAAM,eAAe,SAAS,SAAS,aAAa,EAClD,QAC0C;CAC1C,MAAM,QAAQ,eACL;EACL,GAAG;EACH,QAAQ,EAAE,MAAM,WAAoB;CACtC,IACA,CAAC,IAAI,CACP;CAEA,OAAO;EACL,gBAAgB;EAChB,qBAAqB,CAAC;EACtB,sBAAsB,CAAC;EACvB,6BAA6B,CAAC;CAChC;AACF,CAAC;AAQD,MAAM,qBAAqB,SAAS,SAAS,mBAAmB,EAC9D,YACA,YACsD;CACtD,OAAO;EACL,gBAAgB;EAChB,QAAQ,YAAY;GAClB,WAAW;EACb;CACF;AACF,CAAC;AAcD,MAAM,kBAAkB,SAAS,SAAS,gBAAgB,EACxD,MACA,SACA,YAK4B;CAC5B,OAAO;EACL,gBAAgB;EAChB,OAAO;EACP,QAAQ;CACV;AACF,CAAC;AAGD,MAAM,yBAAyB,SAAS,SAAS,uBAAuB,EACtE,MACA,WACA,WACA,iBAAiB,OACjB,UACA,aACA,QACA,SACA,SACwD;CACxD,MAAM,CAAC,MAAM,WAAW,SAAS,EAAE;CACnC,MAAM,CAAC,MAAM,WAAW,SAA0C,MAAM;CACxE,MAAM,CAAC,WAAW,gBAAgB,SAAkC,CAAC,CAAC;CACtE,MAAM,CAAC,aAAa,kBAAkB,SAAgC,CAAC,CAAC;CACxE,MAAM,CAAC,OAAO,YAAY,SAExB,KAAA,CAAS;CAGX,MAAM,oBAAoB,qBAAqB;EAC7C,IAAI,SAAS;GAOX,QALkB,QAAQ,QAAQ,QAAQ,SAAS,KAAK,SAAS,MACrC,CAAC,CAC1B,KAAK,SAAU,UAAU,OAAO,KAAK,OAAO,EAAG,CAAC,CAChD,KAAK,MAEU,CAAC;GACnB,QAAQ,QAAQ,IAAI;GACpB,eAAe,QAAQ,eAAe,CAAC,CAAC;EAC1C;CACF,CAAC;CAED,gBAAgB;EACd,IAAI,WACF,kBAAkB;CAEtB,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,oBAAoB,sBAEtB,YAAY,KAAK,YAAY,QAC3B,QACE,WAAW,IACX,mBAAmB;EACjB;EACA,gBAAgB;GACd,eAAe,YAAY,QAAQ,GAAG,MAAM,MAAM,GAAG,CAAC;EACxD;CACF,CAAC,CACH,CACF,GACF,CAAC,WAAW,CACd;CAEA,MAAM,aAAa,OAAO,SAAS;CACnC,MAAM,mBAAmB,sBAErB,WAAW,KAAK,SACd,QACE,KAAK,IACL,gBAAgB;EACd;EACA,eAAe,OAAO,MAAM,KAAK,EAAE;EACnC,gBAAgB,OAAO,OAAO,KAAK,EAAE;CACvC,CAAC,CACH,CACF,GACF,CAAC,UAAU,CACb;CAEA,MAAM,QAAQ,cAAc;EAC1B,MAAM,UAAU,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY;EAC7C,OAAO;GACL;GACA;GACA,aAAa,kBAAkB;GAC/B;GACA;GACA;GACA,SAAS,aAAa,CAAC,WAAW,CAAC;GACnC,kBAAkB;GAClB;GACA;GACA,WAAW,KAAA;GACX;GACA,OAAO;EACT;CACF,GAAG;EACD;EACA;EACA,kBAAkB;EAClB;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA;CACF,CAAC;CAED,OAAO;EACL,gBAAgB;EAChB;EACA;EACA;EACA,eAAe,OAAO,qBAA8C;GAClE,IAAI,4BAA4B,MAAM;IACpC,MAAM,gBAA4B;KAChC,IAAI,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;KAC1C,MAAM;KACN,MAAM,iBAAiB;KACvB,aAAa,iBAAiB;KAC9B,MAAM;KACN,QAAQ,EAAE,MAAM,WAAW;KAC3B,SAAS,CAAC;IACZ;IACA,eAAe,CAAC,GAAG,aAAa,aAAa,CAAC;GAChD,OAAO;IACL,MAAM,gBAA4B;KAChC,IAAI,iBAAiB,MAAM,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;KACjE,MAAM,iBAAiB,QAAQ;KAC/B,MAAM,iBAAiB;KACvB,aAAa,iBAAiB;KAC9B,SAAS,iBAAiB;KAC1B,QAAQ,EAAE,MAAM,WAAW;IAC7B;IACA,eAAe,CAAC,GAAG,aAAa,aAAa,CAAC;GAChD;EACF;EACA,kBAAkB,YAAY;GAC5B,eAAe,CAAC,CAAC;EACnB;EACA,aAAa,aAAa;GACxB,IAAI,QAAQ,UACV,OAAO,kBAAkB,IAAI,EAAE,KAAK,SAAS,GAAG,CAAC;GAEnD,OAAO,kBAAkB,IAAI,QAAQ;EACvC;EACA,OAAO,YAAY;GACjB,QAAQ,EAAE;GACV,QAAQ,MAAM;GACd,aAAa,CAAC,CAAC;GACf,eAAe,CAAC,CAAC;GACjB,SAAS,KAAA,CAAS;EACpB;EACA,OAAO,SAA+B;GACpC,IAAI,CAAC,MAAM,SAAS;GAEpB,MAAM,eAAe;GACrB,MAAM,kBAAiC;IACrC;IACA,SAAS,OAAO,CAAC;KAAE,MAAM;KAAiB;IAAK,CAAC,IAAI,CAAC;IACxC;IACb,2BAAW,IAAI,KAAK;IACpB,UAAU;IACV,UAAU;IACV;IACA,UAAU,MAAM;IAChB,UAAU,EACR,QAAQ,EAAE,GAAI,eAAe,EAAE,OAAO,aAAa,IAAI,CAAC,EAAG,EAC7D;GACF;GACA,IAAI,OACF,MAAM,QAAQ,iBAAiB,EAAE,OAAO,MAAM,SAAS,MAAM,CAAC;QAE9D,SAAS,eAAe;GAE1B,QAAQ,EAAE;GACV,eAAe,CAAC,CAAC;GACjB,SAAS,KAAA,CAAS;EACpB;EACA,QAAQ;EACR,iBAAiB;GACf,cAAc;EAChB;EACA,sBAAsB,CAAC;EACvB,qBAAqB,CAAC;EACtB;EACA,YAAY,aAAgC;GAC1C,OAAO,iBAAiB,IAAI,QAAQ;EACtC;CACF;AACF,CAAC;AAGD,MAAa,iBAAiB,SAAS,SAAS,eAAe,EAC7D,UACA,YAAY,OACZ,iBAAiB,OACjB,OACA,QACA,UACA,YACA,UACA,SAC8C;CAC9C,MAAM,gBAAgB,cAAsB;EAC1C,MAAM,eAAe,SAAS,WAAW,MAAM,EAAE,OAAO,SAAS;EACjE,IAAI,iBAAiB,IAAI;EAEzB,MAAM,WAAW,eAAe,IAAI,SAAS,eAAe,EAAE,CAAE,KAAK;EACrE,OAAO,MAAM,QAAQ;EACrB,WAAW,QAAQ;CACrB;CAEA,MAAM,iBAAiB,sBAEnB,SAAS,KAAK,KAAK,UAAU;EAC3B,MAAM,QAA4B;GAChC,SAAS;GACT;GACA,gBAAgB,aAAa,IAAI,EAAE;GACnC;EACF;EACA,IAAI,QAAQ,MAAM,SAAS;EAC3B,OAAO,QAAQ,IAAI,IAAI,cAAc,KAAK,CAAC;CAC7C,CAAC,GACH;EAAC;EAAU;EAAQ;CAAK,CAC1B;CAEA,MAAM,wBAAwB;EAC5B,OAAO,MAAM,YAAY;EACzB,WAAW;CACb;CAEA,MAAM,iBAAiB,YAA2B;EAChD,QAAQ,OAAO;CACjB;CAEA,MAAM,iBAAiB,kBACrB,uBAAuB;EACrB,MAAM;EACN,WAAW;EACX,WAAW;EACX;EACA,UAAU;EACV,QAAQ;EACR;CACF,CAAC,CACH;CAEA,MAAM,WAAW,CAAC,CAAC;CACnB,MAAM,QAAQ,cAAc;EAC1B,MAAM,gBAAgB,eAAe,MAAM,KAAK,GAAG,KAAK,SAAS;GAC/D,GAAG;GACH,QAAQ,QAAQ,IAAI,SAAS;EAC/B,EAAE;EAEF,OAAO;GACL,SAAS,SAAS,WAAW;GAC7B,YAAY;GACZ,WAAW;GACX;GACA,cAAc;IACZ,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,UAAU;IACV,OAAO;IACP,gBAAgB;IAChB,uBAAuB;IACvB,eAAe;IACf,WAAW;IACX,OAAO;GACT;GACA,UAAU;GACV,OAAO,CAAC;GACR,aAAa,CAAC;GACd,QAAQ,KAAA;GACR,QAAQ,KAAA;GACR,OAAO,KAAA;GACP,UAAU,eAAe;EAC3B;CACF,GAAG;EACD;EACA;EACA;EACA,eAAe;EACf,eAAe;CACjB,CAAC;CAED,OAAO;EACL,gBAAgB;EAChB,gBAAgB,eAAe;EAC/B,SAAS,YAAY;GACnB,MAAM,gBACJ,OAAO,YAAY,WACf;IACE,2BAAW,IAAI,KAAK;IACpB,UAAU,SAAS,GAAG,EAAE,CAAC,EAAE,MAAM;IACjC,UAAU;IACV,WAAW,CAAC;IACZ,MAAM;IACN,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;IAAQ,CAAC;IACzC,aAAa,CAAC;IACd,UAAU,EAAE,QAAQ,CAAC,EAAE;GACzB,IACA;IACE,WAAW,QAAQ,6BAAa,IAAI,KAAK;IACzC,UAAU,QAAQ,YAAY,SAAS,GAAG,EAAE,CAAC,EAAE,MAAM;IACrD,UAAU,QAAQ,YAAY;IAC9B,MAAM,QAAQ,QAAQ;IACtB,SAAS,QAAQ;IACjB,aAAa,QAAQ,eAAe,CAAC;IACrC,UAAU,QAAQ,YAAY,EAAE,QAAQ,CAAC,EAAE;IAC3C,WAAW,QAAQ,aAAa,CAAC;IACjC,UAAU,QAAQ;GACpB;GACN,IAAI,OACF,MAAM,QAAQ,eAAe,EAAE,OAAO,MAAM,CAAC;QAE7C,QAAQ,aAAa;EAEzB;EACA,gBAAgB;GACd,aAAa;EACf;EACA,iBAAiB,CAAC;EAClB,WAAW;EACX,wBAAwB;GAAE,OAAO,CAAC;GAAG,QAAQ,CAAC;EAAE;EAChD,eAAe,EAAE,UAAU,CAAC,EAAE;EAC9B,cAAc,CAAC;EACf,aAAa,CAAC;EACd,UAAU,aAAa;GACrB,IAAI,QAAQ,UACV,OAAO,eAAe,IAAI,EAAE,KAAK,SAAS,GAAG,CAAC;GAEhD,OAAO,eAAe,IAAI,QAAQ;EACpC;EACA,oBAAoB,CAAC;EACrB,oBAAoB,CAAC;EACrB,uBAAuB,CAAC;EACxB,sBAAsB;EACtB,kCAAkC,CAAC;EACnC,iBAAiB,CAAC;EAClB,mBAAmB,CAAC;CACtB;AACF,CAAC;AAED,sBAAsB,iBAAiB,QAAQ,WAAW;CACxD,IAAI,CAAC,OAAO,WAAW,OAAO,QAAQ,WAAW,MAAM;EACrD,MAAM,gBAAgB,OAAO;EAC7B,OAAO,UAAU,iBAAiB,EAAE,QAAQ,cAAc,CAAC;EAC3D,OAAO,SAAS,QAAQ;GACtB,QAAQ;GACR,OAAO,EAAE,MAAM,OAAO;GACtB,MAAM,QAAQ,IAAI,QAAQ,CAAC,CAAC,OAAO,MAAM;EAC3C,CAAC;CACH;CAEA,IAAI,CAAC,OAAO,kBAAkB,OAAO,eAAe,WAAW,MAC7D,OAAO,iBAAiB,QAAQ;EAC9B,QAAQ;EACR,OAAO,EAAE,MAAM,OAAO;EACtB,MAAM,QAAQ,IAAI,QAAQ,CAAC,CAAC,KAAK,MAAM;CACzC,CAAC;CAGH,OAAO,aAAa,QAAQ;EAC1B,QAAQ;EACR,OAAO,CAAC;EACR,MAAM,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS;CACtC,CAAC;CAED,IAAI,CAAC,OAAO,gBAAgB,OAAO,aAAa,WAAW,MACzD,OAAO,eAAe,aAAa;CAErC,IAAI,CAAC,OAAO,SAAS,OAAO,MAAM,WAAW,MAC3C,OAAO,QAAQ,MAAM,CAAC,CAAC;CAEzB,IAAI,CAAC,OAAO,iBAAiB,OAAO,cAAc,WAAW,MAC3D,OAAO,gBAAgB,cAAc;CAEvC,IAAI,CAAC,OAAO,eAAe,OAAO,YAAY,WAAW,MACvD,OAAO,cAAc,YAAY;AAErC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryThreadList.d.ts","names":[],"sources":["../../src/client/InMemoryThreadList.ts"],"mappings":";;;;KAgBY,uBAAA;EACV,MAAA,GAAS,QAAA,aAAqB,eAAe,CAAC,YAAA;EAC9C,gBAAA,IAAoB,QAAA;EACpB,mBAAA;AAAA;AAAA,cAwDW,kBAAA,GAAkB,KAAA,EAAA,uBAAA,KAAA,eAAA,CAAA,YAAA,aAAA,uBAAA"}
1
+ {"version":3,"file":"InMemoryThreadList.d.ts","names":[],"sources":["../../src/client/InMemoryThreadList.ts"],"mappings":";;;;KAeY,uBAAA;EACV,MAAA,GAAS,QAAA,aAAqB,eAAe,CAAC,YAAA;EAC9C,gBAAA,IAAoB,QAAA;EACpB,mBAAA;AAAA;AAAA,cAgDW,kBAAA,GAAkB,KAAA,EAAA,uBAAA,KAAA,eAAA,CAAA,YAAA,aAAA,uBAAA"}
@@ -1,12 +1,13 @@
1
- import { Derived, attachTransformScopes, tapClientLookup, tapClientResource } from "@assistant-ui/store";
1
+ import { Derived, attachTransformScopes, useClientLookup, useClientResource } from "@assistant-ui/store";
2
2
  import { DataRenderers, Tools } from "@assistant-ui/core/react";
3
+ import { useMemo, useState } from "@assistant-ui/tap/react-shim";
3
4
  import { ModelContext, Suggestions } from "@assistant-ui/core/store";
4
- import { resource, tapMemo, tapState, withKey } from "@assistant-ui/tap";
5
+ import { resource, withKey } from "@assistant-ui/tap";
5
6
  //#region src/client/InMemoryThreadList.ts
6
7
  const RESOLVED_PROMISE = Promise.resolve();
7
- const ThreadListItemClient = resource((props) => {
8
+ const ThreadListItemClient = resource(function ThreadListItemClient(props) {
8
9
  const { data, onSwitchTo, onUpdateCustom, onArchive, onUnarchive, onDelete } = props;
9
- const state = tapMemo(() => ({
10
+ const state = useMemo(() => ({
10
11
  id: data.id,
11
12
  remoteId: void 0,
12
13
  externalId: void 0,
@@ -35,10 +36,10 @@ const ThreadListItemClient = resource((props) => {
35
36
  detach: () => {}
36
37
  };
37
38
  });
38
- const InMemoryThreadList = resource((props) => {
39
+ const InMemoryThreadList = resource(function InMemoryThreadList(props) {
39
40
  const { thread: threadFactory, onSwitchToThread, onSwitchToNewThread } = props;
40
- const [mainThreadId, setMainThreadId] = tapState("main");
41
- const [threads, setThreads] = tapState(() => [{
41
+ const [mainThreadId, setMainThreadId] = useState("main");
42
+ const [threads, setThreads] = useState(() => [{
42
43
  id: "main",
43
44
  title: "Main Thread",
44
45
  status: "regular"
@@ -79,7 +80,7 @@ const InMemoryThreadList = resource((props) => {
79
80
  setMainThreadId(newId);
80
81
  onSwitchToNewThread?.();
81
82
  };
82
- const threadListItems = tapClientLookup(() => threads.map((t) => withKey(t.id, ThreadListItemClient({
83
+ const threadListItems = useClientLookup(() => threads.map((t) => withKey(t.id, ThreadListItemClient({
83
84
  data: t,
84
85
  onSwitchTo: () => handleSwitchToThread(t.id),
85
86
  onUpdateCustom: (custom) => handleUpdateCustom(t.id, custom),
@@ -87,8 +88,8 @@ const InMemoryThreadList = resource((props) => {
87
88
  onUnarchive: () => handleUnarchive(t.id),
88
89
  onDelete: () => handleDelete(t.id)
89
90
  }))), [threads]);
90
- const mainThreadClient = tapClientResource(threadFactory(mainThreadId));
91
- const state = tapMemo(() => {
91
+ const mainThreadClient = useClientResource(threadFactory(mainThreadId));
92
+ const state = useMemo(() => {
92
93
  const regularThreads = threads.filter((t) => t.status === "regular");
93
94
  const archivedThreads = threads.filter((t) => t.status === "archived");
94
95
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryThreadList.js","names":[],"sources":["../../src/client/InMemoryThreadList.ts"],"sourcesContent":["import { resource, tapState, tapMemo } from \"@assistant-ui/tap\";\nimport {\n type ClientOutput,\n tapClientLookup,\n Derived,\n attachTransformScopes,\n tapClientResource,\n} from \"@assistant-ui/store\";\nimport { withKey } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\n\nimport { ModelContext, Suggestions } from \"@assistant-ui/core/store\";\nimport { Tools, DataRenderers } from \"@assistant-ui/core/react\";\n\nconst RESOLVED_PROMISE = Promise.resolve();\n\nexport type InMemoryThreadListProps = {\n thread: (threadId: string) => ResourceElement<ClientOutput<\"thread\">>;\n onSwitchToThread?: (threadId: string) => void;\n onSwitchToNewThread?: () => void;\n};\n\ntype ThreadData = {\n id: string;\n title?: string;\n status: \"regular\" | \"archived\";\n custom?: Record<string, unknown> | undefined;\n};\n\n// ThreadListItem Client\nconst ThreadListItemClient = resource(\n (props: {\n data: ThreadData;\n onSwitchTo: () => void;\n onUpdateCustom: (custom: Record<string, unknown> | undefined) => void;\n onArchive: () => void;\n onUnarchive: () => void;\n onDelete: () => void;\n }): ClientOutput<\"threadListItem\"> => {\n const {\n data,\n onSwitchTo,\n onUpdateCustom,\n onArchive,\n onUnarchive,\n onDelete,\n } = props;\n const state = tapMemo(\n () => ({\n id: data.id,\n remoteId: undefined,\n externalId: undefined,\n title: data.title,\n status: data.status,\n custom: data.custom,\n }),\n [data.id, data.title, data.status, data.custom],\n );\n\n return {\n getState: () => state,\n switchTo: onSwitchTo,\n rename: () => {},\n updateCustom: onUpdateCustom,\n archive: onArchive,\n unarchive: onUnarchive,\n delete: onDelete,\n generateTitle: () => {},\n initialize: async () => ({ remoteId: data.id, externalId: undefined }),\n detach: () => {},\n };\n },\n);\n\n// InMemoryThreadList Client\nexport const InMemoryThreadList = resource(\n (props: InMemoryThreadListProps): ClientOutput<\"threads\"> => {\n const {\n thread: threadFactory,\n onSwitchToThread,\n onSwitchToNewThread,\n } = props;\n\n const [mainThreadId, setMainThreadId] = tapState(\"main\");\n const [threads, setThreads] = tapState<readonly ThreadData[]>(() => [\n { id: \"main\", title: \"Main Thread\", status: \"regular\" },\n ]);\n\n const handleSwitchToThread = (threadId: string) => {\n setMainThreadId(threadId);\n onSwitchToThread?.(threadId);\n };\n\n const handleArchive = (threadId: string) => {\n setThreads((prev) =>\n prev.map((t) =>\n t.id === threadId ? { ...t, status: \"archived\" as const } : t,\n ),\n );\n };\n\n const handleUnarchive = (threadId: string) => {\n setThreads((prev) =>\n prev.map((t) =>\n t.id === threadId ? { ...t, status: \"regular\" as const } : t,\n ),\n );\n };\n\n const handleUpdateCustom = (\n threadId: string,\n custom: Record<string, unknown> | undefined,\n ) => {\n setThreads((prev) =>\n prev.map((t) => (t.id === threadId ? { ...t, custom } : t)),\n );\n };\n\n const handleDelete = (threadId: string) => {\n setThreads((prev) => prev.filter((t) => t.id !== threadId));\n if (mainThreadId === threadId) {\n const remaining = threads.filter((t) => t.id !== threadId);\n setMainThreadId(remaining[0]?.id || \"main\");\n }\n };\n\n const handleSwitchToNewThread = () => {\n const newId = `thread-${Date.now()}`;\n setThreads((prev) => [\n ...prev,\n { id: newId, title: \"New Thread\", status: \"regular\" },\n ]);\n setMainThreadId(newId);\n onSwitchToNewThread?.();\n };\n\n const threadListItems = tapClientLookup(\n () =>\n threads.map((t) =>\n withKey(\n t.id,\n ThreadListItemClient({\n data: t,\n onSwitchTo: () => handleSwitchToThread(t.id),\n onUpdateCustom: (custom) => handleUpdateCustom(t.id, custom),\n onArchive: () => handleArchive(t.id),\n onUnarchive: () => handleUnarchive(t.id),\n onDelete: () => handleDelete(t.id),\n }),\n ),\n ),\n [threads],\n );\n\n // Create the main thread\n const mainThreadClient = tapClientResource(threadFactory(mainThreadId));\n\n const state = tapMemo(() => {\n const regularThreads = threads.filter((t) => t.status === \"regular\");\n const archivedThreads = threads.filter((t) => t.status === \"archived\");\n\n return {\n mainThreadId,\n newThreadId: null,\n isLoading: false,\n isLoadingMore: false,\n hasMore: false,\n threadIds: regularThreads.map((t) => t.id),\n archivedThreadIds: archivedThreads.map((t) => t.id),\n threadItems: threadListItems.state,\n main: mainThreadClient.state,\n };\n }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);\n\n return {\n getState: () => state,\n switchToThread: handleSwitchToThread,\n switchToNewThread: handleSwitchToNewThread,\n getLoadThreadsPromise: () => RESOLVED_PROMISE,\n reload: () => RESOLVED_PROMISE,\n loadMore: () => RESOLVED_PROMISE,\n item: (selector) => {\n if (selector === \"main\") {\n const index = threads.findIndex((t) => t.id === mainThreadId);\n return threadListItems.get({ index: index === -1 ? 0 : index });\n }\n if (\"id\" in selector) {\n const index = threads.findIndex((t) => t.id === selector.id);\n return threadListItems.get({ index });\n }\n return threadListItems.get(selector);\n },\n thread: () => mainThreadClient.methods,\n };\n },\n);\n\nattachTransformScopes(InMemoryThreadList, (scopes, parent) => {\n scopes.thread ??= Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().thread(\"main\"),\n });\n scopes.threadListItem ??= Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().item(\"main\"),\n });\n scopes.composer ??= Derived({\n source: \"thread\",\n query: {},\n get: (aui) => aui.threads().thread(\"main\").composer(),\n });\n\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n if (!scopes.tools && parent.tools.source === null) {\n scopes.tools = Tools({});\n }\n if (!scopes.dataRenderers && parent.dataRenderers.source === null) {\n scopes.dataRenderers = DataRenderers();\n }\n if (!scopes.suggestions && parent.suggestions.source === null) {\n scopes.suggestions = Suggestions();\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"InMemoryThreadList.js","names":[],"sources":["../../src/client/InMemoryThreadList.ts"],"sourcesContent":["import { useState, useMemo } from \"react\";\nimport { resource, withKey, type ResourceElement } from \"@assistant-ui/tap\";\nimport {\n type ClientOutput,\n useClientLookup,\n Derived,\n attachTransformScopes,\n useClientResource,\n} from \"@assistant-ui/store\";\n\nimport { ModelContext, Suggestions } from \"@assistant-ui/core/store\";\nimport { Tools, DataRenderers } from \"@assistant-ui/core/react\";\n\nconst RESOLVED_PROMISE = Promise.resolve();\n\nexport type InMemoryThreadListProps = {\n thread: (threadId: string) => ResourceElement<ClientOutput<\"thread\">>;\n onSwitchToThread?: (threadId: string) => void;\n onSwitchToNewThread?: () => void;\n};\n\ntype ThreadData = {\n id: string;\n title?: string;\n status: \"regular\" | \"archived\";\n custom?: Record<string, unknown> | undefined;\n};\n\n// ThreadListItem Client\nconst ThreadListItemClient = resource(function ThreadListItemClient(props: {\n data: ThreadData;\n onSwitchTo: () => void;\n onUpdateCustom: (custom: Record<string, unknown> | undefined) => void;\n onArchive: () => void;\n onUnarchive: () => void;\n onDelete: () => void;\n}): ClientOutput<\"threadListItem\"> {\n const { data, onSwitchTo, onUpdateCustom, onArchive, onUnarchive, onDelete } =\n props;\n const state = useMemo(\n () => ({\n id: data.id,\n remoteId: undefined,\n externalId: undefined,\n title: data.title,\n status: data.status,\n custom: data.custom,\n }),\n [data.id, data.title, data.status, data.custom],\n );\n\n return {\n getState: () => state,\n switchTo: onSwitchTo,\n rename: () => {},\n updateCustom: onUpdateCustom,\n archive: onArchive,\n unarchive: onUnarchive,\n delete: onDelete,\n generateTitle: () => {},\n initialize: async () => ({ remoteId: data.id, externalId: undefined }),\n detach: () => {},\n };\n});\n\n// InMemoryThreadList Client\nexport const InMemoryThreadList = resource(function InMemoryThreadList(\n props: InMemoryThreadListProps,\n): ClientOutput<\"threads\"> {\n const {\n thread: threadFactory,\n onSwitchToThread,\n onSwitchToNewThread,\n } = props;\n\n const [mainThreadId, setMainThreadId] = useState(\"main\");\n const [threads, setThreads] = useState<readonly ThreadData[]>(() => [\n { id: \"main\", title: \"Main Thread\", status: \"regular\" },\n ]);\n\n const handleSwitchToThread = (threadId: string) => {\n setMainThreadId(threadId);\n onSwitchToThread?.(threadId);\n };\n\n const handleArchive = (threadId: string) => {\n setThreads((prev) =>\n prev.map((t) =>\n t.id === threadId ? { ...t, status: \"archived\" as const } : t,\n ),\n );\n };\n\n const handleUnarchive = (threadId: string) => {\n setThreads((prev) =>\n prev.map((t) =>\n t.id === threadId ? { ...t, status: \"regular\" as const } : t,\n ),\n );\n };\n\n const handleUpdateCustom = (\n threadId: string,\n custom: Record<string, unknown> | undefined,\n ) => {\n setThreads((prev) =>\n prev.map((t) => (t.id === threadId ? { ...t, custom } : t)),\n );\n };\n\n const handleDelete = (threadId: string) => {\n setThreads((prev) => prev.filter((t) => t.id !== threadId));\n if (mainThreadId === threadId) {\n const remaining = threads.filter((t) => t.id !== threadId);\n setMainThreadId(remaining[0]?.id || \"main\");\n }\n };\n\n const handleSwitchToNewThread = () => {\n const newId = `thread-${Date.now()}`;\n setThreads((prev) => [\n ...prev,\n { id: newId, title: \"New Thread\", status: \"regular\" },\n ]);\n setMainThreadId(newId);\n onSwitchToNewThread?.();\n };\n\n const threadListItems = useClientLookup(\n () =>\n threads.map((t) =>\n withKey(\n t.id,\n ThreadListItemClient({\n data: t,\n onSwitchTo: () => handleSwitchToThread(t.id),\n onUpdateCustom: (custom) => handleUpdateCustom(t.id, custom),\n onArchive: () => handleArchive(t.id),\n onUnarchive: () => handleUnarchive(t.id),\n onDelete: () => handleDelete(t.id),\n }),\n ),\n ),\n [threads],\n );\n\n // Create the main thread\n const mainThreadClient = useClientResource(threadFactory(mainThreadId));\n\n const state = useMemo(() => {\n const regularThreads = threads.filter((t) => t.status === \"regular\");\n const archivedThreads = threads.filter((t) => t.status === \"archived\");\n\n return {\n mainThreadId,\n newThreadId: null,\n isLoading: false,\n isLoadingMore: false,\n hasMore: false,\n threadIds: regularThreads.map((t) => t.id),\n archivedThreadIds: archivedThreads.map((t) => t.id),\n threadItems: threadListItems.state,\n main: mainThreadClient.state,\n };\n }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);\n\n return {\n getState: () => state,\n switchToThread: handleSwitchToThread,\n switchToNewThread: handleSwitchToNewThread,\n getLoadThreadsPromise: () => RESOLVED_PROMISE,\n reload: () => RESOLVED_PROMISE,\n loadMore: () => RESOLVED_PROMISE,\n item: (selector) => {\n if (selector === \"main\") {\n const index = threads.findIndex((t) => t.id === mainThreadId);\n return threadListItems.get({ index: index === -1 ? 0 : index });\n }\n if (\"id\" in selector) {\n const index = threads.findIndex((t) => t.id === selector.id);\n return threadListItems.get({ index });\n }\n return threadListItems.get(selector);\n },\n thread: () => mainThreadClient.methods,\n };\n});\n\nattachTransformScopes(InMemoryThreadList, (scopes, parent) => {\n scopes.thread ??= Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().thread(\"main\"),\n });\n scopes.threadListItem ??= Derived({\n source: \"threads\",\n query: { type: \"main\" },\n get: (aui) => aui.threads().item(\"main\"),\n });\n scopes.composer ??= Derived({\n source: \"thread\",\n query: {},\n get: (aui) => aui.threads().thread(\"main\").composer(),\n });\n\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n if (!scopes.tools && parent.tools.source === null) {\n scopes.tools = Tools({});\n }\n if (!scopes.dataRenderers && parent.dataRenderers.source === null) {\n scopes.dataRenderers = DataRenderers();\n }\n if (!scopes.suggestions && parent.suggestions.source === null) {\n scopes.suggestions = Suggestions();\n }\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SingleThreadList.d.ts","names":[],"sources":["../../src/client/SingleThreadList.ts"],"mappings":";;;KAkCK,qBAAA;EACH,MAAA,EAAQ,aAAa;AAAA;;;;AAAA;AAQvB;cAAa,gBAAA,GAAgB,KAAA,EAAA,qBAAA,iCAAA,eAAA,CAAA,YAAA,aAAA,qBAAA"}
1
+ {"version":3,"file":"SingleThreadList.d.ts","names":[],"sources":["../../src/client/SingleThreadList.ts"],"mappings":";;;KAqCK,qBAAA;EACH,MAAA,EAAQ,aAAa;AAAA;;;;AAAA;AAQvB;cAAa,gBAAA,GAAgB,KAAA,EAAA,qBAAA,iCAAA,eAAA,CAAA,YAAA,aAAA,qBAAA"}
@@ -1,10 +1,11 @@
1
- import { tapClientResource } from "@assistant-ui/store";
2
- import { resource, tapMemo, tapState } from "@assistant-ui/tap";
1
+ import { useClientResource } from "@assistant-ui/store";
2
+ import { useMemo, useState } from "@assistant-ui/tap/react-shim";
3
+ import { resource } from "@assistant-ui/tap";
3
4
  //#region src/client/SingleThreadList.ts
4
5
  const RESOLVED_PROMISE = Promise.resolve();
5
6
  const THREAD_ID = "default";
6
- const SingleThreadListItem = resource(() => {
7
- const [custom, setCustom] = tapState();
7
+ const SingleThreadListItem = resource(function SingleThreadListItem() {
8
+ const [custom, setCustom] = useState();
8
9
  return {
9
10
  getState: () => ({
10
11
  id: THREAD_ID,
@@ -33,10 +34,10 @@ const SingleThreadListItem = resource(() => {
33
34
  * Automatically provided by ExternalThread when no threads scope exists.
34
35
  * Mounts the provided thread resource element.
35
36
  */
36
- const SingleThreadList = resource(({ thread }) => {
37
- const itemClient = tapClientResource(SingleThreadListItem());
38
- const threadClient = tapClientResource(thread);
39
- const state = tapMemo(() => ({
37
+ const SingleThreadList = resource(function SingleThreadList({ thread }) {
38
+ const itemClient = useClientResource(SingleThreadListItem());
39
+ const threadClient = useClientResource(thread);
40
+ const state = useMemo(() => ({
40
41
  mainThreadId: THREAD_ID,
41
42
  newThreadId: null,
42
43
  isLoading: false,
@@ -1 +1 @@
1
- {"version":3,"file":"SingleThreadList.js","names":[],"sources":["../../src/client/SingleThreadList.ts"],"sourcesContent":["import { resource, tapMemo, tapState } from \"@assistant-ui/tap\";\nimport {\n type ClientElement,\n type ClientOutput,\n tapClientResource,\n} from \"@assistant-ui/store\";\n\nconst RESOLVED_PROMISE = Promise.resolve();\nconst THREAD_ID = \"default\";\n\nconst SingleThreadListItem = resource((): ClientOutput<\"threadListItem\"> => {\n const [custom, setCustom] = tapState<Record<string, unknown> | undefined>();\n\n return {\n getState: () => ({\n id: THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n title: undefined,\n status: \"regular\",\n custom,\n }),\n switchTo: () => {},\n rename: () => {},\n updateCustom: setCustom,\n archive: () => {},\n unarchive: () => {},\n delete: () => {},\n generateTitle: () => {},\n initialize: async () => ({ remoteId: THREAD_ID, externalId: undefined }),\n detach: () => {},\n };\n});\n\ntype SingleThreadListProps = {\n thread: ClientElement<\"thread\">;\n};\n\n/**\n * A minimal threads scope that wraps a single thread.\n * Automatically provided by ExternalThread when no threads scope exists.\n * Mounts the provided thread resource element.\n */\nexport const SingleThreadList = resource(\n ({ thread }: SingleThreadListProps): ClientOutput<\"threads\"> => {\n const itemClient = tapClientResource(SingleThreadListItem());\n const threadClient = tapClientResource(thread);\n\n const state = tapMemo(\n () => ({\n mainThreadId: THREAD_ID,\n newThreadId: null,\n isLoading: false,\n isLoadingMore: false,\n hasMore: false,\n threadIds: [THREAD_ID],\n archivedThreadIds: [],\n threadItems: [itemClient.state],\n main: threadClient.state,\n }),\n [itemClient.state, threadClient.state],\n );\n\n return {\n getState: () => state,\n switchToThread: () => {\n throw new Error(\"SingleThreadList does not support switchToThread\");\n },\n switchToNewThread: () => {\n throw new Error(\"SingleThreadList does not support switchToNewThread\");\n },\n getLoadThreadsPromise: () => RESOLVED_PROMISE,\n reload: () => RESOLVED_PROMISE,\n loadMore: () => RESOLVED_PROMISE,\n item: (selector) => {\n if (\n selector !== \"main\" &&\n !(\n typeof selector === \"object\" &&\n \"id\" in selector &&\n selector.id === THREAD_ID\n ) &&\n !(\n typeof selector === \"object\" &&\n \"index\" in selector &&\n selector.index === 0\n )\n ) {\n throw new Error(\n `SingleThreadList: unknown item selector ${JSON.stringify(selector)}`,\n );\n }\n return itemClient.methods;\n },\n thread: (selector) => {\n if (selector !== \"main\" && selector !== THREAD_ID) {\n throw new Error(\n `SingleThreadList: unknown thread selector ${JSON.stringify(selector)}`,\n );\n }\n return threadClient.methods;\n },\n };\n },\n);\n"],"mappings":";;;AAOA,MAAM,mBAAmB,QAAQ,QAAQ;AACzC,MAAM,YAAY;AAElB,MAAM,uBAAuB,eAA+C;CAC1E,MAAM,CAAC,QAAQ,aAAa,SAA8C;CAE1E,OAAO;EACL,iBAAiB;GACf,IAAI;GACJ,UAAU,KAAA;GACV,YAAY,KAAA;GACZ,OAAO,KAAA;GACP,QAAQ;GACR;EACF;EACA,gBAAgB,CAAC;EACjB,cAAc,CAAC;EACf,cAAc;EACd,eAAe,CAAC;EAChB,iBAAiB,CAAC;EAClB,cAAc,CAAC;EACf,qBAAqB,CAAC;EACtB,YAAY,aAAa;GAAE,UAAU;GAAW,YAAY,KAAA;EAAU;EACtE,cAAc,CAAC;CACjB;AACF,CAAC;;;;;;AAWD,MAAa,mBAAmB,UAC7B,EAAE,aAA6D;CAC9D,MAAM,aAAa,kBAAkB,qBAAqB,CAAC;CAC3D,MAAM,eAAe,kBAAkB,MAAM;CAE7C,MAAM,QAAQ,eACL;EACL,cAAc;EACd,aAAa;EACb,WAAW;EACX,eAAe;EACf,SAAS;EACT,WAAW,CAAC,SAAS;EACrB,mBAAmB,CAAC;EACpB,aAAa,CAAC,WAAW,KAAK;EAC9B,MAAM,aAAa;CACrB,IACA,CAAC,WAAW,OAAO,aAAa,KAAK,CACvC;CAEA,OAAO;EACL,gBAAgB;EAChB,sBAAsB;GACpB,MAAM,IAAI,MAAM,kDAAkD;EACpE;EACA,yBAAyB;GACvB,MAAM,IAAI,MAAM,qDAAqD;EACvE;EACA,6BAA6B;EAC7B,cAAc;EACd,gBAAgB;EAChB,OAAO,aAAa;GAClB,IACE,aAAa,UACb,EACE,OAAO,aAAa,YACpB,QAAQ,YACR,SAAS,OAAO,cAElB,EACE,OAAO,aAAa,YACpB,WAAW,YACX,SAAS,UAAU,IAGrB,MAAM,IAAI,MACR,2CAA2C,KAAK,UAAU,QAAQ,GACpE;GAEF,OAAO,WAAW;EACpB;EACA,SAAS,aAAa;GACpB,IAAI,aAAa,UAAU,aAAa,WACtC,MAAM,IAAI,MACR,6CAA6C,KAAK,UAAU,QAAQ,GACtE;GAEF,OAAO,aAAa;EACtB;CACF;AACF,CACF"}
1
+ {"version":3,"file":"SingleThreadList.js","names":[],"sources":["../../src/client/SingleThreadList.ts"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport {\n type ClientElement,\n type ClientOutput,\n useClientResource,\n} from \"@assistant-ui/store\";\n\nconst RESOLVED_PROMISE = Promise.resolve();\nconst THREAD_ID = \"default\";\n\nconst SingleThreadListItem = resource(\n function SingleThreadListItem(): ClientOutput<\"threadListItem\"> {\n const [custom, setCustom] = useState<Record<string, unknown> | undefined>();\n\n return {\n getState: () => ({\n id: THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n title: undefined,\n status: \"regular\",\n custom,\n }),\n switchTo: () => {},\n rename: () => {},\n updateCustom: setCustom,\n archive: () => {},\n unarchive: () => {},\n delete: () => {},\n generateTitle: () => {},\n initialize: async () => ({ remoteId: THREAD_ID, externalId: undefined }),\n detach: () => {},\n };\n },\n);\n\ntype SingleThreadListProps = {\n thread: ClientElement<\"thread\">;\n};\n\n/**\n * A minimal threads scope that wraps a single thread.\n * Automatically provided by ExternalThread when no threads scope exists.\n * Mounts the provided thread resource element.\n */\nexport const SingleThreadList = resource(function SingleThreadList({\n thread,\n}: SingleThreadListProps): ClientOutput<\"threads\"> {\n const itemClient = useClientResource(SingleThreadListItem());\n const threadClient = useClientResource(thread);\n\n const state = useMemo(\n () => ({\n mainThreadId: THREAD_ID,\n newThreadId: null,\n isLoading: false,\n isLoadingMore: false,\n hasMore: false,\n threadIds: [THREAD_ID],\n archivedThreadIds: [],\n threadItems: [itemClient.state],\n main: threadClient.state,\n }),\n [itemClient.state, threadClient.state],\n );\n\n return {\n getState: () => state,\n switchToThread: () => {\n throw new Error(\"SingleThreadList does not support switchToThread\");\n },\n switchToNewThread: () => {\n throw new Error(\"SingleThreadList does not support switchToNewThread\");\n },\n getLoadThreadsPromise: () => RESOLVED_PROMISE,\n reload: () => RESOLVED_PROMISE,\n loadMore: () => RESOLVED_PROMISE,\n item: (selector) => {\n if (\n selector !== \"main\" &&\n !(\n typeof selector === \"object\" &&\n \"id\" in selector &&\n selector.id === THREAD_ID\n ) &&\n !(\n typeof selector === \"object\" &&\n \"index\" in selector &&\n selector.index === 0\n )\n ) {\n throw new Error(\n `SingleThreadList: unknown item selector ${JSON.stringify(selector)}`,\n );\n }\n return itemClient.methods;\n },\n thread: (selector) => {\n if (selector !== \"main\" && selector !== THREAD_ID) {\n throw new Error(\n `SingleThreadList: unknown thread selector ${JSON.stringify(selector)}`,\n );\n }\n return threadClient.methods;\n },\n };\n});\n"],"mappings":";;;;AAQA,MAAM,mBAAmB,QAAQ,QAAQ;AACzC,MAAM,YAAY;AAElB,MAAM,uBAAuB,SAC3B,SAAS,uBAAuD;CAC9D,MAAM,CAAC,QAAQ,aAAa,SAA8C;CAE1E,OAAO;EACL,iBAAiB;GACf,IAAI;GACJ,UAAU,KAAA;GACV,YAAY,KAAA;GACZ,OAAO,KAAA;GACP,QAAQ;GACR;EACF;EACA,gBAAgB,CAAC;EACjB,cAAc,CAAC;EACf,cAAc;EACd,eAAe,CAAC;EAChB,iBAAiB,CAAC;EAClB,cAAc,CAAC;EACf,qBAAqB,CAAC;EACtB,YAAY,aAAa;GAAE,UAAU;GAAW,YAAY,KAAA;EAAU;EACtE,cAAc,CAAC;CACjB;AACF,CACF;;;;;;AAWA,MAAa,mBAAmB,SAAS,SAAS,iBAAiB,EACjE,UACiD;CACjD,MAAM,aAAa,kBAAkB,qBAAqB,CAAC;CAC3D,MAAM,eAAe,kBAAkB,MAAM;CAE7C,MAAM,QAAQ,eACL;EACL,cAAc;EACd,aAAa;EACb,WAAW;EACX,eAAe;EACf,SAAS;EACT,WAAW,CAAC,SAAS;EACrB,mBAAmB,CAAC;EACpB,aAAa,CAAC,WAAW,KAAK;EAC9B,MAAM,aAAa;CACrB,IACA,CAAC,WAAW,OAAO,aAAa,KAAK,CACvC;CAEA,OAAO;EACL,gBAAgB;EAChB,sBAAsB;GACpB,MAAM,IAAI,MAAM,kDAAkD;EACpE;EACA,yBAAyB;GACvB,MAAM,IAAI,MAAM,qDAAqD;EACvE;EACA,6BAA6B;EAC7B,cAAc;EACd,gBAAgB;EAChB,OAAO,aAAa;GAClB,IACE,aAAa,UACb,EACE,OAAO,aAAa,YACpB,QAAQ,YACR,SAAS,OAAO,cAElB,EACE,OAAO,aAAa,YACpB,WAAW,YACX,SAAS,UAAU,IAGrB,MAAM,IAAI,MACR,2CAA2C,KAAK,UAAU,QAAQ,GACpE;GAEF,OAAO,WAAW;EACpB;EACA,SAAS,aAAa;GACpB,IAAI,aAAa,UAAU,aAAa,WACtC,MAAM,IAAI,MACR,6CAA6C,KAAK,UAAU,QAAQ,GACtE;GAEF,OAAO,aAAa;EACtB;CACF;AACF,CAAC"}
@@ -2,7 +2,7 @@
2
2
  import { makeThreadViewportStore } from "../stores/ThreadViewport.js";
3
3
  import { ThreadViewportContext, useThreadViewportStore } from "../react/ThreadViewportContext.js";
4
4
  import { writableStore } from "../ReadonlyStore.js";
5
- import { useEffect, useState } from "react";
5
+ import { useEffect, useState } from "@assistant-ui/tap/react-shim";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/context/providers/ThreadViewportProvider.tsx
8
8
  const useThreadViewportStoreValue = (options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadViewportProvider.js","names":[],"sources":["../../../src/context/providers/ThreadViewportProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport type { FC, PropsWithChildren } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport {\n makeThreadViewportStore,\n type ThreadViewportStoreOptions,\n} from \"../stores/ThreadViewport\";\nimport {\n ThreadViewportContext,\n type ThreadViewportContextValue,\n useThreadViewportStore,\n} from \"../react/ThreadViewportContext\";\nimport { writableStore } from \"../ReadonlyStore\";\n\nexport type ThreadViewportProviderProps = PropsWithChildren<{\n options?: ThreadViewportStoreOptions;\n}>;\n\nconst useThreadViewportStoreValue = (options: ThreadViewportStoreOptions) => {\n const outerViewport = useThreadViewportStore({ optional: true });\n // Viewport options are initial configuration. Keeping them non-reactive avoids\n // fanout through every message in long threads when anchoring config changes.\n const [store] = useState(() => makeThreadViewportStore(options));\n\n // Forward scrollToBottom from outer viewport to inner viewport\n useEffect(() => {\n return outerViewport?.getState().onScrollToBottom(() => {\n store.getState().scrollToBottom();\n });\n }, [outerViewport, store]);\n\n useEffect(() => {\n if (!outerViewport) return;\n return store.subscribe((state) => {\n if (outerViewport.getState().isAtBottom !== state.isAtBottom) {\n writableStore(outerViewport).setState({ isAtBottom: state.isAtBottom });\n }\n });\n }, [store, outerViewport]);\n\n return store;\n};\n\nexport const ThreadPrimitiveViewportProvider: FC<\n ThreadViewportProviderProps\n> = ({ children, options = {} }) => {\n const useThreadViewport = useThreadViewportStoreValue(options);\n\n const [context] = useState<ThreadViewportContextValue>(() => {\n return {\n useThreadViewport,\n };\n });\n\n return (\n <ThreadViewportContext.Provider value={context}>\n {children}\n </ThreadViewportContext.Provider>\n );\n};\n"],"mappings":";;;;;;;AAmBA,MAAM,+BAA+B,YAAwC;CAC3E,MAAM,gBAAgB,uBAAuB,EAAE,UAAU,KAAK,CAAC;CAG/D,MAAM,CAAC,SAAS,eAAe,wBAAwB,OAAO,CAAC;CAG/D,gBAAgB;EACd,OAAO,eAAe,SAAS,EAAE,uBAAuB;GACtD,MAAM,SAAS,EAAE,eAAe;EAClC,CAAC;CACH,GAAG,CAAC,eAAe,KAAK,CAAC;CAEzB,gBAAgB;EACd,IAAI,CAAC,eAAe;EACpB,OAAO,MAAM,WAAW,UAAU;GAChC,IAAI,cAAc,SAAS,EAAE,eAAe,MAAM,YAChD,cAAc,aAAa,EAAE,SAAS,EAAE,YAAY,MAAM,WAAW,CAAC;EAE1E,CAAC;CACH,GAAG,CAAC,OAAO,aAAa,CAAC;CAEzB,OAAO;AACT;AAEA,MAAa,mCAER,EAAE,UAAU,UAAU,CAAC,QAAQ;CAClC,MAAM,oBAAoB,4BAA4B,OAAO;CAE7D,MAAM,CAAC,WAAW,eAA2C;EAC3D,OAAO,EACL,kBACF;CACF,CAAC;CAED,OACE,oBAAC,sBAAsB,UAAvB;EAAgC,OAAO;EACpC;CAC6B,CAAA;AAEpC"}
1
+ {"version":3,"file":"ThreadViewportProvider.js","names":[],"sources":["../../../src/context/providers/ThreadViewportProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport { type FC, type PropsWithChildren, useEffect, useState } from \"react\";\n\nimport {\n makeThreadViewportStore,\n type ThreadViewportStoreOptions,\n} from \"../stores/ThreadViewport\";\nimport {\n ThreadViewportContext,\n type ThreadViewportContextValue,\n useThreadViewportStore,\n} from \"../react/ThreadViewportContext\";\nimport { writableStore } from \"../ReadonlyStore\";\n\nexport type ThreadViewportProviderProps = PropsWithChildren<{\n options?: ThreadViewportStoreOptions;\n}>;\n\nconst useThreadViewportStoreValue = (options: ThreadViewportStoreOptions) => {\n const outerViewport = useThreadViewportStore({ optional: true });\n // Viewport options are initial configuration. Keeping them non-reactive avoids\n // fanout through every message in long threads when anchoring config changes.\n const [store] = useState(() => makeThreadViewportStore(options));\n\n // Forward scrollToBottom from outer viewport to inner viewport\n useEffect(() => {\n return outerViewport?.getState().onScrollToBottom(() => {\n store.getState().scrollToBottom();\n });\n }, [outerViewport, store]);\n\n useEffect(() => {\n if (!outerViewport) return;\n return store.subscribe((state) => {\n if (outerViewport.getState().isAtBottom !== state.isAtBottom) {\n writableStore(outerViewport).setState({ isAtBottom: state.isAtBottom });\n }\n });\n }, [store, outerViewport]);\n\n return store;\n};\n\nexport const ThreadPrimitiveViewportProvider: FC<\n ThreadViewportProviderProps\n> = ({ children, options = {} }) => {\n const useThreadViewport = useThreadViewportStoreValue(options);\n\n const [context] = useState<ThreadViewportContextValue>(() => {\n return {\n useThreadViewport,\n };\n });\n\n return (\n <ThreadViewportContext.Provider value={context}>\n {children}\n </ThreadViewportContext.Provider>\n );\n};\n"],"mappings":";;;;;;;AAmBA,MAAM,+BAA+B,YAAwC;CAC3E,MAAM,gBAAgB,uBAAuB,EAAE,UAAU,KAAK,CAAC;CAG/D,MAAM,CAAC,SAAS,eAAe,wBAAwB,OAAO,CAAC;CAG/D,gBAAgB;EACd,OAAO,eAAe,SAAS,CAAC,CAAC,uBAAuB;GACtD,MAAM,SAAS,CAAC,CAAC,eAAe;EAClC,CAAC;CACH,GAAG,CAAC,eAAe,KAAK,CAAC;CAEzB,gBAAgB;EACd,IAAI,CAAC,eAAe;EACpB,OAAO,MAAM,WAAW,UAAU;GAChC,IAAI,cAAc,SAAS,CAAC,CAAC,eAAe,MAAM,YAChD,cAAc,aAAa,CAAC,CAAC,SAAS,EAAE,YAAY,MAAM,WAAW,CAAC;EAE1E,CAAC;CACH,GAAG,CAAC,OAAO,aAAa,CAAC;CAEzB,OAAO;AACT;AAEA,MAAa,mCAER,EAAE,UAAU,UAAU,CAAC,QAAQ;CAClC,MAAM,oBAAoB,4BAA4B,OAAO;CAE7D,MAAM,CAAC,WAAW,eAA2C;EAC3D,OAAO,EACL,kBACF;CACF,CAAC;CAED,OACE,oBAAC,sBAAsB,UAAvB;EAAgC,OAAO;EACpC;CAC6B,CAAA;AAEpC"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { createContextHook } from "./utils/createContextHook.js";
3
3
  import { createContextStoreHook } from "./utils/createContextStoreHook.js";
4
- import { createContext } from "react";
4
+ import { createContext } from "@assistant-ui/tap/react-shim";
5
5
  //#region src/context/react/ThreadViewportContext.ts
6
6
  const ThreadViewportContext = createContext(null);
7
7
  const { useThreadViewport, useThreadViewportStore } = createContextStoreHook(createContextHook(ThreadViewportContext, "ThreadPrimitive.Viewport"), "useThreadViewport");
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { useContext } from "react";
2
+ import { useContext } from "@assistant-ui/tap/react-shim";
3
3
  //#region src/context/react/utils/createContextHook.ts
4
4
  /**
5
5
  * Creates a context hook with optional support.
@@ -1 +1 @@
1
- {"version":3,"file":"ensureBinding.js","names":[],"sources":["../../../../src/context/react/utils/ensureBinding.ts"],"sourcesContent":["type Bindable = {\n __internal_bindMethods?: () => void;\n __isBound?: boolean;\n};\nconst debugVerifyPrototype = (\n runtime: Record<string, unknown>,\n prototype: any,\n) => {\n const unboundMethods = Object.getOwnPropertyNames(prototype).filter(\n (methodStr) => {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodStr);\n const isMethod = descriptor && typeof descriptor.value === \"function\";\n if (!isMethod) return false;\n\n const methodName = methodStr as keyof typeof runtime | \"constructor\";\n return (\n isMethod &&\n !methodName.startsWith(\"_\") &&\n methodName !== \"constructor\" &&\n prototype[methodName] === runtime[methodName]\n );\n },\n );\n\n if (unboundMethods.length > 0) {\n throw new Error(\n `The following methods are not bound: ${JSON.stringify(unboundMethods)}`,\n );\n }\n\n const prototypePrototype = Object.getPrototypeOf(prototype);\n if (prototypePrototype && prototypePrototype !== Object.prototype) {\n debugVerifyPrototype(runtime, prototypePrototype);\n }\n};\nexport const ensureBinding = (r: unknown) => {\n const runtime = r as Bindable;\n if (runtime.__isBound) return;\n\n runtime.__internal_bindMethods?.();\n runtime.__isBound = true;\n\n if (process.env.NODE_ENV !== \"production\") {\n debugVerifyPrototype(runtime, Object.getPrototypeOf(runtime));\n }\n};\n"],"mappings":";AAIA,MAAM,wBACJ,SACA,cACG;CACH,MAAM,iBAAiB,OAAO,oBAAoB,SAAS,EAAE,QAC1D,cAAc;EACb,MAAM,aAAa,OAAO,yBAAyB,WAAW,SAAS;EACvE,MAAM,WAAW,cAAc,OAAO,WAAW,UAAU;EAC3D,IAAI,CAAC,UAAU,OAAO;EAEtB,MAAM,aAAa;EACnB,OACE,YACA,CAAC,WAAW,WAAW,GAAG,KAC1B,eAAe,iBACf,UAAU,gBAAgB,QAAQ;CAEtC,CACF;CAEA,IAAI,eAAe,SAAS,GAC1B,MAAM,IAAI,MACR,wCAAwC,KAAK,UAAU,cAAc,GACvE;CAGF,MAAM,qBAAqB,OAAO,eAAe,SAAS;CAC1D,IAAI,sBAAsB,uBAAuB,OAAO,WACtD,qBAAqB,SAAS,kBAAkB;AAEpD;AACA,MAAa,iBAAiB,MAAe;CAC3C,MAAM,UAAU;CAChB,IAAI,QAAQ,WAAW;CAEvB,QAAQ,yBAAyB;CACjC,QAAQ,YAAY;CAEpB,IAAI,QAAQ,IAAI,aAAa,cAC3B,qBAAqB,SAAS,OAAO,eAAe,OAAO,CAAC;AAEhE"}
1
+ {"version":3,"file":"ensureBinding.js","names":[],"sources":["../../../../src/context/react/utils/ensureBinding.ts"],"sourcesContent":["type Bindable = {\n __internal_bindMethods?: () => void;\n __isBound?: boolean;\n};\nconst debugVerifyPrototype = (\n runtime: Record<string, unknown>,\n prototype: any,\n) => {\n const unboundMethods = Object.getOwnPropertyNames(prototype).filter(\n (methodStr) => {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodStr);\n const isMethod = descriptor && typeof descriptor.value === \"function\";\n if (!isMethod) return false;\n\n const methodName = methodStr as keyof typeof runtime | \"constructor\";\n return (\n isMethod &&\n !methodName.startsWith(\"_\") &&\n methodName !== \"constructor\" &&\n prototype[methodName] === runtime[methodName]\n );\n },\n );\n\n if (unboundMethods.length > 0) {\n throw new Error(\n `The following methods are not bound: ${JSON.stringify(unboundMethods)}`,\n );\n }\n\n const prototypePrototype = Object.getPrototypeOf(prototype);\n if (prototypePrototype && prototypePrototype !== Object.prototype) {\n debugVerifyPrototype(runtime, prototypePrototype);\n }\n};\nexport const ensureBinding = (r: unknown) => {\n const runtime = r as Bindable;\n if (runtime.__isBound) return;\n\n runtime.__internal_bindMethods?.();\n runtime.__isBound = true;\n\n if (process.env.NODE_ENV !== \"production\") {\n debugVerifyPrototype(runtime, Object.getPrototypeOf(runtime));\n }\n};\n"],"mappings":";AAIA,MAAM,wBACJ,SACA,cACG;CACH,MAAM,iBAAiB,OAAO,oBAAoB,SAAS,CAAC,CAAC,QAC1D,cAAc;EACb,MAAM,aAAa,OAAO,yBAAyB,WAAW,SAAS;EACvE,MAAM,WAAW,cAAc,OAAO,WAAW,UAAU;EAC3D,IAAI,CAAC,UAAU,OAAO;EAEtB,MAAM,aAAa;EACnB,OACE,YACA,CAAC,WAAW,WAAW,GAAG,KAC1B,eAAe,iBACf,UAAU,gBAAgB,QAAQ;CAEtC,CACF;CAEA,IAAI,eAAe,SAAS,GAC1B,MAAM,IAAI,MACR,wCAAwC,KAAK,UAAU,cAAc,GACvE;CAGF,MAAM,qBAAqB,OAAO,eAAe,SAAS;CAC1D,IAAI,sBAAsB,uBAAuB,OAAO,WACtD,qBAAqB,SAAS,kBAAkB;AAEpD;AACA,MAAa,iBAAiB,MAAe;CAC3C,MAAM,UAAU;CAChB,IAAI,QAAQ,WAAW;CAEvB,QAAQ,yBAAyB;CACjC,QAAQ,YAAY;CAEpB,IAAI,QAAQ,IAAI,aAAa,cAC3B,qBAAqB,SAAS,OAAO,eAAe,OAAO,CAAC;AAEhE"}
@@ -1,5 +1,5 @@
1
1
  import { ensureBinding } from "./ensureBinding.js";
2
- import { useDebugValue, useSyncExternalStore } from "react";
2
+ import { useDebugValue, useSyncExternalStore } from "@assistant-ui/tap/react-shim";
3
3
  //#region src/context/react/utils/useRuntimeState.ts
4
4
  function useRuntimeStateInternal(runtime, selector = identity) {
5
5
  ensureBinding(runtime);