@assistant-ui/react 0.15.13 → 0.15.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 (160) hide show
  1. package/dist/assistant-transport.d.ts +32 -0
  2. package/dist/assistant-transport.d.ts.map +1 -0
  3. package/dist/assistant-transport.js +27 -0
  4. package/dist/assistant-transport.js.map +1 -0
  5. package/dist/context/providers/MessageProvider.js +1 -1
  6. package/dist/hooks/useMessageQuote.js +1 -1
  7. package/dist/hooks/useToolCallElapsed.js +1 -1
  8. package/dist/index.d.ts +5 -8
  9. package/dist/index.js +7 -9
  10. package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -1
  11. package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
  12. package/dist/mcp-apps/McpAppsRemoteHost.js +18 -2
  13. package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
  14. package/dist/mcp-apps/bridge.js +39 -24
  15. package/dist/mcp-apps/bridge.js.map +1 -1
  16. package/dist/model-context/makeAssistantVisible.js +1 -1
  17. package/dist/primitives/actionBar/ActionBarCopy.js +1 -1
  18. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -1
  19. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -1
  20. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -1
  21. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -1
  22. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +24 -37
  23. package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -1
  24. package/dist/primitives/actionBar/useActionBarFloatStatus.js +1 -1
  25. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -1
  26. package/dist/primitives/attachment/AttachmentName.js +1 -1
  27. package/dist/primitives/attachment/AttachmentRemove.js +1 -1
  28. package/dist/primitives/attachment/AttachmentThumb.js +1 -1
  29. package/dist/primitives/branchPicker/BranchPickerCount.js +1 -1
  30. package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -1
  31. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -1
  32. package/dist/primitives/composer/ComposerAddAttachment.js +1 -1
  33. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -1
  34. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -1
  35. package/dist/primitives/composer/ComposerInput.js +2 -2
  36. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  37. package/dist/primitives/composer/ComposerQuote.js +1 -1
  38. package/dist/primitives/composer/ComposerRoot.js +1 -1
  39. package/dist/primitives/composer/ComposerStopDictation.js +1 -1
  40. package/dist/primitives/composer/trigger/TriggerPopover.js +1 -1
  41. package/dist/primitives/composer/useComposerInputState.js +1 -1
  42. package/dist/primitives/message/MessageIf.js +1 -1
  43. package/dist/primitives/message/MessagePartsGrouped.js +1 -1
  44. package/dist/primitives/message/MessageRoot.js +1 -1
  45. package/dist/primitives/queueItem/QueueItemRemove.js +1 -1
  46. package/dist/primitives/queueItem/QueueItemSteer.js +1 -1
  47. package/dist/primitives/queueItem/QueueItemText.js +1 -1
  48. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -1
  49. package/dist/primitives/suggestion/SuggestionDescription.js +1 -1
  50. package/dist/primitives/suggestion/SuggestionTitle.js +1 -1
  51. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -1
  52. package/dist/primitives/thread/ThreadIf.js +1 -1
  53. package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
  54. package/dist/primitives/thread/ThreadRoot.js +41 -9
  55. package/dist/primitives/thread/ThreadRoot.js.map +1 -1
  56. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  57. package/dist/primitives/thread/ThreadViewport.js +2 -13
  58. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  59. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  60. package/dist/primitives/thread/useThreadViewportAutoScroll.js +23 -8
  61. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  62. package/dist/primitives/threadList/ThreadListNew.js +1 -1
  63. package/dist/sandbox-host/SandboxHost.js +2 -0
  64. package/dist/sandbox-host/SandboxHost.js.map +1 -1
  65. package/dist/unstable/useComposerInput.d.ts +2 -2
  66. package/dist/unstable/useComposerInput.js +1 -1
  67. package/dist/unstable/useComposerInput.js.map +1 -1
  68. package/dist/unstable/useComposerInputHistory.js +1 -1
  69. package/dist/unstable/useComposerInputHistory.js.map +1 -1
  70. package/dist/unstable/useLiveCompletionAdapter.d.ts +5 -0
  71. package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
  72. package/dist/unstable/useLiveCompletionAdapter.js +16 -3
  73. package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
  74. package/dist/unstable/useMentionAdapter.d.ts +1 -1
  75. package/dist/utils/smooth/SmoothContext.js +1 -1
  76. package/dist/utils/useToolArgsFieldStatus.js +1 -1
  77. package/package.json +9 -9
  78. package/src/assistant-transport.ts +94 -0
  79. package/src/index.ts +9 -4
  80. package/src/mcp-apps/McpAppsRemoteHost.test.ts +29 -3
  81. package/src/mcp-apps/McpAppsRemoteHost.ts +42 -7
  82. package/src/mcp-apps/bridge.test.ts +132 -0
  83. package/src/mcp-apps/bridge.ts +54 -30
  84. package/src/primitives/actionBar/ActionBarStopSpeaking.tsx +0 -9
  85. package/src/primitives/composer/ComposerInput.tsx +1 -1
  86. package/src/primitives/thread/ThreadRoot.test.tsx +251 -0
  87. package/src/primitives/thread/ThreadRoot.tsx +30 -0
  88. package/src/primitives/thread/ThreadViewport.tsx +1 -8
  89. package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +152 -0
  90. package/src/primitives/thread/useThreadViewportAutoScroll.ts +26 -19
  91. package/src/sandbox-host/SandboxHost.test.tsx +29 -0
  92. package/src/sandbox-host/SandboxHost.tsx +2 -0
  93. package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +24 -3
  94. package/src/tests/RemoteThreadListRuntime.reloadMainThread.test.tsx +1 -2
  95. package/src/tests/augmentations.test.ts +49 -0
  96. package/src/tests/in-memory-thread-list.test.tsx +87 -3
  97. package/src/tests/threadMessageById.test.tsx +61 -1
  98. package/src/unstable/useComposerInput.ts +2 -2
  99. package/src/unstable/useComposerInputHistory.test.tsx +4 -4
  100. package/src/unstable/useComposerInputHistory.ts +1 -1
  101. package/src/unstable/useLiveCompletionAdapter.test.tsx +100 -0
  102. package/src/unstable/useLiveCompletionAdapter.ts +41 -17
  103. package/dist/client/InMemoryThreadList.d.ts +0 -12
  104. package/dist/client/InMemoryThreadList.d.ts.map +0 -1
  105. package/dist/client/InMemoryThreadList.js +0 -365
  106. package/dist/client/InMemoryThreadList.js.map +0 -1
  107. package/dist/legacy-runtime/cloud/auiV0.d.ts +0 -119
  108. package/dist/legacy-runtime/cloud/auiV0.d.ts.map +0 -1
  109. package/dist/legacy-runtime/cloud/auiV0.js +0 -137
  110. package/dist/legacy-runtime/cloud/auiV0.js.map +0 -1
  111. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts +0 -16
  112. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts.map +0 -1
  113. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.js +0 -36
  114. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.js.map +0 -1
  115. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts +0 -17
  116. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts.map +0 -1
  117. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js +0 -55
  118. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js.map +0 -1
  119. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts +0 -11
  120. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +0 -1
  121. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +0 -141
  122. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js.map +0 -1
  123. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts +0 -15
  124. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +0 -1
  125. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +0 -81
  126. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js.map +0 -1
  127. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +0 -126
  128. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +0 -1
  129. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.js +0 -0
  130. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts +0 -14
  131. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +0 -1
  132. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +0 -290
  133. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +0 -1
  134. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts +0 -7
  135. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts.map +0 -1
  136. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +0 -25
  137. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js.map +0 -1
  138. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.d.ts +0 -7
  139. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.d.ts.map +0 -1
  140. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js +0 -27
  141. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js.map +0 -1
  142. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts +0 -2
  143. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js +0 -2
  144. package/src/client/InMemoryThreadList.ts +0 -241
  145. package/src/legacy-runtime/cloud/auiV0.ts +0 -331
  146. package/src/legacy-runtime/cloud/useCloudThreadListRuntime.ts +0 -31
  147. package/src/legacy-runtime/runtime-cores/assistant-transport/commandQueue.ts +0 -68
  148. package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.test.ts +0 -430
  149. package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.ts +0 -146
  150. package/src/legacy-runtime/runtime-cores/assistant-transport/runManager.ts +0 -113
  151. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-delivery.test.tsx +0 -79
  152. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-parentid.test.tsx +0 -97
  153. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-scheduling.test.ts +0 -307
  154. package/src/legacy-runtime/runtime-cores/assistant-transport/types.ts +0 -170
  155. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransport.spec.md +0 -141
  156. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.test.tsx +0 -585
  157. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts +0 -476
  158. package/src/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.ts +0 -20
  159. package/src/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.ts +0 -9
  160. package/src/legacy-runtime/runtime-cores/assistant-transport/utils.ts +0 -1
