@assistant-ui/react 0.1.2 → 0.1.3

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.mjs DELETED
@@ -1,1440 +0,0 @@
1
- import {
2
- AssistantContext,
3
- ContentPartContext,
4
- MessageContext,
5
- ThreadContext,
6
- __export,
7
- useComposerContext,
8
- useContentPartContext,
9
- useMessageContext,
10
- useThreadContext
11
- } from "./chunk-SCWPIDP6.mjs";
12
-
13
- // src/actions/useCopyMessage.tsx
14
- import { useCallback } from "react";
15
-
16
- // src/utils/combined/useCombinedStore.ts
17
- import { useMemo } from "react";
18
-
19
- // src/utils/combined/createCombinedStore.ts
20
- import { useSyncExternalStore } from "react";
21
- var createCombinedStore = (stores) => {
22
- const subscribe = (callback) => {
23
- const unsubscribes = stores.map((store) => store.subscribe(callback));
24
- return () => {
25
- for (const unsub of unsubscribes) {
26
- unsub();
27
- }
28
- };
29
- };
30
- return (selector) => {
31
- const getSnapshot = () => selector(...stores.map((store) => store.getState()));
32
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
33
- };
34
- };
35
-
36
- // src/utils/combined/useCombinedStore.ts
37
- var useCombinedStore = (stores, selector) => {
38
- const useCombined = useMemo(() => createCombinedStore(stores), stores);
39
- return useCombined(selector);
40
- };
41
-
42
- // src/utils/getMessageText.tsx
43
- var getMessageText = (message) => {
44
- const textParts = message.content.filter(
45
- (part) => part.type === "text"
46
- );
47
- return textParts.map((part) => part.text).join("\n\n");
48
- };
49
-
50
- // src/actions/useCopyMessage.tsx
51
- var useCopyMessage = ({ copiedDuration = 3e3 }) => {
52
- const { useMessage, useComposer } = useMessageContext();
53
- const hasCopyableContent = useCombinedStore(
54
- [useMessage, useComposer],
55
- (m, c) => {
56
- return c.isEditing || m.message.content.some((c2) => c2.type === "text");
57
- }
58
- );
59
- const callback = useCallback(() => {
60
- const { isEditing, value: composerValue } = useComposer.getState();
61
- const { message, setIsCopied } = useMessage.getState();
62
- const valueToCopy = isEditing ? composerValue : getMessageText(message);
63
- navigator.clipboard.writeText(valueToCopy);
64
- setIsCopied(true);
65
- setTimeout(() => setIsCopied(false), copiedDuration);
66
- }, [useComposer, useMessage, copiedDuration]);
67
- if (!hasCopyableContent) return null;
68
- return callback;
69
- };
70
-
71
- // src/actions/useReloadMessage.tsx
72
- import { useCallback as useCallback2 } from "react";
73
- var useReloadMessage = () => {
74
- const { useThread, useViewport } = useThreadContext();
75
- const { useMessage } = useMessageContext();
76
- const disabled = useCombinedStore(
77
- [useThread, useMessage],
78
- (t, m) => t.isRunning || m.message.role !== "assistant"
79
- );
80
- const callback = useCallback2(() => {
81
- const { parentId } = useMessage.getState();
82
- useThread.getState().startRun(parentId);
83
- useViewport.getState().scrollToBottom();
84
- }, [useMessage, useThread, useViewport]);
85
- if (disabled) return null;
86
- return callback;
87
- };
88
-
89
- // src/actions/useBeginMessageEdit.tsx
90
- import { useCallback as useCallback3 } from "react";
91
- var useBeginMessageEdit = () => {
92
- const { useMessage, useComposer } = useMessageContext();
93
- const disabled = useCombinedStore(
94
- [useMessage, useComposer],
95
- (m, c) => m.message.role !== "user" || c.isEditing
96
- );
97
- const callback = useCallback3(() => {
98
- const { edit } = useComposer.getState();
99
- edit();
100
- }, [useComposer]);
101
- if (disabled) return null;
102
- return callback;
103
- };
104
-
105
- // src/actions/useGoToNextBranch.tsx
106
- import { useCallback as useCallback4 } from "react";
107
- var useGoToNextBranch = () => {
108
- const { useThread } = useThreadContext();
109
- const { useMessage, useComposer } = useMessageContext();
110
- const disabled = useCombinedStore(
111
- [useMessage, useComposer],
112
- (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
113
- );
114
- const callback = useCallback4(() => {
115
- const { message, branches } = useMessage.getState();
116
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
117
- }, [useMessage, useThread]);
118
- if (disabled) return null;
119
- return callback;
120
- };
121
-
122
- // src/actions/useGoToPreviousBranch.tsx
123
- import { useCallback as useCallback5 } from "react";
124
- var useGoToPreviousBranch = () => {
125
- const { useThread } = useThreadContext();
126
- const { useMessage, useComposer } = useMessageContext();
127
- const disabled = useCombinedStore(
128
- [useMessage, useComposer],
129
- (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
130
- );
131
- const callback = useCallback5(() => {
132
- const { message, branches } = useMessage.getState();
133
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
134
- }, [useMessage, useThread]);
135
- if (disabled) return null;
136
- return callback;
137
- };
138
-
139
- // src/primitives/thread/index.ts
140
- var thread_exports = {};
141
- __export(thread_exports, {
142
- Empty: () => ThreadEmpty,
143
- If: () => ThreadIf,
144
- Messages: () => ThreadMessages,
145
- Root: () => ThreadRoot,
146
- ScrollToBottom: () => ThreadScrollToBottom,
147
- Suggestion: () => ThreadSuggestion,
148
- Viewport: () => ThreadViewport
149
- });
150
-
151
- // src/primitives/thread/ThreadRoot.tsx
152
- import {
153
- Primitive
154
- } from "@radix-ui/react-primitive";
155
- import { forwardRef } from "react";
156
- import { jsx } from "react/jsx-runtime";
157
- var ThreadRoot = forwardRef(
158
- (props, ref) => {
159
- return /* @__PURE__ */ jsx(Primitive.div, { ...props, ref });
160
- }
161
- );
162
-
163
- // src/primitives/thread/ThreadIf.tsx
164
- var useThreadIf = (props) => {
165
- const { useThread } = useThreadContext();
166
- return useThread((thread) => {
167
- if (props.empty === true && thread.messages.length !== 0) return false;
168
- if (props.empty === false && thread.messages.length === 0) return false;
169
- if (props.running === true && !thread.isRunning) return false;
170
- if (props.running === false && thread.isRunning) return false;
171
- return true;
172
- });
173
- };
174
- var ThreadIf = ({ children, ...query }) => {
175
- const result = useThreadIf(query);
176
- return result ? children : null;
177
- };
178
-
179
- // src/primitives/thread/ThreadEmpty.tsx
180
- import { jsx as jsx2 } from "react/jsx-runtime";
181
- var ThreadEmpty = ({ children }) => {
182
- return /* @__PURE__ */ jsx2(ThreadIf, { empty: true, children });
183
- };
184
-
185
- // src/primitives/thread/ThreadViewport.tsx
186
- import { composeEventHandlers } from "@radix-ui/primitive";
187
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
188
- import {
189
- Primitive as Primitive2
190
- } from "@radix-ui/react-primitive";
191
- import { forwardRef as forwardRef2, useRef } from "react";
192
-
193
- // src/utils/hooks/useOnResizeContent.tsx
194
- import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
195
- import { useEffect } from "react";
196
- var useOnResizeContent = (ref, callback) => {
197
- const callbackRef = useCallbackRef(callback);
198
- useEffect(() => {
199
- const el = ref.current;
200
- if (!el) return;
201
- const resizeObserver = new ResizeObserver(() => {
202
- callbackRef();
203
- });
204
- const mutationObserver = new MutationObserver((mutations) => {
205
- for (const mutation of mutations) {
206
- for (const node of mutation.addedNodes) {
207
- if (node instanceof Element) {
208
- resizeObserver.observe(node);
209
- }
210
- }
211
- for (const node of mutation.removedNodes) {
212
- if (node instanceof Element) {
213
- resizeObserver.unobserve(node);
214
- }
215
- }
216
- }
217
- callbackRef();
218
- });
219
- resizeObserver.observe(el);
220
- mutationObserver.observe(el, { childList: true });
221
- for (const child of el.children) {
222
- resizeObserver.observe(child);
223
- }
224
- return () => {
225
- resizeObserver.disconnect();
226
- mutationObserver.disconnect();
227
- };
228
- }, [ref.current, callbackRef]);
229
- };
230
-
231
- // src/utils/hooks/useOnScrollToBottom.tsx
232
- import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
233
- import { useEffect as useEffect2 } from "react";
234
- var useOnScrollToBottom = (callback) => {
235
- const callbackRef = useCallbackRef2(callback);
236
- const { useViewport } = useThreadContext();
237
- useEffect2(() => {
238
- return useViewport.getState().onScrollToBottom(() => {
239
- callbackRef();
240
- });
241
- }, [useViewport, callbackRef]);
242
- };
243
-
244
- // src/primitives/thread/ThreadViewport.tsx
245
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
246
- var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
247
- const messagesEndRef = useRef(null);
248
- const divRef = useRef(null);
249
- const ref = useComposedRefs(forwardedRef, divRef);
250
- const { useViewport } = useThreadContext();
251
- const firstRenderRef = useRef(true);
252
- const isScrollingToBottomRef = useRef(false);
253
- const lastScrollTop = useRef(0);
254
- const scrollToBottom = () => {
255
- const div = messagesEndRef.current;
256
- if (!div || !autoScroll) return;
257
- const behavior = firstRenderRef.current ? "instant" : "auto";
258
- firstRenderRef.current = false;
259
- isScrollingToBottomRef.current = true;
260
- div.scrollIntoView({ behavior });
261
- };
262
- useOnResizeContent(divRef, () => {
263
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
264
- handleScroll();
265
- } else {
266
- scrollToBottom();
267
- }
268
- });
269
- useOnScrollToBottom(() => {
270
- scrollToBottom();
271
- });
272
- const handleScroll = () => {
273
- const div = divRef.current;
274
- if (!div) return;
275
- const isAtBottom = useViewport.getState().isAtBottom;
276
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
277
- if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
278
- } else if (newIsAtBottom !== isAtBottom) {
279
- isScrollingToBottomRef.current = false;
280
- useViewport.setState({ isAtBottom: newIsAtBottom });
281
- }
282
- lastScrollTop.current = div.scrollTop;
283
- };
284
- return /* @__PURE__ */ jsxs(
285
- Primitive2.div,
286
- {
287
- ...rest,
288
- onScroll: composeEventHandlers(onScroll, handleScroll),
289
- ref,
290
- children: [
291
- children,
292
- /* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
293
- ]
294
- }
295
- );
296
- });
297
-
298
- // src/context/providers/MessageProvider.tsx
299
- import { useEffect as useEffect3, useState } from "react";
300
- import { create as create2 } from "zustand";
301
-
302
- // src/context/stores/MessageComposer.ts
303
- import { create } from "zustand";
304
-
305
- // src/context/stores/BaseComposer.ts
306
- var makeBaseComposer = (set) => ({
307
- value: "",
308
- setValue: (value) => {
309
- set({ value });
310
- }
311
- });
312
-
313
- // src/context/stores/MessageComposer.ts
314
- var makeEditComposerStore = ({
315
- onEdit,
316
- onSend
317
- }) => create()((set, get, store) => ({
318
- ...makeBaseComposer(set, get, store),
319
- isEditing: false,
320
- edit: () => {
321
- const value = onEdit();
322
- set({ isEditing: true, value });
323
- },
324
- send: () => {
325
- const value = get().value;
326
- set({ isEditing: false });
327
- onSend(value);
328
- },
329
- cancel: () => {
330
- if (!get().isEditing) return false;
331
- set({ isEditing: false });
332
- return true;
333
- }
334
- }));
335
-
336
- // src/context/providers/MessageProvider.tsx
337
- import { jsx as jsx4 } from "react/jsx-runtime";
338
- var getIsLast = (thread, message) => {
339
- return thread.messages[thread.messages.length - 1]?.id === message.id;
340
- };
341
- var syncMessage = (thread, useMessage, messageIndex) => {
342
- const parentId = thread.messages[messageIndex - 1]?.id ?? null;
343
- const message = thread.messages[messageIndex];
344
- if (!message) return;
345
- const isLast = getIsLast(thread, message);
346
- const branches = thread.getBranches(message.id);
347
- const currentState = useMessage.getState();
348
- if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
349
- return;
350
- useMessage.setState({
351
- message,
352
- parentId,
353
- branches,
354
- isLast
355
- });
356
- };
357
- var useMessageContext2 = (messageIndex) => {
358
- const { useThread } = useThreadContext();
359
- const [context] = useState(() => {
360
- const useMessage = create2((set) => ({
361
- message: null,
362
- parentId: null,
363
- branches: [],
364
- isLast: false,
365
- inProgressIndicator: null,
366
- isCopied: false,
367
- isHovering: false,
368
- setInProgressIndicator: (value) => {
369
- set({ inProgressIndicator: value });
370
- },
371
- setIsCopied: (value) => {
372
- set({ isCopied: value });
373
- },
374
- setIsHovering: (value) => {
375
- set({ isHovering: value });
376
- }
377
- }));
378
- const useComposer = makeEditComposerStore({
379
- onEdit: () => {
380
- const message = useMessage.getState().message;
381
- if (message.role !== "user")
382
- throw new Error(
383
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
384
- );
385
- const text = getMessageText(message);
386
- return text;
387
- },
388
- onSend: (text) => {
389
- const { message, parentId } = useMessage.getState();
390
- if (message.role !== "user")
391
- throw new Error(
392
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
393
- );
394
- const nonTextParts = message.content.filter(
395
- (part) => part.type !== "text" && part.type !== "ui"
396
- );
397
- useThread.getState().append({
398
- parentId,
399
- content: [{ type: "text", text }, ...nonTextParts]
400
- });
401
- }
402
- });
403
- syncMessage(useThread.getState(), useMessage, messageIndex);
404
- return { useMessage, useComposer };
405
- });
406
- useEffect3(() => {
407
- return useThread.subscribe((thread) => {
408
- syncMessage(thread, context.useMessage, messageIndex);
409
- });
410
- }, [context, useThread, messageIndex]);
411
- return context;
412
- };
413
- var MessageProvider = ({
414
- messageIndex,
415
- children
416
- }) => {
417
- const context = useMessageContext2(messageIndex);
418
- return /* @__PURE__ */ jsx4(MessageContext.Provider, { value: context, children });
419
- };
420
-
421
- // src/primitives/composer/ComposerIf.tsx
422
- var useComposerIf = (props) => {
423
- const { useComposer } = useComposerContext();
424
- return useComposer((composer) => {
425
- if (props.editing === true && !composer.isEditing) return false;
426
- if (props.editing === false && composer.isEditing) return false;
427
- return true;
428
- });
429
- };
430
- var ComposerIf = ({ children, ...query }) => {
431
- const result = useComposerIf(query);
432
- return result ? children : null;
433
- };
434
-
435
- // src/primitives/message/MessageIf.tsx
436
- var useMessageIf = (props) => {
437
- const { useMessage } = useMessageContext();
438
- return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
439
- if (props.hasBranches === true && branches.length < 2) return false;
440
- if (props.user && message.role !== "user") return false;
441
- if (props.assistant && message.role !== "assistant") return false;
442
- if (props.lastOrHover === true && !isHovering && !isLast) return false;
443
- if (props.copied === true && !isCopied) return false;
444
- if (props.copied === false && isCopied) return false;
445
- return true;
446
- });
447
- };
448
- var MessageIf = ({ children, ...query }) => {
449
- const result = useMessageIf(query);
450
- return result ? children : null;
451
- };
452
-
453
- // src/primitives/thread/ThreadMessages.tsx
454
- import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
455
- var getComponents = (components) => {
456
- return {
457
- EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
458
- UserMessage: components.UserMessage ?? components.Message,
459
- AssistantMessage: components.AssistantMessage ?? components.Message
460
- };
461
- };
462
- var ThreadMessages = ({ components }) => {
463
- const { useThread } = useThreadContext();
464
- const messagesLength = useThread((t) => t.messages.length);
465
- const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
466
- if (messagesLength === 0) return null;
467
- return /* @__PURE__ */ jsx5(Fragment, { children: new Array(messagesLength).fill(null).map((_, idx) => {
468
- const messageIndex = idx;
469
- return /* @__PURE__ */ jsxs2(
470
- MessageProvider,
471
- {
472
- messageIndex,
473
- children: [
474
- /* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
475
- /* @__PURE__ */ jsx5(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx5(UserMessage, {}) }),
476
- /* @__PURE__ */ jsx5(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx5(EditComposer, {}) })
477
- ] }),
478
- /* @__PURE__ */ jsx5(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx5(AssistantMessage, {}) })
479
- ]
480
- },
481
- messageIndex
482
- );
483
- }) });
484
- };
485
-
486
- // src/primitives/thread/ThreadScrollToBottom.tsx
487
- import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
488
- import {
489
- Primitive as Primitive3
490
- } from "@radix-ui/react-primitive";
491
- import { forwardRef as forwardRef3 } from "react";
492
- import { jsx as jsx6 } from "react/jsx-runtime";
493
- var ThreadScrollToBottom = forwardRef3(({ onClick, ...rest }, ref) => {
494
- const { useViewport } = useThreadContext();
495
- const isAtBottom = useViewport((s) => s.isAtBottom);
496
- const handleScrollToBottom = () => {
497
- useViewport.getState().scrollToBottom();
498
- };
499
- return /* @__PURE__ */ jsx6(
500
- Primitive3.button,
501
- {
502
- ...rest,
503
- disabled: isAtBottom,
504
- ref,
505
- onClick: composeEventHandlers2(onClick, handleScrollToBottom)
506
- }
507
- );
508
- });
509
-
510
- // src/primitives/thread/ThreadSuggestion.tsx
511
- import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
512
- import {
513
- Primitive as Primitive4
514
- } from "@radix-ui/react-primitive";
515
- import { forwardRef as forwardRef4 } from "react";
516
- import { jsx as jsx7 } from "react/jsx-runtime";
517
- var ThreadSuggestion = forwardRef4(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
518
- const { useThread, useComposer } = useThreadContext();
519
- const isDisabled = useThread((t) => t.isRunning);
520
- const handleApplySuggestion = () => {
521
- const thread = useThread.getState();
522
- const composer = useComposer.getState();
523
- composer.setValue(prompt);
524
- if (send && !thread.isRunning) {
525
- composer.send();
526
- }
527
- };
528
- return /* @__PURE__ */ jsx7(
529
- Primitive4.button,
530
- {
531
- ...rest,
532
- disabled: isDisabled,
533
- ref,
534
- onClick: composeEventHandlers3(onClick, handleApplySuggestion)
535
- }
536
- );
537
- });
538
-
539
- // src/primitives/composer/index.ts
540
- var composer_exports = {};
541
- __export(composer_exports, {
542
- Cancel: () => ComposerCancel,
543
- If: () => ComposerIf,
544
- Input: () => ComposerInput,
545
- Root: () => ComposerRoot,
546
- Send: () => ComposerSend
547
- });
548
-
549
- // src/primitives/composer/ComposerRoot.tsx
550
- import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
551
- import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
552
- import {
553
- Primitive as Primitive5
554
- } from "@radix-ui/react-primitive";
555
- import { forwardRef as forwardRef5, useRef as useRef2 } from "react";
556
- import { jsx as jsx8 } from "react/jsx-runtime";
557
- var ComposerRoot = forwardRef5(
558
- ({ onSubmit, ...rest }, forwardedRef) => {
559
- const { useViewport } = useThreadContext();
560
- const { useComposer } = useComposerContext();
561
- const formRef = useRef2(null);
562
- const ref = useComposedRefs2(forwardedRef, formRef);
563
- const handleSubmit = (e) => {
564
- const composerState = useComposer.getState();
565
- if (!composerState.isEditing) return;
566
- e.preventDefault();
567
- composerState.send();
568
- useViewport.getState().scrollToBottom();
569
- };
570
- return /* @__PURE__ */ jsx8(
571
- Primitive5.form,
572
- {
573
- ...rest,
574
- ref,
575
- onSubmit: composeEventHandlers4(onSubmit, handleSubmit)
576
- }
577
- );
578
- }
579
- );
580
-
581
- // src/primitives/composer/ComposerInput.tsx
582
- import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
583
- import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
584
- import { Slot } from "@radix-ui/react-slot";
585
- import {
586
- forwardRef as forwardRef6,
587
- useCallback as useCallback6,
588
- useEffect as useEffect4,
589
- useRef as useRef3
590
- } from "react";
591
- import TextareaAutosize from "react-textarea-autosize";
592
- import { jsx as jsx9 } from "react/jsx-runtime";
593
- var ComposerInput = forwardRef6(
594
- ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
595
- const { useThread, useViewport } = useThreadContext();
596
- const { useComposer, type } = useComposerContext();
597
- const value = useComposer((c) => {
598
- if (!c.isEditing) return "";
599
- return c.value;
600
- });
601
- const Component = asChild ? Slot : TextareaAutosize;
602
- const handleKeyPress = (e) => {
603
- if (disabled) return;
604
- const composer = useComposer.getState();
605
- if (e.key === "Escape") {
606
- if (useComposer.getState().cancel()) {
607
- e.preventDefault();
608
- }
609
- } else if (e.key === "Enter" && e.shiftKey === false) {
610
- const isRunning = useThread.getState().isRunning;
611
- if (!isRunning) {
612
- e.preventDefault();
613
- composer.send();
614
- useViewport.getState().scrollToBottom();
615
- }
616
- }
617
- };
618
- const textareaRef = useRef3(null);
619
- const ref = useComposedRefs3(forwardedRef, textareaRef);
620
- const autoFocusEnabled = autoFocus && !disabled;
621
- const focus = useCallback6(() => {
622
- const textarea = textareaRef.current;
623
- if (!textarea || !autoFocusEnabled) return;
624
- textarea.focus();
625
- textarea.setSelectionRange(
626
- textareaRef.current.value.length,
627
- textareaRef.current.value.length
628
- );
629
- }, [autoFocusEnabled]);
630
- useEffect4(() => focus(), [focus]);
631
- useOnScrollToBottom(() => {
632
- if (type === "new") {
633
- focus();
634
- }
635
- });
636
- return /* @__PURE__ */ jsx9(
637
- Component,
638
- {
639
- value,
640
- ...rest,
641
- ref,
642
- disabled,
643
- onChange: composeEventHandlers5(onChange, (e) => {
644
- const composerState = useComposer.getState();
645
- if (!composerState.isEditing) return;
646
- return composerState.setValue(e.target.value);
647
- }),
648
- onKeyDown: composeEventHandlers5(onKeyDown, handleKeyPress)
649
- }
650
- );
651
- }
652
- );
653
-
654
- // src/primitives/composer/ComposerSend.tsx
655
- import {
656
- Primitive as Primitive6
657
- } from "@radix-ui/react-primitive";
658
- import { forwardRef as forwardRef7 } from "react";
659
- import { jsx as jsx10 } from "react/jsx-runtime";
660
- var ComposerSend = forwardRef7(
661
- ({ disabled, ...rest }, ref) => {
662
- const { useComposer } = useComposerContext();
663
- const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
664
- return /* @__PURE__ */ jsx10(
665
- Primitive6.button,
666
- {
667
- type: "submit",
668
- ...rest,
669
- ref,
670
- disabled: disabled || !hasValue
671
- }
672
- );
673
- }
674
- );
675
-
676
- // src/primitives/composer/ComposerCancel.tsx
677
- import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
678
- import {
679
- Primitive as Primitive7
680
- } from "@radix-ui/react-primitive";
681
- import { forwardRef as forwardRef8 } from "react";
682
- import { jsx as jsx11 } from "react/jsx-runtime";
683
- var ComposerCancel = forwardRef8(({ onClick, ...rest }, ref) => {
684
- const { useComposer } = useComposerContext();
685
- const handleCancel = () => {
686
- useComposer.getState().cancel();
687
- };
688
- return /* @__PURE__ */ jsx11(
689
- Primitive7.button,
690
- {
691
- type: "button",
692
- ...rest,
693
- ref,
694
- onClick: composeEventHandlers6(onClick, handleCancel)
695
- }
696
- );
697
- });
698
-
699
- // src/primitives/message/index.ts
700
- var message_exports = {};
701
- __export(message_exports, {
702
- Content: () => MessageContent,
703
- If: () => MessageIf,
704
- InProgress: () => MessageInProgress,
705
- Root: () => MessageRoot
706
- });
707
-
708
- // src/primitives/message/MessageRoot.tsx
709
- import { composeEventHandlers as composeEventHandlers7 } from "@radix-ui/primitive";
710
- import {
711
- Primitive as Primitive8
712
- } from "@radix-ui/react-primitive";
713
- import { forwardRef as forwardRef9 } from "react";
714
- import { jsx as jsx12 } from "react/jsx-runtime";
715
- var MessageRoot = forwardRef9(
716
- ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
717
- const { useMessage } = useMessageContext();
718
- const setIsHovering = useMessage((s) => s.setIsHovering);
719
- const handleMouseEnter = () => {
720
- setIsHovering(true);
721
- };
722
- const handleMouseLeave = () => {
723
- setIsHovering(false);
724
- };
725
- return /* @__PURE__ */ jsx12(
726
- Primitive8.div,
727
- {
728
- ...rest,
729
- ref,
730
- onMouseEnter: composeEventHandlers7(onMouseEnter, handleMouseEnter),
731
- onMouseLeave: composeEventHandlers7(onMouseLeave, handleMouseLeave)
732
- }
733
- );
734
- }
735
- );
736
-
737
- // src/context/providers/ContentPartProvider.tsx
738
- import { useEffect as useEffect5, useState as useState2 } from "react";
739
- import { create as create3 } from "zustand";
740
- import { jsx as jsx13 } from "react/jsx-runtime";
741
- var syncContentPart = ({ message }, useContentPart, partIndex) => {
742
- const part = message.content[partIndex];
743
- if (!part) return;
744
- const messageStatus = message.role === "assistant" ? message.status : "done";
745
- const status = partIndex === message.content.length - 1 ? messageStatus : "done";
746
- useContentPart.setState({ part, status });
747
- };
748
- var useContentPartContext2 = (partIndex) => {
749
- const { useMessage } = useMessageContext();
750
- const [context] = useState2(() => {
751
- const useContentPart = create3(() => ({
752
- part: { type: "text", text: "" },
753
- status: "done"
754
- }));
755
- syncContentPart(useMessage.getState(), useContentPart, partIndex);
756
- return { useContentPart };
757
- });
758
- useEffect5(() => {
759
- return useMessage.subscribe((message) => {
760
- syncContentPart(message, context.useContentPart, partIndex);
761
- });
762
- }, [context, useMessage, partIndex]);
763
- return context;
764
- };
765
- var ContentPartProvider = ({
766
- partIndex,
767
- children
768
- }) => {
769
- const context = useContentPartContext2(partIndex);
770
- return /* @__PURE__ */ jsx13(ContentPartContext.Provider, { value: context, children });
771
- };
772
-
773
- // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
774
- var ContentPartInProgressIndicator = () => {
775
- const { useMessage } = useMessageContext();
776
- const { useContentPart } = useContentPartContext();
777
- const indicator = useCombinedStore(
778
- [useMessage, useContentPart],
779
- (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
780
- );
781
- return indicator;
782
- };
783
-
784
- // src/primitives/message/MessageContent.tsx
785
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs3 } from "react/jsx-runtime";
786
- var defaultComponents = {
787
- Text: ({ part }) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
788
- part.text,
789
- /* @__PURE__ */ jsx14(ContentPartInProgressIndicator, {})
790
- ] }),
791
- Image: () => null,
792
- UI: ({ part }) => part.display,
793
- tools: {
794
- Fallback: () => null
795
- }
796
- };
797
- var MessageContent = ({
798
- components: {
799
- Text = defaultComponents.Text,
800
- Image = defaultComponents.Image,
801
- UI = defaultComponents.UI,
802
- tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
803
- } = {}
804
- }) => {
805
- const { useMessage } = useMessageContext();
806
- const message = useMessage((s) => s.message);
807
- const content = message.content;
808
- return /* @__PURE__ */ jsx14(Fragment2, { children: content.map((part, i) => {
809
- const partIndex = i;
810
- const type = part.type;
811
- let component = null;
812
- switch (type) {
813
- case "text":
814
- component = /* @__PURE__ */ jsx14(Text, { part });
815
- break;
816
- case "image":
817
- component = /* @__PURE__ */ jsx14(Image, { part });
818
- break;
819
- case "ui":
820
- component = /* @__PURE__ */ jsx14(UI, { part });
821
- break;
822
- case "tool-call": {
823
- const Tool = by_name[part.name] || Fallback;
824
- component = /* @__PURE__ */ jsx14(Tool, { part });
825
- break;
826
- }
827
- default:
828
- throw new Error(`Unknown content part type: ${type}`);
829
- }
830
- return /* @__PURE__ */ jsx14(ContentPartProvider, { partIndex, children: component }, partIndex);
831
- }) });
832
- };
833
-
834
- // src/primitives/message/MessageInProgress.tsx
835
- import {
836
- Primitive as Primitive9
837
- } from "@radix-ui/react-primitive";
838
- import { forwardRef as forwardRef10, useMemo as useMemo2 } from "react";
839
- import { jsx as jsx15 } from "react/jsx-runtime";
840
- var MessageInProgress = forwardRef10((props, ref) => {
841
- const { useMessage } = useMessageContext();
842
- useMemo2(() => {
843
- useMessage.getState().setInProgressIndicator(/* @__PURE__ */ jsx15(Primitive9.span, { ...props, ref }));
844
- }, [useMessage, props, ref]);
845
- return null;
846
- });
847
-
848
- // src/primitives/branchPicker/index.ts
849
- var branchPicker_exports = {};
850
- __export(branchPicker_exports, {
851
- Count: () => BranchPickerCount,
852
- Next: () => BranchPickerNext,
853
- Number: () => BranchPickerNumber,
854
- Previous: () => BranchPickerPrevious,
855
- Root: () => BranchPickerRoot
856
- });
857
-
858
- // src/utils/createActionButton.tsx
859
- import { composeEventHandlers as composeEventHandlers8 } from "@radix-ui/primitive";
860
- import {
861
- Primitive as Primitive10
862
- } from "@radix-ui/react-primitive";
863
- import { forwardRef as forwardRef11 } from "react";
864
- import { jsx as jsx16 } from "react/jsx-runtime";
865
- var createActionButton = (useActionButton) => {
866
- return forwardRef11(
867
- (props, forwardedRef) => {
868
- const onClick = useActionButton(props);
869
- return /* @__PURE__ */ jsx16(
870
- Primitive10.button,
871
- {
872
- type: "button",
873
- disabled: !onClick,
874
- ...props,
875
- ref: forwardedRef,
876
- onClick: composeEventHandlers8(props.onClick, onClick ?? void 0)
877
- }
878
- );
879
- }
880
- );
881
- };
882
-
883
- // src/primitives/branchPicker/BranchPickerNext.tsx
884
- var BranchPickerNext = createActionButton(useGoToNextBranch);
885
-
886
- // src/primitives/branchPicker/BranchPickerPrevious.tsx
887
- var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
888
-
889
- // src/primitives/branchPicker/BranchPickerCount.tsx
890
- import { Fragment as Fragment3, jsx as jsx17 } from "react/jsx-runtime";
891
- var BranchPickerCount = () => {
892
- const { useMessage } = useMessageContext();
893
- const branchCount = useMessage((s) => s.branches.length);
894
- return /* @__PURE__ */ jsx17(Fragment3, { children: branchCount });
895
- };
896
-
897
- // src/primitives/branchPicker/BranchPickerNumber.tsx
898
- import { Fragment as Fragment4, jsx as jsx18 } from "react/jsx-runtime";
899
- var BranchPickerNumber = () => {
900
- const { useMessage } = useMessageContext();
901
- const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
902
- return /* @__PURE__ */ jsx18(Fragment4, { children: branchIdx + 1 });
903
- };
904
-
905
- // src/primitives/branchPicker/BranchPickerRoot.tsx
906
- import {
907
- Primitive as Primitive11
908
- } from "@radix-ui/react-primitive";
909
- import { forwardRef as forwardRef12 } from "react";
910
- import { jsx as jsx19 } from "react/jsx-runtime";
911
- var BranchPickerRoot = forwardRef12(({ hideWhenSingleBranch, ...rest }, ref) => {
912
- return /* @__PURE__ */ jsx19(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx19(Primitive11.div, { ...rest, ref }) });
913
- });
914
-
915
- // src/primitives/actionBar/index.ts
916
- var actionBar_exports = {};
917
- __export(actionBar_exports, {
918
- Copy: () => ActionBarCopy,
919
- Edit: () => ActionBarEdit,
920
- Reload: () => ActionBarReload,
921
- Root: () => ActionBarRoot
922
- });
923
-
924
- // src/primitives/actionBar/ActionBarRoot.tsx
925
- import {
926
- Primitive as Primitive12
927
- } from "@radix-ui/react-primitive";
928
- import { forwardRef as forwardRef13 } from "react";
929
- import { jsx as jsx20 } from "react/jsx-runtime";
930
- var ActionBarRoot = forwardRef13(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
931
- const { useThread } = useThreadContext();
932
- const { useMessage } = useMessageContext();
933
- const hideAndfloatStatus = useCombinedStore(
934
- [useThread, useMessage],
935
- (t, m) => {
936
- if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
937
- const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
938
- if (!autohideEnabled) return "normal" /* Normal */;
939
- if (!m.isHovering) return "hidden" /* Hidden */;
940
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
941
- return "floating" /* Floating */;
942
- return "normal" /* Normal */;
943
- }
944
- );
945
- if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
946
- return /* @__PURE__ */ jsx20(
947
- Primitive12.div,
948
- {
949
- "data-floating": hideAndfloatStatus === "floating" /* Floating */,
950
- ...rest,
951
- ref
952
- }
953
- );
954
- });
955
-
956
- // src/primitives/actionBar/ActionBarCopy.tsx
957
- var ActionBarCopy = createActionButton(useCopyMessage);
958
-
959
- // src/primitives/actionBar/ActionBarReload.tsx
960
- var ActionBarReload = createActionButton(useReloadMessage);
961
-
962
- // src/primitives/actionBar/ActionBarEdit.tsx
963
- var ActionBarEdit = createActionButton(useBeginMessageEdit);
964
-
965
- // src/primitives/contentPart/index.ts
966
- var contentPart_exports = {};
967
- __export(contentPart_exports, {
968
- InProgressIndicator: () => ContentPartInProgressIndicator
969
- });
970
-
971
- // src/runtime/local/useLocalRuntime.tsx
972
- import { useInsertionEffect, useState as useState3 } from "react";
973
-
974
- // src/utils/ModelConfigTypes.ts
975
- var mergeModelConfigs = (configs) => {
976
- return configs.reduce((acc, config) => {
977
- if (config.system) {
978
- if (acc.system) {
979
- acc.system += `
980
-
981
- ${config.system}`;
982
- } else {
983
- acc.system = config.system;
984
- }
985
- }
986
- if (config.tools) {
987
- acc.tools = { ...acc.tools, ...config.tools };
988
- }
989
- return acc;
990
- }, {});
991
- };
992
-
993
- // src/runtime/utils/idUtils.tsx
994
- import { customAlphabet } from "nanoid/non-secure";
995
- var generateId = customAlphabet(
996
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
997
- 7
998
- );
999
- var optimisticPrefix = "__optimistic__";
1000
- var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
1001
-
1002
- // src/runtime/utils/MessageRepository.tsx
1003
- var findHead = (message) => {
1004
- if (message.next) return findHead(message.next);
1005
- return message;
1006
- };
1007
- var MessageRepository = class {
1008
- messages = /* @__PURE__ */ new Map();
1009
- // message_id -> item
1010
- head = null;
1011
- root = {
1012
- children: []
1013
- };
1014
- performOp(newParent, child, operation) {
1015
- const parentOrRoot = child.prev ?? this.root;
1016
- const newParentOrRoot = newParent ?? this.root;
1017
- if (operation === "relink" && parentOrRoot === newParentOrRoot) return;
1018
- if (operation !== "link") {
1019
- parentOrRoot.children = parentOrRoot.children.filter(
1020
- (m) => m !== child.current.id
1021
- );
1022
- if (child.prev?.next === child) {
1023
- const fallbackId = child.prev.children.at(-1);
1024
- const fallback = fallbackId ? this.messages.get(fallbackId) : null;
1025
- if (fallback === void 0) {
1026
- throw new Error(
1027
- "MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
1028
- );
1029
- }
1030
- child.prev.next = fallback;
1031
- }
1032
- }
1033
- if (operation !== "cut") {
1034
- newParentOrRoot.children = [
1035
- ...newParentOrRoot.children,
1036
- child.current.id
1037
- ];
1038
- if (newParent && (findHead(child) === this.head || newParent.next === null)) {
1039
- newParent.next = child;
1040
- }
1041
- child.prev = newParent;
1042
- }
1043
- }
1044
- getMessages() {
1045
- const messages = new Array(this.head?.level ?? 0);
1046
- for (let current = this.head; current; current = current.prev) {
1047
- messages[current.level] = current.current;
1048
- }
1049
- return messages;
1050
- }
1051
- addOrUpdateMessage(parentId, message) {
1052
- const existingItem = this.messages.get(message.id);
1053
- const prev = parentId ? this.messages.get(parentId) : null;
1054
- if (prev === void 0)
1055
- throw new Error(
1056
- "MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui."
1057
- );
1058
- if (existingItem) {
1059
- existingItem.current = message;
1060
- this.performOp(prev, existingItem, "relink");
1061
- return;
1062
- }
1063
- const newItem = {
1064
- prev,
1065
- current: message,
1066
- next: null,
1067
- children: [],
1068
- level: prev ? prev.level + 1 : 0
1069
- };
1070
- this.messages.set(message.id, newItem);
1071
- this.performOp(prev, newItem, "link");
1072
- if (this.head === prev) {
1073
- this.head = newItem;
1074
- }
1075
- }
1076
- appendOptimisticMessage(parentId, message) {
1077
- let optimisticId;
1078
- do {
1079
- optimisticId = generateOptimisticId();
1080
- } while (this.messages.has(optimisticId));
1081
- this.addOrUpdateMessage(parentId, {
1082
- ...message,
1083
- id: optimisticId,
1084
- createdAt: /* @__PURE__ */ new Date(),
1085
- ...message.role === "assistant" ? { status: "in_progress" } : void 0
1086
- });
1087
- return optimisticId;
1088
- }
1089
- deleteMessage(messageId, replacementId) {
1090
- const message = this.messages.get(messageId);
1091
- if (!message)
1092
- throw new Error(
1093
- "MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
1094
- );
1095
- const replacement = replacementId === void 0 ? message.prev : replacementId === null ? null : this.messages.get(replacementId);
1096
- if (replacement === void 0)
1097
- throw new Error(
1098
- "MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui."
1099
- );
1100
- for (const child of message.children) {
1101
- const childMessage = this.messages.get(child);
1102
- if (!childMessage)
1103
- throw new Error(
1104
- "MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
1105
- );
1106
- this.performOp(replacement, childMessage, "relink");
1107
- }
1108
- this.performOp(null, message, "cut");
1109
- this.messages.delete(messageId);
1110
- if (this.head === message) {
1111
- this.head = replacement ? findHead(replacement) : null;
1112
- }
1113
- }
1114
- getBranches(messageId) {
1115
- const message = this.messages.get(messageId);
1116
- if (!message)
1117
- throw new Error(
1118
- "MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui."
1119
- );
1120
- const { children } = message.prev ?? this.root;
1121
- return children;
1122
- }
1123
- switchToBranch(messageId) {
1124
- const message = this.messages.get(messageId);
1125
- if (!message)
1126
- throw new Error(
1127
- "MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui."
1128
- );
1129
- if (message.prev) {
1130
- message.prev.next = message;
1131
- }
1132
- this.head = findHead(message);
1133
- }
1134
- resetHead(messageId) {
1135
- if (messageId === null) {
1136
- this.head = null;
1137
- return;
1138
- }
1139
- const message = this.messages.get(messageId);
1140
- if (!message)
1141
- throw new Error(
1142
- "MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui."
1143
- );
1144
- this.head = message;
1145
- for (let current = message; current; current = current.prev) {
1146
- if (current.prev) {
1147
- current.prev.next = current;
1148
- }
1149
- }
1150
- }
1151
- };
1152
-
1153
- // src/runtime/local/LocalRuntime.tsx
1154
- var LocalRuntime = class {
1155
- constructor(adapter) {
1156
- this.adapter = adapter;
1157
- }
1158
- _subscriptions = /* @__PURE__ */ new Set();
1159
- _configProviders = /* @__PURE__ */ new Set();
1160
- abortController = null;
1161
- repository = new MessageRepository();
1162
- get messages() {
1163
- return this.repository.getMessages();
1164
- }
1165
- get isRunning() {
1166
- return this.abortController != null;
1167
- }
1168
- getBranches(messageId) {
1169
- return this.repository.getBranches(messageId);
1170
- }
1171
- switchToBranch(branchId) {
1172
- this.repository.switchToBranch(branchId);
1173
- this.notifySubscribers();
1174
- }
1175
- async append(message) {
1176
- const userMessageId = generateId();
1177
- const userMessage = {
1178
- id: userMessageId,
1179
- role: "user",
1180
- content: message.content,
1181
- createdAt: /* @__PURE__ */ new Date()
1182
- };
1183
- this.repository.addOrUpdateMessage(message.parentId, userMessage);
1184
- await this.startRun(userMessageId);
1185
- }
1186
- async startRun(parentId) {
1187
- const id = generateId();
1188
- this.repository.resetHead(parentId);
1189
- const messages = this.repository.getMessages();
1190
- const message = {
1191
- id,
1192
- role: "assistant",
1193
- status: "in_progress",
1194
- content: [{ type: "text", text: "" }],
1195
- createdAt: /* @__PURE__ */ new Date()
1196
- };
1197
- this.repository.addOrUpdateMessage(parentId, { ...message });
1198
- this.abortController?.abort();
1199
- this.abortController = new AbortController();
1200
- this.notifySubscribers();
1201
- try {
1202
- const updateHandler = ({ content }) => {
1203
- message.content = content;
1204
- this.repository.addOrUpdateMessage(parentId, { ...message });
1205
- this.notifySubscribers();
1206
- };
1207
- const result = await this.adapter.run({
1208
- messages,
1209
- abortSignal: this.abortController.signal,
1210
- config: mergeModelConfigs([...this._configProviders].map((p) => p())),
1211
- onUpdate: updateHandler
1212
- });
1213
- updateHandler(result);
1214
- message.status = "done";
1215
- this.repository.addOrUpdateMessage(parentId, { ...message });
1216
- } catch (e) {
1217
- message.status = "error";
1218
- this.repository.addOrUpdateMessage(parentId, { ...message });
1219
- console.error(e);
1220
- } finally {
1221
- this.abortController = null;
1222
- this.notifySubscribers();
1223
- }
1224
- }
1225
- cancelRun() {
1226
- if (!this.abortController) return;
1227
- this.abortController.abort();
1228
- this.abortController = null;
1229
- this.notifySubscribers();
1230
- }
1231
- notifySubscribers() {
1232
- for (const callback of this._subscriptions) callback();
1233
- }
1234
- subscribe(callback) {
1235
- this._subscriptions.add(callback);
1236
- return () => this._subscriptions.delete(callback);
1237
- }
1238
- registerModelConfigProvider(provider) {
1239
- this._configProviders.add(provider);
1240
- return () => this._configProviders.delete(provider);
1241
- }
1242
- };
1243
-
1244
- // src/runtime/local/useLocalRuntime.tsx
1245
- var useLocalRuntime = (adapter) => {
1246
- const [runtime] = useState3(() => new LocalRuntime(adapter));
1247
- useInsertionEffect(() => {
1248
- runtime.adapter = adapter;
1249
- });
1250
- return runtime;
1251
- };
1252
-
1253
- // src/context/providers/AssistantRuntimeProvider.tsx
1254
- import { memo } from "react";
1255
-
1256
- // src/context/providers/AssistantProvider.tsx
1257
- import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState5 } from "react";
1258
-
1259
- // src/context/stores/AssistantModelConfig.ts
1260
- import { create as create4 } from "zustand";
1261
-
1262
- // src/utils/ProxyConfigProvider.ts
1263
- var ProxyConfigProvider = class {
1264
- _providers = /* @__PURE__ */ new Set();
1265
- getModelConfig() {
1266
- return mergeModelConfigs([...this._providers].map((p) => p()));
1267
- }
1268
- registerModelConfigProvider(provider) {
1269
- this._providers.add(provider);
1270
- return () => {
1271
- this._providers.delete(provider);
1272
- };
1273
- }
1274
- };
1275
-
1276
- // src/context/stores/AssistantModelConfig.ts
1277
- var makeAssistantModelConfigStore = () => create4(() => {
1278
- const proxy = new ProxyConfigProvider();
1279
- return {
1280
- getModelConfig: () => {
1281
- return proxy.getModelConfig();
1282
- },
1283
- registerModelConfigProvider: (provider) => {
1284
- return proxy.registerModelConfigProvider(provider);
1285
- }
1286
- };
1287
- });
1288
-
1289
- // src/context/providers/ThreadProvider.tsx
1290
- import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState4 } from "react";
1291
-
1292
- // src/context/stores/Composer.ts
1293
- import { create as create5 } from "zustand";
1294
- var makeComposerStore = (useThread) => create5()((set, get, store) => {
1295
- return {
1296
- ...makeBaseComposer(set, get, store),
1297
- isEditing: true,
1298
- send: () => {
1299
- const { setValue, value } = get();
1300
- setValue("");
1301
- useThread.getState().append({
1302
- parentId: useThread.getState().messages.at(-1)?.id ?? null,
1303
- content: [{ type: "text", text: value }]
1304
- });
1305
- },
1306
- cancel: () => {
1307
- const thread = useThread.getState();
1308
- if (!thread.isRunning) return false;
1309
- useThread.getState().cancelRun();
1310
- return true;
1311
- }
1312
- };
1313
- });
1314
-
1315
- // src/context/stores/Thread.ts
1316
- import { create as create6 } from "zustand";
1317
- var makeThreadStore = (runtimeRef) => {
1318
- const useThread = create6(() => ({
1319
- messages: runtimeRef.current.messages,
1320
- isRunning: runtimeRef.current.isRunning,
1321
- getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1322
- switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1323
- startRun: (parentId) => runtimeRef.current.startRun(parentId),
1324
- append: (message) => runtimeRef.current.append(message),
1325
- cancelRun: () => runtimeRef.current.cancelRun()
1326
- }));
1327
- const onRuntimeUpdate = () => {
1328
- useThread.setState({
1329
- messages: runtimeRef.current.messages,
1330
- isRunning: runtimeRef.current.isRunning
1331
- });
1332
- };
1333
- return {
1334
- useThread,
1335
- onRuntimeUpdate
1336
- };
1337
- };
1338
-
1339
- // src/context/stores/ThreadViewport.tsx
1340
- import { create as create7 } from "zustand";
1341
- var makeThreadViewportStore = () => {
1342
- const scrollToBottomListeners = /* @__PURE__ */ new Set();
1343
- return create7(() => ({
1344
- isAtBottom: true,
1345
- scrollToBottom: () => {
1346
- for (const listener of scrollToBottomListeners) {
1347
- listener();
1348
- }
1349
- },
1350
- onScrollToBottom: (callback) => {
1351
- scrollToBottomListeners.add(callback);
1352
- return () => {
1353
- scrollToBottomListeners.delete(callback);
1354
- };
1355
- }
1356
- }));
1357
- };
1358
-
1359
- // src/context/providers/ThreadProvider.tsx
1360
- import { jsx as jsx21, jsxs as jsxs4 } from "react/jsx-runtime";
1361
- var ThreadProvider = ({
1362
- children,
1363
- runtime
1364
- }) => {
1365
- const runtimeRef = useRef4(runtime);
1366
- useInsertionEffect2(() => {
1367
- runtimeRef.current = runtime;
1368
- });
1369
- const [{ context, onRuntimeUpdate }] = useState4(() => {
1370
- const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1371
- const useViewport = makeThreadViewportStore();
1372
- const useComposer = makeComposerStore(useThread);
1373
- return {
1374
- context: {
1375
- useViewport,
1376
- useThread,
1377
- useComposer
1378
- },
1379
- onRuntimeUpdate: onRuntimeUpdate2
1380
- };
1381
- });
1382
- useEffect6(() => {
1383
- onRuntimeUpdate();
1384
- return runtime.subscribe(onRuntimeUpdate);
1385
- }, [onRuntimeUpdate, runtime]);
1386
- const RuntimeSynchronizer = runtime.unstable_synchronizer;
1387
- return /* @__PURE__ */ jsxs4(ThreadContext.Provider, { value: context, children: [
1388
- RuntimeSynchronizer && /* @__PURE__ */ jsx21(RuntimeSynchronizer, {}),
1389
- children
1390
- ] });
1391
- };
1392
-
1393
- // src/context/providers/AssistantProvider.tsx
1394
- import { jsx as jsx22 } from "react/jsx-runtime";
1395
- var AssistantProvider = ({ children, runtime }) => {
1396
- const runtimeRef = useRef5(runtime);
1397
- useInsertionEffect3(() => {
1398
- runtimeRef.current = runtime;
1399
- });
1400
- const [context] = useState5(() => {
1401
- const useModelConfig = makeAssistantModelConfigStore();
1402
- return { useModelConfig };
1403
- });
1404
- const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1405
- useEffect7(() => {
1406
- return runtime.registerModelConfigProvider(getModelCOnfig);
1407
- }, [runtime, getModelCOnfig]);
1408
- return /* @__PURE__ */ jsx22(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx22(ThreadProvider, { runtime, children }) });
1409
- };
1410
-
1411
- // src/context/providers/AssistantRuntimeProvider.tsx
1412
- import { jsx as jsx23 } from "react/jsx-runtime";
1413
- var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1414
- return /* @__PURE__ */ jsx23(AssistantProvider, { runtime, children });
1415
- };
1416
- var AssistantRuntimeProvider = memo(AssistantRuntimeProviderImpl);
1417
-
1418
- // src/internal.ts
1419
- var internal_exports = {};
1420
- __export(internal_exports, {
1421
- MessageRepository: () => MessageRepository,
1422
- ProxyConfigProvider: () => ProxyConfigProvider
1423
- });
1424
- export {
1425
- actionBar_exports as ActionBarPrimitive,
1426
- AssistantRuntimeProvider,
1427
- branchPicker_exports as BranchPickerPrimitive,
1428
- composer_exports as ComposerPrimitive,
1429
- contentPart_exports as ContentPartPrimitive,
1430
- internal_exports as INTERNAL,
1431
- message_exports as MessagePrimitive,
1432
- thread_exports as ThreadPrimitive,
1433
- useBeginMessageEdit,
1434
- useCopyMessage,
1435
- useGoToNextBranch,
1436
- useGoToPreviousBranch,
1437
- useLocalRuntime,
1438
- useReloadMessage
1439
- };
1440
- //# sourceMappingURL=index.mjs.map