@assistant-ui/react 0.12.3 → 0.12.5

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 (33) 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 +7 -1
  23. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  24. package/dist/primitives/message/MessagePartsGrouped.js +1 -1
  25. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  26. package/package.json +8 -8
  27. package/src/client/ExternalThread.ts +491 -0
  28. package/src/client/InMemoryThreadList.ts +197 -0
  29. package/src/client/index.ts +12 -0
  30. package/src/devtools/index.ts +1 -1
  31. package/src/index.ts +1 -0
  32. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +7 -1
  33. 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,11 @@ 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 (process.env["NODE_ENV"] === "production") return;
36
+ return DevToolsProviderApi.register(aui);
37
+ }, [aui]);
38
+
33
39
  const RenderComponent = getRenderComponent(runtime);
34
40
 
35
41
  return (
@@ -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} />;