@assistant-ui/react 0.0.19 → 0.0.21
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.
- package/dist/index.d.mts +193 -105
- package/dist/index.d.ts +193 -105
- package/dist/index.js +954 -899
- package/dist/index.mjs +927 -889
- package/package.json +8 -7
package/dist/index.mjs
CHANGED
@@ -4,6 +4,156 @@ var __export = (target, all) => {
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
5
5
|
};
|
6
6
|
|
7
|
+
// src/actions/useCopyMessage.tsx
|
8
|
+
import { useCallback } from "react";
|
9
|
+
|
10
|
+
// src/context/MessageContext.ts
|
11
|
+
import { createContext, useContext } from "react";
|
12
|
+
var MessageContext = createContext(null);
|
13
|
+
var useMessageContext = () => {
|
14
|
+
const context = useContext(MessageContext);
|
15
|
+
if (!context)
|
16
|
+
throw new Error(
|
17
|
+
"This component can only be used inside a component passed to <ThreadPrimitive.Messages components={...} />."
|
18
|
+
);
|
19
|
+
return context;
|
20
|
+
};
|
21
|
+
|
22
|
+
// src/utils/combined/useCombinedStore.ts
|
23
|
+
import { useMemo } from "react";
|
24
|
+
|
25
|
+
// src/utils/combined/createCombinedStore.ts
|
26
|
+
import { useSyncExternalStore } from "react";
|
27
|
+
var createCombinedStore = (stores) => {
|
28
|
+
const subscribe = (callback) => {
|
29
|
+
const unsubscribes = stores.map((store) => store.subscribe(callback));
|
30
|
+
return () => {
|
31
|
+
for (const unsub of unsubscribes) {
|
32
|
+
unsub();
|
33
|
+
}
|
34
|
+
};
|
35
|
+
};
|
36
|
+
return (selector) => {
|
37
|
+
const getSnapshot = () => selector(...stores.map((store) => store.getState()));
|
38
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
39
|
+
};
|
40
|
+
};
|
41
|
+
|
42
|
+
// src/utils/combined/useCombinedStore.ts
|
43
|
+
var useCombinedStore = (stores, selector) => {
|
44
|
+
const useCombined = useMemo(() => createCombinedStore(stores), stores);
|
45
|
+
return useCombined(selector);
|
46
|
+
};
|
47
|
+
|
48
|
+
// src/utils/getMessageText.tsx
|
49
|
+
var getMessageText = (message) => {
|
50
|
+
const textParts = message.content.filter(
|
51
|
+
(part) => part.type === "text"
|
52
|
+
);
|
53
|
+
return textParts.map((part) => part.text).join("\n\n");
|
54
|
+
};
|
55
|
+
|
56
|
+
// src/actions/useCopyMessage.tsx
|
57
|
+
var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
58
|
+
const { useMessage, useComposer } = useMessageContext();
|
59
|
+
const hasCopyableContent = useCombinedStore(
|
60
|
+
[useMessage, useComposer],
|
61
|
+
(m, c) => {
|
62
|
+
return c.isEditing || m.message.content.some((c2) => c2.type === "text");
|
63
|
+
}
|
64
|
+
);
|
65
|
+
const callback = useCallback(() => {
|
66
|
+
const { isEditing, value: composerValue } = useComposer.getState();
|
67
|
+
const { message, setIsCopied } = useMessage.getState();
|
68
|
+
const valueToCopy = isEditing ? composerValue : getMessageText(message);
|
69
|
+
navigator.clipboard.writeText(valueToCopy);
|
70
|
+
setIsCopied(true);
|
71
|
+
setTimeout(() => setIsCopied(false), copiedDuration);
|
72
|
+
}, [useComposer, useMessage, copiedDuration]);
|
73
|
+
if (!hasCopyableContent) return null;
|
74
|
+
return callback;
|
75
|
+
};
|
76
|
+
|
77
|
+
// src/actions/useReloadMessage.tsx
|
78
|
+
import { useCallback as useCallback2 } from "react";
|
79
|
+
|
80
|
+
// src/context/ThreadContext.ts
|
81
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
82
|
+
var ThreadContext = createContext2(null);
|
83
|
+
var useThreadContext = () => {
|
84
|
+
const context = useContext2(ThreadContext);
|
85
|
+
if (!context)
|
86
|
+
throw new Error("This component must be used within an AssistantProvider.");
|
87
|
+
return context;
|
88
|
+
};
|
89
|
+
|
90
|
+
// src/actions/useReloadMessage.tsx
|
91
|
+
var useReloadMessage = () => {
|
92
|
+
const { useThread, useViewport } = useThreadContext();
|
93
|
+
const { useMessage } = useMessageContext();
|
94
|
+
const disabled = useCombinedStore(
|
95
|
+
[useThread, useMessage],
|
96
|
+
(t, m) => t.isRunning || m.message.role !== "assistant"
|
97
|
+
);
|
98
|
+
const callback = useCallback2(() => {
|
99
|
+
const { parentId } = useMessage.getState();
|
100
|
+
useThread.getState().startRun(parentId);
|
101
|
+
useViewport.getState().scrollToBottom();
|
102
|
+
}, [useMessage, useThread, useViewport]);
|
103
|
+
if (disabled) return null;
|
104
|
+
return callback;
|
105
|
+
};
|
106
|
+
|
107
|
+
// src/actions/useBeginMessageEdit.tsx
|
108
|
+
import { useCallback as useCallback3 } from "react";
|
109
|
+
var useBeginMessageEdit = () => {
|
110
|
+
const { useMessage, useComposer } = useMessageContext();
|
111
|
+
const disabled = useCombinedStore(
|
112
|
+
[useMessage, useComposer],
|
113
|
+
(m, c) => m.message.role !== "user" || c.isEditing
|
114
|
+
);
|
115
|
+
const callback = useCallback3(() => {
|
116
|
+
const { edit } = useComposer.getState();
|
117
|
+
edit();
|
118
|
+
}, [useComposer]);
|
119
|
+
if (disabled) return null;
|
120
|
+
return callback;
|
121
|
+
};
|
122
|
+
|
123
|
+
// src/actions/useGoToNextBranch.tsx
|
124
|
+
import { useCallback as useCallback4 } from "react";
|
125
|
+
var useGoToNextBranch = () => {
|
126
|
+
const { useThread } = useThreadContext();
|
127
|
+
const { useMessage, useComposer } = useMessageContext();
|
128
|
+
const disabled = useCombinedStore(
|
129
|
+
[useMessage, useComposer],
|
130
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
|
131
|
+
);
|
132
|
+
const callback = useCallback4(() => {
|
133
|
+
const { message, branches } = useMessage.getState();
|
134
|
+
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
|
135
|
+
}, [useMessage, useThread]);
|
136
|
+
if (disabled) return null;
|
137
|
+
return callback;
|
138
|
+
};
|
139
|
+
|
140
|
+
// src/actions/useGoToPreviousBranch.tsx
|
141
|
+
import { useCallback as useCallback5 } from "react";
|
142
|
+
var useGoToPreviousBranch = () => {
|
143
|
+
const { useThread } = useThreadContext();
|
144
|
+
const { useMessage, useComposer } = useMessageContext();
|
145
|
+
const disabled = useCombinedStore(
|
146
|
+
[useMessage, useComposer],
|
147
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
|
148
|
+
);
|
149
|
+
const callback = useCallback5(() => {
|
150
|
+
const { message, branches } = useMessage.getState();
|
151
|
+
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
|
152
|
+
}, [useMessage, useThread]);
|
153
|
+
if (disabled) return null;
|
154
|
+
return callback;
|
155
|
+
};
|
156
|
+
|
7
157
|
// src/primitives/thread/index.ts
|
8
158
|
var thread_exports = {};
|
9
159
|
__export(thread_exports, {
|
@@ -28,21 +178,9 @@ var ThreadRoot = forwardRef(
|
|
28
178
|
}
|
29
179
|
);
|
30
180
|
|
31
|
-
// src/utils/context/AssistantContext.ts
|
32
|
-
import { createContext, useContext } from "react";
|
33
|
-
var AssistantContext = createContext(null);
|
34
|
-
var useAssistantContext = () => {
|
35
|
-
const context = useContext(AssistantContext);
|
36
|
-
if (!context)
|
37
|
-
throw new Error(
|
38
|
-
"This component must be used within a AssistantProvider."
|
39
|
-
);
|
40
|
-
return context;
|
41
|
-
};
|
42
|
-
|
43
181
|
// src/primitives/thread/ThreadIf.tsx
|
44
182
|
var useThreadIf = (props) => {
|
45
|
-
const { useThread } =
|
183
|
+
const { useThread } = useThreadContext();
|
46
184
|
return useThread((thread) => {
|
47
185
|
if (props.empty === true && thread.messages.length !== 0) return false;
|
48
186
|
if (props.empty === false && thread.messages.length === 0) return false;
|
@@ -113,7 +251,7 @@ import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-
|
|
113
251
|
import { useEffect as useEffect2 } from "react";
|
114
252
|
var useOnScrollToBottom = (callback) => {
|
115
253
|
const callbackRef = useCallbackRef2(callback);
|
116
|
-
const { useViewport } =
|
254
|
+
const { useViewport } = useThreadContext();
|
117
255
|
useEffect2(() => {
|
118
256
|
return useViewport.getState().onScrollToBottom(() => {
|
119
257
|
callbackRef();
|
@@ -127,7 +265,7 @@ var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...re
|
|
127
265
|
const messagesEndRef = useRef(null);
|
128
266
|
const divRef = useRef(null);
|
129
267
|
const ref = useComposedRefs(forwardedRef, divRef);
|
130
|
-
const { useViewport } =
|
268
|
+
const { useViewport } = useThreadContext();
|
131
269
|
const firstRenderRef = useRef(true);
|
132
270
|
const isScrollingToBottomRef = useRef(false);
|
133
271
|
const lastScrollTop = useRef(0);
|
@@ -175,78 +313,23 @@ var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...re
|
|
175
313
|
);
|
176
314
|
});
|
177
315
|
|
178
|
-
// src/
|
179
|
-
import {
|
180
|
-
|
181
|
-
// src/utils/context/useMessageContext.ts
|
182
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
183
|
-
var MessageContext = createContext2(null);
|
184
|
-
var useMessageContext = () => {
|
185
|
-
const context = useContext2(MessageContext);
|
186
|
-
if (!context)
|
187
|
-
throw new Error(
|
188
|
-
"This component must be used within a MessagePrimitive.Provider."
|
189
|
-
);
|
190
|
-
return context;
|
191
|
-
};
|
192
|
-
|
193
|
-
// src/utils/context/useComposerContext.ts
|
194
|
-
var useComposerContext = () => {
|
195
|
-
const { useComposer: useAssisstantComposer } = useAssistantContext();
|
196
|
-
const { useComposer: useMessageComposer } = useContext3(MessageContext) ?? {};
|
197
|
-
return {
|
198
|
-
useComposer: useMessageComposer ?? useAssisstantComposer,
|
199
|
-
type: useMessageComposer ? "message" : "assistant"
|
200
|
-
};
|
201
|
-
};
|
202
|
-
|
203
|
-
// src/primitives/composer/ComposerIf.tsx
|
204
|
-
var useComposerIf = (props) => {
|
205
|
-
const { useComposer } = useComposerContext();
|
206
|
-
return useComposer((composer) => {
|
207
|
-
if (props.editing === true && !composer.isEditing) return false;
|
208
|
-
if (props.editing === false && composer.isEditing) return false;
|
209
|
-
return true;
|
210
|
-
});
|
211
|
-
};
|
212
|
-
var ComposerIf = ({ children, ...query }) => {
|
213
|
-
const result = useComposerIf(query);
|
214
|
-
return result ? children : null;
|
215
|
-
};
|
216
|
-
|
217
|
-
// src/primitives/message/index.ts
|
218
|
-
var message_exports = {};
|
219
|
-
__export(message_exports, {
|
220
|
-
Content: () => MessageContent,
|
221
|
-
If: () => MessageIf,
|
222
|
-
InProgress: () => MessageInProgress,
|
223
|
-
Provider: () => MessageProvider,
|
224
|
-
Root: () => MessageRoot
|
225
|
-
});
|
226
|
-
|
227
|
-
// src/primitives/message/MessageProvider.tsx
|
228
|
-
import { useMemo, useState } from "react";
|
316
|
+
// src/context/providers/MessageProvider.tsx
|
317
|
+
import { useEffect as useEffect3, useState } from "react";
|
229
318
|
import { create as create2 } from "zustand";
|
230
319
|
|
231
|
-
// src/
|
232
|
-
|
233
|
-
const textParts = message.content.filter(
|
234
|
-
(part) => part.type === "text"
|
235
|
-
);
|
236
|
-
return textParts.map((part) => part.text).join("\n\n");
|
237
|
-
};
|
320
|
+
// src/context/stores/MessageComposer.ts
|
321
|
+
import { create } from "zustand";
|
238
322
|
|
239
|
-
// src/
|
240
|
-
import {
|
241
|
-
create
|
242
|
-
} from "zustand";
|
323
|
+
// src/context/stores/BaseComposer.ts
|
243
324
|
var makeBaseComposer = (set) => ({
|
244
325
|
value: "",
|
245
326
|
setValue: (value) => {
|
246
327
|
set({ value });
|
247
328
|
}
|
248
329
|
});
|
249
|
-
|
330
|
+
|
331
|
+
// src/context/stores/MessageComposer.ts
|
332
|
+
var makeEditComposerStore = ({
|
250
333
|
onEdit,
|
251
334
|
onSend
|
252
335
|
}) => create()((set, get, store) => ({
|
@@ -267,34 +350,30 @@ var makeMessageComposerStore = ({
|
|
267
350
|
return true;
|
268
351
|
}
|
269
352
|
}));
|
270
|
-
var makeThreadComposerStore = (useThread) => create()((set, get, store) => {
|
271
|
-
return {
|
272
|
-
...makeBaseComposer(set, get, store),
|
273
|
-
isEditing: true,
|
274
|
-
send: () => {
|
275
|
-
const { value } = get();
|
276
|
-
set({ value: "" });
|
277
|
-
useThread.getState().append({
|
278
|
-
parentId: useThread.getState().messages.at(-1)?.id ?? null,
|
279
|
-
content: [{ type: "text", text: value }]
|
280
|
-
});
|
281
|
-
},
|
282
|
-
cancel: () => {
|
283
|
-
const thread = useThread.getState();
|
284
|
-
if (!thread.isRunning) return false;
|
285
|
-
useThread.getState().cancelRun();
|
286
|
-
return true;
|
287
|
-
}
|
288
|
-
};
|
289
|
-
});
|
290
353
|
|
291
|
-
// src/
|
354
|
+
// src/context/providers/MessageProvider.tsx
|
292
355
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
293
356
|
var getIsLast = (thread, message) => {
|
294
357
|
return thread.messages[thread.messages.length - 1]?.id === message.id;
|
295
358
|
};
|
296
|
-
var
|
297
|
-
const
|
359
|
+
var syncMessage = (thread, useMessage, messageIndex) => {
|
360
|
+
const parentId = thread.messages[messageIndex - 1]?.id ?? null;
|
361
|
+
const message = thread.messages[messageIndex];
|
362
|
+
if (!message) return;
|
363
|
+
const isLast = getIsLast(thread, message);
|
364
|
+
const branches = thread.getBranches(message.id);
|
365
|
+
const currentState = useMessage.getState();
|
366
|
+
if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
|
367
|
+
return;
|
368
|
+
useMessage.setState({
|
369
|
+
message,
|
370
|
+
parentId,
|
371
|
+
branches,
|
372
|
+
isLast
|
373
|
+
});
|
374
|
+
};
|
375
|
+
var useMessageContext2 = (messageIndex) => {
|
376
|
+
const { useThread } = useThreadContext();
|
298
377
|
const [context] = useState(() => {
|
299
378
|
const useMessage = create2((set) => ({
|
300
379
|
message: null,
|
@@ -314,7 +393,7 @@ var useMessageContext2 = () => {
|
|
314
393
|
set({ isHovering: value });
|
315
394
|
}
|
316
395
|
}));
|
317
|
-
const useComposer =
|
396
|
+
const useComposer = makeEditComposerStore({
|
318
397
|
onEdit: () => {
|
319
398
|
const message = useMessage.getState().message;
|
320
399
|
if (message.role !== "user")
|
@@ -339,58 +418,51 @@ var useMessageContext2 = () => {
|
|
339
418
|
});
|
340
419
|
}
|
341
420
|
});
|
421
|
+
syncMessage(useThread.getState(), useMessage, messageIndex);
|
342
422
|
return { useMessage, useComposer };
|
343
423
|
});
|
424
|
+
useEffect3(() => {
|
425
|
+
return useThread.subscribe((thread) => {
|
426
|
+
syncMessage(thread, context.useMessage, messageIndex);
|
427
|
+
});
|
428
|
+
}, [context, useThread, messageIndex]);
|
344
429
|
return context;
|
345
430
|
};
|
346
431
|
var MessageProvider = ({
|
347
|
-
|
348
|
-
parentId,
|
432
|
+
messageIndex,
|
349
433
|
children
|
350
434
|
}) => {
|
351
|
-
const
|
352
|
-
const context = useMessageContext2();
|
353
|
-
const isLast = useThread((thread) => getIsLast(thread, message));
|
354
|
-
const branches = useThread((thread) => thread.getBranches(message.id));
|
355
|
-
useMemo(() => {
|
356
|
-
context.useMessage.setState({
|
357
|
-
message,
|
358
|
-
parentId,
|
359
|
-
branches,
|
360
|
-
isLast
|
361
|
-
});
|
362
|
-
}, [context, message, parentId, branches, isLast]);
|
435
|
+
const context = useMessageContext2(messageIndex);
|
363
436
|
return /* @__PURE__ */ jsx4(MessageContext.Provider, { value: context, children });
|
364
437
|
};
|
365
438
|
|
366
|
-
// src/
|
367
|
-
import {
|
368
|
-
|
369
|
-
|
370
|
-
}
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
);
|
439
|
+
// src/context/ComposerContext.ts
|
440
|
+
import { useContext as useContext3, useMemo as useMemo2 } from "react";
|
441
|
+
var useComposerContext = () => {
|
442
|
+
const { useComposer } = useThreadContext();
|
443
|
+
const { useComposer: useEditComposer } = useContext3(MessageContext) ?? {};
|
444
|
+
return useMemo2(
|
445
|
+
() => ({
|
446
|
+
useComposer: useEditComposer ?? useComposer,
|
447
|
+
type: useEditComposer ? "edit" : "new"
|
448
|
+
}),
|
449
|
+
[useEditComposer, useComposer]
|
450
|
+
);
|
451
|
+
};
|
452
|
+
|
453
|
+
// src/primitives/composer/ComposerIf.tsx
|
454
|
+
var useComposerIf = (props) => {
|
455
|
+
const { useComposer } = useComposerContext();
|
456
|
+
return useComposer((composer) => {
|
457
|
+
if (props.editing === true && !composer.isEditing) return false;
|
458
|
+
if (props.editing === false && composer.isEditing) return false;
|
459
|
+
return true;
|
460
|
+
});
|
461
|
+
};
|
462
|
+
var ComposerIf = ({ children, ...query }) => {
|
463
|
+
const result = useComposerIf(query);
|
464
|
+
return result ? children : null;
|
465
|
+
};
|
394
466
|
|
395
467
|
// src/primitives/message/MessageIf.tsx
|
396
468
|
var useMessageIf = (props) => {
|
@@ -410,162 +482,8 @@ var MessageIf = ({ children, ...query }) => {
|
|
410
482
|
return result ? children : null;
|
411
483
|
};
|
412
484
|
|
413
|
-
// src/utils/context/combined/useCombinedStore.ts
|
414
|
-
import { useMemo as useMemo2 } from "react";
|
415
|
-
|
416
|
-
// src/utils/context/combined/createCombinedStore.ts
|
417
|
-
import { useSyncExternalStore } from "react";
|
418
|
-
var createCombinedStore = (stores) => {
|
419
|
-
const subscribe = (callback) => {
|
420
|
-
const unsubscribes = stores.map((store) => store.subscribe(callback));
|
421
|
-
return () => {
|
422
|
-
for (const unsub of unsubscribes) {
|
423
|
-
unsub();
|
424
|
-
}
|
425
|
-
};
|
426
|
-
};
|
427
|
-
return (selector) => {
|
428
|
-
const getSnapshot = () => selector(...stores.map((store) => store.getState()));
|
429
|
-
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
430
|
-
};
|
431
|
-
};
|
432
|
-
|
433
|
-
// src/utils/context/combined/useCombinedStore.ts
|
434
|
-
var useCombinedStore = (stores, selector) => {
|
435
|
-
const useCombined = useMemo2(() => createCombinedStore(stores), stores);
|
436
|
-
return useCombined(selector);
|
437
|
-
};
|
438
|
-
|
439
|
-
// src/utils/context/useContentPartContext.ts
|
440
|
-
import { createContext as createContext3, useContext as useContext4 } from "react";
|
441
|
-
var ContentPartContext = createContext3(null);
|
442
|
-
var useContentPartContext = () => {
|
443
|
-
const context = useContext4(ContentPartContext);
|
444
|
-
if (!context)
|
445
|
-
throw new Error(
|
446
|
-
"This component must be used within a ContentPartPrimitive.Provider."
|
447
|
-
);
|
448
|
-
return context;
|
449
|
-
};
|
450
|
-
|
451
|
-
// src/primitives/contentPart/ContentPartInProgressIndicator.tsx
|
452
|
-
var ContentPartInProgressIndicator = () => {
|
453
|
-
const { useMessage } = useMessageContext();
|
454
|
-
const { useContentPart } = useContentPartContext();
|
455
|
-
const indicator = useCombinedStore(
|
456
|
-
[useMessage, useContentPart],
|
457
|
-
(m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
|
458
|
-
);
|
459
|
-
return indicator;
|
460
|
-
};
|
461
|
-
|
462
|
-
// src/primitives/contentPart/ContentPartProvider.tsx
|
463
|
-
import { useMemo as useMemo3, useState as useState2 } from "react";
|
464
|
-
import { create as create3 } from "zustand";
|
465
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
466
|
-
var useContentPartContext2 = () => {
|
467
|
-
const [context] = useState2(() => {
|
468
|
-
const useContentPart = create3(() => ({
|
469
|
-
part: null,
|
470
|
-
status: "done"
|
471
|
-
}));
|
472
|
-
return { useContentPart };
|
473
|
-
});
|
474
|
-
return context;
|
475
|
-
};
|
476
|
-
var ContentPartProvider = ({
|
477
|
-
part,
|
478
|
-
status,
|
479
|
-
children
|
480
|
-
}) => {
|
481
|
-
const context = useContentPartContext2();
|
482
|
-
useMemo3(() => {
|
483
|
-
context.useContentPart.setState(
|
484
|
-
{
|
485
|
-
part,
|
486
|
-
status
|
487
|
-
},
|
488
|
-
true
|
489
|
-
);
|
490
|
-
}, [context, part, status]);
|
491
|
-
return /* @__PURE__ */ jsx6(ContentPartContext.Provider, { value: context, children });
|
492
|
-
};
|
493
|
-
|
494
|
-
// src/primitives/message/MessageContent.tsx
|
495
|
-
import { Fragment, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
496
|
-
var defaultComponents = {
|
497
|
-
Text: ({ part }) => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
498
|
-
part.text,
|
499
|
-
/* @__PURE__ */ jsx7(ContentPartInProgressIndicator, {})
|
500
|
-
] }),
|
501
|
-
Image: () => null,
|
502
|
-
UI: ({ part }) => part.display,
|
503
|
-
tools: {
|
504
|
-
Fallback: () => null
|
505
|
-
}
|
506
|
-
};
|
507
|
-
var MessageContent = ({
|
508
|
-
components: {
|
509
|
-
Text = defaultComponents.Text,
|
510
|
-
Image = defaultComponents.Image,
|
511
|
-
UI = defaultComponents.UI,
|
512
|
-
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
513
|
-
} = {}
|
514
|
-
}) => {
|
515
|
-
const { useMessage } = useMessageContext();
|
516
|
-
const message = useMessage((s) => s.message);
|
517
|
-
const content = message.content;
|
518
|
-
const status = message.role === "assistant" ? message.status : "done";
|
519
|
-
return /* @__PURE__ */ jsx7(Fragment, { children: content.map((part, i) => {
|
520
|
-
const key = i;
|
521
|
-
const type = part.type;
|
522
|
-
let component = null;
|
523
|
-
switch (type) {
|
524
|
-
case "text":
|
525
|
-
component = /* @__PURE__ */ jsx7(Text, { part });
|
526
|
-
break;
|
527
|
-
case "image":
|
528
|
-
component = /* @__PURE__ */ jsx7(Image, { part });
|
529
|
-
break;
|
530
|
-
case "ui":
|
531
|
-
component = /* @__PURE__ */ jsx7(UI, { part });
|
532
|
-
break;
|
533
|
-
case "tool-call": {
|
534
|
-
const Tool = by_name[part.name] || Fallback;
|
535
|
-
component = /* @__PURE__ */ jsx7(Tool, { part });
|
536
|
-
break;
|
537
|
-
}
|
538
|
-
default:
|
539
|
-
throw new Error(`Unknown content part type: ${type}`);
|
540
|
-
}
|
541
|
-
return /* @__PURE__ */ jsx7(
|
542
|
-
ContentPartProvider,
|
543
|
-
{
|
544
|
-
part,
|
545
|
-
status: i === content.length - 1 ? status : "done",
|
546
|
-
children: component
|
547
|
-
},
|
548
|
-
key
|
549
|
-
);
|
550
|
-
}) });
|
551
|
-
};
|
552
|
-
|
553
|
-
// src/primitives/message/MessageInProgress.tsx
|
554
|
-
import {
|
555
|
-
Primitive as Primitive4
|
556
|
-
} from "@radix-ui/react-primitive";
|
557
|
-
import { forwardRef as forwardRef4, useMemo as useMemo4 } from "react";
|
558
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
559
|
-
var MessageInProgress = forwardRef4((props, ref) => {
|
560
|
-
const { useMessage } = useMessageContext();
|
561
|
-
useMemo4(() => {
|
562
|
-
useMessage.getState().setInProgressIndicator(/* @__PURE__ */ jsx8(Primitive4.div, { ...props, ref }));
|
563
|
-
}, [useMessage, props, ref]);
|
564
|
-
return null;
|
565
|
-
});
|
566
|
-
|
567
485
|
// src/primitives/thread/ThreadMessages.tsx
|
568
|
-
import { Fragment
|
486
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
569
487
|
var getComponents = (components) => {
|
570
488
|
return {
|
571
489
|
EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
|
@@ -574,64 +492,62 @@ var getComponents = (components) => {
|
|
574
492
|
};
|
575
493
|
};
|
576
494
|
var ThreadMessages = ({ components }) => {
|
577
|
-
const { useThread } =
|
578
|
-
const
|
579
|
-
const messages = thread.messages;
|
495
|
+
const { useThread } = useThreadContext();
|
496
|
+
const messagesLength = useThread((t) => t.messages.length);
|
580
497
|
const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
|
581
|
-
if (
|
582
|
-
return /* @__PURE__ */
|
583
|
-
const
|
584
|
-
return /* @__PURE__ */
|
498
|
+
if (messagesLength === 0) return null;
|
499
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: new Array(messagesLength).fill(null).map((_, idx) => {
|
500
|
+
const messageIndex = idx;
|
501
|
+
return /* @__PURE__ */ jsxs2(
|
585
502
|
MessageProvider,
|
586
503
|
{
|
587
|
-
|
588
|
-
parentId,
|
504
|
+
messageIndex,
|
589
505
|
children: [
|
590
|
-
/* @__PURE__ */
|
591
|
-
/* @__PURE__ */
|
592
|
-
/* @__PURE__ */
|
506
|
+
/* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
|
507
|
+
/* @__PURE__ */ jsx5(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx5(UserMessage, {}) }),
|
508
|
+
/* @__PURE__ */ jsx5(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx5(EditComposer, {}) })
|
593
509
|
] }),
|
594
|
-
/* @__PURE__ */
|
510
|
+
/* @__PURE__ */ jsx5(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx5(AssistantMessage, {}) })
|
595
511
|
]
|
596
512
|
},
|
597
|
-
|
513
|
+
messageIndex
|
598
514
|
);
|
599
515
|
}) });
|
600
516
|
};
|
601
517
|
|
602
518
|
// src/primitives/thread/ThreadScrollToBottom.tsx
|
603
|
-
import { composeEventHandlers as
|
519
|
+
import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
|
604
520
|
import {
|
605
|
-
Primitive as
|
521
|
+
Primitive as Primitive3
|
606
522
|
} from "@radix-ui/react-primitive";
|
607
|
-
import { forwardRef as
|
608
|
-
import { jsx as
|
609
|
-
var ThreadScrollToBottom =
|
610
|
-
const { useViewport } =
|
523
|
+
import { forwardRef as forwardRef3 } from "react";
|
524
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
525
|
+
var ThreadScrollToBottom = forwardRef3(({ onClick, ...rest }, ref) => {
|
526
|
+
const { useViewport } = useThreadContext();
|
611
527
|
const isAtBottom = useViewport((s) => s.isAtBottom);
|
612
528
|
const handleScrollToBottom = () => {
|
613
529
|
useViewport.getState().scrollToBottom();
|
614
530
|
};
|
615
|
-
return /* @__PURE__ */
|
616
|
-
|
531
|
+
return /* @__PURE__ */ jsx6(
|
532
|
+
Primitive3.button,
|
617
533
|
{
|
618
534
|
...rest,
|
619
535
|
disabled: isAtBottom,
|
620
536
|
ref,
|
621
|
-
onClick:
|
537
|
+
onClick: composeEventHandlers2(onClick, handleScrollToBottom)
|
622
538
|
}
|
623
539
|
);
|
624
540
|
});
|
625
541
|
|
626
542
|
// src/primitives/thread/ThreadSuggestion.tsx
|
627
|
-
import { composeEventHandlers as
|
543
|
+
import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
|
628
544
|
import {
|
629
|
-
Primitive as
|
545
|
+
Primitive as Primitive4
|
630
546
|
} from "@radix-ui/react-primitive";
|
631
|
-
import { forwardRef as
|
632
|
-
import { jsx as
|
633
|
-
var ThreadSuggestion =
|
634
|
-
const { useThread, useComposer } =
|
547
|
+
import { forwardRef as forwardRef4 } from "react";
|
548
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
549
|
+
var ThreadSuggestion = forwardRef4(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
|
550
|
+
const { useThread, useComposer } = useThreadContext();
|
635
551
|
const isDisabled = useThread((t) => t.isRunning);
|
636
552
|
const handleApplySuggestion = () => {
|
637
553
|
const thread = useThread.getState();
|
@@ -641,13 +557,13 @@ var ThreadSuggestion = forwardRef6(({ onClick, prompt, method, autoSend: send, .
|
|
641
557
|
composer.send();
|
642
558
|
}
|
643
559
|
};
|
644
|
-
return /* @__PURE__ */
|
645
|
-
|
560
|
+
return /* @__PURE__ */ jsx7(
|
561
|
+
Primitive4.button,
|
646
562
|
{
|
647
563
|
...rest,
|
648
564
|
disabled: isDisabled,
|
649
565
|
ref,
|
650
|
-
onClick:
|
566
|
+
onClick: composeEventHandlers3(onClick, handleApplySuggestion)
|
651
567
|
}
|
652
568
|
);
|
653
569
|
});
|
@@ -663,16 +579,16 @@ __export(composer_exports, {
|
|
663
579
|
});
|
664
580
|
|
665
581
|
// src/primitives/composer/ComposerRoot.tsx
|
666
|
-
import { composeEventHandlers as
|
582
|
+
import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
|
667
583
|
import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
|
668
584
|
import {
|
669
|
-
Primitive as
|
585
|
+
Primitive as Primitive5
|
670
586
|
} from "@radix-ui/react-primitive";
|
671
|
-
import { forwardRef as
|
672
|
-
import { jsx as
|
673
|
-
var ComposerRoot =
|
587
|
+
import { forwardRef as forwardRef5, useRef as useRef2 } from "react";
|
588
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
589
|
+
var ComposerRoot = forwardRef5(
|
674
590
|
({ onSubmit, ...rest }, forwardedRef) => {
|
675
|
-
const { useViewport } =
|
591
|
+
const { useViewport } = useThreadContext();
|
676
592
|
const { useComposer } = useComposerContext();
|
677
593
|
const formRef = useRef2(null);
|
678
594
|
const ref = useComposedRefs2(forwardedRef, formRef);
|
@@ -683,32 +599,32 @@ var ComposerRoot = forwardRef7(
|
|
683
599
|
composerState.send();
|
684
600
|
useViewport.getState().scrollToBottom();
|
685
601
|
};
|
686
|
-
return /* @__PURE__ */
|
687
|
-
|
602
|
+
return /* @__PURE__ */ jsx8(
|
603
|
+
Primitive5.form,
|
688
604
|
{
|
689
605
|
...rest,
|
690
606
|
ref,
|
691
|
-
onSubmit:
|
607
|
+
onSubmit: composeEventHandlers4(onSubmit, handleSubmit)
|
692
608
|
}
|
693
609
|
);
|
694
610
|
}
|
695
611
|
);
|
696
612
|
|
697
613
|
// src/primitives/composer/ComposerInput.tsx
|
698
|
-
import { composeEventHandlers as
|
614
|
+
import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
|
699
615
|
import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
|
700
616
|
import { Slot } from "@radix-ui/react-slot";
|
701
617
|
import {
|
702
|
-
forwardRef as
|
703
|
-
useCallback,
|
704
|
-
useEffect as
|
618
|
+
forwardRef as forwardRef6,
|
619
|
+
useCallback as useCallback6,
|
620
|
+
useEffect as useEffect4,
|
705
621
|
useRef as useRef3
|
706
622
|
} from "react";
|
707
623
|
import TextareaAutosize from "react-textarea-autosize";
|
708
|
-
import { jsx as
|
709
|
-
var ComposerInput =
|
624
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
625
|
+
var ComposerInput = forwardRef6(
|
710
626
|
({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
|
711
|
-
const { useThread, useViewport } =
|
627
|
+
const { useThread, useViewport } = useThreadContext();
|
712
628
|
const { useComposer, type } = useComposerContext();
|
713
629
|
const value = useComposer((c) => {
|
714
630
|
if (!c.isEditing) return "";
|
@@ -734,7 +650,7 @@ var ComposerInput = forwardRef8(
|
|
734
650
|
const textareaRef = useRef3(null);
|
735
651
|
const ref = useComposedRefs3(forwardedRef, textareaRef);
|
736
652
|
const autoFocusEnabled = autoFocus && !disabled;
|
737
|
-
const focus =
|
653
|
+
const focus = useCallback6(() => {
|
738
654
|
const textarea = textareaRef.current;
|
739
655
|
if (!textarea || !autoFocusEnabled) return;
|
740
656
|
textarea.focus();
|
@@ -743,25 +659,25 @@ var ComposerInput = forwardRef8(
|
|
743
659
|
textareaRef.current.value.length
|
744
660
|
);
|
745
661
|
}, [autoFocusEnabled]);
|
746
|
-
|
662
|
+
useEffect4(() => focus(), [focus]);
|
747
663
|
useOnScrollToBottom(() => {
|
748
|
-
if (type === "
|
664
|
+
if (type === "new") {
|
749
665
|
focus();
|
750
666
|
}
|
751
667
|
});
|
752
|
-
return /* @__PURE__ */
|
668
|
+
return /* @__PURE__ */ jsx9(
|
753
669
|
Component,
|
754
670
|
{
|
755
671
|
value,
|
756
672
|
...rest,
|
757
673
|
ref,
|
758
674
|
disabled,
|
759
|
-
onChange:
|
675
|
+
onChange: composeEventHandlers5(onChange, (e) => {
|
760
676
|
const composerState = useComposer.getState();
|
761
677
|
if (!composerState.isEditing) return;
|
762
678
|
return composerState.setValue(e.target.value);
|
763
679
|
}),
|
764
|
-
onKeyDown:
|
680
|
+
onKeyDown: composeEventHandlers5(onKeyDown, handleKeyPress)
|
765
681
|
}
|
766
682
|
);
|
767
683
|
}
|
@@ -769,16 +685,16 @@ var ComposerInput = forwardRef8(
|
|
769
685
|
|
770
686
|
// src/primitives/composer/ComposerSend.tsx
|
771
687
|
import {
|
772
|
-
Primitive as
|
688
|
+
Primitive as Primitive6
|
773
689
|
} from "@radix-ui/react-primitive";
|
774
|
-
import { forwardRef as
|
775
|
-
import { jsx as
|
776
|
-
var ComposerSend =
|
690
|
+
import { forwardRef as forwardRef7 } from "react";
|
691
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
692
|
+
var ComposerSend = forwardRef7(
|
777
693
|
({ disabled, ...rest }, ref) => {
|
778
694
|
const { useComposer } = useComposerContext();
|
779
695
|
const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
|
780
|
-
return /* @__PURE__ */
|
781
|
-
|
696
|
+
return /* @__PURE__ */ jsx10(
|
697
|
+
Primitive6.button,
|
782
698
|
{
|
783
699
|
type: "submit",
|
784
700
|
...rest,
|
@@ -790,28 +706,193 @@ var ComposerSend = forwardRef9(
|
|
790
706
|
);
|
791
707
|
|
792
708
|
// src/primitives/composer/ComposerCancel.tsx
|
793
|
-
import { composeEventHandlers as
|
709
|
+
import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
|
794
710
|
import {
|
795
|
-
Primitive as
|
711
|
+
Primitive as Primitive7
|
796
712
|
} from "@radix-ui/react-primitive";
|
797
|
-
import { forwardRef as
|
798
|
-
import { jsx as
|
799
|
-
var ComposerCancel =
|
713
|
+
import { forwardRef as forwardRef8 } from "react";
|
714
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
715
|
+
var ComposerCancel = forwardRef8(({ onClick, ...rest }, ref) => {
|
800
716
|
const { useComposer } = useComposerContext();
|
801
717
|
const handleCancel = () => {
|
802
718
|
useComposer.getState().cancel();
|
803
719
|
};
|
804
|
-
return /* @__PURE__ */
|
805
|
-
|
720
|
+
return /* @__PURE__ */ jsx11(
|
721
|
+
Primitive7.button,
|
806
722
|
{
|
807
723
|
type: "button",
|
808
724
|
...rest,
|
809
725
|
ref,
|
810
|
-
onClick:
|
726
|
+
onClick: composeEventHandlers6(onClick, handleCancel)
|
811
727
|
}
|
812
728
|
);
|
813
729
|
});
|
814
730
|
|
731
|
+
// src/primitives/message/index.ts
|
732
|
+
var message_exports = {};
|
733
|
+
__export(message_exports, {
|
734
|
+
Content: () => MessageContent,
|
735
|
+
If: () => MessageIf,
|
736
|
+
InProgress: () => MessageInProgress,
|
737
|
+
Root: () => MessageRoot
|
738
|
+
});
|
739
|
+
|
740
|
+
// src/primitives/message/MessageRoot.tsx
|
741
|
+
import { composeEventHandlers as composeEventHandlers7 } from "@radix-ui/primitive";
|
742
|
+
import {
|
743
|
+
Primitive as Primitive8
|
744
|
+
} from "@radix-ui/react-primitive";
|
745
|
+
import { forwardRef as forwardRef9 } from "react";
|
746
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
747
|
+
var MessageRoot = forwardRef9(
|
748
|
+
({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
|
749
|
+
const { useMessage } = useMessageContext();
|
750
|
+
const setIsHovering = useMessage((s) => s.setIsHovering);
|
751
|
+
const handleMouseEnter = () => {
|
752
|
+
setIsHovering(true);
|
753
|
+
};
|
754
|
+
const handleMouseLeave = () => {
|
755
|
+
setIsHovering(false);
|
756
|
+
};
|
757
|
+
return /* @__PURE__ */ jsx12(
|
758
|
+
Primitive8.div,
|
759
|
+
{
|
760
|
+
...rest,
|
761
|
+
ref,
|
762
|
+
onMouseEnter: composeEventHandlers7(onMouseEnter, handleMouseEnter),
|
763
|
+
onMouseLeave: composeEventHandlers7(onMouseLeave, handleMouseLeave)
|
764
|
+
}
|
765
|
+
);
|
766
|
+
}
|
767
|
+
);
|
768
|
+
|
769
|
+
// src/context/providers/ContentPartProvider.tsx
|
770
|
+
import { useEffect as useEffect5, useState as useState2 } from "react";
|
771
|
+
import { create as create3 } from "zustand";
|
772
|
+
|
773
|
+
// src/context/ContentPartContext.ts
|
774
|
+
import { createContext as createContext3, useContext as useContext4 } from "react";
|
775
|
+
var ContentPartContext = createContext3(
|
776
|
+
null
|
777
|
+
);
|
778
|
+
var useContentPartContext = () => {
|
779
|
+
const context = useContext4(ContentPartContext);
|
780
|
+
if (!context)
|
781
|
+
throw new Error(
|
782
|
+
"This component can only be used inside a component passed to <MessagePrimitive.Content components={...} >."
|
783
|
+
);
|
784
|
+
return context;
|
785
|
+
};
|
786
|
+
|
787
|
+
// src/context/providers/ContentPartProvider.tsx
|
788
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
789
|
+
var syncContentPart = ({ message }, useContentPart, partIndex) => {
|
790
|
+
const part = message.content[partIndex];
|
791
|
+
if (!part) return;
|
792
|
+
const messageStatus = message.role === "assistant" ? message.status : "done";
|
793
|
+
const status = partIndex === message.content.length - 1 ? messageStatus : "done";
|
794
|
+
useContentPart.setState({ part, status });
|
795
|
+
};
|
796
|
+
var useContentPartContext2 = (partIndex) => {
|
797
|
+
const { useMessage } = useMessageContext();
|
798
|
+
const [context] = useState2(() => {
|
799
|
+
const useContentPart = create3(() => ({
|
800
|
+
part: { type: "text", text: "" },
|
801
|
+
status: "done"
|
802
|
+
}));
|
803
|
+
syncContentPart(useMessage.getState(), useContentPart, partIndex);
|
804
|
+
return { useContentPart };
|
805
|
+
});
|
806
|
+
useEffect5(() => {
|
807
|
+
return useMessage.subscribe((message) => {
|
808
|
+
syncContentPart(message, context.useContentPart, partIndex);
|
809
|
+
});
|
810
|
+
}, [context, useMessage, partIndex]);
|
811
|
+
return context;
|
812
|
+
};
|
813
|
+
var ContentPartProvider = ({
|
814
|
+
partIndex,
|
815
|
+
children
|
816
|
+
}) => {
|
817
|
+
const context = useContentPartContext2(partIndex);
|
818
|
+
return /* @__PURE__ */ jsx13(ContentPartContext.Provider, { value: context, children });
|
819
|
+
};
|
820
|
+
|
821
|
+
// src/primitives/contentPart/ContentPartInProgressIndicator.tsx
|
822
|
+
var ContentPartInProgressIndicator = () => {
|
823
|
+
const { useMessage } = useMessageContext();
|
824
|
+
const { useContentPart } = useContentPartContext();
|
825
|
+
const indicator = useCombinedStore(
|
826
|
+
[useMessage, useContentPart],
|
827
|
+
(m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
|
828
|
+
);
|
829
|
+
return indicator;
|
830
|
+
};
|
831
|
+
|
832
|
+
// src/primitives/message/MessageContent.tsx
|
833
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs3 } from "react/jsx-runtime";
|
834
|
+
var defaultComponents = {
|
835
|
+
Text: ({ part }) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
836
|
+
part.text,
|
837
|
+
/* @__PURE__ */ jsx14(ContentPartInProgressIndicator, {})
|
838
|
+
] }),
|
839
|
+
Image: () => null,
|
840
|
+
UI: ({ part }) => part.display,
|
841
|
+
tools: {
|
842
|
+
Fallback: () => null
|
843
|
+
}
|
844
|
+
};
|
845
|
+
var MessageContent = ({
|
846
|
+
components: {
|
847
|
+
Text = defaultComponents.Text,
|
848
|
+
Image = defaultComponents.Image,
|
849
|
+
UI = defaultComponents.UI,
|
850
|
+
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
851
|
+
} = {}
|
852
|
+
}) => {
|
853
|
+
const { useMessage } = useMessageContext();
|
854
|
+
const message = useMessage((s) => s.message);
|
855
|
+
const content = message.content;
|
856
|
+
return /* @__PURE__ */ jsx14(Fragment2, { children: content.map((part, i) => {
|
857
|
+
const partIndex = i;
|
858
|
+
const type = part.type;
|
859
|
+
let component = null;
|
860
|
+
switch (type) {
|
861
|
+
case "text":
|
862
|
+
component = /* @__PURE__ */ jsx14(Text, { part });
|
863
|
+
break;
|
864
|
+
case "image":
|
865
|
+
component = /* @__PURE__ */ jsx14(Image, { part });
|
866
|
+
break;
|
867
|
+
case "ui":
|
868
|
+
component = /* @__PURE__ */ jsx14(UI, { part });
|
869
|
+
break;
|
870
|
+
case "tool-call": {
|
871
|
+
const Tool = by_name[part.name] || Fallback;
|
872
|
+
component = /* @__PURE__ */ jsx14(Tool, { part });
|
873
|
+
break;
|
874
|
+
}
|
875
|
+
default:
|
876
|
+
throw new Error(`Unknown content part type: ${type}`);
|
877
|
+
}
|
878
|
+
return /* @__PURE__ */ jsx14(ContentPartProvider, { partIndex, children: component }, partIndex);
|
879
|
+
}) });
|
880
|
+
};
|
881
|
+
|
882
|
+
// src/primitives/message/MessageInProgress.tsx
|
883
|
+
import {
|
884
|
+
Primitive as Primitive9
|
885
|
+
} from "@radix-ui/react-primitive";
|
886
|
+
import { forwardRef as forwardRef10, useMemo as useMemo3 } from "react";
|
887
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
888
|
+
var MessageInProgress = forwardRef10((props, ref) => {
|
889
|
+
const { useMessage } = useMessageContext();
|
890
|
+
useMemo3(() => {
|
891
|
+
useMessage.getState().setInProgressIndicator(/* @__PURE__ */ jsx15(Primitive9.span, { ...props, ref }));
|
892
|
+
}, [useMessage, props, ref]);
|
893
|
+
return null;
|
894
|
+
});
|
895
|
+
|
815
896
|
// src/primitives/branchPicker/index.ts
|
816
897
|
var branchPicker_exports = {};
|
817
898
|
__export(branchPicker_exports, {
|
@@ -822,23 +903,6 @@ __export(branchPicker_exports, {
|
|
822
903
|
Root: () => BranchPickerRoot
|
823
904
|
});
|
824
905
|
|
825
|
-
// src/actions/useGoToNextBranch.tsx
|
826
|
-
import { useCallback as useCallback2 } from "react";
|
827
|
-
var useGoToNextBranch = () => {
|
828
|
-
const { useThread } = useAssistantContext();
|
829
|
-
const { useMessage, useComposer } = useMessageContext();
|
830
|
-
const disabled = useCombinedStore(
|
831
|
-
[useMessage, useComposer],
|
832
|
-
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
|
833
|
-
);
|
834
|
-
const callback = useCallback2(() => {
|
835
|
-
const { message, branches } = useMessage.getState();
|
836
|
-
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
|
837
|
-
}, [useMessage, useThread]);
|
838
|
-
if (disabled) return null;
|
839
|
-
return callback;
|
840
|
-
};
|
841
|
-
|
842
906
|
// src/utils/createActionButton.tsx
|
843
907
|
import { composeEventHandlers as composeEventHandlers8 } from "@radix-ui/primitive";
|
844
908
|
import {
|
@@ -867,23 +931,6 @@ var createActionButton = (useActionButton) => {
|
|
867
931
|
// src/primitives/branchPicker/BranchPickerNext.tsx
|
868
932
|
var BranchPickerNext = createActionButton(useGoToNextBranch);
|
869
933
|
|
870
|
-
// src/actions/useGoToPreviousBranch.tsx
|
871
|
-
import { useCallback as useCallback3 } from "react";
|
872
|
-
var useGoToPreviousBranch = () => {
|
873
|
-
const { useThread } = useAssistantContext();
|
874
|
-
const { useMessage, useComposer } = useMessageContext();
|
875
|
-
const disabled = useCombinedStore(
|
876
|
-
[useMessage, useComposer],
|
877
|
-
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
|
878
|
-
);
|
879
|
-
const callback = useCallback3(() => {
|
880
|
-
const { message, branches } = useMessage.getState();
|
881
|
-
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
|
882
|
-
}, [useMessage, useThread]);
|
883
|
-
if (disabled) return null;
|
884
|
-
return callback;
|
885
|
-
};
|
886
|
-
|
887
934
|
// src/primitives/branchPicker/BranchPickerPrevious.tsx
|
888
935
|
var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
|
889
936
|
|
@@ -929,7 +976,7 @@ import {
|
|
929
976
|
import { forwardRef as forwardRef13 } from "react";
|
930
977
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
931
978
|
var ActionBarRoot = forwardRef13(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
|
932
|
-
const { useThread } =
|
979
|
+
const { useThread } = useThreadContext();
|
933
980
|
const { useMessage } = useMessageContext();
|
934
981
|
const hideAndfloatStatus = useCombinedStore(
|
935
982
|
[useThread, useMessage],
|
@@ -954,142 +1001,166 @@ var ActionBarRoot = forwardRef13(({ hideWhenRunning, autohide, autohideFloat, ..
|
|
954
1001
|
);
|
955
1002
|
});
|
956
1003
|
|
957
|
-
// src/actions/useCopyMessage.tsx
|
958
|
-
import { useCallback as useCallback4 } from "react";
|
959
|
-
var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
960
|
-
const { useMessage, useComposer } = useMessageContext();
|
961
|
-
const hasCopyableContent = useCombinedStore(
|
962
|
-
[useMessage, useComposer],
|
963
|
-
(m, c) => {
|
964
|
-
return c.isEditing || m.message.content.some((c2) => c2.type === "text");
|
965
|
-
}
|
966
|
-
);
|
967
|
-
const callback = useCallback4(() => {
|
968
|
-
const { isEditing, value: composerValue } = useComposer.getState();
|
969
|
-
const { message, setIsCopied } = useMessage.getState();
|
970
|
-
const valueToCopy = isEditing ? composerValue : getMessageText(message);
|
971
|
-
navigator.clipboard.writeText(valueToCopy);
|
972
|
-
setIsCopied(true);
|
973
|
-
setTimeout(() => setIsCopied(false), copiedDuration);
|
974
|
-
}, [useComposer, useMessage, copiedDuration]);
|
975
|
-
if (!hasCopyableContent) return null;
|
976
|
-
return callback;
|
977
|
-
};
|
978
|
-
|
979
1004
|
// src/primitives/actionBar/ActionBarCopy.tsx
|
980
1005
|
var ActionBarCopy = createActionButton(useCopyMessage);
|
981
1006
|
|
982
|
-
// src/actions/useReloadMessage.tsx
|
983
|
-
import { useCallback as useCallback5 } from "react";
|
984
|
-
var useReloadMessage = () => {
|
985
|
-
const { useThread, useViewport } = useAssistantContext();
|
986
|
-
const { useMessage } = useMessageContext();
|
987
|
-
const disabled = useCombinedStore(
|
988
|
-
[useThread, useMessage],
|
989
|
-
(t, m) => t.isRunning || m.message.role !== "assistant"
|
990
|
-
);
|
991
|
-
const callback = useCallback5(() => {
|
992
|
-
const { parentId } = useMessage.getState();
|
993
|
-
useThread.getState().startRun(parentId);
|
994
|
-
useViewport.getState().scrollToBottom();
|
995
|
-
}, [useMessage, useThread, useViewport]);
|
996
|
-
if (disabled) return null;
|
997
|
-
return callback;
|
998
|
-
};
|
999
|
-
|
1000
1007
|
// src/primitives/actionBar/ActionBarReload.tsx
|
1001
1008
|
var ActionBarReload = createActionButton(useReloadMessage);
|
1002
1009
|
|
1003
|
-
// src/actions/useBeginMessageEdit.tsx
|
1004
|
-
import { useCallback as useCallback6 } from "react";
|
1005
|
-
var useBeginMessageEdit = () => {
|
1006
|
-
const { useMessage, useComposer } = useMessageContext();
|
1007
|
-
const disabled = useCombinedStore(
|
1008
|
-
[useMessage, useComposer],
|
1009
|
-
(m, c) => m.message.role !== "user" || c.isEditing
|
1010
|
-
);
|
1011
|
-
const callback = useCallback6(() => {
|
1012
|
-
const { edit } = useComposer.getState();
|
1013
|
-
edit();
|
1014
|
-
}, [useComposer]);
|
1015
|
-
if (disabled) return null;
|
1016
|
-
return callback;
|
1017
|
-
};
|
1018
|
-
|
1019
1010
|
// src/primitives/actionBar/ActionBarEdit.tsx
|
1020
1011
|
var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
1021
1012
|
|
1022
1013
|
// src/primitives/contentPart/index.ts
|
1023
1014
|
var contentPart_exports = {};
|
1024
1015
|
__export(contentPart_exports, {
|
1025
|
-
InProgressIndicator: () => ContentPartInProgressIndicator
|
1026
|
-
Provider: () => ContentPartProvider
|
1016
|
+
InProgressIndicator: () => ContentPartInProgressIndicator
|
1027
1017
|
});
|
1028
1018
|
|
1029
|
-
// src/
|
1030
|
-
import {
|
1031
|
-
|
1032
|
-
// src/adapters/vercel/useDummyAIAssistantContext.tsx
|
1033
|
-
import { useState as useState3 } from "react";
|
1034
|
-
import { create as create5 } from "zustand";
|
1019
|
+
// src/runtime/vercel-ai/rsc/useVercelRSCRuntime.tsx
|
1020
|
+
import { useEffect as useEffect7, useInsertionEffect, useState as useState3 } from "react";
|
1035
1021
|
|
1036
|
-
// src/
|
1022
|
+
// src/runtime/vercel-ai/rsc/VercelRSCRuntime.tsx
|
1037
1023
|
import { create as create4 } from "zustand";
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
}));
|
1024
|
+
|
1025
|
+
// src/runtime/vercel-ai/rsc/useVercelRSCSync.tsx
|
1026
|
+
import { useEffect as useEffect6, useMemo as useMemo4 } from "react";
|
1027
|
+
|
1028
|
+
// src/runtime/vercel-ai/utils/ThreadMessageConverter.ts
|
1029
|
+
var ThreadMessageConverter = class {
|
1030
|
+
cache = /* @__PURE__ */ new WeakMap();
|
1031
|
+
convertMessages(converter, messages) {
|
1032
|
+
return messages.map((m) => {
|
1033
|
+
const cached = this.cache.get(m);
|
1034
|
+
const newMessage = converter(m, cached);
|
1035
|
+
this.cache.set(m, newMessage);
|
1036
|
+
return newMessage;
|
1037
|
+
});
|
1038
|
+
}
|
1054
1039
|
};
|
1055
1040
|
|
1056
|
-
// src/
|
1057
|
-
var
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1041
|
+
// src/runtime/vercel-ai/rsc/getVercelRSCMessage.tsx
|
1042
|
+
var symbolInnerRSCMessage = Symbol("innerVercelRSCMessage");
|
1043
|
+
var getVercelRSCMessage = (message) => {
|
1044
|
+
return message[symbolInnerRSCMessage];
|
1045
|
+
};
|
1046
|
+
|
1047
|
+
// src/runtime/vercel-ai/rsc/useVercelRSCSync.tsx
|
1048
|
+
var vercelToThreadMessage = (converter, rawMessage) => {
|
1049
|
+
const message = converter(rawMessage);
|
1050
|
+
return {
|
1051
|
+
id: message.id,
|
1052
|
+
role: message.role,
|
1053
|
+
content: [{ type: "ui", display: message.display }],
|
1054
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1055
|
+
...{ status: "done" },
|
1056
|
+
[symbolInnerRSCMessage]: rawMessage
|
1057
|
+
};
|
1058
|
+
};
|
1059
|
+
var useVercelRSCSync = (adapter, updateData) => {
|
1060
|
+
const [converter, convertCallback] = useMemo4(() => {
|
1061
|
+
const rscConverter = adapter.convertMessage ?? ((m) => m);
|
1062
|
+
const convertCallback2 = (m, cache) => {
|
1063
|
+
if (cache) return cache;
|
1064
|
+
return vercelToThreadMessage(rscConverter, m);
|
1065
|
+
};
|
1066
|
+
return [new ThreadMessageConverter(), convertCallback2];
|
1067
|
+
}, [adapter.convertMessage]);
|
1068
|
+
useEffect6(() => {
|
1069
|
+
updateData(converter.convertMessages(convertCallback, adapter.messages));
|
1070
|
+
}, [updateData, converter, convertCallback, adapter.messages]);
|
1071
|
+
};
|
1072
|
+
|
1073
|
+
// src/runtime/vercel-ai/rsc/VercelRSCRuntime.tsx
|
1074
|
+
var EMPTY_BRANCHES = Object.freeze([]);
|
1075
|
+
var VercelRSCRuntime = class {
|
1076
|
+
constructor(adapter) {
|
1077
|
+
this.adapter = adapter;
|
1078
|
+
this.useAdapter = create4(() => ({
|
1079
|
+
adapter
|
1080
|
+
}));
|
1081
|
+
}
|
1082
|
+
useAdapter;
|
1083
|
+
_subscriptions = /* @__PURE__ */ new Set();
|
1084
|
+
isRunning = false;
|
1085
|
+
messages = [];
|
1086
|
+
withRunning = (callback) => {
|
1087
|
+
this.isRunning = true;
|
1088
|
+
return callback.finally(() => {
|
1089
|
+
this.isRunning = false;
|
1090
|
+
});
|
1091
|
+
};
|
1092
|
+
getBranches() {
|
1093
|
+
return EMPTY_BRANCHES;
|
1094
|
+
}
|
1095
|
+
switchToBranch() {
|
1096
|
+
throw new Error(
|
1097
|
+
"Branch switching is not supported by VercelRSCAssistantProvider."
|
1098
|
+
);
|
1099
|
+
}
|
1100
|
+
async append(message) {
|
1101
|
+
if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
|
1102
|
+
if (!this.adapter.edit)
|
1103
|
+
throw new Error(
|
1104
|
+
"Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
|
1105
|
+
);
|
1106
|
+
await this.withRunning(this.adapter.edit(message));
|
1107
|
+
} else {
|
1108
|
+
await this.withRunning(this.adapter.append(message));
|
1075
1109
|
}
|
1076
|
-
}
|
1110
|
+
}
|
1111
|
+
async startRun(parentId) {
|
1112
|
+
if (!this.adapter.reload)
|
1113
|
+
throw new Error(
|
1114
|
+
"Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
|
1115
|
+
);
|
1116
|
+
await this.withRunning(this.adapter.reload(parentId));
|
1117
|
+
}
|
1118
|
+
cancelRun() {
|
1119
|
+
if (process.env["NODE_ENV"] === "development") {
|
1120
|
+
console.warn(
|
1121
|
+
"Run cancellation is not supported by VercelRSCAssistantProvider."
|
1122
|
+
);
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
subscribe(callback) {
|
1126
|
+
this._subscriptions.add(callback);
|
1127
|
+
return () => this._subscriptions.delete(callback);
|
1128
|
+
}
|
1129
|
+
onAdapterUpdated() {
|
1130
|
+
if (this.useAdapter.getState().adapter !== this.adapter) {
|
1131
|
+
this.useAdapter.setState({ adapter: this.adapter });
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
updateData = (messages) => {
|
1135
|
+
this.messages = messages;
|
1136
|
+
for (const callback of this._subscriptions) callback();
|
1137
|
+
};
|
1138
|
+
unstable_synchronizer = () => {
|
1139
|
+
const { adapter } = this.useAdapter();
|
1140
|
+
useVercelRSCSync(adapter, this.updateData);
|
1141
|
+
return null;
|
1142
|
+
};
|
1077
1143
|
};
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1144
|
+
|
1145
|
+
// src/runtime/vercel-ai/rsc/useVercelRSCRuntime.tsx
|
1146
|
+
var useVercelRSCRuntime = (adapter) => {
|
1147
|
+
const [runtime] = useState3(() => new VercelRSCRuntime(adapter));
|
1148
|
+
useInsertionEffect(() => {
|
1149
|
+
runtime.adapter = adapter;
|
1150
|
+
});
|
1151
|
+
useEffect7(() => {
|
1152
|
+
runtime.onAdapterUpdated();
|
1084
1153
|
});
|
1085
|
-
return
|
1154
|
+
return runtime;
|
1086
1155
|
};
|
1087
1156
|
|
1088
|
-
// src/
|
1089
|
-
import {
|
1090
|
-
|
1157
|
+
// src/runtime/vercel-ai/ui/use-chat/useVercelUseChatRuntime.tsx
|
1158
|
+
import { useEffect as useEffect10, useInsertionEffect as useInsertionEffect2, useState as useState4 } from "react";
|
1159
|
+
|
1160
|
+
// src/runtime/vercel-ai/ui/VercelAIRuntime.tsx
|
1161
|
+
import { create as create5 } from "zustand";
|
1091
1162
|
|
1092
|
-
// src/
|
1163
|
+
// src/runtime/utils/idUtils.tsx
|
1093
1164
|
import { customAlphabet } from "nanoid/non-secure";
|
1094
1165
|
var generateId = customAlphabet(
|
1095
1166
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
@@ -1098,7 +1169,7 @@ var generateId = customAlphabet(
|
|
1098
1169
|
var optimisticPrefix = "__optimistic__";
|
1099
1170
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1100
1171
|
|
1101
|
-
// src/
|
1172
|
+
// src/runtime/utils/MessageRepository.tsx
|
1102
1173
|
var findHead = (message) => {
|
1103
1174
|
if (message.next) return findHead(message.next);
|
1104
1175
|
return message;
|
@@ -1167,10 +1238,10 @@ var MessageRepository = class {
|
|
1167
1238
|
level: prev ? prev.level + 1 : 0
|
1168
1239
|
};
|
1169
1240
|
this.messages.set(message.id, newItem);
|
1241
|
+
this.performOp(prev, newItem, "link");
|
1170
1242
|
if (this.head === prev) {
|
1171
1243
|
this.head = newItem;
|
1172
1244
|
}
|
1173
|
-
this.performOp(prev, newItem, "link");
|
1174
1245
|
}
|
1175
1246
|
appendOptimisticMessage(parentId, message) {
|
1176
1247
|
let optimisticId;
|
@@ -1187,14 +1258,14 @@ var MessageRepository = class {
|
|
1187
1258
|
}
|
1188
1259
|
deleteMessage(messageId, replacementId) {
|
1189
1260
|
const message = this.messages.get(messageId);
|
1190
|
-
const replacement = replacementId ? this.messages.get(replacementId) : null;
|
1191
1261
|
if (!message)
|
1192
1262
|
throw new Error(
|
1193
1263
|
"MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
|
1194
1264
|
);
|
1265
|
+
const replacement = replacementId === void 0 ? message.prev : replacementId === null ? null : this.messages.get(replacementId);
|
1195
1266
|
if (replacement === void 0)
|
1196
1267
|
throw new Error(
|
1197
|
-
"MessageRepository(deleteMessage):
|
1268
|
+
"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui."
|
1198
1269
|
);
|
1199
1270
|
for (const child of message.children) {
|
1200
1271
|
const childMessage = this.messages.get(child);
|
@@ -1204,11 +1275,11 @@ var MessageRepository = class {
|
|
1204
1275
|
);
|
1205
1276
|
this.performOp(replacement, childMessage, "relink");
|
1206
1277
|
}
|
1278
|
+
this.performOp(null, message, "cut");
|
1207
1279
|
this.messages.delete(messageId);
|
1208
1280
|
if (this.head === message) {
|
1209
|
-
this.head = replacement;
|
1281
|
+
this.head = replacement ? findHead(replacement) : null;
|
1210
1282
|
}
|
1211
|
-
this.performOp(null, message, "cut");
|
1212
1283
|
}
|
1213
1284
|
getBranches(messageId) {
|
1214
1285
|
const message = this.messages.get(messageId);
|
@@ -1249,35 +1320,46 @@ var MessageRepository = class {
|
|
1249
1320
|
}
|
1250
1321
|
};
|
1251
1322
|
|
1252
|
-
// src/
|
1253
|
-
var
|
1254
|
-
|
1255
|
-
|
1256
|
-
return messages.map((m) => {
|
1257
|
-
const cached = this.cache.get(m);
|
1258
|
-
const newMessage = converter(m, cached);
|
1259
|
-
this.cache.set(m, newMessage);
|
1260
|
-
return newMessage;
|
1261
|
-
});
|
1262
|
-
}
|
1323
|
+
// src/runtime/vercel-ai/ui/getVercelAIMessage.tsx
|
1324
|
+
var symbolInnerAIMessage = Symbol("innerVercelAIUIMessage");
|
1325
|
+
var getVercelAIMessage = (message) => {
|
1326
|
+
return message[symbolInnerAIMessage];
|
1263
1327
|
};
|
1264
1328
|
|
1265
|
-
// src/
|
1266
|
-
var
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1329
|
+
// src/runtime/vercel-ai/ui/utils/sliceMessagesUntil.tsx
|
1330
|
+
var sliceMessagesUntil = (messages, messageId) => {
|
1331
|
+
if (messageId == null) return [];
|
1332
|
+
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1333
|
+
if (messageIdx === -1)
|
1334
|
+
throw new Error(
|
1335
|
+
"useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
|
1336
|
+
);
|
1337
|
+
return messages.slice(0, messageIdx + 1);
|
1270
1338
|
};
|
1271
|
-
|
1272
|
-
|
1339
|
+
|
1340
|
+
// src/runtime/vercel-ai/ui/utils/useVercelAIComposerSync.tsx
|
1341
|
+
import { useEffect as useEffect8 } from "react";
|
1342
|
+
var useVercelAIComposerSync = (vercel) => {
|
1343
|
+
const { useComposer } = useThreadContext();
|
1344
|
+
useEffect8(() => {
|
1345
|
+
useComposer.setState({
|
1346
|
+
value: vercel.input,
|
1347
|
+
setValue: vercel.setInput
|
1348
|
+
});
|
1349
|
+
}, [useComposer, vercel.input, vercel.setInput]);
|
1273
1350
|
};
|
1274
1351
|
|
1275
|
-
// src/
|
1276
|
-
|
1352
|
+
// src/runtime/vercel-ai/ui/utils/useVercelAIThreadSync.tsx
|
1353
|
+
import { useEffect as useEffect9, useMemo as useMemo5 } from "react";
|
1354
|
+
var getIsRunning = (vercel) => {
|
1355
|
+
if ("isLoading" in vercel) return vercel.isLoading;
|
1356
|
+
return vercel.status === "in_progress";
|
1357
|
+
};
|
1358
|
+
var vercelToThreadMessage2 = (message, status) => {
|
1277
1359
|
const common = {
|
1278
1360
|
id: message.id,
|
1279
1361
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1280
|
-
[
|
1362
|
+
[symbolInnerAIMessage]: message
|
1281
1363
|
};
|
1282
1364
|
switch (message.role) {
|
1283
1365
|
case "user":
|
@@ -1309,47 +1391,115 @@ var vercelToThreadMessage = (message, status) => {
|
|
1309
1391
|
);
|
1310
1392
|
}
|
1311
1393
|
};
|
1312
|
-
var
|
1313
|
-
if (messageId == null) return [];
|
1314
|
-
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1315
|
-
if (messageIdx === -1)
|
1316
|
-
throw new Error(
|
1317
|
-
"useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
|
1318
|
-
);
|
1319
|
-
return messages.slice(0, messageIdx + 1);
|
1320
|
-
};
|
1321
|
-
var hasUpcomingMessage = (isRunning, messages) => {
|
1322
|
-
return isRunning && messages[messages.length - 1]?.role !== "assistant";
|
1323
|
-
};
|
1324
|
-
var getIsRunning = (vercel) => {
|
1325
|
-
if ("isLoading" in vercel) return vercel.isLoading;
|
1326
|
-
return vercel.status === "in_progress";
|
1327
|
-
};
|
1328
|
-
var useVercelAIThreadState = (vercel) => {
|
1329
|
-
const [data] = useState4(() => new MessageRepository());
|
1394
|
+
var useVercelAIThreadSync = (vercel, updateData) => {
|
1330
1395
|
const isRunning = getIsRunning(vercel);
|
1331
1396
|
const converter = useMemo5(() => new ThreadMessageConverter(), []);
|
1332
|
-
|
1333
|
-
const messages = useMemo5(() => {
|
1397
|
+
useEffect9(() => {
|
1334
1398
|
const lastMessageId = vercel.messages.at(-1)?.id;
|
1335
1399
|
const convertCallback = (message, cache) => {
|
1336
1400
|
const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
|
1337
1401
|
if (cache && (cache.role === "user" || cache.status === status))
|
1338
1402
|
return cache;
|
1339
|
-
return
|
1403
|
+
return vercelToThreadMessage2(message, status);
|
1340
1404
|
};
|
1341
|
-
const
|
1405
|
+
const messages = converter.convertMessages(
|
1406
|
+
convertCallback,
|
1407
|
+
vercel.messages
|
1408
|
+
);
|
1409
|
+
updateData(isRunning, messages);
|
1410
|
+
}, [updateData, isRunning, vercel.messages, converter]);
|
1411
|
+
};
|
1412
|
+
|
1413
|
+
// src/runtime/vercel-ai/ui/VercelAIRuntime.tsx
|
1414
|
+
var hasUpcomingMessage = (isRunning, messages) => {
|
1415
|
+
return isRunning && messages[messages.length - 1]?.role !== "assistant";
|
1416
|
+
};
|
1417
|
+
var VercelAIRuntime = class {
|
1418
|
+
constructor(vercel) {
|
1419
|
+
this.vercel = vercel;
|
1420
|
+
this.useVercel = create5(() => ({
|
1421
|
+
vercel
|
1422
|
+
}));
|
1423
|
+
}
|
1424
|
+
_subscriptions = /* @__PURE__ */ new Set();
|
1425
|
+
repository = new MessageRepository();
|
1426
|
+
assistantOptimisticId = null;
|
1427
|
+
useVercel;
|
1428
|
+
messages = [];
|
1429
|
+
isRunning = false;
|
1430
|
+
getBranches(messageId) {
|
1431
|
+
return this.repository.getBranches(messageId);
|
1432
|
+
}
|
1433
|
+
switchToBranch(branchId) {
|
1434
|
+
this.repository.switchToBranch(branchId);
|
1435
|
+
this.updateVercelMessages(this.repository.getMessages());
|
1436
|
+
}
|
1437
|
+
async append(message) {
|
1438
|
+
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1439
|
+
throw new Error("Only text content is supported by Vercel AI SDK.");
|
1440
|
+
const newMessages = sliceMessagesUntil(
|
1441
|
+
this.vercel.messages,
|
1442
|
+
message.parentId
|
1443
|
+
);
|
1444
|
+
this.vercel.setMessages(newMessages);
|
1445
|
+
await this.vercel.append({
|
1446
|
+
role: "user",
|
1447
|
+
content: message.content[0].text
|
1448
|
+
});
|
1449
|
+
}
|
1450
|
+
async startRun(parentId) {
|
1451
|
+
const reloadMaybe = "reload" in this.vercel ? this.vercel.reload : void 0;
|
1452
|
+
if (!reloadMaybe)
|
1453
|
+
throw new Error(
|
1454
|
+
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1455
|
+
);
|
1456
|
+
const newMessages = sliceMessagesUntil(this.vercel.messages, parentId);
|
1457
|
+
this.vercel.setMessages(newMessages);
|
1458
|
+
await reloadMaybe();
|
1459
|
+
}
|
1460
|
+
cancelRun() {
|
1461
|
+
const previousMessage = this.vercel.messages.at(-1);
|
1462
|
+
this.vercel.stop();
|
1463
|
+
if (this.assistantOptimisticId) {
|
1464
|
+
this.repository.deleteMessage(this.assistantOptimisticId);
|
1465
|
+
this.assistantOptimisticId = null;
|
1466
|
+
}
|
1467
|
+
let messages = this.repository.getMessages();
|
1468
|
+
if (previousMessage?.role === "user" && previousMessage.id === messages.at(-1)?.id) {
|
1469
|
+
this.vercel.setInput(previousMessage.content);
|
1470
|
+
this.repository.deleteMessage(previousMessage.id);
|
1471
|
+
messages = this.repository.getMessages();
|
1472
|
+
}
|
1473
|
+
setTimeout(() => {
|
1474
|
+
this.updateVercelMessages(messages);
|
1475
|
+
}, 0);
|
1476
|
+
}
|
1477
|
+
subscribe(callback) {
|
1478
|
+
this._subscriptions.add(callback);
|
1479
|
+
return () => this._subscriptions.delete(callback);
|
1480
|
+
}
|
1481
|
+
updateVercelMessages = (messages) => {
|
1482
|
+
this.vercel.setMessages(
|
1483
|
+
messages.map(getVercelAIMessage).filter((m) => m != null)
|
1484
|
+
);
|
1485
|
+
};
|
1486
|
+
onVercelUpdated() {
|
1487
|
+
if (this.useVercel.getState().vercel !== this.vercel) {
|
1488
|
+
this.useVercel.setState({ vercel: this.vercel });
|
1489
|
+
}
|
1490
|
+
}
|
1491
|
+
updateData = (isRunning, vm) => {
|
1342
1492
|
for (let i = 0; i < vm.length; i++) {
|
1343
1493
|
const message = vm[i];
|
1344
1494
|
const parent = vm[i - 1];
|
1345
|
-
|
1495
|
+
this.repository.addOrUpdateMessage(parent?.id ?? null, message);
|
1346
1496
|
}
|
1347
|
-
if (
|
1348
|
-
|
1349
|
-
|
1497
|
+
if (this.assistantOptimisticId) {
|
1498
|
+
this.repository.deleteMessage(this.assistantOptimisticId);
|
1499
|
+
this.assistantOptimisticId = null;
|
1350
1500
|
}
|
1351
1501
|
if (hasUpcomingMessage(isRunning, vm)) {
|
1352
|
-
|
1502
|
+
this.assistantOptimisticId = this.repository.appendOptimisticMessage(
|
1353
1503
|
vm.at(-1)?.id ?? null,
|
1354
1504
|
{
|
1355
1505
|
role: "assistant",
|
@@ -1357,330 +1507,220 @@ var useVercelAIThreadState = (vercel) => {
|
|
1357
1507
|
}
|
1358
1508
|
);
|
1359
1509
|
}
|
1360
|
-
|
1361
|
-
|
1362
|
-
}, [converter, data, isRunning, vercel.messages]);
|
1363
|
-
const getBranches2 = useCallback7(
|
1364
|
-
(messageId) => {
|
1365
|
-
return data.getBranches(messageId);
|
1366
|
-
},
|
1367
|
-
[data]
|
1368
|
-
);
|
1369
|
-
const switchToBranch2 = useCallbackRef3((messageId) => {
|
1370
|
-
data.switchToBranch(messageId);
|
1371
|
-
vercel.setMessages(
|
1372
|
-
data.getMessages().map(getVercelMessage).filter((m) => m != null)
|
1510
|
+
this.repository.resetHead(
|
1511
|
+
this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
|
1373
1512
|
);
|
1513
|
+
this.messages = this.repository.getMessages();
|
1514
|
+
this.isRunning = isRunning;
|
1515
|
+
for (const callback of this._subscriptions) callback();
|
1516
|
+
};
|
1517
|
+
unstable_synchronizer = () => {
|
1518
|
+
const { vercel } = this.useVercel();
|
1519
|
+
useVercelAIThreadSync(vercel, this.updateData);
|
1520
|
+
useVercelAIComposerSync(vercel);
|
1521
|
+
return null;
|
1522
|
+
};
|
1523
|
+
};
|
1524
|
+
|
1525
|
+
// src/runtime/vercel-ai/ui/use-chat/useVercelUseChatRuntime.tsx
|
1526
|
+
var useVercelUseChatRuntime = (chatHelpers) => {
|
1527
|
+
const [runtime] = useState4(() => new VercelAIRuntime(chatHelpers));
|
1528
|
+
useInsertionEffect2(() => {
|
1529
|
+
runtime.vercel = chatHelpers;
|
1374
1530
|
});
|
1375
|
-
|
1376
|
-
|
1377
|
-
if (!reloadMaybe)
|
1378
|
-
throw new Error(
|
1379
|
-
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1380
|
-
);
|
1381
|
-
const newMessages = sliceMessagesUntil(vercel.messages, parentId);
|
1382
|
-
vercel.setMessages(newMessages);
|
1383
|
-
await reloadMaybe();
|
1531
|
+
useEffect10(() => {
|
1532
|
+
runtime.onVercelUpdated();
|
1384
1533
|
});
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1534
|
+
return runtime;
|
1535
|
+
};
|
1536
|
+
|
1537
|
+
// src/runtime/vercel-ai/ui/use-assistant/useVercelUseAssistantRuntime.tsx
|
1538
|
+
import { useEffect as useEffect11, useInsertionEffect as useInsertionEffect3, useState as useState5 } from "react";
|
1539
|
+
var useVercelUseAssistantRuntime = (assistantHelpers) => {
|
1540
|
+
const [runtime] = useState5(() => new VercelAIRuntime(assistantHelpers));
|
1541
|
+
useInsertionEffect3(() => {
|
1542
|
+
runtime.vercel = assistantHelpers;
|
1394
1543
|
});
|
1395
|
-
|
1396
|
-
|
1397
|
-
vercel.stop();
|
1398
|
-
if (lastMessage?.role === "user") {
|
1399
|
-
vercel.setInput(lastMessage.content);
|
1400
|
-
}
|
1544
|
+
useEffect11(() => {
|
1545
|
+
runtime.onVercelUpdated();
|
1401
1546
|
});
|
1402
|
-
return
|
1403
|
-
() => ({
|
1404
|
-
isRunning,
|
1405
|
-
messages,
|
1406
|
-
getBranches: getBranches2,
|
1407
|
-
switchToBranch: switchToBranch2,
|
1408
|
-
append,
|
1409
|
-
startRun,
|
1410
|
-
cancelRun: cancelRun2
|
1411
|
-
}),
|
1412
|
-
[
|
1413
|
-
isRunning,
|
1414
|
-
messages,
|
1415
|
-
getBranches2,
|
1416
|
-
switchToBranch2,
|
1417
|
-
append,
|
1418
|
-
startRun,
|
1419
|
-
cancelRun2
|
1420
|
-
]
|
1421
|
-
);
|
1547
|
+
return runtime;
|
1422
1548
|
};
|
1423
1549
|
|
1424
|
-
// src/
|
1425
|
-
import {
|
1426
|
-
var VercelAIAssistantProvider = ({
|
1427
|
-
children,
|
1428
|
-
...rest
|
1429
|
-
}) => {
|
1430
|
-
const context = useDummyAIAssistantContext();
|
1431
|
-
const vercel = "chat" in rest ? rest.chat : rest.assistant;
|
1432
|
-
const threadState = useVercelAIThreadState(vercel);
|
1433
|
-
useMemo6(() => {
|
1434
|
-
context.useThread.setState(threadState, true);
|
1435
|
-
}, [context, threadState]);
|
1436
|
-
useMemo6(() => {
|
1437
|
-
context.useComposer.setState({
|
1438
|
-
value: vercel.input,
|
1439
|
-
setValue: vercel.setInput
|
1440
|
-
});
|
1441
|
-
}, [context, vercel.input, vercel.setInput]);
|
1442
|
-
return /* @__PURE__ */ jsx21(AssistantContext.Provider, { value: context, children });
|
1443
|
-
};
|
1550
|
+
// src/context/providers/AssistantRuntimeProvider.tsx
|
1551
|
+
import { memo } from "react";
|
1444
1552
|
|
1445
|
-
// src/
|
1446
|
-
import {
|
1447
|
-
useCallback as useCallback8,
|
1448
|
-
useMemo as useMemo7,
|
1449
|
-
useState as useState5
|
1450
|
-
} from "react";
|
1451
|
-
import { jsx as jsx22 } from "react/jsx-runtime";
|
1452
|
-
var vercelToThreadMessage2 = (converter, rawMessage) => {
|
1453
|
-
const message = converter(rawMessage);
|
1454
|
-
return {
|
1455
|
-
id: message.id,
|
1456
|
-
role: message.role,
|
1457
|
-
content: [{ type: "ui", display: message.display }],
|
1458
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1459
|
-
...{ status: "done" },
|
1460
|
-
[symbolInnerRSCMessage]: rawMessage
|
1461
|
-
};
|
1462
|
-
};
|
1463
|
-
var EMPTY_BRANCHES = [];
|
1464
|
-
var getBranches = () => {
|
1465
|
-
return EMPTY_BRANCHES;
|
1466
|
-
};
|
1467
|
-
var switchToBranch = () => {
|
1468
|
-
throw new Error(
|
1469
|
-
"Branch switching is not supported by VercelRSCAssistantProvider."
|
1470
|
-
);
|
1471
|
-
};
|
1472
|
-
var cancelRun = () => {
|
1473
|
-
if (process.env["NODE_ENV"] === "development") {
|
1474
|
-
console.warn(
|
1475
|
-
"Run cancellation is not supported by VercelRSCAssistantProvider."
|
1476
|
-
);
|
1477
|
-
}
|
1478
|
-
};
|
1479
|
-
var VercelRSCAssistantProvider = ({
|
1480
|
-
children,
|
1481
|
-
convertMessage,
|
1482
|
-
messages: vercelMessages,
|
1483
|
-
append: appendCallback,
|
1484
|
-
edit,
|
1485
|
-
reload
|
1486
|
-
}) => {
|
1487
|
-
const context = useDummyAIAssistantContext();
|
1488
|
-
const [isRunning, setIsRunning] = useState5(false);
|
1489
|
-
const withRunning = useCallback8((callback) => {
|
1490
|
-
setIsRunning(true);
|
1491
|
-
return callback.finally(() => setIsRunning(false));
|
1492
|
-
}, []);
|
1493
|
-
const [converter, convertCallback] = useMemo7(() => {
|
1494
|
-
const rscConverter = convertMessage ?? ((m) => m);
|
1495
|
-
const convertCallback2 = (m, cache) => {
|
1496
|
-
if (cache) return cache;
|
1497
|
-
return vercelToThreadMessage2(rscConverter, m);
|
1498
|
-
};
|
1499
|
-
return [new ThreadMessageConverter(), convertCallback2];
|
1500
|
-
}, [convertMessage]);
|
1501
|
-
const messages = useMemo7(() => {
|
1502
|
-
return converter.convertMessages(convertCallback, vercelMessages);
|
1503
|
-
}, [converter, convertCallback, vercelMessages]);
|
1504
|
-
const append = useCallback8(
|
1505
|
-
async (message) => {
|
1506
|
-
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
1507
|
-
if (!edit)
|
1508
|
-
throw new Error(
|
1509
|
-
"Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
|
1510
|
-
);
|
1511
|
-
await withRunning(edit(message));
|
1512
|
-
} else {
|
1513
|
-
await withRunning(appendCallback(message));
|
1514
|
-
}
|
1515
|
-
},
|
1516
|
-
[context, withRunning, appendCallback, edit]
|
1517
|
-
);
|
1518
|
-
const startRun = useCallback8(
|
1519
|
-
async (parentId) => {
|
1520
|
-
if (!reload)
|
1521
|
-
throw new Error(
|
1522
|
-
"Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
|
1523
|
-
);
|
1524
|
-
await withRunning(reload(parentId));
|
1525
|
-
},
|
1526
|
-
[withRunning, reload]
|
1527
|
-
);
|
1528
|
-
useMemo7(() => {
|
1529
|
-
context.useThread.setState(
|
1530
|
-
{
|
1531
|
-
messages,
|
1532
|
-
isRunning,
|
1533
|
-
getBranches,
|
1534
|
-
switchToBranch,
|
1535
|
-
append,
|
1536
|
-
startRun,
|
1537
|
-
cancelRun
|
1538
|
-
},
|
1539
|
-
true
|
1540
|
-
);
|
1541
|
-
}, [context, messages, isRunning, append, startRun]);
|
1542
|
-
return /* @__PURE__ */ jsx22(AssistantContext.Provider, { value: context, children });
|
1543
|
-
};
|
1553
|
+
// src/context/providers/ThreadProvider.tsx
|
1554
|
+
import { useEffect as useEffect12, useInsertionEffect as useInsertionEffect4, useRef as useRef4, useState as useState6 } from "react";
|
1544
1555
|
|
1545
|
-
// src/
|
1546
|
-
import {
|
1547
|
-
useEffect as useEffect4,
|
1548
|
-
useInsertionEffect,
|
1549
|
-
useRef as useRef5,
|
1550
|
-
useState as useState6
|
1551
|
-
} from "react";
|
1556
|
+
// src/context/stores/Composer.ts
|
1552
1557
|
import { create as create6 } from "zustand";
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
withModifications(callback) {
|
1564
|
-
const res = callback(this.repository);
|
1565
|
-
this.flushCallback(this.repository.getMessages());
|
1566
|
-
return res;
|
1567
|
-
}
|
1568
|
-
};
|
1569
|
-
|
1570
|
-
// src/adapters/core/utils/useAssistantContext.tsx
|
1571
|
-
var makeThreadStore = (runtimeRef) => {
|
1572
|
-
const repository = new AssistantMessageRepository((messages) => {
|
1573
|
-
useThread.setState({ messages });
|
1574
|
-
});
|
1575
|
-
const useThread = create6(() => ({
|
1576
|
-
messages: [],
|
1577
|
-
isRunning: false,
|
1578
|
-
getBranches: (messageId) => repository.getBranches(messageId),
|
1579
|
-
switchToBranch: (branchId) => {
|
1580
|
-
repository.withModifications((repository2) => {
|
1581
|
-
repository2.switchToBranch(branchId);
|
1582
|
-
});
|
1583
|
-
},
|
1584
|
-
startRun: async (parentId) => {
|
1585
|
-
const optimisticId = repository.withModifications((repository2) => {
|
1586
|
-
const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
|
1587
|
-
role: "assistant",
|
1588
|
-
content: [{ type: "text", text: "" }]
|
1589
|
-
});
|
1590
|
-
repository2.resetHead(optimisticId2);
|
1591
|
-
return optimisticId2;
|
1592
|
-
});
|
1593
|
-
const { id } = await runtimeRef.current.startRun(parentId);
|
1594
|
-
repository.withModifications((repository2) => {
|
1595
|
-
repository2.deleteMessage(optimisticId, id);
|
1596
|
-
});
|
1597
|
-
},
|
1598
|
-
append: async (message) => {
|
1599
|
-
const [parentOptimisticId, optimisticId] = repository.withModifications(
|
1600
|
-
(repository2) => {
|
1601
|
-
const parentOptimisticId2 = repository2.appendOptimisticMessage(
|
1602
|
-
message.parentId,
|
1603
|
-
{
|
1604
|
-
role: "user",
|
1605
|
-
content: message.content
|
1606
|
-
}
|
1607
|
-
);
|
1608
|
-
const optimisticId2 = repository2.appendOptimisticMessage(
|
1609
|
-
parentOptimisticId2,
|
1610
|
-
{
|
1611
|
-
role: "assistant",
|
1612
|
-
content: [{ type: "text", text: "" }]
|
1613
|
-
}
|
1614
|
-
);
|
1615
|
-
repository2.resetHead(optimisticId2);
|
1616
|
-
return [parentOptimisticId2, optimisticId2];
|
1617
|
-
}
|
1618
|
-
);
|
1619
|
-
const { parentId, id } = await runtimeRef.current.append(message);
|
1620
|
-
repository.withModifications((repository2) => {
|
1621
|
-
repository2.deleteMessage(parentOptimisticId, parentId);
|
1622
|
-
repository2.deleteMessage(optimisticId, id);
|
1558
|
+
var makeComposerStore = (useThread) => create6()((set, get, store) => {
|
1559
|
+
return {
|
1560
|
+
...makeBaseComposer(set, get, store),
|
1561
|
+
isEditing: true,
|
1562
|
+
send: () => {
|
1563
|
+
const { setValue, value } = get();
|
1564
|
+
setValue("");
|
1565
|
+
useThread.getState().append({
|
1566
|
+
parentId: useThread.getState().messages.at(-1)?.id ?? null,
|
1567
|
+
content: [{ type: "text", text: value }]
|
1623
1568
|
});
|
1624
1569
|
},
|
1570
|
+
cancel: () => {
|
1571
|
+
const thread = useThread.getState();
|
1572
|
+
if (!thread.isRunning) return false;
|
1573
|
+
useThread.getState().cancelRun();
|
1574
|
+
return true;
|
1575
|
+
}
|
1576
|
+
};
|
1577
|
+
});
|
1578
|
+
|
1579
|
+
// src/context/stores/Thread.ts
|
1580
|
+
import { create as create7 } from "zustand";
|
1581
|
+
var makeThreadStore = (runtimeRef) => {
|
1582
|
+
const useThread = create7(() => ({
|
1583
|
+
messages: runtimeRef.current.messages,
|
1584
|
+
isRunning: runtimeRef.current.isRunning,
|
1585
|
+
getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
|
1586
|
+
switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
|
1587
|
+
startRun: (parentId) => runtimeRef.current.startRun(parentId),
|
1588
|
+
append: (message) => runtimeRef.current.append(message),
|
1625
1589
|
cancelRun: () => runtimeRef.current.cancelRun()
|
1626
1590
|
}));
|
1627
|
-
const
|
1628
|
-
|
1629
|
-
|
1591
|
+
const onRuntimeUpdate = () => {
|
1592
|
+
useThread.setState({
|
1593
|
+
messages: runtimeRef.current.messages,
|
1594
|
+
isRunning: runtimeRef.current.isRunning
|
1630
1595
|
});
|
1631
1596
|
};
|
1632
|
-
const onRunningChange = (isRunning) => {
|
1633
|
-
useThread.setState({ isRunning });
|
1634
|
-
};
|
1635
1597
|
return {
|
1636
1598
|
useThread,
|
1637
|
-
|
1638
|
-
onRunningChange
|
1599
|
+
onRuntimeUpdate
|
1639
1600
|
};
|
1640
1601
|
};
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1602
|
+
|
1603
|
+
// src/context/stores/ThreadViewport.tsx
|
1604
|
+
import { create as create8 } from "zustand";
|
1605
|
+
var makeThreadViewportStore = () => {
|
1606
|
+
const scrollToBottomListeners = /* @__PURE__ */ new Set();
|
1607
|
+
return create8(() => ({
|
1608
|
+
isAtBottom: true,
|
1609
|
+
scrollToBottom: () => {
|
1610
|
+
for (const listener of scrollToBottomListeners) {
|
1611
|
+
listener();
|
1612
|
+
}
|
1613
|
+
},
|
1614
|
+
onScrollToBottom: (callback) => {
|
1615
|
+
scrollToBottomListeners.add(callback);
|
1616
|
+
return () => {
|
1617
|
+
scrollToBottomListeners.delete(callback);
|
1618
|
+
};
|
1619
|
+
}
|
1620
|
+
}));
|
1621
|
+
};
|
1622
|
+
|
1623
|
+
// src/context/providers/ThreadProvider.tsx
|
1624
|
+
import { jsx as jsx21, jsxs as jsxs4 } from "react/jsx-runtime";
|
1625
|
+
var ThreadProvider = ({
|
1626
|
+
children,
|
1627
|
+
runtime
|
1628
|
+
}) => {
|
1629
|
+
const runtimeRef = useRef4(runtime);
|
1630
|
+
useInsertionEffect4(() => {
|
1644
1631
|
runtimeRef.current = runtime;
|
1645
1632
|
});
|
1646
|
-
const [{ context,
|
1647
|
-
const { useThread,
|
1648
|
-
const useViewport =
|
1649
|
-
const useComposer =
|
1633
|
+
const [{ context, onRuntimeUpdate }] = useState6(() => {
|
1634
|
+
const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
|
1635
|
+
const useViewport = makeThreadViewportStore();
|
1636
|
+
const useComposer = makeComposerStore(useThread);
|
1650
1637
|
return {
|
1651
|
-
context: {
|
1652
|
-
|
1653
|
-
|
1638
|
+
context: {
|
1639
|
+
useViewport,
|
1640
|
+
useThread,
|
1641
|
+
useComposer
|
1642
|
+
},
|
1643
|
+
onRuntimeUpdate: onRuntimeUpdate2
|
1654
1644
|
};
|
1655
1645
|
});
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1646
|
+
useEffect12(() => {
|
1647
|
+
onRuntimeUpdate();
|
1648
|
+
return runtime.subscribe(onRuntimeUpdate);
|
1649
|
+
}, [onRuntimeUpdate, runtime]);
|
1650
|
+
const RuntimeSynchronizer = runtime.unstable_synchronizer;
|
1651
|
+
return /* @__PURE__ */ jsxs4(ThreadContext.Provider, { value: context, children: [
|
1652
|
+
RuntimeSynchronizer && /* @__PURE__ */ jsx21(RuntimeSynchronizer, {}),
|
1653
|
+
children
|
1654
|
+
] });
|
1655
|
+
};
|
1656
|
+
|
1657
|
+
// src/context/providers/AssistantRuntimeProvider.tsx
|
1658
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
1659
|
+
var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
|
1660
|
+
return /* @__PURE__ */ jsx22(ThreadProvider, { runtime, children });
|
1663
1661
|
};
|
1662
|
+
var AssistantRuntimeProvider = memo(AssistantRuntimeProviderImpl);
|
1664
1663
|
|
1665
|
-
// src/
|
1664
|
+
// src/runtime/vercel-deprecated/VercelAIAssistantProvider.tsx
|
1666
1665
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
1667
|
-
var
|
1668
|
-
|
1669
|
-
|
1666
|
+
var VercelUseChatRuntimeProvider = ({
|
1667
|
+
chat,
|
1668
|
+
children
|
1669
|
+
}) => {
|
1670
|
+
const runtime = useVercelUseChatRuntime(chat);
|
1671
|
+
return /* @__PURE__ */ jsx23(AssistantRuntimeProvider, { runtime, children });
|
1672
|
+
};
|
1673
|
+
var VercelUseAssistantRuntimeProvider = ({
|
1674
|
+
assistant,
|
1675
|
+
children
|
1676
|
+
}) => {
|
1677
|
+
const runtime = useVercelUseAssistantRuntime(assistant);
|
1678
|
+
return /* @__PURE__ */ jsx23(AssistantRuntimeProvider, { runtime, children });
|
1679
|
+
};
|
1680
|
+
var VercelAIAssistantProvider = ({
|
1681
|
+
children,
|
1682
|
+
...rest
|
1683
|
+
}) => {
|
1684
|
+
if ("chat" in rest) {
|
1685
|
+
return /* @__PURE__ */ jsx23(VercelUseChatRuntimeProvider, { chat: rest.chat, children });
|
1686
|
+
}
|
1687
|
+
return /* @__PURE__ */ jsx23(VercelUseAssistantRuntimeProvider, { assistant: rest.assistant, children });
|
1688
|
+
};
|
1689
|
+
|
1690
|
+
// src/runtime/vercel-deprecated/VercelRSCAssistantProvider.tsx
|
1691
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
1692
|
+
var VercelRSCAssistantProvider = ({
|
1693
|
+
children,
|
1694
|
+
...adapter
|
1695
|
+
}) => {
|
1696
|
+
const runtime = useVercelRSCRuntime(adapter);
|
1697
|
+
return /* @__PURE__ */ jsx24(AssistantRuntimeProvider, { runtime, children });
|
1670
1698
|
};
|
1671
1699
|
|
1672
|
-
// src/
|
1673
|
-
import { useState as useState7 } from "react";
|
1700
|
+
// src/runtime/local/useLocalRuntime.tsx
|
1701
|
+
import { useInsertionEffect as useInsertionEffect5, useState as useState7 } from "react";
|
1674
1702
|
|
1675
|
-
// src/
|
1703
|
+
// src/runtime/local/LocalRuntime.tsx
|
1676
1704
|
var LocalRuntime = class {
|
1677
1705
|
constructor(adapter) {
|
1678
1706
|
this.adapter = adapter;
|
1679
1707
|
}
|
1680
|
-
|
1681
|
-
_statusUpdateCallbacks = /* @__PURE__ */ new Set();
|
1708
|
+
_subscriptions = /* @__PURE__ */ new Set();
|
1682
1709
|
abortController = null;
|
1683
1710
|
repository = new MessageRepository();
|
1711
|
+
get messages() {
|
1712
|
+
return this.repository.getMessages();
|
1713
|
+
}
|
1714
|
+
get isRunning() {
|
1715
|
+
return this.abortController != null;
|
1716
|
+
}
|
1717
|
+
getBranches(messageId) {
|
1718
|
+
return this.repository.getBranches(messageId);
|
1719
|
+
}
|
1720
|
+
switchToBranch(branchId) {
|
1721
|
+
this.repository.switchToBranch(branchId);
|
1722
|
+
this.notifySubscribers();
|
1723
|
+
}
|
1684
1724
|
async append(message) {
|
1685
1725
|
const userMessageId = generateId();
|
1686
1726
|
const userMessage = {
|
@@ -1689,9 +1729,8 @@ var LocalRuntime = class {
|
|
1689
1729
|
content: message.content,
|
1690
1730
|
createdAt: /* @__PURE__ */ new Date()
|
1691
1731
|
};
|
1692
|
-
this.addOrUpdateMessage(message.parentId, userMessage);
|
1693
|
-
|
1694
|
-
return { parentId: userMessageId, id };
|
1732
|
+
this.repository.addOrUpdateMessage(message.parentId, userMessage);
|
1733
|
+
await this.startRun(userMessageId);
|
1695
1734
|
}
|
1696
1735
|
async startRun(parentId) {
|
1697
1736
|
const id = generateId();
|
@@ -1704,63 +1743,56 @@ var LocalRuntime = class {
|
|
1704
1743
|
content: [{ type: "text", text: "" }],
|
1705
1744
|
createdAt: /* @__PURE__ */ new Date()
|
1706
1745
|
};
|
1707
|
-
this.addOrUpdateMessage(parentId, message);
|
1708
|
-
|
1709
|
-
return { id };
|
1710
|
-
}
|
1711
|
-
addOrUpdateMessage(parentId, message) {
|
1712
|
-
const clone = { ...message };
|
1713
|
-
this.repository.addOrUpdateMessage(parentId, clone);
|
1714
|
-
for (const callback of this._messageUpdateCallbacks)
|
1715
|
-
callback(parentId, clone);
|
1716
|
-
}
|
1717
|
-
async run(parentId, messages, message) {
|
1718
|
-
this.cancelRun();
|
1719
|
-
for (const callback of this._statusUpdateCallbacks) callback(true);
|
1746
|
+
this.repository.addOrUpdateMessage(parentId, { ...message });
|
1747
|
+
this.abortController?.abort();
|
1720
1748
|
this.abortController = new AbortController();
|
1749
|
+
this.notifySubscribers();
|
1721
1750
|
try {
|
1722
1751
|
await this.adapter.run({
|
1723
1752
|
messages,
|
1724
1753
|
abortSignal: this.abortController.signal,
|
1725
1754
|
onUpdate: ({ content }) => {
|
1726
1755
|
message.content = content;
|
1727
|
-
this.addOrUpdateMessage(parentId, message);
|
1756
|
+
this.repository.addOrUpdateMessage(parentId, { ...message });
|
1757
|
+
this.notifySubscribers();
|
1728
1758
|
}
|
1729
1759
|
});
|
1730
1760
|
message.status = "done";
|
1731
|
-
this.addOrUpdateMessage(parentId, message);
|
1761
|
+
this.repository.addOrUpdateMessage(parentId, { ...message });
|
1732
1762
|
} catch (e) {
|
1733
1763
|
message.status = "error";
|
1734
|
-
this.addOrUpdateMessage(parentId, message);
|
1764
|
+
this.repository.addOrUpdateMessage(parentId, { ...message });
|
1735
1765
|
console.error(e);
|
1736
1766
|
} finally {
|
1737
|
-
this.
|
1767
|
+
this.abortController = null;
|
1768
|
+
this.notifySubscribers();
|
1738
1769
|
}
|
1739
1770
|
}
|
1740
1771
|
cancelRun() {
|
1741
1772
|
if (!this.abortController) return;
|
1742
1773
|
this.abortController.abort();
|
1743
1774
|
this.abortController = null;
|
1744
|
-
|
1775
|
+
this.notifySubscribers();
|
1745
1776
|
}
|
1746
|
-
|
1747
|
-
this.
|
1748
|
-
return () => this._messageUpdateCallbacks.delete(callback);
|
1777
|
+
notifySubscribers() {
|
1778
|
+
for (const callback of this._subscriptions) callback();
|
1749
1779
|
}
|
1750
|
-
|
1751
|
-
this.
|
1752
|
-
return () => this.
|
1780
|
+
subscribe(callback) {
|
1781
|
+
this._subscriptions.add(callback);
|
1782
|
+
return () => this._subscriptions.delete(callback);
|
1753
1783
|
}
|
1754
1784
|
};
|
1755
1785
|
|
1756
|
-
// src/
|
1786
|
+
// src/runtime/local/useLocalRuntime.tsx
|
1757
1787
|
var useLocalRuntime = (adapter) => {
|
1758
1788
|
const [runtime] = useState7(() => new LocalRuntime(adapter));
|
1759
|
-
|
1789
|
+
useInsertionEffect5(() => {
|
1790
|
+
runtime.adapter = adapter;
|
1791
|
+
});
|
1760
1792
|
return runtime;
|
1761
1793
|
};
|
1762
1794
|
|
1763
|
-
// src/
|
1795
|
+
// src/runtime/local/vercel/VercelModelAdapter.tsx
|
1764
1796
|
import { streamText } from "ai";
|
1765
1797
|
var VercelModelAdapter = class {
|
1766
1798
|
constructor(model) {
|
@@ -1803,6 +1835,7 @@ var VercelModelAdapter = class {
|
|
1803
1835
|
};
|
1804
1836
|
export {
|
1805
1837
|
actionBar_exports as ActionBarPrimitive,
|
1838
|
+
AssistantRuntimeProvider,
|
1806
1839
|
branchPicker_exports as BranchPickerPrimitive,
|
1807
1840
|
composer_exports as ComposerPrimitive,
|
1808
1841
|
contentPart_exports as ContentPartPrimitive,
|
@@ -1810,15 +1843,20 @@ export {
|
|
1810
1843
|
thread_exports as ThreadPrimitive,
|
1811
1844
|
VercelAIAssistantProvider,
|
1812
1845
|
VercelRSCAssistantProvider,
|
1813
|
-
|
1846
|
+
getVercelAIMessage,
|
1847
|
+
getVercelRSCMessage,
|
1814
1848
|
VercelModelAdapter as unstable_VercelModelAdapter,
|
1815
|
-
|
1816
|
-
|
1849
|
+
useComposerContext as unstable_useComposerContext,
|
1850
|
+
useContentPartContext as unstable_useContentPartContext,
|
1817
1851
|
useLocalRuntime as unstable_useLocalRuntime,
|
1818
1852
|
useMessageContext as unstable_useMessageContext,
|
1853
|
+
useThreadContext as unstable_useThreadContext,
|
1819
1854
|
useBeginMessageEdit,
|
1820
1855
|
useCopyMessage,
|
1821
1856
|
useGoToNextBranch,
|
1822
1857
|
useGoToPreviousBranch,
|
1823
|
-
useReloadMessage
|
1858
|
+
useReloadMessage,
|
1859
|
+
useVercelRSCRuntime,
|
1860
|
+
useVercelUseAssistantRuntime,
|
1861
|
+
useVercelUseChatRuntime
|
1824
1862
|
};
|