@assistant-ui/react 0.12.3 → 0.12.6

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 (66) hide show
  1. package/dist/client/ExternalThread.d.ts +16 -0
  2. package/dist/client/ExternalThread.d.ts.map +1 -0
  3. package/dist/client/ExternalThread.js +329 -0
  4. package/dist/client/ExternalThread.js.map +1 -0
  5. package/dist/client/InMemoryThreadList.d.ts +9 -0
  6. package/dist/client/InMemoryThreadList.d.ts.map +1 -0
  7. package/dist/client/InMemoryThreadList.js +129 -0
  8. package/dist/client/InMemoryThreadList.js.map +1 -0
  9. package/dist/client/index.d.ts +6 -0
  10. package/dist/client/index.d.ts.map +1 -0
  11. package/dist/client/index.js +6 -0
  12. package/dist/client/index.js.map +1 -0
  13. package/dist/devtools/index.d.ts +1 -1
  14. package/dist/devtools/index.d.ts.map +1 -1
  15. package/dist/devtools/index.js +1 -1
  16. package/dist/devtools/index.js.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  22. package/dist/legacy-runtime/AssistantRuntimeProvider.js +8 -1
  23. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  24. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +19 -0
  25. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +1 -1
  26. package/dist/legacy-runtime/runtime/ThreadRuntime.js +8 -0
  27. package/dist/legacy-runtime/runtime/ThreadRuntime.js.map +1 -1
  28. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts +2 -0
  29. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts.map +1 -1
  30. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.js.map +1 -1
  31. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts +17 -0
  32. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts.map +1 -1
  33. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts +1 -0
  34. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts.map +1 -1
  35. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts +2 -0
  36. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts.map +1 -1
  37. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.js +10 -2
  38. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.js.map +1 -1
  39. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts +2 -0
  40. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts.map +1 -1
  41. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js +6 -0
  42. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js.map +1 -1
  43. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +1 -1
  44. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js +6 -0
  45. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js.map +1 -1
  46. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +4 -0
  47. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  48. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +4 -0
  49. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  50. package/dist/primitives/message/MessagePartsGrouped.js +1 -1
  51. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  52. package/package.json +8 -8
  53. package/src/client/ExternalThread.ts +491 -0
  54. package/src/client/InMemoryThreadList.ts +197 -0
  55. package/src/client/index.ts +12 -0
  56. package/src/devtools/index.ts +1 -1
  57. package/src/index.ts +1 -0
  58. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +11 -1
  59. package/src/legacy-runtime/runtime/ThreadRuntime.ts +27 -0
  60. package/src/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.tsx +2 -0
  61. package/src/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.tsx +20 -0
  62. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.tsx +1 -0
  63. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.tsx +13 -2
  64. package/src/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.tsx +8 -0
  65. package/src/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.tsx +8 -0
  66. package/src/primitives/message/MessagePartsGrouped.tsx +1 -1
