@assistant-ui/react 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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