@assistant-ui/react 0.14.13 → 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 (214) 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 +24 -13
  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 +12 -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.d.ts +14 -0
  34. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  35. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +101 -0
  36. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js.map +1 -0
  37. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +1 -1
  38. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  39. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +13 -2
  40. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  41. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +1 -1
  42. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js +1 -1
  43. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  44. package/dist/mcp-apps/McpAppRenderer.js +7 -7
  45. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  46. package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
  47. package/dist/mcp-apps/McpAppsRemoteHost.js +5 -4
  48. package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
  49. package/dist/mcp-apps/app-frame.d.ts +1 -1
  50. package/dist/mcp-apps/app-frame.d.ts.map +1 -1
  51. package/dist/mcp-apps/app-frame.js +82 -104
  52. package/dist/mcp-apps/app-frame.js.map +1 -1
  53. package/dist/mcp-apps/bridge.d.ts +3 -3
  54. package/dist/mcp-apps/bridge.d.ts.map +1 -1
  55. package/dist/mcp-apps/bridge.js +35 -10
  56. package/dist/mcp-apps/bridge.js.map +1 -1
  57. package/dist/mcp-apps/types.d.ts +2 -12
  58. package/dist/mcp-apps/types.d.ts.map +1 -1
  59. package/dist/mcp-apps/types.js.map +1 -1
  60. package/dist/model-context/frame/useAssistantFrameHost.js +1 -1
  61. package/dist/model-context/makeAssistantVisible.js +1 -1
  62. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  63. package/dist/primitives/actionBar/ActionBarCopy.js +1 -1
  64. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -1
  65. package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
  66. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -1
  67. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -1
  68. package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -1
  69. package/dist/primitives/actionBar/ActionBarRoot.js +1 -1
  70. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -1
  71. package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -1
  72. package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -1
  73. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -1
  74. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -1
  75. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -1
  76. package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -1
  77. package/dist/primitives/assistantModal/AssistantModalContent.js +1 -1
  78. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -1
  79. package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -1
  80. package/dist/primitives/attachment/AttachmentRemove.js +1 -1
  81. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  82. package/dist/primitives/attachment/AttachmentRoot.js +1 -1
  83. package/dist/primitives/attachment/AttachmentThumb.js +1 -1
  84. package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -1
  85. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -1
  86. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  87. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -1
  88. package/dist/primitives/composer/ComposerAddAttachment.js +1 -1
  89. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  90. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -1
  91. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  92. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -1
  93. package/dist/primitives/composer/ComposerInput.js +1 -1
  94. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  95. package/dist/primitives/composer/ComposerInputPluginContext.js +1 -1
  96. package/dist/primitives/composer/ComposerQuote.js +1 -1
  97. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  98. package/dist/primitives/composer/ComposerRoot.js +1 -1
  99. package/dist/primitives/composer/ComposerSend.js +1 -1
  100. package/dist/primitives/composer/ComposerStopDictation.js +1 -1
  101. package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
  102. package/dist/primitives/composer/trigger/TriggerPopover.js +2 -2
  103. package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
  104. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -1
  105. package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -1
  106. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -1
  107. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -1
  108. package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -1
  109. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
  110. package/dist/primitives/composer/trigger/TriggerPopoverResource.js +8 -7
  111. package/dist/primitives/composer/trigger/TriggerPopoverResource.js.map +1 -1
  112. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -1
  113. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
  114. package/dist/primitives/composer/trigger/triggerDetectionResource.js +5 -4
  115. package/dist/primitives/composer/trigger/triggerDetectionResource.js.map +1 -1
  116. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  117. package/dist/primitives/composer/trigger/triggerKeyboardResource.js +8 -7
  118. package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
  119. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  120. package/dist/primitives/composer/trigger/triggerNavigationResource.js +13 -12
  121. package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
  122. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  123. package/dist/primitives/composer/trigger/triggerSelectionResource.js +7 -6
  124. package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
  125. package/dist/primitives/error/ErrorMessage.js +1 -1
  126. package/dist/primitives/error/ErrorRoot.js +1 -1
  127. package/dist/primitives/message/MessagePartsGrouped.js +1 -1
  128. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  129. package/dist/primitives/message/MessageRoot.js +1 -1
  130. package/dist/primitives/message/MessageRoot.js.map +1 -1
  131. package/dist/primitives/messagePart/MessagePartImage.js +1 -1
  132. package/dist/primitives/messagePart/MessagePartText.js +1 -1
  133. package/dist/primitives/queueItem/QueueItemRemove.js +1 -1
  134. package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
  135. package/dist/primitives/queueItem/QueueItemSteer.js +1 -1
  136. package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
  137. package/dist/primitives/queueItem/QueueItemText.js +1 -1
  138. package/dist/primitives/reasoning/useScrollLock.js +1 -1
  139. package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
  140. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -1
  141. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
  142. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -1
  143. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
  144. package/dist/primitives/suggestion/SuggestionDescription.js +1 -1
  145. package/dist/primitives/suggestion/SuggestionTitle.js +1 -1
  146. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -1
  147. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  148. package/dist/primitives/thread/ThreadRoot.js +1 -1
  149. package/dist/primitives/thread/ThreadScrollToBottom.js +1 -1
  150. package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
  151. package/dist/primitives/thread/ThreadViewport.js +1 -1
  152. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  153. package/dist/primitives/thread/ThreadViewportFooter.js +1 -1
  154. package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
  155. package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
  156. package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -1
  157. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -1
  158. package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -1
  159. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  160. package/dist/primitives/threadList/ThreadListNew.js +1 -1
  161. package/dist/primitives/threadList/ThreadListRoot.js +1 -1
  162. package/dist/primitives/threadListItem/ThreadListItemRoot.js +1 -1
  163. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -1
  164. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -1
  165. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -1
  166. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -1
  167. package/dist/sandbox-host/SandboxHost.d.ts +50 -0
  168. package/dist/sandbox-host/SandboxHost.d.ts.map +1 -0
  169. package/dist/sandbox-host/SandboxHost.js +85 -0
  170. package/dist/sandbox-host/SandboxHost.js.map +1 -0
  171. package/dist/unstable/useMentionAdapter.d.ts +2 -2
  172. package/dist/unstable/useMentionAdapter.js +2 -2
  173. package/dist/unstable/useMentionAdapter.js.map +1 -1
  174. package/dist/unstable/useSlashCommandAdapter.js +1 -1
  175. package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
  176. package/dist/utils/Primitive.js +1 -1
  177. package/dist/utils/createActionButton.js +1 -1
  178. package/dist/utils/createActionButton.js.map +1 -1
  179. package/dist/utils/hooks/useManagedRef.js +1 -1
  180. package/dist/utils/hooks/useMediaQuery.js +1 -1
  181. package/dist/utils/hooks/useMediaQuery.js.map +1 -1
  182. package/dist/utils/hooks/useOnResizeContent.js +1 -1
  183. package/dist/utils/hooks/useOnScrollToBottom.js +1 -1
  184. package/dist/utils/hooks/useSizeHandle.js +1 -1
  185. package/dist/utils/json/is-json.js.map +1 -1
  186. package/dist/utils/smooth/SmoothContext.js +1 -1
  187. package/dist/utils/smooth/SmoothContext.js.map +1 -1
  188. package/dist/utils/smooth/useSmooth.js +1 -1
  189. package/dist/utils/smooth/useSmooth.js.map +1 -1
  190. package/package.json +21 -20
  191. package/src/client/ExternalThread.ts +484 -515
  192. package/src/client/InMemoryThreadList.ts +154 -142
  193. package/src/client/SingleThreadList.ts +88 -81
  194. package/src/context/providers/ThreadViewportProvider.tsx +2 -2
  195. package/src/index.ts +18 -3
  196. package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.test.ts +426 -0
  197. package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.ts +146 -0
  198. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts +16 -1
  199. package/src/mcp-apps/McpAppRenderer.tsx +28 -35
  200. package/src/mcp-apps/McpAppsRemoteHost.ts +25 -24
  201. package/src/mcp-apps/app-frame.tsx +100 -141
  202. package/src/mcp-apps/bridge.test.ts +100 -60
  203. package/src/mcp-apps/bridge.ts +43 -21
  204. package/src/mcp-apps/types.ts +2 -12
  205. package/src/primitives/composer/trigger/TriggerPopover.tsx +1 -1
  206. package/src/primitives/composer/trigger/TriggerPopoverResource.ts +75 -76
  207. package/src/primitives/composer/trigger/triggerDetectionResource.ts +6 -5
  208. package/src/primitives/composer/trigger/triggerKeyboardResource.ts +9 -13
  209. package/src/primitives/composer/trigger/triggerNavigationResource.ts +14 -19
  210. package/src/primitives/composer/trigger/triggerSelectionResource.ts +8 -7
  211. package/src/sandbox-host/SandboxHost.test.tsx +231 -0
  212. package/src/sandbox-host/SandboxHost.tsx +185 -0
  213. package/src/tests/local-runtime-queue.test.tsx +305 -0
  214. package/src/unstable/useMentionAdapter.ts +2 -2