@@ -1,241 +0,0 @@
1
- import { useState, useMemo } from "react";
2
- import { resource, withKey, type ResourceElement } from "@assistant-ui/tap";
3
- import {
4
- type ClientOutput,
5
- useClientLookup,
6
- Derived,
7
- attachTransformScopes,
8
- useClientResource,
9
- } from "@assistant-ui/store";
10
-
11
- import { ModelContext, Suggestions } from "@assistant-ui/core/store";
12
- import { Tools, DataRenderers } from "@assistant-ui/core/react";
13
-
14
- const RESOLVED_PROMISE = Promise.resolve();
15
-
16
- export type InMemoryThreadListProps = {
17
- thread: (threadId: string) => ResourceElement<ClientOutput<"thread">>;
18
- onSwitchToThread?: (threadId: string) => void;
19
- onSwitchToNewThread?: () => void;
20
- };
21
-
22
- type ThreadData = {
23
- id: string;
24
- title?: string;
25
- status: "regular" | "archived";
26
- custom?: Record<string, unknown> | undefined;
27
- };
28
-
29
- // ThreadListItem Client
30
- const useThreadListItemClient = (props: {
31
- data: ThreadData;
32
- isRunning: boolean;
33
- onSwitchTo: () => void;
34
- onRename: (title: string) => void;
35
- onUpdateCustom: (custom: Record<string, unknown> | undefined) => void;
36
- onArchive: () => void;
37
- onUnarchive: () => void;
38
- onDelete: () => void;
39
- }): ClientOutput<"threadListItem"> => {
40
- const {
41
- data,
42
- isRunning,
43
- onSwitchTo,
44
- onRename,
45
- onUpdateCustom,
46
- onArchive,
47
- onUnarchive,
48
- onDelete,
49
- } = props;
50
- const state = useMemo(
51
- () => ({
52
- id: data.id,
53
- remoteId: undefined,
54
- externalId: undefined,
55
- title: data.title,
56
- status: data.status,
57
- custom: data.custom,
58
- isRunning,
59
- }),
60
- [data.id, data.title, data.status, data.custom, isRunning],
61
- );
62
-
63
- return {
64
- getState: () => state,
65
- switchTo: onSwitchTo,
66
- rename: onRename,
67
- updateCustom: onUpdateCustom,
68
- archive: onArchive,
69
- unarchive: onUnarchive,
70
- delete: onDelete,
71
- generateTitle: () => {},
72
- initialize: async () => ({ remoteId: data.id, externalId: undefined }),
73
- detach: () => {},
74
- };
75
- };
76
-
77
- const ThreadListItemClient = resource(useThreadListItemClient);
78
-
79
- // InMemoryThreadList Client
80
- const useInMemoryThreadList = (
81
- props: InMemoryThreadListProps,
82
- ): ClientOutput<"threads"> => {
83
- const {
84
- thread: threadFactory,
85
- onSwitchToThread,
86
- onSwitchToNewThread,
87
- } = props;
88
-
89
- const [mainThreadId, setMainThreadId] = useState("main");
90
- const [threads, setThreads] = useState<readonly ThreadData[]>(() => [
91
- { id: "main", title: "Main Thread", status: "regular" },
92
- ]);
93
-
94
- const handleSwitchToThread = (threadId: string) => {
95
- setMainThreadId(threadId);
96
- onSwitchToThread?.(threadId);
97
- };
98
-
99
- const handleRename = (threadId: string, title: string) => {
100
- setThreads((prev) =>
101
- prev.map((t) => (t.id === threadId ? { ...t, title } : t)),
102
- );
103
- };
104
-
105
- const handleArchive = (threadId: string) => {
106
- setThreads((prev) =>
107
- prev.map((t) =>
108
- t.id === threadId ? { ...t, status: "archived" as const } : t,
109
- ),
110
- );
111
- };
112
-
113
- const handleUnarchive = (threadId: string) => {
114
- setThreads((prev) =>
115
- prev.map((t) =>
116
- t.id === threadId ? { ...t, status: "regular" as const } : t,
117
- ),
118
- );
119
- };
120
-
121
- const handleUpdateCustom = (
122
- threadId: string,
123
- custom: Record<string, unknown> | undefined,
124
- ) => {
125
- setThreads((prev) =>
126
- prev.map((t) => (t.id === threadId ? { ...t, custom } : t)),
127
- );
128
- };
129
-
130
- const handleDelete = (threadId: string) => {
131
- setThreads((prev) => prev.filter((t) => t.id !== threadId));
132
- setMainThreadId((prev) =>
133
- prev === threadId
134
- ? threads.find((t) => t.id !== threadId)?.id || "main"
135
- : prev,
136
- );
137
- };
138
-
139
- const handleSwitchToNewThread = () => {
140
- const newId = `thread-${Date.now()}`;
141
- setThreads((prev) => [
142
- ...prev,
143
- { id: newId, title: "New Thread", status: "regular" },
144
- ]);
145
- setMainThreadId(newId);
146
- onSwitchToNewThread?.();
147
- };
148
-
149
- // Only the main thread is mounted, so it is the only thread that can run.
150
- const mainThreadClient = useClientResource(threadFactory(mainThreadId));
151
-
152
- const threadListItems = useClientLookup(
153
- threads.map((t) =>
154
- withKey(
155
- t.id,
156
- ThreadListItemClient({
157
- data: t,
158
- isRunning: t.id === mainThreadId && mainThreadClient.state.isRunning,
159
- onSwitchTo: () => handleSwitchToThread(t.id),
160
- onRename: (title) => handleRename(t.id, title),
161
- onUpdateCustom: (custom) => handleUpdateCustom(t.id, custom),
162
- onArchive: () => handleArchive(t.id),
163
- onUnarchive: () => handleUnarchive(t.id),
164
- onDelete: () => handleDelete(t.id),
165
- }),
166
- ),
167
- ),
168
- );
169
-
170
- const state = useMemo(() => {
171
- const regularThreads = threads.filter((t) => t.status === "regular");
172
- const archivedThreads = threads.filter((t) => t.status === "archived");
173
-
174
- return {
175
- mainThreadId,
176
- newThreadId: null,
177
- isLoading: false,
178
- isLoadingMore: false,
179
- hasMore: false,
180
- threadIds: regularThreads.map((t) => t.id),
181
- archivedThreadIds: archivedThreads.map((t) => t.id),
182
- threadItems: threadListItems.state,
183
- main: mainThreadClient.state,
184
- };
185
- }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);
186
-
187
- return {
188
- getState: () => state,
189
- switchToThread: handleSwitchToThread,
190
- switchToNewThread: handleSwitchToNewThread,
191
- getLoadThreadsPromise: () => RESOLVED_PROMISE,
192
- reload: () => RESOLVED_PROMISE,
193
- reloadMainThread: () => RESOLVED_PROMISE,
194
- loadMore: () => RESOLVED_PROMISE,
195
- item: (selector) => {
196
- if (selector === "main") {
197
- const index = threads.findIndex((t) => t.id === mainThreadId);
198
- return threadListItems.get({ index: index === -1 ? 0 : index });
199
- }
200
- if ("id" in selector) {
201
- const index = threads.findIndex((t) => t.id === selector.id);
202
- return threadListItems.get({ index });
203
- }
204
- return threadListItems.get(selector);
205
- },
206
- thread: () => mainThreadClient.methods,
207
- };
208
- };
209
-
210
- export const InMemoryThreadList = resource(useInMemoryThreadList);
211
-
212
- attachTransformScopes(useInMemoryThreadList, (scopes, parent) => {
213
- scopes.thread ??= Derived({
214
- source: "threads",
215
- query: { type: "main" },
216
- get: (aui) => aui.threads.thread("main"),
217
- });
218
- scopes.threadListItem ??= Derived({
219
- source: "threads",
220
- query: { type: "main" },
221
- get: (aui) => aui.threads.item("main"),
222
- });
223
- scopes.composer ??= Derived({
224
- source: "thread",
225
- query: {},
226
- get: (aui) => aui.threads.thread("main").composer(),
227
- });
228
-
229
- if (!scopes.modelContext && parent.modelContext.source === null) {
230
- scopes.modelContext = ModelContext();
231
- }
232
- if (!scopes.tools && parent.tools.source === null) {
233
- scopes.tools = Tools({});
234
- }
235
- if (!scopes.dataRenderers && parent.dataRenderers.source === null) {
236
- scopes.dataRenderers = DataRenderers();
237
- }
238
- if (!scopes.suggestions && parent.suggestions.source === null) {
239
- scopes.suggestions = Suggestions();
240
- }
241
- });
@@ -1,331 +0,0 @@
1
- import type {
2
- CompleteAttachment,
3
- MessageStatus,
4
- SourceProviderMetadata,
5
- ThreadMessage,
6
- ToolApprovalOption,
7
- } from "@assistant-ui/core";
8
- import { fromThreadMessageLike } from "../runtime-cores/external-store/ThreadMessageLike";
9
- import type { CloudMessage } from "assistant-cloud";
10
- import { isJSONValue } from "@assistant-ui/core/internal";
11
- import type {
12
- ReadonlyJSONObject,
13
- ReadonlyJSONValue,
14
- } from "assistant-stream/utils";
15
- import type { ExportedMessageRepositoryItem } from "../runtime-cores/utils/MessageRepository";
16
-
17
- type AuiV0ToolApproval = {
18
- readonly id: string;
19
- readonly approved?: boolean;
20
- readonly reason?: string;
21
- readonly isAutomatic?: boolean;
22
- readonly options?: readonly ToolApprovalOption[];
23
- readonly optionId?: string;
24
- readonly resolution?: "cancelled" | "expired";
25
- };
26
-
27
- type AuiV0MessagePart =
28
- | {
29
- readonly type: "text";
30
- readonly text: string;
31
- }
32
- | {
33
- readonly type: "reasoning";
34
- readonly text: string;
35
- readonly unstable_summary?: string;
36
- }
37
- | {
38
- readonly type: "source";
39
- readonly sourceType: "url";
40
- readonly id: string;
41
- readonly url: string;
42
- readonly title?: string;
43
- readonly providerMetadata?: SourceProviderMetadata;
44
- }
45
- | {
46
- readonly type: "source";
47
- readonly sourceType: "document";
48
- readonly id: string;
49
- readonly title: string;
50
- readonly mediaType: string;
51
- readonly filename?: string;
52
- readonly providerMetadata?: SourceProviderMetadata;
53
- }
54
- | {
55
- readonly type: "tool-call";
56
- readonly toolCallId: string;
57
- readonly toolName: string;
58
- readonly args: ReadonlyJSONObject;
59
- readonly result?: ReadonlyJSONValue;
60
- readonly isError?: true;
61
- readonly approval?: AuiV0ToolApproval;
62
- }
63
- | {
64
- readonly type: "tool-call";
65
- readonly toolCallId: string;
66
- readonly toolName: string;
67
- readonly argsText: string;
68
- readonly result?: ReadonlyJSONValue;
69
- readonly isError?: true;
70
- readonly approval?: AuiV0ToolApproval;
71
- }
72
- | {
73
- readonly type: "image";
74
- readonly image: string;
75
- }
76
- | {
77
- readonly type: "file";
78
- readonly data: string;
79
- readonly mimeType: string;
80
- readonly filename?: string;
81
- readonly sourceType?: "url" | "id";
82
- };
83
-
84
- type AuiV0AttachmentPart =
85
- | {
86
- readonly type: "text";
87
- readonly text: string;
88
- }
89
- | {
90
- readonly type: "image";
91
- readonly image: string;
92
- readonly filename?: string;
93
- }
94
- | {
95
- readonly type: "file";
96
- readonly data: string;
97
- readonly mimeType: string;
98
- readonly filename?: string;
99
- readonly sourceType?: "url" | "id";
100
- }
101
- | {
102
- readonly type: "audio";
103
- readonly audio: {
104
- readonly data: string;
105
- readonly format: "mp3" | "wav";
106
- };
107
- }
108
- | {
109
- readonly type: "data";
110
- readonly name: string;
111
- readonly data: ReadonlyJSONValue;
112
- };
113
-
114
- type AuiV0Attachment = {
115
- readonly id: string;
116
- readonly type: CompleteAttachment["type"];
117
- readonly name: string;
118
- readonly contentType?: string;
119
- readonly status: CompleteAttachment["status"];
120
- readonly content: readonly AuiV0AttachmentPart[];
121
- };
122
-
123
- type AuiV0Message = {
124
- readonly role: "assistant" | "user" | "system";
125
- readonly status?: MessageStatus;
126
- readonly content: readonly AuiV0MessagePart[];
127
- readonly attachments?: readonly AuiV0Attachment[];
128
- readonly metadata: {
129
- readonly unstable_state?: ReadonlyJSONValue;
130
- readonly unstable_annotations: readonly ReadonlyJSONValue[];
131
- readonly unstable_data: readonly ReadonlyJSONValue[];
132
- readonly steps: readonly {
133
- readonly usage?: {
134
- readonly inputTokens: number;
135
- readonly outputTokens: number;
136
- };
137
- }[];
138
- readonly custom: ReadonlyJSONObject;
139
- };
140
- };
141
-
142
- const encodeAttachmentPart = (
143
- part: CompleteAttachment["content"][number],
144
- ): AuiV0AttachmentPart => {
145
- const type = part.type;
146
- switch (type) {
147
- case "text":
148
- return { type: "text", text: part.text };
149
-
150
- case "image":
151
- return {
152
- type: "image",
153
- image: part.image,
154
- ...(part.filename != null ? { filename: part.filename } : undefined),
155
- };
156
-
157
- case "file":
158
- return {
159
- type: "file",
160
- data: part.data,
161
- mimeType: part.mimeType,
162
- ...(part.filename != null ? { filename: part.filename } : undefined),
163
- ...(part.sourceType != null
164
- ? { sourceType: part.sourceType }
165
- : undefined),
166
- };
167
-
168
- case "audio":
169
- return {
170
- type: "audio",
171
- audio: { data: part.audio.data, format: part.audio.format },
172
- };
173
-
174
- case "data": {
175
- if (!isJSONValue(part.data)) {
176
- console.warn(`attachment data is not JSON! ${JSON.stringify(part)}`);
177
- }
178
- return {
179
- type: "data",
180
- name: part.name,
181
- data: part.data as ReadonlyJSONValue,
182
- };
183
- }
184
-
185
- default: {
186
- const unhandledType: never = type;
187
- throw new Error(
188
- `Attachment part type not supported by aui/v0: ${unhandledType}`,
189
- );
190
- }
191
- }
192
- };
193
-
194
- const encodeAttachments = (
195
- message: ThreadMessage,
196
- ): readonly AuiV0Attachment[] | undefined => {
197
- if (message.role !== "user" || message.attachments.length === 0) {
198
- return undefined;
199
- }
200
-
201
- return message.attachments.map(
202
- ({ id, type, name, contentType, status, content }) => ({
203
- id,
204
- type,
205
- name,
206
- status,
207
- ...(contentType != null ? { contentType } : undefined),
208
- content: content.map(encodeAttachmentPart),
209
- }),
210
- );
211
- };
212
-
213
- export function auiV0Encode(message: ThreadMessage): AuiV0Message {
214
- // info: ID and createdAt are ignored (we use the server value instead)
215
- const status: MessageStatus | undefined =
216
- message.status?.type === "running"
217
- ? { type: "incomplete", reason: "cancelled" }
218
- : message.status;
219
- const attachments = encodeAttachments(message);
220
-
221
- return {
222
- role: message.role,
223
- content: message.content.map((part) => {
224
- const type = part.type;
225
- switch (type) {
226
- case "text":
227
- return { type: "text", text: part.text };
228
-
229
- case "reasoning":
230
- return {
231
- type: "reasoning",
232
- text: part.text,
233
- ...(part.unstable_summary !== undefined
234
- ? { unstable_summary: part.unstable_summary }
235
- : undefined),
236
- };
237
-
238
- case "source":
239
- if (part.sourceType === "url") {
240
- return {
241
- type: "source",
242
- sourceType: "url",
243
- id: part.id,
244
- url: part.url,
245
- ...(part.title != null ? { title: part.title } : undefined),
246
- ...(part.providerMetadata != null
247
- ? { providerMetadata: part.providerMetadata }
248
- : undefined),
249
- };
250
- }
251
-
252
- return {
253
- type: "source",
254
- sourceType: "document",
255
- id: part.id,
256
- title: part.title,
257
- mediaType: part.mediaType,
258
- ...(part.filename != null
259
- ? { filename: part.filename }
260
- : undefined),
261
- ...(part.providerMetadata != null
262
- ? { providerMetadata: part.providerMetadata }
263
- : undefined),
264
- };
265
-
266
- case "tool-call": {
267
- if (part.result !== undefined && !isJSONValue(part.result)) {
268
- console.warn(
269
- `tool-call result is not JSON! ${JSON.stringify(part)}`,
270
- );
271
- }
272
- return {
273
- type: "tool-call",
274
- toolCallId: part.toolCallId,
275
- toolName: part.toolName,
276
- ...(JSON.stringify(part.args) === part.argsText
277
- ? { args: part.args }
278
- : { argsText: part.argsText }),
279
- ...(part.result !== undefined
280
- ? { result: part.result as ReadonlyJSONValue }
281
- : undefined),
282
- ...(part.isError ? { isError: true } : undefined),
283
- ...(part.approval ? { approval: part.approval } : undefined),
284
- };
285
- }
286
-
287
- case "image":
288
- return { type: "image", image: part.image };
289
-
290
- case "file":
291
- return {
292
- type: "file",
293
- data: part.data,
294
- mimeType: part.mimeType,
295
- ...(part.filename ? { filename: part.filename } : undefined),
296
- ...(part.sourceType ? { sourceType: part.sourceType } : undefined),
297
- };
298
-
299
- default: {
300
- const unhandledType: "audio" | "data" | "generative-ui" = type;
301
- throw new Error(
302
- `Message part type not supported by aui/v0: ${unhandledType}`,
303
- );
304
- }
305
- }
306
- }),
307
- metadata: message.metadata as AuiV0Message["metadata"],
308
- ...(status ? { status } : undefined),
309
- ...(attachments ? { attachments } : undefined),
310
- };
311
- }
312
-
313
- export function auiV0Decode(
314
- cloudMessage: CloudMessage & { format: "aui/v0" },
315
- ): ExportedMessageRepositoryItem {
316
- const payload = cloudMessage.content as unknown as AuiV0Message;
317
- const message = fromThreadMessageLike(
318
- {
319
- id: cloudMessage.id,
320
- createdAt: cloudMessage.created_at,
321
- ...payload,
322
- },
323
- cloudMessage.id,
324
- { type: "complete", reason: "unknown" },
325
- );
326
-
327
- return {
328
- parentId: cloudMessage.parent_id,
329
- message,
330
- };
331
- }
@@ -1,31 +0,0 @@
1
- "use client";
2
-
3
- import type { AssistantCloud } from "assistant-cloud";
4
- import type { AssistantRuntime } from "@assistant-ui/core";
5
- import { useRemoteThreadListRuntime } from "../runtime-cores/remote-thread-list/useRemoteThreadListRuntime";
6
- import { useCloudThreadListAdapter } from "../runtime-cores/remote-thread-list/adapter/cloud";
7
-
8
- type ThreadData = {
9
- externalId: string;
10
- };
11
-
12
- type CloudThreadListAdapter = {
13
- cloud: AssistantCloud;
14
-
15
- runtimeHook: () => AssistantRuntime;
16
-
17
- create?(): Promise<ThreadData>;
18
- delete?(threadId: string): Promise<void>;
19
- };
20
-
21
- export function useCloudThreadListRuntime({
22
- runtimeHook,
23
- ...adapterOptions
24
- }: CloudThreadListAdapter) {
25
- const adapter = useCloudThreadListAdapter(adapterOptions);
26
- return useRemoteThreadListRuntime({
27
- runtimeHook,
28
- adapter,
29
- allowNesting: true,
30
- });
31
- }
@@ -1,68 +0,0 @@
1
- import { useState, useCallback, useRef, useEffect } from "react";
2
- import type {
3
- AssistantTransportCommand,
4
- CommandQueueState,
5
- QueuedCommand,
6
- } from "./types";
7
-
8
- export const createInitialQueueState = (): CommandQueueState => ({
9
- queued: [],
10
- inTransit: [],
11
- });
12
-
13
- export const useCommandQueue = (opts: { onQueue: () => void }) => {
14
- const onQueueRef = useRef(opts.onQueue);
15
- useEffect(() => {
16
- onQueueRef.current = opts.onQueue;
17
- });
18
-
19
- const [, rerender] = useState(0);
20
- const queueStateRef = useRef<CommandQueueState>(createInitialQueueState());
21
-
22
- const enqueue = (
23
- command: AssistantTransportCommand,
24
- options?: { schedule?: boolean },
25
- ) => {
26
- queueStateRef.current = {
27
- queued: [...queueStateRef.current.queued, command],
28
- inTransit: queueStateRef.current.inTransit,
29
- };
30
- rerender((prev) => prev + 1);
31
-
32
- if (options?.schedule !== false) onQueueRef.current();
33
- };
34
-
35
- const flush = (): QueuedCommand[] => {
36
- if (queueStateRef.current.queued.length === 0) return [];
37
-
38
- const queued = queueStateRef.current.queued;
39
- queueStateRef.current = {
40
- queued: [],
41
- inTransit: [...queueStateRef.current.inTransit, ...queued],
42
- };
43
- rerender((prev) => prev + 1);
44
-
45
- return queued;
46
- };
47
-
48
- const markDelivered = () => {
49
- queueStateRef.current = { ...queueStateRef.current, inTransit: [] };
50
- rerender((prev) => prev + 1);
51
- };
52
-
53
- const reset = useCallback(() => {
54
- queueStateRef.current = createInitialQueueState();
55
- rerender((prev) => prev + 1);
56
- }, []);
57
-
58
- return {
59
- // live getter — callbacks firing between renders must not see a stale snapshot
60
- get state() {
61
- return queueStateRef.current;
62
- },
63
- enqueue,
64
- flush,
65
- markDelivered,
66
- reset,
67
- };
68
- };