@@ -0,0 +1,197 @@
1
+ import { resource, tapState, tapMemo } from "@assistant-ui/tap";
2
+ import {
3
+ type ClientOutput,
4
+ tapClientLookup,
5
+ Derived,
6
+ attachDefaultPeers,
7
+ tapClientResource,
8
+ } from "@assistant-ui/store";
9
+ import { withKey } from "@assistant-ui/tap";
10
+ import type { ResourceElement } from "@assistant-ui/tap";
11
+ import type { ThreadState } from "../types/scopes/thread";
12
+ import { Suggestions } from "./Suggestions";
13
+ import { ModelContext } from "./ModelContextClient";
14
+ import { Tools } from "./Tools";
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
+ };
27
+
28
+ // ThreadListItem Client
29
+ const ThreadListItemClient = resource(
30
+ (props: {
31
+ data: ThreadData;
32
+ onSwitchTo: () => void;
33
+ onArchive: () => void;
34
+ onUnarchive: () => void;
35
+ onDelete: () => void;
36
+ }): ClientOutput<"threadListItem"> => {
37
+ const { data, onSwitchTo, onArchive, onUnarchive, onDelete } = props;
38
+ const state = tapMemo(
39
+ () => ({
40
+ id: data.id,
41
+ remoteId: undefined,
42
+ externalId: undefined,
43
+ title: data.title,
44
+ status: data.status,
45
+ }),
46
+ [data.id, data.title, data.status],
47
+ );
48
+
49
+ return {
50
+ state,
51
+ methods: {
52
+ getState: () => state,
53
+ switchTo: onSwitchTo,
54
+ rename: () => {},
55
+ archive: onArchive,
56
+ unarchive: onUnarchive,
57
+ delete: onDelete,
58
+ generateTitle: () => {},
59
+ initialize: async () => ({ remoteId: data.id, externalId: undefined }),
60
+ detach: () => {},
61
+ },
62
+ };
63
+ },
64
+ );
65
+
66
+ // InMemoryThreadList Client
67
+ export const InMemoryThreadList = resource(
68
+ (props: InMemoryThreadListProps): ClientOutput<"threads"> => {
69
+ const {
70
+ thread: threadFactory,
71
+ onSwitchToThread,
72
+ onSwitchToNewThread,
73
+ } = props;
74
+
75
+ const [mainThreadId, setMainThreadId] = tapState("main");
76
+ const [threads, setThreads] = tapState<readonly ThreadData[]>(() => [
77
+ { id: "main", title: "Main Thread", status: "regular" },
78
+ ]);
79
+
80
+ const handleSwitchToThread = (threadId: string) => {
81
+ setMainThreadId(threadId);
82
+ onSwitchToThread?.(threadId);
83
+ };
84
+
85
+ const handleArchive = (threadId: string) => {
86
+ setThreads((prev) =>
87
+ prev.map((t) =>
88
+ t.id === threadId ? { ...t, status: "archived" as const } : t,
89
+ ),
90
+ );
91
+ };
92
+
93
+ const handleUnarchive = (threadId: string) => {
94
+ setThreads((prev) =>
95
+ prev.map((t) =>
96
+ t.id === threadId ? { ...t, status: "regular" as const } : t,
97
+ ),
98
+ );
99
+ };
100
+
101
+ const handleDelete = (threadId: string) => {
102
+ setThreads((prev) => prev.filter((t) => t.id !== threadId));
103
+ if (mainThreadId === threadId) {
104
+ const remaining = threads.filter((t) => t.id !== threadId);
105
+ setMainThreadId(remaining[0]?.id || "main");
106
+ }
107
+ };
108
+
109
+ const handleSwitchToNewThread = () => {
110
+ const newId = `thread-${Date.now()}`;
111
+ setThreads((prev) => [
112
+ ...prev,
113
+ { id: newId, title: "New Thread", status: "regular" },
114
+ ]);
115
+ setMainThreadId(newId);
116
+ onSwitchToNewThread?.();
117
+ };
118
+
119
+ const threadListItems = tapClientLookup(
120
+ () =>
121
+ threads.map((t) =>
122
+ withKey(
123
+ t.id,
124
+ ThreadListItemClient({
125
+ data: t,
126
+ onSwitchTo: () => handleSwitchToThread(t.id),
127
+ onArchive: () => handleArchive(t.id),
128
+ onUnarchive: () => handleUnarchive(t.id),
129
+ onDelete: () => handleDelete(t.id),
130
+ }),
131
+ ),
132
+ ),
133
+ [threads],
134
+ );
135
+
136
+ // Create the main thread
137
+ const mainThreadClient = tapClientResource(threadFactory(mainThreadId));
138
+
139
+ const state = tapMemo(() => {
140
+ const regularThreads = threads.filter((t) => t.status === "regular");
141
+ const archivedThreads = threads.filter((t) => t.status === "archived");
142
+ const mainThreadState = mainThreadClient.state as ThreadState;
143
+
144
+ return {
145
+ mainThreadId,
146
+ newThreadId: null,
147
+ isLoading: false,
148
+ threadIds: regularThreads.map((t) => t.id),
149
+ archivedThreadIds: archivedThreads.map((t) => t.id),
150
+ threadItems: threadListItems.state,
151
+ main: mainThreadState,
152
+ };
153
+ }, [mainThreadId, threads, threadListItems.state, mainThreadClient.state]);
154
+
155
+ return {
156
+ state,
157
+ methods: {
158
+ getState: () => state,
159
+ switchToThread: handleSwitchToThread,
160
+ switchToNewThread: handleSwitchToNewThread,
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,
173
+ },
174
+ };
175
+ },
176
+ );
177
+
178
+ attachDefaultPeers(InMemoryThreadList, {
179
+ thread: Derived({
180
+ source: "threads",
181
+ query: { type: "main" },
182
+ get: (aui) => aui.threads().thread("main"),
183
+ }),
184
+ threadListItem: Derived({
185
+ source: "threads",
186
+ query: { type: "main" },
187
+ get: (aui) => aui.threads().item("main"),
188
+ }),
189
+ composer: Derived({
190
+ source: "thread",
191
+ query: {},
192
+ get: (aui) => aui.threads().thread("main").composer,
193
+ }),
194
+ modelContext: ModelContext(),
195
+ tools: Tools({}),
196
+ suggestions: Suggestions(),
197
+ });
@@ -0,0 +1,12 @@
1
+ export { ModelContext as ModelContextClient } from "./ModelContextClient";
2
+ export { Tools } from "./Tools";
3
+ export { Suggestions, type SuggestionConfig } from "./Suggestions";
4
+ export {
5
+ ExternalThread,
6
+ type ExternalThreadProps,
7
+ type ExternalThreadMessage,
8
+ } from "./ExternalThread";
9
+ export {
10
+ InMemoryThreadList,
11
+ type InMemoryThreadListProps,
12
+ } from "./InMemoryThreadList";
@@ -1 +1 @@
1
- export { DevToolsHooks } from "./DevToolsHooks";
1
+ export { DevToolsHooks, DevToolsProviderApi } from "./DevToolsHooks";
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ export * from "./model-context";
25
25
  export * from "./primitives";