@@ -1,13 +1,12 @@
1
- import { resource, tapState, tapMemo } from "@assistant-ui/tap";
1
+ import { useState, useMemo } from "react";
2
+ import { resource, withKey, type ResourceElement } from "@assistant-ui/tap";
2
3
  import {
3
4
  type ClientOutput,
4
- tapClientLookup,
5
+ useClientLookup,
5
6
  Derived,
6
7
  attachTransformScopes,
7
- tapClientResource,
8
+ useClientResource,
8
9
  } from "@assistant-ui/store";
9
- import { withKey } from "@assistant-ui/tap";
10
- import type { ResourceElement } from "@assistant-ui/tap";
11
10
 
12
11
  import { ModelContext, Suggestions } from "@assistant-ui/core/store";
13
12
  import { Tools, DataRenderers } from "@assistant-ui/core/react";
@@ -24,155 +23,168 @@ type ThreadData = {
24
23
  id: string;
25
24
  title?: string;
26
25
  status: "regular" | "archived";
26
+ custom?: Record<string, unknown> | undefined;
27
27
  };
28
28
 
29
29
  // ThreadListItem Client
30
- const ThreadListItemClient = resource(
31
- (props: {
32
- data: ThreadData;
33
- onSwitchTo: () => void;
34
- onArchive: () => void;
35
- onUnarchive: () => void;
36
- onDelete: () => void;
37
- }): ClientOutput<"threadListItem"> => {
38
- const { data, onSwitchTo, onArchive, onUnarchive, onDelete } = props;
39
- const state = tapMemo(
40
- () => ({
41
- id: data.id,
42
- remoteId: undefined,
43
- externalId: undefined,
44
- title: data.title,
45
- status: data.status,
46
- }),
47
- [data.id, data.title, data.status],
48
- );
49
-
50
- return {
51
- getState: () => state,
52
- switchTo: onSwitchTo,
53
- rename: () => {},
54
- archive: onArchive,
55
- unarchive: onUnarchive,
56
- delete: onDelete,
57
- generateTitle: () => {},
58
- initialize: async () => ({ remoteId: data.id, externalId: undefined }),
59
- detach: () => {},
60
- };
61
- },
62
- );
30
+ const ThreadListItemClient = resource(function ThreadListItemClient(props: {
31
+ data: ThreadData;
32
+ onSwitchTo: () => void;
33
+ onUpdateCustom: (custom: Record<string, unknown> | undefined) => void;
34
+ onArchive: () => void;
35
+ onUnarchive: () => void;
36
+ onDelete: () => void;
37
+ }): ClientOutput<"threadListItem"> {
38
+ const { data, onSwitchTo, onUpdateCustom, onArchive, onUnarchive, onDelete } =
39
+ props;
40
+ const state = useMemo(
41
+ () => ({
42
+ id: data.id,
43
+ remoteId: undefined,
44
+ externalId: undefined,
45
+ title: data.title,
46
+ status: data.status,
47
+ custom: data.custom,
48
+ }),
49
+ [data.id, data.title, data.status, data.custom],
50
+ );
51
+
52
+ return {
53
+ getState: () => state,
54
+ switchTo: onSwitchTo,
55
+ rename: () => {},
56
+ updateCustom: onUpdateCustom,
57
+ archive: onArchive,
58
+ unarchive: onUnarchive,
59
+ delete: onDelete,
60
+ generateTitle: () => {},
61
+ initialize: async () => ({ remoteId: data.id, externalId: undefined }),
62
+ detach: () => {},
63
+ };
64
+ });
63
65
 
