@assistant-ui/react 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js ADDED
@@ -0,0 +1,1642 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ ActionBarPrimitive: () => actionBar_exports,
34
+ AssistantRuntimeProvider: () => AssistantRuntimeProvider,
35
+ BranchPickerPrimitive: () => branchPicker_exports,
36
+ ComposerPrimitive: () => composer_exports,
37
+ ContentPartPrimitive: () => contentPart_exports,
38
+ INTERNAL: () => internal_exports,
39
+ MessagePrimitive: () => message_exports,
40
+ ThreadPrimitive: () => thread_exports,
41
+ useBeginMessageEdit: () => useBeginMessageEdit,
42
+ useCopyMessage: () => useCopyMessage,
43
+ useGoToNextBranch: () => useGoToNextBranch,
44
+ useGoToPreviousBranch: () => useGoToPreviousBranch,
45
+ useLocalRuntime: () => useLocalRuntime,
46
+ useReloadMessage: () => useReloadMessage
47
+ });
48
+ module.exports = __toCommonJS(src_exports);
49
+
50
+ // src/actions/useCopyMessage.tsx
51
+ var import_react4 = require("react");
52
+
53
+ // src/context/MessageContext.ts
54
+ var import_react = require("react");
55
+ var MessageContext = (0, import_react.createContext)(null);
56
+ var useMessageContext = () => {
57
+ const context = (0, import_react.useContext)(MessageContext);
58
+ if (!context)
59
+ throw new Error(
60
+ "This component can only be used inside a component passed to <ThreadPrimitive.Messages components={...} />."
61
+ );
62
+ return context;
63
+ };
64
+
65
+ // src/utils/combined/useCombinedStore.ts
66
+ var import_react3 = require("react");
67
+
68
+ // src/utils/combined/createCombinedStore.ts
69
+ var import_react2 = require("react");
70
+ var createCombinedStore = (stores) => {
71
+ const subscribe = (callback) => {
72
+ const unsubscribes = stores.map((store) => store.subscribe(callback));
73
+ return () => {
74
+ for (const unsub of unsubscribes) {
75
+ unsub();
76
+ }
77
+ };
78
+ };
79
+ return (selector) => {
80
+ const getSnapshot = () => selector(...stores.map((store) => store.getState()));
81
+ return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
82
+ };
83
+ };
84
+
85
+ // src/utils/combined/useCombinedStore.ts
86
+ var useCombinedStore = (stores, selector) => {
87
+ const useCombined = (0, import_react3.useMemo)(() => createCombinedStore(stores), stores);
88
+ return useCombined(selector);
89
+ };
90
+
91
+ // src/utils/getMessageText.tsx
92
+ var getMessageText = (message) => {
93
+ const textParts = message.content.filter(
94
+ (part) => part.type === "text"
95
+ );
96
+ return textParts.map((part) => part.text).join("\n\n");
97
+ };
98
+
99
+ // src/actions/useCopyMessage.tsx
100
+ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
101
+ const { useMessage, useComposer } = useMessageContext();
102
+ const hasCopyableContent = useCombinedStore(
103
+ [useMessage, useComposer],
104
+ (m, c) => {
105
+ return c.isEditing || m.message.content.some((c2) => c2.type === "text");
106
+ }
107
+ );
108
+ const callback = (0, import_react4.useCallback)(() => {
109
+ const { isEditing, value: composerValue } = useComposer.getState();
110
+ const { message, setIsCopied } = useMessage.getState();
111
+ const valueToCopy = isEditing ? composerValue : getMessageText(message);
112
+ navigator.clipboard.writeText(valueToCopy);
113
+ setIsCopied(true);
114
+ setTimeout(() => setIsCopied(false), copiedDuration);
115
+ }, [useComposer, useMessage, copiedDuration]);
116
+ if (!hasCopyableContent) return null;
117
+ return callback;
118
+ };
119
+
120
+ // src/actions/useReloadMessage.tsx
121
+ var import_react6 = require("react");
122
+
123
+ // src/context/ThreadContext.ts
124
+ var import_react5 = require("react");
125
+ var ThreadContext = (0, import_react5.createContext)(null);
126
+ var useThreadContext = () => {
127
+ const context = (0, import_react5.useContext)(ThreadContext);
128
+ if (!context)
129
+ throw new Error("This component must be used within an AssistantRuntimeProvider.");
130
+ return context;
131
+ };
132
+
133
+ // src/actions/useReloadMessage.tsx
134
+ var useReloadMessage = () => {
135
+ const { useThread, useViewport } = useThreadContext();
136
+ const { useMessage } = useMessageContext();
137
+ const disabled = useCombinedStore(
138
+ [useThread, useMessage],
139
+ (t, m) => t.isRunning || m.message.role !== "assistant"
140
+ );
141
+ const callback = (0, import_react6.useCallback)(() => {
142
+ const { parentId } = useMessage.getState();
143
+ useThread.getState().startRun(parentId);
144
+ useViewport.getState().scrollToBottom();
145
+ }, [useMessage, useThread, useViewport]);
146
+ if (disabled) return null;
147
+ return callback;
148
+ };
149
+
150
+ // src/actions/useBeginMessageEdit.tsx
151
+ var import_react7 = require("react");
152
+ var useBeginMessageEdit = () => {
153
+ const { useMessage, useComposer } = useMessageContext();
154
+ const disabled = useCombinedStore(
155
+ [useMessage, useComposer],
156
+ (m, c) => m.message.role !== "user" || c.isEditing
157
+ );
158
+ const callback = (0, import_react7.useCallback)(() => {
159
+ const { edit } = useComposer.getState();
160
+ edit();
161
+ }, [useComposer]);
162
+ if (disabled) return null;
163
+ return callback;
164
+ };
165
+
166
+ // src/actions/useGoToNextBranch.tsx
167
+ var import_react8 = require("react");
168
+ var useGoToNextBranch = () => {
169
+ const { useThread } = useThreadContext();
170
+ const { useMessage, useComposer } = useMessageContext();
171
+ const disabled = useCombinedStore(
172
+ [useMessage, useComposer],
173
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
174
+ );
175
+ const callback = (0, import_react8.useCallback)(() => {
176
+ const { message, branches } = useMessage.getState();
177
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
178
+ }, [useMessage, useThread]);
179
+ if (disabled) return null;
180
+ return callback;
181
+ };
182
+
183
+ // src/actions/useGoToPreviousBranch.tsx
184
+ var import_react9 = require("react");
185
+ var useGoToPreviousBranch = () => {
186
+ const { useThread } = useThreadContext();
187
+ const { useMessage, useComposer } = useMessageContext();
188
+ const disabled = useCombinedStore(
189
+ [useMessage, useComposer],
190
+ (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
191
+ );
192
+ const callback = (0, import_react9.useCallback)(() => {
193
+ const { message, branches } = useMessage.getState();
194
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
195
+ }, [useMessage, useThread]);
196
+ if (disabled) return null;
197
+ return callback;
198
+ };
199
+
200
+ // src/primitives/thread/index.ts
201
+ var thread_exports = {};
202
+ __export(thread_exports, {
203
+ Empty: () => ThreadEmpty,
204
+ If: () => ThreadIf,
205
+ Messages: () => ThreadMessages,
206
+ Root: () => ThreadRoot,
207
+ ScrollToBottom: () => ThreadScrollToBottom,
208
+ Suggestion: () => ThreadSuggestion,
209
+ Viewport: () => ThreadViewport
210
+ });
211
+
212
+ // src/primitives/thread/ThreadRoot.tsx
213
+ var import_react_primitive = require("@radix-ui/react-primitive");
214
+ var import_react10 = require("react");
215
+ var import_jsx_runtime = require("react/jsx-runtime");
216
+ var ThreadRoot = (0, import_react10.forwardRef)(
217
+ (props, ref) => {
218
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
219
+ }
220
+ );
221
+
222
+ // src/primitives/thread/ThreadIf.tsx
223
+ var useThreadIf = (props) => {
224
+ const { useThread } = useThreadContext();
225
+ return useThread((thread) => {
226
+ if (props.empty === true && thread.messages.length !== 0) return false;
227
+ if (props.empty === false && thread.messages.length === 0) return false;
228
+ if (props.running === true && !thread.isRunning) return false;
229
+ if (props.running === false && thread.isRunning) return false;
230
+ return true;
231
+ });
232
+ };
233
+ var ThreadIf = ({ children, ...query }) => {
234
+ const result = useThreadIf(query);
235
+ return result ? children : null;
236
+ };
237
+
238
+ // src/primitives/thread/ThreadEmpty.tsx
239
+ var import_jsx_runtime2 = require("react/jsx-runtime");
240
+ var ThreadEmpty = ({ children }) => {
241
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThreadIf, { empty: true, children });
242
+ };
243
+
244
+ // src/primitives/thread/ThreadViewport.tsx
245
+ var import_primitive = require("@radix-ui/primitive");
246
+ var import_react_compose_refs = require("@radix-ui/react-compose-refs");
247
+ var import_react_primitive2 = require("@radix-ui/react-primitive");
248
+ var import_react13 = require("react");
249
+
250
+ // src/utils/hooks/useOnResizeContent.tsx
251
+ var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
252
+ var import_react11 = require("react");
253
+ var useOnResizeContent = (ref, callback) => {
254
+ const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
255
+ (0, import_react11.useEffect)(() => {
256
+ const el = ref.current;
257
+ if (!el) return;
258
+ const resizeObserver = new ResizeObserver(() => {
259
+ callbackRef();
260
+ });
261
+ const mutationObserver = new MutationObserver((mutations) => {
262
+ for (const mutation of mutations) {
263
+ for (const node of mutation.addedNodes) {
264
+ if (node instanceof Element) {
265
+ resizeObserver.observe(node);
266
+ }
267
+ }
268
+ for (const node of mutation.removedNodes) {
269
+ if (node instanceof Element) {
270
+ resizeObserver.unobserve(node);
271
+ }
272
+ }
273
+ }
274
+ callbackRef();
275
+ });
276
+ resizeObserver.observe(el);
277
+ mutationObserver.observe(el, { childList: true });
278
+ for (const child of el.children) {
279
+ resizeObserver.observe(child);
280
+ }
281
+ return () => {
282
+ resizeObserver.disconnect();
283
+ mutationObserver.disconnect();
284
+ };
285
+ }, [ref.current, callbackRef]);
286
+ };
287
+
288
+ // src/utils/hooks/useOnScrollToBottom.tsx
289
+ var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
290
+ var import_react12 = require("react");
291
+ var useOnScrollToBottom = (callback) => {
292
+ const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
293
+ const { useViewport } = useThreadContext();
294
+ (0, import_react12.useEffect)(() => {
295
+ return useViewport.getState().onScrollToBottom(() => {
296
+ callbackRef();
297
+ });
298
+ }, [useViewport, callbackRef]);
299
+ };
300
+
301
+ // src/primitives/thread/ThreadViewport.tsx
302
+ var import_jsx_runtime3 = require("react/jsx-runtime");
303
+ var ThreadViewport = (0, import_react13.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
304
+ const messagesEndRef = (0, import_react13.useRef)(null);
305
+ const divRef = (0, import_react13.useRef)(null);
306
+ const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, divRef);
307
+ const { useViewport } = useThreadContext();
308
+ const firstRenderRef = (0, import_react13.useRef)(true);
309
+ const isScrollingToBottomRef = (0, import_react13.useRef)(false);
310
+ const lastScrollTop = (0, import_react13.useRef)(0);
311
+ const scrollToBottom = () => {
312
+ const div = messagesEndRef.current;
313
+ if (!div || !autoScroll) return;
314
+ const behavior = firstRenderRef.current ? "instant" : "auto";
315
+ firstRenderRef.current = false;
316
+ isScrollingToBottomRef.current = true;
317
+ div.scrollIntoView({ behavior });
318
+ };
319
+ useOnResizeContent(divRef, () => {
320
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
321
+ handleScroll();
322
+ } else {
323
+ scrollToBottom();
324
+ }
325
+ });
326
+ useOnScrollToBottom(() => {
327
+ scrollToBottom();
328
+ });
329
+ const handleScroll = () => {
330
+ const div = divRef.current;
331
+ if (!div) return;
332
+ const isAtBottom = useViewport.getState().isAtBottom;
333
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
334
+ if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
335
+ } else if (newIsAtBottom !== isAtBottom) {
336
+ isScrollingToBottomRef.current = false;
337
+ useViewport.setState({ isAtBottom: newIsAtBottom });
338
+ }
339
+ lastScrollTop.current = div.scrollTop;
340
+ };
341
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
342
+ import_react_primitive2.Primitive.div,
343
+ {
344
+ ...rest,
345
+ onScroll: (0, import_primitive.composeEventHandlers)(onScroll, handleScroll),
346
+ ref,
347
+ children: [
348
+ children,
349
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
350
+ ]
351
+ }
352
+ );
353
+ });
354
+
355
+ // src/primitives/thread/ThreadMessages.tsx
356
+ var import_react16 = require("react");
357
+
358
+ // src/context/providers/MessageProvider.tsx
359
+ var import_react14 = require("react");
360
+ var import_zustand2 = require("zustand");
361
+
362
+ // src/context/stores/MessageComposer.ts
363
+ var import_zustand = require("zustand");
364
+
365
+ // src/context/stores/BaseComposer.ts
366
+ var makeBaseComposer = (set) => ({
367
+ value: "",
368
+ setValue: (value) => {
369
+ set({ value });
370
+ }
371
+ });
372
+
373
+ // src/context/stores/MessageComposer.ts
374
+ var makeEditComposerStore = ({
375
+ onEdit,
376
+ onSend
377
+ }) => (0, import_zustand.create)()((set, get, store) => ({
378
+ ...makeBaseComposer(set, get, store),
379
+ isEditing: false,
380
+ edit: () => {
381
+ const value = onEdit();
382
+ set({ isEditing: true, value });
383
+ },
384
+ send: () => {
385
+ const value = get().value;
386
+ set({ isEditing: false });
387
+ onSend(value);
388
+ },
389
+ cancel: () => {
390
+ if (!get().isEditing) return false;
391
+ set({ isEditing: false });
392
+ return true;
393
+ }
394
+ }));
395
+
396
+ // src/context/providers/MessageProvider.tsx
397
+ var import_jsx_runtime4 = require("react/jsx-runtime");
398
+ var getIsLast = (thread, message) => {
399
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
400
+ };
401
+ var syncMessage = (thread, useMessage, messageIndex) => {
402
+ const parentId = thread.messages[messageIndex - 1]?.id ?? null;
403
+ const message = thread.messages[messageIndex];
404
+ if (!message) return;
405
+ const isLast = getIsLast(thread, message);
406
+ const branches = thread.getBranches(message.id);
407
+ const currentState = useMessage.getState();
408
+ if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
409
+ return;
410
+ useMessage.setState({
411
+ message,
412
+ parentId,
413
+ branches,
414
+ isLast
415
+ });
416
+ };
417
+ var useMessageContext2 = (messageIndex) => {
418
+ const { useThread } = useThreadContext();
419
+ const [context] = (0, import_react14.useState)(() => {
420
+ const useMessage = (0, import_zustand2.create)((set) => ({
421
+ message: null,
422
+ parentId: null,
423
+ branches: [],
424
+ isLast: false,
425
+ inProgressIndicator: null,
426
+ isCopied: false,
427
+ isHovering: false,
428
+ setInProgressIndicator: (value) => {
429
+ set({ inProgressIndicator: value });
430
+ },
431
+ setIsCopied: (value) => {
432
+ set({ isCopied: value });
433
+ },
434
+ setIsHovering: (value) => {
435
+ set({ isHovering: value });
436
+ }
437
+ }));
438
+ const useComposer = makeEditComposerStore({
439
+ onEdit: () => {
440
+ const message = useMessage.getState().message;
441
+ if (message.role !== "user")
442
+ throw new Error(
443
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
444
+ );
445
+ const text = getMessageText(message);
446
+ return text;
447
+ },
448
+ onSend: (text) => {
449
+ const { message, parentId } = useMessage.getState();
450
+ if (message.role !== "user")
451
+ throw new Error(
452
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
453
+ );
454
+ const nonTextParts = message.content.filter(
455
+ (part) => part.type !== "text" && part.type !== "ui"
456
+ );
457
+ useThread.getState().append({
458
+ parentId,
459
+ content: [{ type: "text", text }, ...nonTextParts]
460
+ });
461
+ }
462
+ });
463
+ syncMessage(useThread.getState(), useMessage, messageIndex);
464
+ return { useMessage, useComposer };
465
+ });
466
+ (0, import_react14.useEffect)(() => {
467
+ return useThread.subscribe((thread) => {
468
+ syncMessage(thread, context.useMessage, messageIndex);
469
+ });
470
+ }, [context, useThread, messageIndex]);
471
+ return context;
472
+ };
473
+ var MessageProvider = ({
474
+ messageIndex,
475
+ children
476
+ }) => {
477
+ const context = useMessageContext2(messageIndex);
478
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
479
+ };
480
+
481
+ // src/context/ComposerContext.ts
482
+ var import_react15 = require("react");
483
+ var useComposerContext = () => {
484
+ const { useComposer } = useThreadContext();
485
+ const { useComposer: useEditComposer } = (0, import_react15.useContext)(MessageContext) ?? {};
486
+ return (0, import_react15.useMemo)(
487
+ () => ({
488
+ useComposer: useEditComposer ?? useComposer,
489
+ type: useEditComposer ? "edit" : "new"
490
+ }),
491
+ [useEditComposer, useComposer]
492
+ );
493
+ };
494
+
495
+ // src/primitives/composer/ComposerIf.tsx
496
+ var useComposerIf = (props) => {
497
+ const { useComposer } = useComposerContext();
498
+ return useComposer((composer) => {
499
+ if (props.editing === true && !composer.isEditing) return false;
500
+ if (props.editing === false && composer.isEditing) return false;
501
+ return true;
502
+ });
503
+ };
504
+ var ComposerIf = ({ children, ...query }) => {
505
+ const result = useComposerIf(query);
506
+ return result ? children : null;
507
+ };
508
+
509
+ // src/primitives/message/MessageIf.tsx
510
+ var useMessageIf = (props) => {
511
+ const { useMessage } = useMessageContext();
512
+ return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
513
+ if (props.hasBranches === true && branches.length < 2) return false;
514
+ if (props.user && message.role !== "user") return false;
515
+ if (props.assistant && message.role !== "assistant") return false;
516
+ if (props.lastOrHover === true && !isHovering && !isLast) return false;
517
+ if (props.copied === true && !isCopied) return false;
518
+ if (props.copied === false && isCopied) return false;
519
+ return true;
520
+ });
521
+ };
522
+ var MessageIf = ({ children, ...query }) => {
523
+ const result = useMessageIf(query);
524
+ return result ? children : null;
525
+ };
526
+
527
+ // src/primitives/thread/ThreadMessages.tsx
528
+ var import_jsx_runtime5 = require("react/jsx-runtime");
529
+ var getComponents = (components) => {
530
+ return {
531
+ EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
532
+ UserMessage: components.UserMessage ?? components.Message,
533
+ AssistantMessage: components.AssistantMessage ?? components.Message
534
+ };
535
+ };
536
+ var ThreadMessageImpl = ({
537
+ messageIndex,
538
+ components
539
+ }) => {
540
+ const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
541
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageProvider, { messageIndex, children: [
542
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageIf, { user: true, children: [
543
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UserMessage, {}) }),
544
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EditComposer, {}) })
545
+ ] }),
546
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantMessage, {}) })
547
+ ] });
548
+ };
549
+ var ThreadMessage = (0, import_react16.memo)(
550
+ ThreadMessageImpl,
551
+ (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
552
+ );
553
+ var ThreadMessages = ({ components }) => {
554
+ const { useThread } = useThreadContext();
555
+ const messagesLength = useThread((t) => t.messages.length);
556
+ if (messagesLength === 0) return null;
557
+ return new Array(messagesLength).fill(null).map((_, idx) => {
558
+ const messageIndex = idx;
559
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
560
+ ThreadMessage,
561
+ {
562
+ messageIndex,
563
+ components
564
+ },
565
+ messageIndex
566
+ );
567
+ });
568
+ };
569
+
570
+ // src/primitives/thread/ThreadScrollToBottom.tsx
571
+ var import_primitive2 = require("@radix-ui/primitive");
572
+ var import_react_primitive3 = require("@radix-ui/react-primitive");
573
+ var import_react17 = require("react");
574
+ var import_jsx_runtime6 = require("react/jsx-runtime");
575
+ var ThreadScrollToBottom = (0, import_react17.forwardRef)(({ onClick, ...rest }, ref) => {
576
+ const { useViewport } = useThreadContext();
577
+ const isAtBottom = useViewport((s) => s.isAtBottom);
578
+ const handleScrollToBottom = () => {
579
+ useViewport.getState().scrollToBottom();
580
+ };
581
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
582
+ import_react_primitive3.Primitive.button,
583
+ {
584
+ ...rest,
585
+ disabled: isAtBottom,
586
+ ref,
587
+ onClick: (0, import_primitive2.composeEventHandlers)(onClick, handleScrollToBottom)
588
+ }
589
+ );
590
+ });
591
+
592
+ // src/primitives/thread/ThreadSuggestion.tsx
593
+ var import_primitive3 = require("@radix-ui/primitive");
594
+ var import_react_primitive4 = require("@radix-ui/react-primitive");
595
+ var import_react18 = require("react");
596
+ var import_jsx_runtime7 = require("react/jsx-runtime");
597
+ var ThreadSuggestion = (0, import_react18.forwardRef)(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
598
+ const { useThread, useComposer } = useThreadContext();
599
+ const isDisabled = useThread((t) => t.isRunning);
600
+ const handleApplySuggestion = () => {
601
+ const thread = useThread.getState();
602
+ const composer = useComposer.getState();
603
+ composer.setValue(prompt);
604
+ if (send && !thread.isRunning) {
605
+ composer.send();
606
+ }
607
+ };
608
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
609
+ import_react_primitive4.Primitive.button,
610
+ {
611
+ ...rest,
612
+ disabled: isDisabled,
613
+ ref,
614
+ onClick: (0, import_primitive3.composeEventHandlers)(onClick, handleApplySuggestion)
615
+ }
616
+ );
617
+ });
618
+
619
+ // src/primitives/composer/index.ts
620
+ var composer_exports = {};
621
+ __export(composer_exports, {
622
+ Cancel: () => ComposerCancel,
623
+ If: () => ComposerIf,
624
+ Input: () => ComposerInput,
625
+ Root: () => ComposerRoot,
626
+ Send: () => ComposerSend
627
+ });
628
+
629
+ // src/primitives/composer/ComposerRoot.tsx
630
+ var import_primitive4 = require("@radix-ui/primitive");
631
+ var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
632
+ var import_react_primitive5 = require("@radix-ui/react-primitive");
633
+ var import_react19 = require("react");
634
+ var import_jsx_runtime8 = require("react/jsx-runtime");
635
+ var ComposerRoot = (0, import_react19.forwardRef)(
636
+ ({ onSubmit, ...rest }, forwardedRef) => {
637
+ const { useViewport } = useThreadContext();
638
+ const { useComposer } = useComposerContext();
639
+ const formRef = (0, import_react19.useRef)(null);
640
+ const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
641
+ const handleSubmit = (e) => {
642
+ const composerState = useComposer.getState();
643
+ if (!composerState.isEditing) return;
644
+ e.preventDefault();
645
+ composerState.send();
646
+ useViewport.getState().scrollToBottom();
647
+ };
648
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
649
+ import_react_primitive5.Primitive.form,
650
+ {
651
+ ...rest,
652
+ ref,
653
+ onSubmit: (0, import_primitive4.composeEventHandlers)(onSubmit, handleSubmit)
654
+ }
655
+ );
656
+ }
657
+ );
658
+
659
+ // src/primitives/composer/ComposerInput.tsx
660
+ var import_primitive5 = require("@radix-ui/primitive");
661
+ var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
662
+ var import_react_slot = require("@radix-ui/react-slot");
663
+ var import_react20 = require("react");
664
+ var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
665
+ var import_jsx_runtime9 = require("react/jsx-runtime");
666
+ var ComposerInput = (0, import_react20.forwardRef)(
667
+ ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
668
+ const { useThread } = useThreadContext();
669
+ const { useComposer, type } = useComposerContext();
670
+ const value = useComposer((c) => {
671
+ if (!c.isEditing) return "";
672
+ return c.value;
673
+ });
674
+ const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
675
+ const textareaRef = (0, import_react20.useRef)(null);
676
+ const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
677
+ const handleKeyPress = (e) => {
678
+ if (disabled) return;
679
+ if (e.key === "Escape") {
680
+ const composer = useComposer.getState();
681
+ if (composer.cancel()) {
682
+ e.preventDefault();
683
+ }
684
+ } else if (e.key === "Enter" && e.shiftKey === false) {
685
+ const isRunning = useThread.getState().isRunning;
686
+ if (!isRunning) {
687
+ e.preventDefault();
688
+ textareaRef.current?.closest("form")?.requestSubmit();
689
+ }
690
+ }
691
+ };
692
+ const autoFocusEnabled = autoFocus && !disabled;
693
+ const focus = (0, import_react20.useCallback)(() => {
694
+ const textarea = textareaRef.current;
695
+ if (!textarea || !autoFocusEnabled) return;
696
+ textarea.focus();
697
+ textarea.setSelectionRange(
698
+ textareaRef.current.value.length,
699
+ textareaRef.current.value.length
700
+ );
701
+ }, [autoFocusEnabled]);
702
+ (0, import_react20.useEffect)(() => focus(), [focus]);
703
+ useOnScrollToBottom(() => {
704
+ if (type === "new") {
705
+ focus();
706
+ }
707
+ });
708
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
709
+ Component,
710
+ {
711
+ value,
712
+ ...rest,
713
+ ref,
714
+ disabled,
715
+ onChange: (0, import_primitive5.composeEventHandlers)(onChange, (e) => {
716
+ const composerState = useComposer.getState();
717
+ if (!composerState.isEditing) return;
718
+ return composerState.setValue(e.target.value);
719
+ }),
720
+ onKeyDown: (0, import_primitive5.composeEventHandlers)(onKeyDown, handleKeyPress)
721
+ }
722
+ );
723
+ }
724
+ );
725
+
726
+ // src/primitives/composer/ComposerSend.tsx
727
+ var import_react_primitive6 = require("@radix-ui/react-primitive");
728
+ var import_react21 = require("react");
729
+ var import_jsx_runtime10 = require("react/jsx-runtime");
730
+ var ComposerSend = (0, import_react21.forwardRef)(
731
+ ({ disabled, ...rest }, ref) => {
732
+ const { useComposer } = useComposerContext();
733
+ const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
734
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
735
+ import_react_primitive6.Primitive.button,
736
+ {
737
+ type: "submit",
738
+ ...rest,
739
+ ref,
740
+ disabled: disabled || !hasValue
741
+ }
742
+ );
743
+ }
744
+ );
745
+
746
+ // src/primitives/composer/ComposerCancel.tsx
747
+ var import_primitive6 = require("@radix-ui/primitive");
748
+ var import_react_primitive7 = require("@radix-ui/react-primitive");
749
+ var import_react22 = require("react");
750
+ var import_jsx_runtime11 = require("react/jsx-runtime");
751
+ var ComposerCancel = (0, import_react22.forwardRef)(({ onClick, ...rest }, ref) => {
752
+ const { useComposer } = useComposerContext();
753
+ const handleCancel = () => {
754
+ useComposer.getState().cancel();
755
+ };
756
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
757
+ import_react_primitive7.Primitive.button,
758
+ {
759
+ type: "button",
760
+ ...rest,
761
+ ref,
762
+ onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleCancel)
763
+ }
764
+ );
765
+ });
766
+
767
+ // src/primitives/message/index.ts
768
+ var message_exports = {};
769
+ __export(message_exports, {
770
+ Content: () => MessageContent,
771
+ If: () => MessageIf,
772
+ InProgress: () => MessageInProgress,
773
+ Root: () => MessageRoot
774
+ });
775
+
776
+ // src/primitives/message/MessageRoot.tsx
777
+ var import_primitive7 = require("@radix-ui/primitive");
778
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
779
+ var import_react23 = require("react");
780
+ var import_jsx_runtime12 = require("react/jsx-runtime");
781
+ var MessageRoot = (0, import_react23.forwardRef)(
782
+ ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
783
+ const { useMessage } = useMessageContext();
784
+ const setIsHovering = useMessage((s) => s.setIsHovering);
785
+ const handleMouseEnter = () => {
786
+ setIsHovering(true);
787
+ };
788
+ const handleMouseLeave = () => {
789
+ setIsHovering(false);
790
+ };
791
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
792
+ import_react_primitive8.Primitive.div,
793
+ {
794
+ ...rest,
795
+ ref,
796
+ onMouseEnter: (0, import_primitive7.composeEventHandlers)(onMouseEnter, handleMouseEnter),
797
+ onMouseLeave: (0, import_primitive7.composeEventHandlers)(onMouseLeave, handleMouseLeave)
798
+ }
799
+ );
800
+ }
801
+ );
802
+
803
+ // src/primitives/message/MessageContent.tsx
804
+ var import_react28 = require("react");
805
+
806
+ // src/context/AssistantContext.ts
807
+ var import_react24 = require("react");
808
+ var AssistantContext = (0, import_react24.createContext)(
809
+ null
810
+ );
811
+ var useAssistantContext = () => {
812
+ const context = (0, import_react24.useContext)(AssistantContext);
813
+ if (!context)
814
+ throw new Error(
815
+ "This component must be used within an AssistantRuntimeProvider."
816
+ );
817
+ return context;
818
+ };
819
+
820
+ // src/context/ContentPartContext.ts
821
+ var import_react25 = require("react");
822
+ var ContentPartContext = (0, import_react25.createContext)(
823
+ null
824
+ );
825
+ var useContentPartContext = () => {
826
+ const context = (0, import_react25.useContext)(ContentPartContext);
827
+ if (!context)
828
+ throw new Error(
829
+ "This component can only be used inside a component passed to <MessagePrimitive.Content components={...} >."
830
+ );
831
+ return context;
832
+ };
833
+
834
+ // src/context/providers/ContentPartProvider.tsx
835
+ var import_react26 = require("react");
836
+ var import_zustand3 = require("zustand");
837
+ var import_jsx_runtime13 = require("react/jsx-runtime");
838
+ var syncContentPart = ({ message }, useContentPart, partIndex) => {
839
+ const part = message.content[partIndex];
840
+ if (!part) return;
841
+ const messageStatus = message.role === "assistant" ? message.status : "done";
842
+ const status = partIndex === message.content.length - 1 ? messageStatus : "done";
843
+ const currentState = useContentPart.getState();
844
+ if (currentState.part === part && currentState.status === status) return;
845
+ useContentPart.setState({ part, status });
846
+ };
847
+ var useContentPartContext2 = (partIndex) => {
848
+ const { useMessage } = useMessageContext();
849
+ const [context] = (0, import_react26.useState)(() => {
850
+ const useContentPart = (0, import_zustand3.create)(() => ({
851
+ part: { type: "text", text: "" },
852
+ status: "done"
853
+ }));
854
+ syncContentPart(useMessage.getState(), useContentPart, partIndex);
855
+ return { useContentPart };
856
+ });
857
+ (0, import_react26.useEffect)(() => {
858
+ return useMessage.subscribe((message) => {
859
+ syncContentPart(message, context.useContentPart, partIndex);
860
+ });
861
+ }, [context, useMessage, partIndex]);
862
+ return context;
863
+ };
864
+ var ContentPartProvider = ({
865
+ partIndex,
866
+ children
867
+ }) => {
868
+ const context = useContentPartContext2(partIndex);
869
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ContentPartContext.Provider, { value: context, children });
870
+ };
871
+
872
+ // src/primitives/contentPart/ContentPartDisplay.tsx
873
+ var ContentPartDisplay = () => {
874
+ const { useContentPart } = useContentPartContext();
875
+ const display = useContentPart((c) => {
876
+ if (c.part.type !== "ui")
877
+ throw new Error(
878
+ "ContentPartDisplay can only be used inside ui content parts."
879
+ );
880
+ return c.part.display;
881
+ });
882
+ return display ?? null;
883
+ };
884
+
885
+ // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
886
+ var ContentPartInProgressIndicator = () => {
887
+ const { useMessage } = useMessageContext();
888
+ const { useContentPart } = useContentPartContext();
889
+ const indicator = useCombinedStore(
890
+ [useMessage, useContentPart],
891
+ (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
892
+ );
893
+ return indicator;
894
+ };
895
+
896
+ // src/primitives/contentPart/ContentPartText.tsx
897
+ var import_react_primitive9 = require("@radix-ui/react-primitive");
898
+ var import_react27 = require("react");
899
+ var import_jsx_runtime14 = require("react/jsx-runtime");
900
+ var ContentPartText = (0, import_react27.forwardRef)((props, forwardedRef) => {
901
+ const { useContentPart } = useContentPartContext();
902
+ const text = useContentPart((c) => {
903
+ if (c.part.type !== "text")
904
+ throw new Error(
905
+ "ContentPartText can only be used inside text content parts."
906
+ );
907
+ return c.part.text;
908
+ });
909
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_primitive9.Primitive.span, { ...props, ref: forwardedRef, children: text });
910
+ });
911
+
912
+ // src/primitives/message/MessageContent.tsx
913
+ var import_jsx_runtime15 = require("react/jsx-runtime");
914
+ var defaultComponents = {
915
+ Text: () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
916
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentPartText, {}),
917
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentPartInProgressIndicator, {})
918
+ ] }),
919
+ Image: () => null,
920
+ UI: () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentPartDisplay, {}),
921
+ tools: {
922
+ Fallback: (props) => {
923
+ const { useToolRenderers } = useAssistantContext();
924
+ const Render = useToolRenderers(
925
+ (s) => s.getToolRenderer(props.part.toolName)
926
+ );
927
+ if (!Render) return null;
928
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Render, { ...props });
929
+ }
930
+ }
931
+ };
932
+ var MessageContentPartComponent = ({
933
+ components: {
934
+ Text = defaultComponents.Text,
935
+ Image = defaultComponents.Image,
936
+ UI = defaultComponents.UI,
937
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
938
+ } = {}
939
+ }) => {
940
+ const { useContentPart } = useContentPartContext();
941
+ const { part, status } = useContentPart();
942
+ const type = part.type;
943
+ switch (type) {
944
+ case "text":
945
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { part, status });
946
+ case "image":
947
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Image, { part, status });
948
+ case "ui":
949
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UI, { part, status });
950
+ case "tool-call": {
951
+ const Tool = by_name[part.toolName] || Fallback;
952
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Tool, { part, status });
953
+ }
954
+ default:
955
+ throw new Error(`Unknown content part type: ${type}`);
956
+ }
957
+ };
958
+ var MessageContentPartImpl = ({
959
+ partIndex,
960
+ components
961
+ }) => {
962
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentPartProvider, { partIndex, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageContentPartComponent, { components }) });
963
+ };
964
+ var MessageContentPart = (0, import_react28.memo)(
965
+ MessageContentPartImpl,
966
+ (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Image === next.components?.Image && prev.components?.UI === next.components?.UI && prev.components?.tools === next.components?.tools
967
+ );
968
+ var MessageContent = ({ components }) => {
969
+ const { useMessage } = useMessageContext();
970
+ const contentLength = useMessage((s) => s.message.content.length);
971
+ return new Array(contentLength).fill(null).map((_, idx) => {
972
+ const partIndex = idx;
973
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
974
+ MessageContentPart,
975
+ {
976
+ partIndex,
977
+ components
978
+ },
979
+ partIndex
980
+ );
981
+ });
982
+ };
983
+
984
+ // src/primitives/message/MessageInProgress.tsx
985
+ var import_react_primitive10 = require("@radix-ui/react-primitive");
986
+ var import_react29 = require("react");
987
+ var import_jsx_runtime16 = require("react/jsx-runtime");
988
+ var MessageInProgress = (0, import_react29.forwardRef)((props, ref) => {
989
+ const { useMessage } = useMessageContext();
990
+ (0, import_react29.useMemo)(() => {
991
+ useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive10.Primitive.span, { ...props, ref }));
992
+ }, [useMessage, props, ref]);
993
+ return null;
994
+ });
995
+
996
+ // src/primitives/branchPicker/index.ts
997
+ var branchPicker_exports = {};
998
+ __export(branchPicker_exports, {
999
+ Count: () => BranchPickerCount,
1000
+ Next: () => BranchPickerNext,
1001
+ Number: () => BranchPickerNumber,
1002
+ Previous: () => BranchPickerPrevious,
1003
+ Root: () => BranchPickerRoot
1004
+ });
1005
+
1006
+ // src/utils/createActionButton.tsx
1007
+ var import_primitive8 = require("@radix-ui/primitive");
1008
+ var import_react_primitive11 = require("@radix-ui/react-primitive");
1009
+ var import_react30 = require("react");
1010
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1011
+ var createActionButton = (useActionButton) => {
1012
+ return (0, import_react30.forwardRef)(
1013
+ (props, forwardedRef) => {
1014
+ const onClick = useActionButton(props);
1015
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1016
+ import_react_primitive11.Primitive.button,
1017
+ {
1018
+ type: "button",
1019
+ disabled: !onClick,
1020
+ ...props,
1021
+ ref: forwardedRef,
1022
+ onClick: (0, import_primitive8.composeEventHandlers)(props.onClick, onClick ?? void 0)
1023
+ }
1024
+ );
1025
+ }
1026
+ );
1027
+ };
1028
+
1029
+ // src/primitives/branchPicker/BranchPickerNext.tsx
1030
+ var BranchPickerNext = createActionButton(useGoToNextBranch);
1031
+
1032
+ // src/primitives/branchPicker/BranchPickerPrevious.tsx
1033
+ var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
1034
+
1035
+ // src/primitives/branchPicker/BranchPickerCount.tsx
1036
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1037
+ var BranchPickerCount = () => {
1038
+ const { useMessage } = useMessageContext();
1039
+ const branchCount = useMessage((s) => s.branches.length);
1040
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: branchCount });
1041
+ };
1042
+
1043
+ // src/primitives/branchPicker/BranchPickerNumber.tsx
1044
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1045
+ var BranchPickerNumber = () => {
1046
+ const { useMessage } = useMessageContext();
1047
+ const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
1048
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children: branchIdx + 1 });
1049
+ };
1050
+
1051
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
1052
+ var import_react_primitive12 = require("@radix-ui/react-primitive");
1053
+ var import_react31 = require("react");
1054
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1055
+ var BranchPickerRoot = (0, import_react31.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
1056
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_primitive12.Primitive.div, { ...rest, ref }) });
1057
+ });
1058
+
1059
+ // src/primitives/actionBar/index.ts
1060
+ var actionBar_exports = {};
1061
+ __export(actionBar_exports, {
1062
+ Copy: () => ActionBarCopy,
1063
+ Edit: () => ActionBarEdit,
1064
+ Reload: () => ActionBarReload,
1065
+ Root: () => ActionBarRoot
1066
+ });
1067
+
1068
+ // src/primitives/actionBar/ActionBarRoot.tsx
1069
+ var import_react_primitive13 = require("@radix-ui/react-primitive");
1070
+ var import_react32 = require("react");
1071
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1072
+ var ActionBarRoot = (0, import_react32.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1073
+ const { useThread } = useThreadContext();
1074
+ const { useMessage } = useMessageContext();
1075
+ const hideAndfloatStatus = useCombinedStore(
1076
+ [useThread, useMessage],
1077
+ (t, m) => {
1078
+ if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1079
+ const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1080
+ if (!autohideEnabled) return "normal" /* Normal */;
1081
+ if (!m.isHovering) return "hidden" /* Hidden */;
1082
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1083
+ return "floating" /* Floating */;
1084
+ return "normal" /* Normal */;
1085
+ }
1086
+ );
1087
+ if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
1088
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1089
+ import_react_primitive13.Primitive.div,
1090
+ {
1091
+ ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
1092
+ ...rest,
1093
+ ref
1094
+ }
1095
+ );
1096
+ });
1097
+
1098
+ // src/primitives/actionBar/ActionBarCopy.tsx
1099
+ var ActionBarCopy = createActionButton(useCopyMessage);
1100
+
1101
+ // src/primitives/actionBar/ActionBarReload.tsx
1102
+ var ActionBarReload = createActionButton(useReloadMessage);
1103
+
1104
+ // src/primitives/actionBar/ActionBarEdit.tsx
1105
+ var ActionBarEdit = createActionButton(useBeginMessageEdit);
1106
+
1107
+ // src/primitives/contentPart/index.ts
1108
+ var contentPart_exports = {};
1109
+ __export(contentPart_exports, {
1110
+ Display: () => ContentPartDisplay,
1111
+ Image: () => ContentPartImage,
1112
+ InProgressIndicator: () => ContentPartInProgressIndicator,
1113
+ Text: () => ContentPartText
1114
+ });
1115
+
1116
+ // src/primitives/contentPart/ContentPartImage.tsx
1117
+ var import_react_primitive14 = require("@radix-ui/react-primitive");
1118
+ var import_react33 = require("react");
1119
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1120
+ var ContentPartImage = (0, import_react33.forwardRef)((props, forwardedRef) => {
1121
+ const { useContentPart } = useContentPartContext();
1122
+ const image = useContentPart((c) => {
1123
+ if (c.part.type !== "image")
1124
+ throw new Error(
1125
+ "ContentPartImage can only be used inside image content parts."
1126
+ );
1127
+ return c.part.image;
1128
+ });
1129
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_primitive14.Primitive.img, { src: image, ...props, ref: forwardedRef });
1130
+ });
1131
+
1132
+ // src/runtime/local/useLocalRuntime.tsx
1133
+ var import_react34 = require("react");
1134
+
1135
+ // src/utils/ModelConfigTypes.ts
1136
+ var mergeModelConfigs = (configSet) => {
1137
+ const configs = Array.from(configSet).map((c) => c()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
1138
+ return configs.reduce((acc, config) => {
1139
+ if (config.system) {
1140
+ if (acc.system) {
1141
+ acc.system += `
1142
+
1143
+ ${config.system}`;
1144
+ } else {
1145
+ acc.system = config.system;
1146
+ }
1147
+ }
1148
+ if (config.tools) {
1149
+ for (const [name, tool] of Object.entries(config.tools)) {
1150
+ if (acc.tools?.[name]) {
1151
+ throw new Error(
1152
+ `You tried to define a tool with the name ${name}, but it already exists.`
1153
+ );
1154
+ }
1155
+ if (!acc.tools) acc.tools = {};
1156
+ acc.tools[name] = tool;
1157
+ }
1158
+ }
1159
+ return acc;
1160
+ }, {});
1161
+ };
1162
+
1163
+ // src/runtime/utils/idUtils.tsx
1164
+ var import_non_secure = require("nanoid/non-secure");
1165
+ var generateId = (0, import_non_secure.customAlphabet)(
1166
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
1167
+ 7
1168
+ );
1169
+ var optimisticPrefix = "__optimistic__";
1170
+ var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
1171
+
1172
+ // src/runtime/utils/MessageRepository.tsx
1173
+ var findHead = (message) => {
1174
+ if (message.next) return findHead(message.next);
1175
+ return message;
1176
+ };
1177
+ var MessageRepository = class {
1178
+ messages = /* @__PURE__ */ new Map();
1179
+ // message_id -> item
1180
+ head = null;
1181
+ root = {
1182
+ children: []
1183
+ };
1184
+ performOp(newParent, child, operation) {
1185
+ const parentOrRoot = child.prev ?? this.root;
1186
+ const newParentOrRoot = newParent ?? this.root;
1187
+ if (operation === "relink" && parentOrRoot === newParentOrRoot) return;
1188
+ if (operation !== "link") {
1189
+ parentOrRoot.children = parentOrRoot.children.filter(
1190
+ (m) => m !== child.current.id
1191
+ );
1192
+ if (child.prev?.next === child) {
1193
+ const fallbackId = child.prev.children.at(-1);
1194
+ const fallback = fallbackId ? this.messages.get(fallbackId) : null;
1195
+ if (fallback === void 0) {
1196
+ throw new Error(
1197
+ "MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
1198
+ );
1199
+ }
1200
+ child.prev.next = fallback;
1201
+ }
1202
+ }
1203
+ if (operation !== "cut") {
1204
+ newParentOrRoot.children = [
1205
+ ...newParentOrRoot.children,
1206
+ child.current.id
1207
+ ];
1208
+ if (newParent && (findHead(child) === this.head || newParent.next === null)) {
1209
+ newParent.next = child;
1210
+ }
1211
+ child.prev = newParent;
1212
+ }
1213
+ }
1214
+ getMessages() {
1215
+ const messages = new Array(this.head?.level ?? 0);
1216
+ for (let current = this.head; current; current = current.prev) {
1217
+ messages[current.level] = current.current;
1218
+ }
1219
+ return messages;
1220
+ }
1221
+ addOrUpdateMessage(parentId, message) {
1222
+ const existingItem = this.messages.get(message.id);
1223
+ const prev = parentId ? this.messages.get(parentId) : null;
1224
+ if (prev === void 0)
1225
+ throw new Error(
1226
+ "MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui."
1227
+ );
1228
+ if (existingItem) {
1229
+ existingItem.current = message;
1230
+ this.performOp(prev, existingItem, "relink");
1231
+ return;
1232
+ }
1233
+ const newItem = {
1234
+ prev,
1235
+ current: message,
1236
+ next: null,
1237
+ children: [],
1238
+ level: prev ? prev.level + 1 : 0
1239
+ };
1240
+ this.messages.set(message.id, newItem);
1241
+ this.performOp(prev, newItem, "link");
1242
+ if (this.head === prev) {
1243
+ this.head = newItem;
1244
+ }
1245
+ }
1246
+ appendOptimisticMessage(parentId, message) {
1247
+ let optimisticId;
1248
+ do {
1249
+ optimisticId = generateOptimisticId();
1250
+ } while (this.messages.has(optimisticId));
1251
+ this.addOrUpdateMessage(parentId, {
1252
+ ...message,
1253
+ id: optimisticId,
1254
+ createdAt: /* @__PURE__ */ new Date(),
1255
+ ...message.role === "assistant" ? { status: "in_progress" } : void 0
1256
+ });
1257
+ return optimisticId;
1258
+ }
1259
+ deleteMessage(messageId, replacementId) {
1260
+ const message = this.messages.get(messageId);
1261
+ if (!message)
1262
+ throw new Error(
1263
+ "MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
1264
+ );
1265
+ const replacement = replacementId === void 0 ? message.prev : replacementId === null ? null : this.messages.get(replacementId);
1266
+ if (replacement === void 0)
1267
+ throw new Error(
1268
+ "MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui."
1269
+ );
1270
+ for (const child of message.children) {
1271
+ const childMessage = this.messages.get(child);
1272
+ if (!childMessage)
1273
+ throw new Error(
1274
+ "MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
1275
+ );
1276
+ this.performOp(replacement, childMessage, "relink");
1277
+ }
1278
+ this.performOp(null, message, "cut");
1279
+ this.messages.delete(messageId);
1280
+ if (this.head === message) {
1281
+ this.head = replacement ? findHead(replacement) : null;
1282
+ }
1283
+ }
1284
+ getBranches(messageId) {
1285
+ const message = this.messages.get(messageId);
1286
+ if (!message)
1287
+ throw new Error(
1288
+ "MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui."
1289
+ );
1290
+ const { children } = message.prev ?? this.root;
1291
+ return children;
1292
+ }
1293
+ switchToBranch(messageId) {
1294
+ const message = this.messages.get(messageId);
1295
+ if (!message)
1296
+ throw new Error(
1297
+ "MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui."
1298
+ );
1299
+ if (message.prev) {
1300
+ message.prev.next = message;
1301
+ }
1302
+ this.head = findHead(message);
1303
+ }
1304
+ resetHead(messageId) {
1305
+ if (messageId === null) {
1306
+ this.head = null;
1307
+ return;
1308
+ }
1309
+ const message = this.messages.get(messageId);
1310
+ if (!message)
1311
+ throw new Error(
1312
+ "MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui."
1313
+ );
1314
+ this.head = message;
1315
+ for (let current = message; current; current = current.prev) {
1316
+ if (current.prev) {
1317
+ current.prev.next = current;
1318
+ }
1319
+ }
1320
+ }
1321
+ };
1322
+
1323
+ // src/runtime/local/LocalRuntime.tsx
1324
+ var LocalRuntime = class {
1325
+ constructor(adapter) {
1326
+ this.adapter = adapter;
1327
+ }
1328
+ _subscriptions = /* @__PURE__ */ new Set();
1329
+ _configProviders = /* @__PURE__ */ new Set();
1330
+ abortController = null;
1331
+ repository = new MessageRepository();
1332
+ get messages() {
1333
+ return this.repository.getMessages();
1334
+ }
1335
+ get isRunning() {
1336
+ return this.abortController != null;
1337
+ }
1338
+ getBranches(messageId) {
1339
+ return this.repository.getBranches(messageId);
1340
+ }
1341
+ switchToBranch(branchId) {
1342
+ this.repository.switchToBranch(branchId);
1343
+ this.notifySubscribers();
1344
+ }
1345
+ async append(message) {
1346
+ const userMessageId = generateId();
1347
+ const userMessage = {
1348
+ id: userMessageId,
1349
+ role: "user",
1350
+ content: message.content,
1351
+ createdAt: /* @__PURE__ */ new Date()
1352
+ };
1353
+ this.repository.addOrUpdateMessage(message.parentId, userMessage);
1354
+ await this.startRun(userMessageId);
1355
+ }
1356
+ async startRun(parentId) {
1357
+ const id = generateId();
1358
+ this.repository.resetHead(parentId);
1359
+ const messages = this.repository.getMessages();
1360
+ const message = {
1361
+ id,
1362
+ role: "assistant",
1363
+ status: "in_progress",
1364
+ content: [{ type: "text", text: "" }],
1365
+ createdAt: /* @__PURE__ */ new Date()
1366
+ };
1367
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1368
+ this.abortController?.abort();
1369
+ this.abortController = new AbortController();
1370
+ this.notifySubscribers();
1371
+ try {
1372
+ const updateHandler = ({ content }) => {
1373
+ message.content = content;
1374
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1375
+ this.notifySubscribers();
1376
+ };
1377
+ const result = await this.adapter.run({
1378
+ messages,
1379
+ abortSignal: this.abortController.signal,
1380
+ config: mergeModelConfigs(this._configProviders),
1381
+ onUpdate: updateHandler
1382
+ });
1383
+ updateHandler(result);
1384
+ message.status = "done";
1385
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1386
+ } catch (e) {
1387
+ message.status = "error";
1388
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1389
+ console.error(e);
1390
+ } finally {
1391
+ this.abortController = null;
1392
+ this.notifySubscribers();
1393
+ }
1394
+ }
1395
+ cancelRun() {
1396
+ if (!this.abortController) return;
1397
+ this.abortController.abort();
1398
+ this.abortController = null;
1399
+ this.notifySubscribers();
1400
+ }
1401
+ notifySubscribers() {
1402
+ for (const callback of this._subscriptions) callback();
1403
+ }
1404
+ subscribe(callback) {
1405
+ this._subscriptions.add(callback);
1406
+ return () => this._subscriptions.delete(callback);
1407
+ }
1408
+ registerModelConfigProvider(provider) {
1409
+ this._configProviders.add(provider);
1410
+ return () => this._configProviders.delete(provider);
1411
+ }
1412
+ };
1413
+
1414
+ // src/runtime/local/useLocalRuntime.tsx
1415
+ var useLocalRuntime = (adapter) => {
1416
+ const [runtime] = (0, import_react34.useState)(() => new LocalRuntime(adapter));
1417
+ (0, import_react34.useInsertionEffect)(() => {
1418
+ runtime.adapter = adapter;
1419
+ });
1420
+ return runtime;
1421
+ };
1422
+
1423
+ // src/context/providers/AssistantRuntimeProvider.tsx
1424
+ var import_react37 = require("react");
1425
+
1426
+ // src/context/providers/AssistantProvider.tsx
1427
+ var import_react36 = require("react");
1428
+
1429
+ // src/context/stores/AssistantModelConfig.ts
1430
+ var import_zustand4 = require("zustand");
1431
+
1432
+ // src/utils/ProxyConfigProvider.ts
1433
+ var ProxyConfigProvider = class {
1434
+ _providers = /* @__PURE__ */ new Set();
1435
+ getModelConfig() {
1436
+ return mergeModelConfigs(this._providers);
1437
+ }
1438
+ registerModelConfigProvider(provider) {
1439
+ this._providers.add(provider);
1440
+ return () => {
1441
+ this._providers.delete(provider);
1442
+ };
1443
+ }
1444
+ };
1445
+
1446
+ // src/context/stores/AssistantModelConfig.ts
1447
+ var makeAssistantModelConfigStore = () => (0, import_zustand4.create)(() => {
1448
+ const proxy = new ProxyConfigProvider();
1449
+ return {
1450
+ getModelConfig: () => {
1451
+ return proxy.getModelConfig();
1452
+ },
1453
+ registerModelConfigProvider: (provider) => {
1454
+ return proxy.registerModelConfigProvider(provider);
1455
+ }
1456
+ };
1457
+ });
1458
+
1459
+ // src/context/stores/AssistantToolRenderers.ts
1460
+ var import_zustand5 = require("zustand");
1461
+ var makeAssistantToolRenderersStore = () => (0, import_zustand5.create)((set) => {
1462
+ const renderers = /* @__PURE__ */ new Map();
1463
+ return {
1464
+ getToolRenderer: (name) => {
1465
+ const arr = renderers.get(name);
1466
+ const last = arr?.at(-1);
1467
+ if (last) return last;
1468
+ return null;
1469
+ },
1470
+ setToolRenderer: (name, render) => {
1471
+ let arr = renderers.get(name);
1472
+ if (!arr) {
1473
+ arr = [];
1474
+ renderers.set(name, arr);
1475
+ }
1476
+ arr.push(render);
1477
+ set({});
1478
+ return () => {
1479
+ const index = arr.indexOf(render);
1480
+ if (index !== -1) {
1481
+ arr.splice(index, 1);
1482
+ }
1483
+ set({});
1484
+ };
1485
+ }
1486
+ };
1487
+ });
1488
+
1489
+ // src/context/providers/ThreadProvider.tsx
1490
+ var import_react35 = require("react");
1491
+
1492
+ // src/context/stores/Composer.ts
1493
+ var import_zustand6 = require("zustand");
1494
+ var makeComposerStore = (useThread) => (0, import_zustand6.create)()((set, get, store) => {
1495
+ return {
1496
+ ...makeBaseComposer(set, get, store),
1497
+ isEditing: true,
1498
+ send: () => {
1499
+ const { setValue, value } = get();
1500
+ setValue("");
1501
+ useThread.getState().append({
1502
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
1503
+ content: [{ type: "text", text: value }]
1504
+ });
1505
+ },
1506
+ cancel: () => {
1507
+ const thread = useThread.getState();
1508
+ if (!thread.isRunning) return false;
1509
+ useThread.getState().cancelRun();
1510
+ return true;
1511
+ }
1512
+ };
1513
+ });
1514
+
1515
+ // src/context/stores/Thread.ts
1516
+ var import_zustand7 = require("zustand");
1517
+ var makeThreadStore = (runtimeRef) => {
1518
+ const useThread = (0, import_zustand7.create)(() => ({
1519
+ messages: runtimeRef.current.messages,
1520
+ isRunning: runtimeRef.current.isRunning,
1521
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1522
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1523
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1524
+ append: (message) => runtimeRef.current.append(message),
1525
+ cancelRun: () => runtimeRef.current.cancelRun()
1526
+ }));
1527
+ const onRuntimeUpdate = () => {
1528
+ useThread.setState({
1529
+ messages: runtimeRef.current.messages,
1530
+ isRunning: runtimeRef.current.isRunning
1531
+ });
1532
+ };
1533
+ return {
1534
+ useThread,
1535
+ onRuntimeUpdate
1536
+ };
1537
+ };
1538
+
1539
+ // src/context/stores/ThreadViewport.tsx
1540
+ var import_zustand8 = require("zustand");
1541
+ var makeThreadViewportStore = () => {
1542
+ const scrollToBottomListeners = /* @__PURE__ */ new Set();
1543
+ return (0, import_zustand8.create)(() => ({
1544
+ isAtBottom: true,
1545
+ scrollToBottom: () => {
1546
+ for (const listener of scrollToBottomListeners) {
1547
+ listener();
1548
+ }
1549
+ },
1550
+ onScrollToBottom: (callback) => {
1551
+ scrollToBottomListeners.add(callback);
1552
+ return () => {
1553
+ scrollToBottomListeners.delete(callback);
1554
+ };
1555
+ }
1556
+ }));
1557
+ };
1558
+
1559
+ // src/context/providers/ThreadProvider.tsx
1560
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1561
+ var ThreadProvider = ({
1562
+ children,
1563
+ runtime
1564
+ }) => {
1565
+ const runtimeRef = (0, import_react35.useRef)(runtime);
1566
+ (0, import_react35.useInsertionEffect)(() => {
1567
+ runtimeRef.current = runtime;
1568
+ });
1569
+ const [{ context, onRuntimeUpdate }] = (0, import_react35.useState)(() => {
1570
+ const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1571
+ const useViewport = makeThreadViewportStore();
1572
+ const useComposer = makeComposerStore(useThread);
1573
+ return {
1574
+ context: {
1575
+ useViewport,
1576
+ useThread,
1577
+ useComposer
1578
+ },
1579
+ onRuntimeUpdate: onRuntimeUpdate2
1580
+ };
1581
+ });
1582
+ (0, import_react35.useEffect)(() => {
1583
+ onRuntimeUpdate();
1584
+ return runtime.subscribe(onRuntimeUpdate);
1585
+ }, [onRuntimeUpdate, runtime]);
1586
+ const RuntimeSynchronizer = runtime.unstable_synchronizer;
1587
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ThreadContext.Provider, { value: context, children: [
1588
+ RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(RuntimeSynchronizer, {}),
1589
+ children
1590
+ ] });
1591
+ };
1592
+
1593
+ // src/context/providers/AssistantProvider.tsx
1594
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1595
+ var AssistantProvider = ({ children, runtime }) => {
1596
+ const runtimeRef = (0, import_react36.useRef)(runtime);
1597
+ (0, import_react36.useInsertionEffect)(() => {
1598
+ runtimeRef.current = runtime;
1599
+ });
1600
+ const [context] = (0, import_react36.useState)(() => {
1601
+ const useModelConfig = makeAssistantModelConfigStore();
1602
+ const useToolRenderers = makeAssistantToolRenderersStore();
1603
+ return { useModelConfig, useToolRenderers };
1604
+ });
1605
+ const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1606
+ (0, import_react36.useEffect)(() => {
1607
+ return runtime.registerModelConfigProvider(getModelCOnfig);
1608
+ }, [runtime, getModelCOnfig]);
1609
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ThreadProvider, { runtime, children }) });
1610
+ };
1611
+
1612
+ // src/context/providers/AssistantRuntimeProvider.tsx
1613
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1614
+ var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1615
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AssistantProvider, { runtime, children });
1616
+ };
1617
+ var AssistantRuntimeProvider = (0, import_react37.memo)(AssistantRuntimeProviderImpl);
1618
+
1619
+ // src/internal.ts
1620
+ var internal_exports = {};
1621
+ __export(internal_exports, {
1622
+ MessageRepository: () => MessageRepository,
1623
+ ProxyConfigProvider: () => ProxyConfigProvider
1624
+ });
1625
+ // Annotate the CommonJS export names for ESM import in node:
1626
+ 0 && (module.exports = {
1627
+ ActionBarPrimitive,
1628
+ AssistantRuntimeProvider,
1629
+ BranchPickerPrimitive,
1630
+ ComposerPrimitive,
1631
+ ContentPartPrimitive,
1632
+ INTERNAL,
1633
+ MessagePrimitive,
1634
+ ThreadPrimitive,
1635
+ useBeginMessageEdit,
1636
+ useCopyMessage,
1637
+ useGoToNextBranch,
1638
+ useGoToPreviousBranch,
1639
+ useLocalRuntime,
1640
+ useReloadMessage
1641
+ });
1642
+ //# sourceMappingURL=index.js.map