26
26
  export * from "./types";
27
27
  export * from "./devtools";
28
+ export * from "./client";
28
29
 
29
30
  export * as INTERNAL from "./internal";
30
31
  export type { ToolExecutionStatus } from "./internal";
@@ -1,11 +1,12 @@
1
1
  "use client";
2
2
 
3
- import { FC, memo, PropsWithChildren } from "react";
3
+ import { FC, memo, PropsWithChildren, useEffect } from "react";
4
4
  import { useAui, AuiProvider, AssistantClient } from "@assistant-ui/store";
5
5
  import { AssistantRuntime } from "./runtime/AssistantRuntime";
6
6
  import { AssistantRuntimeCore } from "./runtime-cores/core/AssistantRuntimeCore";
7
7
  import { RuntimeAdapter } from "./RuntimeAdapter";
8
8
  import { ThreadPrimitiveViewportProvider } from "../context/providers/ThreadViewportProvider";
9
+ import { DevToolsProviderApi } from "../devtools";
9
10
 
10
11
  export namespace AssistantRuntimeProvider {
11
12
  export type Props = PropsWithChildren<{
@@ -30,6 +31,15 @@ export const AssistantRuntimeProviderImpl: FC<
30
31
  > = ({ children, aui: parent = null, runtime }) => {
31
32
  const aui = useAui({ threads: RuntimeAdapter(runtime) }, { parent: parent });
32
33
 
34
+ useEffect(() => {
35
+ if (
36
+ typeof process === "undefined" ||
37
+ process.env["NODE_ENV"] === "production"
38
+ )
39
+ return;
40
+ return DevToolsProviderApi.register(aui);
41
+ }, [aui]);
42
+
33
43
  const RenderComponent = getRenderComponent(runtime);
34
44
 
35
45
  return (
@@ -256,8 +256,25 @@ export type ThreadRuntime = {
256
256
  **/
257
257
  unstable_resumeRun(config: CreateResumeRunConfig): void;
258
258
 
259
+ /**
260
+ * Export the thread state in the external store format.
261
+ * For AI SDK runtimes, this returns the AI SDK message format.
262
+ * For other runtimes, this may return different formats or throw an error.
263
+ * @returns The thread state in the external format (typed as any)
264
+ */
265
+ exportExternalState(): any;
266
+
267
+ /**
268
+ * Import thread state from the external store format.
269
+ * For AI SDK runtimes, this accepts AI SDK messages.
270
+ * For other runtimes, this may accept different formats or throw an error.
271
+ * @param state The thread state in the external format (typed as any)
272
+ */
273
+ importExternalState(state: any): void;
274
+
259
275
  /**
260
276
  * Load external state into the thread.
277
+ * @deprecated Use importExternalState instead. This method will be removed in 0.12.0.
261
278
  * @param state The state to load into the thread
262
279
  */
263
280
  unstable_loadExternalState(state: any): void;
@@ -354,6 +371,8 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
354
371
  this.unstable_resumeRun = this.unstable_resumeRun.bind(this);
355
372
  this.unstable_loadExternalState =
356
373
  this.unstable_loadExternalState.bind(this);
374
+ this.importExternalState = this.importExternalState.bind(this);
375
+ this.exportExternalState = this.exportExternalState.bind(this);
357
376
  this.startRun = this.startRun.bind(this);
358
377
  this.cancelRun = this.cancelRun.bind(this);
359
378
  this.stopSpeaking = this.stopSpeaking.bind(this);
@@ -407,6 +426,14 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
407
426
  return this._threadBinding.getState().resumeRun(toResumeRunConfig(config));
408
427
  }
409
428
 
429
+ public exportExternalState() {
430
+ return this._threadBinding.getState().exportExternalState();
431
+ }
432
+
433
+ public importExternalState(state: any) {
434
+ this._threadBinding.getState().importExternalState(state);
435
+ }
436
+
410
437
  public unstable_loadExternalState(state: any) {
411
438
  this._threadBinding.getState().unstable_loadExternalState(state);
412
439
  }
@@ -48,6 +48,8 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
48
48
  public abstract addToolResult(options: AddToolResultOptions): void;
49
49
  public abstract resumeToolCall(options: ResumeToolCallOptions): void;
50
50
  public abstract cancelRun(): void;
51
+ public abstract exportExternalState(): any;
52
+ public abstract importExternalState(state: any): void;
51
53
  public abstract unstable_loadExternalState(state: any): void;
52
54
 
53
55
  public get messages() {
@@ -127,8 +127,28 @@ export type ThreadRuntimeCore = Readonly<{
127
127
  import(repository: ExportedMessageRepository): void;
128
128
  export(): ExportedMessageRepository;
129
129
 
130
+ /**
131
+ * Export the thread state in the external store format.
132
+ * For AI SDK runtimes, this returns the AI SDK message format.
133
+ * For other runtimes, this may return different formats or throw an error.
134
+ * @returns The thread state in the external format (typed as any)
135
+ */
136
+ exportExternalState(): any;
137
+
138
+ /**
139
+ * Import thread state from the external store format.
140
+ * For AI SDK runtimes, this accepts AI SDK messages.
141
+ * For other runtimes, this may accept different formats or throw an error.
142
+ * @param state The thread state in the external format (typed as any)
143
+ */
144
+ importExternalState(state: any): void;
145
+
130
146
  reset(initialMessages?: readonly ThreadMessageLike[]): void;
131
147
 
132
148
  unstable_on(event: ThreadRuntimeEventType, callback: () => void): Unsubscribe;
149
+
150
+ /**
151
+ * @deprecated Use importExternalState instead. This method will be removed in 0.12.0.
152
+ */
133
153
  unstable_loadExternalState: (state: any) => void;
134
154
  }>;
@@ -69,6 +69,7 @@ type ExternalStoreAdapterBase<T> = {
69
69
 
70
70
  setMessages?: ((messages: readonly T[]) => void) | undefined;
71
71
  onImport?: ((messages: readonly ThreadMessage[]) => void) | undefined;
72
+ onExportExternalState?: (() => any) | undefined;
72
73
  onLoadExternalState?: ((state: any) => void) | undefined;
73
74
  onNew: (message: AppendMessage) => Promise<void>;
74
75
  onEdit?: ((message: AppendMessage) => Promise<void>) | undefined;
@@ -275,13 +275,24 @@ export class ExternalStoreThreadRuntimeCore
275
275
  await this._store.onResume(config);
276
276
  }
277
277
 
278
- public unstable_loadExternalState(state: any): void {
278
+ public exportExternalState(): any {
279
+ if (!this._store.onExportExternalState)
280
+ throw new Error("Runtime does not support exporting external states.");
281
+
282
+ return this._store.onExportExternalState();
283
+ }
284
+
285
+ public importExternalState(state: any): void {
279
286
  if (!this._store.onLoadExternalState)
280
- throw new Error("Runtime does not support importing states.");
287
+ throw new Error("Runtime does not support importing external states.");
281
288
 
282
289
  this._store.onLoadExternalState(state);
283
290
  }
284
291
 
292
+ public unstable_loadExternalState(state: any): void {
293
+ this.importExternalState(state);
294
+ }
295
+
285
296
  public cancelRun(): void {
286
297
  if (!this._store.onCancel)
287
298
  throw new Error("Runtime does not support cancelling runs.");
@@ -203,6 +203,14 @@ export class LocalThreadRuntimeCore
203
203
  return this.startRun(startConfig, stream);
204
204
  }
205
205
 
206
+ public exportExternalState(): any {
207
+ throw new Error("Runtime does not support exporting external states.");
208
+ }
209
+
210
+ public importExternalState(): void {
211
+ throw new Error("Runtime does not support importing external states.");
212
+ }
213
+
206
214
  public unstable_loadExternalState(): void {
207
215
  throw new Error("Runtime does not support importing external states.");
208
216
  }
@@ -56,6 +56,14 @@ export const EMPTY_THREAD_CORE: ThreadRuntimeCore = {
56
56
  return {};
57
57
  },
58
58
 
59
+ exportExternalState() {
60
+ throw EMPTY_THREAD_ERROR;
61
+ },
62
+
63
+ importExternalState() {
64
+ throw EMPTY_THREAD_ERROR;
65
+ },
66
+
59
67
  unstable_loadExternalState() {
60
68
  throw EMPTY_THREAD_ERROR;
61
69
  },
@@ -265,7 +265,7 @@ const MessagePartComponent: FC<MessagePartComponentProps> = ({
265
265
 
266
266
  const type = part.type;
267
267
  if (type === "tool-call") {
268
- const addResult = (result: any) => aui.part().addToolResult(result);
268
+ const addResult = aui.part().addToolResult;
269
269
  const resume = aui.part().resumeToolCall;
270
270
  if ("Override" in tools)
271
271
  return <tools.Override {...part} addResult={addResult} resume={resume} />;