64
66
  // InMemoryThreadList Client
65
- export const InMemoryThreadList = resource(
66
- (props: InMemoryThreadListProps): ClientOutput<"threads"> => {
67
- const {
68
- thread: threadFactory,
69
- onSwitchToThread,
70
- onSwitchToNewThread,
71
- } = props;
72
-
73
- const [mainThreadId, setMainThreadId] = tapState("main");
74
- const [threads, setThreads] = tapState<readonly ThreadData[]>(() => [
75
- { id: "main", title: "Main Thread", status: "regular" },
76
- ]);
77
-
78
- const handleSwitchToThread = (threadId: string) => {
79
- setMainThreadId(threadId);
80
- onSwitchToThread?.(threadId);
81
- };
82
-
83
- const handleArchive = (threadId: string) => {
84
- setThreads((prev) =>
85
- prev.map((t) =>
86
- t.id === threadId ? { ...t, status: "archived" as const } : t,
87
- ),
88
- );
89
- };
67
+ export const InMemoryThreadList = resource(function InMemoryThreadList(
68
+ props: InMemoryThreadListProps,
69
+ ): ClientOutput<"threads"> {
70
+ const {
71
+ thread: threadFactory,
72
+ onSwitchToThread,
73
+ onSwitchToNewThread,
74
+ } = props;
75
+
76
+ const [mainThreadId, setMainThreadId] = useState("main");
77
+ const [threads, setThreads] = useState<readonly ThreadData[]>(() => [
78
+ { id: "main", title: "Main Thread", status: "regular" },
79
+ ]);
80
+
81
+ const handleSwitchToThread = (threadId: string) => {
82
+ setMainThreadId(threadId);
83
+ onSwitchToThread?.(threadId);
84
+ };
85
+
86
+ const handleArchive = (threadId: string) => {
87
+ setThreads((prev) =>
88
+ prev.map((t) =>
89
+ t.id === threadId ? { ...t, status: "archived" as const } : t,
90
+ ),
91
+ );
92
+ };
90
93
 
91
- const handleUnarchive = (threadId: string) => {
92
- setThreads((prev) =>
93
- prev.map((t) =>
94
- t.id === threadId ? { ...t, status: "regular" as const } : t,
94
+ const handleUnarchive = (threadId: string) => {
95
+ setThreads((prev) =>
96
+ prev.map((t) =>
97
+ t.id === threadId ? { ...t, status: "regular" as const } : t,
98
+ ),
99
+ );
100
+ };
101
+
102
+ const handleUpdateCustom = (
103
+ threadId: string,
104
+ custom: Record<string, unknown> | undefined,
105
+ ) => {
106
+ setThreads((prev) =>
107
+ prev.map((t) => (t.id === threadId ? { ...t, custom } : t)),
108
+ );
109
+ };
110
+
111
+ const handleDelete = (threadId: string) => {
112
+ setThreads((prev) => prev.filter((t) => t.id !== threadId));
113
+ if (mainThreadId === threadId) {
114
+ const remaining = threads.filter((t) => t.id !== threadId);
115
+ setMainThreadId(remaining[0]?.id || "main");
116
+ }
117
+ };
118
+
119
+ const handleSwitchToNewThread = () => {
120
+ const newId = `thread-${Date.now()}`;
121
+ setThreads((prev) => [
122
+ ...prev,
123
+ { id: newId, title: "New Thread", status: "regular" },
124
+ ]);
125
+ setMainThreadId(newId);
126
+ onSwitchToNewThread?.();
127
+ };
128
+
129
+ const threadListItems = useClientLookup(
130
+ () =>
131
+ threads.map((t) =>
132
+ withKey(
133
+ t.id,
134
+ ThreadListItemClient({
135
+ data: t,
136
+ onSwitchTo: () => handleSwitchToThread(t.id),
137
+ onUpdateCustom: (custom) => handleUpdateCustom(t.id, custom),
138
+ onArchive: () => handleArchive(t.id),
139
+ onUnarchive: () => handleUnarchive(t.id),
140
+ onDelete: () => handleDelete(t.id),
141
+ }),
95
142
  ),
96
- );
97
- };
143
+ ),
144
+ [threads],
145
+ );
98
146
 
99
- const handleDelete = (threadId: string) => {
100
- setThreads((prev) => prev.filter((t) => t.id !== threadId));
101
- if (mainThreadId === threadId) {
102
- const remaining = threads.filter((t) => t.id !== threadId);
103
- setMainThreadId(remaining[0]?.id || "main");
104
- }
105
- };
147
+ // Create the main thread
148
+ const mainThreadClient = useClientResource(threadFactory(mainThreadId));
106
149
 
107
- const handleSwitchToNewThread = () => {
108
- const newId = `thread-${Date.now()}`;
109
- setThreads((prev) => [
110
- ...prev,
111
- { id: newId, title: "New Thread", status: "regular" },
112
- ]);
113
- setMainThreadId(newId);
114
- onSwitchToNewThread?.();
115
- };
116
-
117
- const threadListItems = tapClientLookup(
118
- () =>
119
- threads.map((t) =>
120
- withKey(
121
- t.id,
122
- ThreadListItemClient({
123
- data: t,
124
- onSwitchTo: () => handleSwitchToThread(t.id),
125
- onArchive: () => handleArchive(t.id),
126
- onUnarchive: () => handleUnarchive(t.id),
127
- onDelete: () => handleDelete(t.id),
128
- }),
129
- ),
130
- ),
131
- [threads],
132
- );
133
-
134
- // Create the main thread
135
- const mainThreadClient = tapClientResource(threadFactory(mainThreadId));
136
-
137
- const state = tapMemo(() => {
138
- const regularThreads = threads.filter((t) => t.status === "regular");
139
- const archivedThreads = threads.filter((t) => t.status === "archived");
140
-
141
- return {
142
- mainThreadId,
143
- newThreadId: null,
144
- isLoading: false,
145
- isLoadingMore: false,
146
- hasMore: false,
147
- threadIds: regularThreads.map((t) => t.id),
148
- archivedThreadIds: archivedThreads.map((t) => t.id),
149
- threadItems: threadListItems.state,
150
- main: mainThreadClient.state,
151
- };
152
- }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);
150
+ const state = useMemo(() => {
151
+ const regularThreads = threads.filter((t) => t.status === "regular");
152
+ const archivedThreads = threads.filter((t) => t.status === "archived");
153
153
 
154
154
  return {
155
- getState: () => state,
156
- switchToThread: handleSwitchToThread,
157
- switchToNewThread: handleSwitchToNewThread,
158
- getLoadThreadsPromise: () => RESOLVED_PROMISE,
159
- reload: () => RESOLVED_PROMISE,
160
- loadMore: () => RESOLVED_PROMISE,
161
- item: (selector) => {
162
- if (selector === "main") {
163
- const index = threads.findIndex((t) => t.id === mainThreadId);
164
- return threadListItems.get({ index: index === -1 ? 0 : index });
165
- }
166
- if ("id" in selector) {
167
- const index = threads.findIndex((t) => t.id === selector.id);
168
- return threadListItems.get({ index });
169
- }
170
- return threadListItems.get(selector);
171
- },
172
- thread: () => mainThreadClient.methods,
155
+ mainThreadId,
156
+ newThreadId: null,
157
+ isLoading: false,
158
+ isLoadingMore: false,
159
+ hasMore: false,
160
+ threadIds: regularThreads.map((t) => t.id),
161
+ archivedThreadIds: archivedThreads.map((t) => t.id),
162
+ threadItems: threadListItems.state,
163
+ main: mainThreadClient.state,
173
164
  };
174
- },
175
- );
165
+ }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);
166
+
167
+ return {
168
+ getState: () => state,
169
+ switchToThread: handleSwitchToThread,
170
+ switchToNewThread: handleSwitchToNewThread,
171
+ getLoadThreadsPromise: () => RESOLVED_PROMISE,
172
+ reload: () => RESOLVED_PROMISE,
173
+ loadMore: () => RESOLVED_PROMISE,
174
+ item: (selector) => {
175
+ if (selector === "main") {
176
+ const index = threads.findIndex((t) => t.id === mainThreadId);
177
+ return threadListItems.get({ index: index === -1 ? 0 : index });
178
+ }
179
+ if ("id" in selector) {
180
+ const index = threads.findIndex((t) => t.id === selector.id);
181
+ return threadListItems.get({ index });
182
+ }
183
+ return threadListItems.get(selector);
184
+ },
185
+ thread: () => mainThreadClient.methods,
186
+ };
187
+ });
176
188
 
177
189
  attachTransformScopes(InMemoryThreadList, (scopes, parent) => {
178
190
  scopes.thread ??= Derived({
@@ -1,32 +1,39 @@
1
- import { resource, tapMemo } from "@assistant-ui/tap";
1
+ import { useMemo, useState } from "react";
2
+ import { resource } from "@assistant-ui/tap";
2
3
  import {
3
4
  type ClientElement,
4
5
  type ClientOutput,
5
- tapClientResource,
6
+ useClientResource,
6
7
  } from "@assistant-ui/store";
7
8
 
8
9
  const RESOLVED_PROMISE = Promise.resolve();
9
10
  const THREAD_ID = "default";
10
11
 
11
- const SingleThreadListItem = resource((): ClientOutput<"threadListItem"> => {
12
- return {
13
- getState: () => ({
14
- id: THREAD_ID,
15
- remoteId: undefined,
16
- externalId: undefined,
17
- title: undefined,
18
- status: "regular",
19
- }),
20
- switchTo: () => {},
21
- rename: () => {},
22
- archive: () => {},
23
- unarchive: () => {},
24
- delete: () => {},
25
- generateTitle: () => {},
26
- initialize: async () => ({ remoteId: THREAD_ID, externalId: undefined }),
27
- detach: () => {},
28
- };
29
- });
12
+ const SingleThreadListItem = resource(
13
+ function SingleThreadListItem(): ClientOutput<"threadListItem"> {
14
+ const [custom, setCustom] = useState<Record<string, unknown> | undefined>();
15
+
16
+ return {
17
+ getState: () => ({
18
+ id: THREAD_ID,
19
+ remoteId: undefined,
20
+ externalId: undefined,
21
+ title: undefined,
22
+ status: "regular",
23
+ custom,
24
+ }),
25
+ switchTo: () => {},
26
+ rename: () => {},
27
+ updateCustom: setCustom,
28
+ archive: () => {},
29
+ unarchive: () => {},
30
+ delete: () => {},
31
+ generateTitle: () => {},
32
+ initialize: async () => ({ remoteId: THREAD_ID, externalId: undefined }),
33
+ detach: () => {},
34
+ };
35
+ },
36
+ );
30
37
 
31
38
  type SingleThreadListProps = {
32
39
  thread: ClientElement<"thread">;
@@ -37,65 +44,65 @@ type SingleThreadListProps = {
37
44
  * Automatically provided by ExternalThread when no threads scope exists.
38
45
  * Mounts the provided thread resource element.
39
46
  */
40
- export const SingleThreadList = resource(
41
- ({ thread }: SingleThreadListProps): ClientOutput<"threads"> => {
42
- const itemClient = tapClientResource(SingleThreadListItem());
43
- const threadClient = tapClientResource(thread);
47
+ export const SingleThreadList = resource(function SingleThreadList({
48
+ thread,
49
+ }: SingleThreadListProps): ClientOutput<"threads"> {
50
+ const itemClient = useClientResource(SingleThreadListItem());
51
+ const threadClient = useClientResource(thread);
44
52
 
45
- const state = tapMemo(
46
- () => ({
47
- mainThreadId: THREAD_ID,
48
- newThreadId: null,
49
- isLoading: false,
50
- isLoadingMore: false,
51
- hasMore: false,
52
- threadIds: [THREAD_ID],
53
- archivedThreadIds: [],
54
- threadItems: [itemClient.state],
55
- main: threadClient.state,
56
- }),
57
- [itemClient.state, threadClient.state],
58
- );
53
+ const state = useMemo(
54
+ () => ({
55
+ mainThreadId: THREAD_ID,
56
+ newThreadId: null,
57
+ isLoading: false,
58
+ isLoadingMore: false,
59
+ hasMore: false,
60
+ threadIds: [THREAD_ID],
61
+ archivedThreadIds: [],
62
+ threadItems: [itemClient.state],
63
+ main: threadClient.state,
64
+ }),
65
+ [itemClient.state, threadClient.state],
66
+ );
59
67
 
60
- return {
61
- getState: () => state,
62
- switchToThread: () => {
63
- throw new Error("SingleThreadList does not support switchToThread");
64
- },
65
- switchToNewThread: () => {
66
- throw new Error("SingleThreadList does not support switchToNewThread");
67
- },
68
- getLoadThreadsPromise: () => RESOLVED_PROMISE,
69
- reload: () => RESOLVED_PROMISE,
70
- loadMore: () => RESOLVED_PROMISE,
71
- item: (selector) => {
72
- if (
73
- selector !== "main" &&
74
- !(
75
- typeof selector === "object" &&
76
- "id" in selector &&
77
- selector.id === THREAD_ID
78
- ) &&
79
- !(
80
- typeof selector === "object" &&
81
- "index" in selector &&
82
- selector.index === 0
83
- )
84
- ) {
85
- throw new Error(
86
- `SingleThreadList: unknown item selector ${JSON.stringify(selector)}`,
87
- );
88
- }
89
- return itemClient.methods;
90
- },
91
- thread: (selector) => {
92
- if (selector !== "main" && selector !== THREAD_ID) {
93
- throw new Error(
94
- `SingleThreadList: unknown thread selector ${JSON.stringify(selector)}`,
95
- );
96
- }
97
- return threadClient.methods;
98
- },
99
- };
100
- },
101
- );
68
+ return {
69
+ getState: () => state,
70
+ switchToThread: () => {
71
+ throw new Error("SingleThreadList does not support switchToThread");
72
+ },
73
+ switchToNewThread: () => {
74
+ throw new Error("SingleThreadList does not support switchToNewThread");
75
+ },
76
+ getLoadThreadsPromise: () => RESOLVED_PROMISE,
77
+ reload: () => RESOLVED_PROMISE,
78
+ loadMore: () => RESOLVED_PROMISE,
79
+ item: (selector) => {
80
+ if (
81
+ selector !== "main" &&
82
+ !(
83
+ typeof selector === "object" &&
84
+ "id" in selector &&
85
+ selector.id === THREAD_ID
86
+ ) &&
87
+ !(
88
+ typeof selector === "object" &&
89
+ "index" in selector &&
90
+ selector.index === 0
91
+ )
92
+ ) {
93
+ throw new Error(
94
+ `SingleThreadList: unknown item selector ${JSON.stringify(selector)}`,
95
+ );
96
+ }
97
+ return itemClient.methods;
98
+ },
99
+ thread: (selector) => {
100
+ if (selector !== "main" && selector !== THREAD_ID) {
101
+ throw new Error(
102
+ `SingleThreadList: unknown thread selector ${JSON.stringify(selector)}`,
103
+ );
104
+ }
105
+ return threadClient.methods;
106
+ },
107
+ };
108
+ });
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
- import type { FC, PropsWithChildren } from "react";
4
- import { useEffect, useState } from "react";
3
+ import { type FC, type PropsWithChildren, useEffect, useState } from "react";
4
+
5
5
  import {
6
6
  makeThreadViewportStore,
7
7
  type ThreadViewportStoreOptions,
package/src/index.ts CHANGED
@@ -136,6 +136,12 @@ export type {
136
136
  ExternalStoreThreadListAdapter,
137
137
  ExternalStoreThreadData,
138
138
  } from "@assistant-ui/core";
139
+ export {
140
+ createMessageQueue,
141
+ type MessageQueueDriver,
142
+ type MessageQueueController,
143
+ type ExternalThreadQueueAdapter,
144
+ } from "@assistant-ui/core";
139
145
  export { useExternalStoreRuntime } from "./legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime";
140
146
  export { useExternalStoreSharedOptions } from "@assistant-ui/core/react";
141
147
  export {
@@ -187,10 +193,20 @@ export {
187
193
  useInlineRender,
188
194
  type Toolkit,
189
195
  type ToolDefinition,
190
- type ToolkitDeclaration,
191
- type ToolkitDeclarationDefinition,
196
+ type ToolCallText,
197
+ type ToolkitDefinition,
198
+ type ToolkitDefinitionEntry,
192
199
  defineToolkit,
200
+ stubTool,
201
+ externalTool,
202
+ useAuiToolOverrides,
193
203
  hitl,
204
+ hitlTool,
205
+ humanTool,
206
+ providerTool,
207
+ type ProviderToolConfig,
208
+ defineMcpToolkit,
209
+ type McpToolkitDefinition,
194
210
  Tools,
195
211
  DataRenderers,
196
212
  Interactables,
@@ -357,7 +373,6 @@ export {
357
373
  ExternalThread,
358
374
  type ExternalThreadProps,
359
375
  type ExternalThreadMessage,
360
- type ExternalThreadQueueAdapter,
361
376
  } from "./client/ExternalThread";
362
377
  export {
363
378
  InMemoryThreadList,