@assistant-ui/react 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  ActionBarPrimitive: () => actionBar_exports,
34
+ AssistantModalPrimitive: () => assistantModal_exports,
34
35
  AssistantRuntimeProvider: () => AssistantRuntimeProvider,
35
36
  BranchPickerPrimitive: () => branchPicker_exports,
36
37
  ComposerPrimitive: () => composer_exports,
@@ -38,22 +39,32 @@ __export(src_exports, {
38
39
  INTERNAL: () => internal_exports,
39
40
  MessagePrimitive: () => message_exports,
40
41
  ThreadPrimitive: () => thread_exports,
42
+ makeAssistantTool: () => makeAssistantTool,
43
+ makeAssistantToolUI: () => makeAssistantToolUI,
41
44
  useActionBarCopy: () => useActionBarCopy,
42
45
  useActionBarEdit: () => useActionBarEdit,
43
46
  useActionBarReload: () => useActionBarReload,
47
+ useAssistantContext: () => useAssistantContext,
48
+ useAssistantInstructions: () => useAssistantInstructions,
49
+ useAssistantTool: () => useAssistantTool,
50
+ useAssistantToolUI: () => useAssistantToolUI,
44
51
  useBranchPickerCount: () => useBranchPickerCount,
45
52
  useBranchPickerNext: () => useBranchPickerNext,
46
53
  useBranchPickerNumber: () => useBranchPickerNumber,
47
54
  useBranchPickerPrevious: () => useBranchPickerPrevious,
48
55
  useComposerCancel: () => useComposerCancel,
56
+ useComposerContext: () => useComposerContext,
49
57
  useComposerIf: () => useComposerIf,
50
58
  useComposerSend: () => useComposerSend,
59
+ useContentPartContext: () => useContentPartContext,
51
60
  useContentPartDisplay: () => useContentPartDisplay,
52
61
  useContentPartImage: () => useContentPartImage,
53
62
  useContentPartInProgressIndicator: () => useContentPartInProgressIndicator,
54
63
  useContentPartText: () => useContentPartText,
55
64
  useLocalRuntime: () => useLocalRuntime,
65
+ useMessageContext: () => useMessageContext,
56
66
  useMessageIf: () => useMessageIf,
67
+ useThreadContext: () => useThreadContext,
57
68
  useThreadEmpty: () => useThreadEmpty,
58
69
  useThreadIf: () => useThreadIf,
59
70
  useThreadScrollToBottom: () => useThreadScrollToBottom,
@@ -167,7 +178,7 @@ var useThreadContext = () => {
167
178
 
168
179
  // src/primitive-hooks/actionBar/useActionBarReload.tsx
169
180
  var useActionBarReload = () => {
170
- const { useThread, useThreadActions, useViewport } = useThreadContext();
181
+ const { useThread, useThreadActions, useComposer, useViewport } = useThreadContext();
171
182
  const { useMessage } = useMessageContext();
172
183
  const disabled = useCombinedStore(
173
184
  [useThread, useMessage],
@@ -177,7 +188,8 @@ var useActionBarReload = () => {
177
188
  const { parentId } = useMessage.getState();
178
189
  useThreadActions.getState().startRun(parentId);
179
190
  useViewport.getState().scrollToBottom();
180
- }, [useThreadActions, useMessage, useViewport]);
191
+ useComposer.getState().focus();
192
+ }, [useThreadActions, useComposer, useViewport, useMessage]);
181
193
  if (disabled) return null;
182
194
  return callback;
183
195
  };
@@ -231,8 +243,14 @@ var useBranchPickerPrevious = () => {
231
243
  };
232
244
 
233
245
  // src/primitive-hooks/composer/useComposerCancel.tsx
246
+ var import_react16 = require("react");
247
+
248
+ // src/context/providers/AssistantRuntimeProvider.tsx
234
249
  var import_react13 = require("react");
235
250
 
251
+ // src/context/providers/AssistantProvider.tsx
252
+ var import_react12 = require("react");
253
+
236
254
  // src/context/react/AssistantContext.ts
237
255
  var import_react10 = require("react");
238
256
  var AssistantContext = (0, import_react10.createContext)(
@@ -247,12 +265,265 @@ var useAssistantContext = () => {
247
265
  return context;
248
266
  };
249
267
 
250
- // src/context/react/ComposerContext.ts
268
+ // src/context/stores/AssistantModelConfig.ts
269
+ var import_zustand = require("zustand");
270
+
271
+ // src/types/ModelConfigTypes.ts
272
+ var mergeModelConfigs = (configSet) => {
273
+ const configs = Array.from(configSet).map((c) => c()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
274
+ return configs.reduce((acc, config) => {
275
+ if (config.system) {
276
+ if (acc.system) {
277
+ acc.system += `
278
+
279
+ ${config.system}`;
280
+ } else {
281
+ acc.system = config.system;
282
+ }
283
+ }
284
+ if (config.tools) {
285
+ for (const [name, tool] of Object.entries(config.tools)) {
286
+ if (acc.tools?.[name]) {
287
+ throw new Error(
288
+ `You tried to define a tool with the name ${name}, but it already exists.`
289
+ );
290
+ }
291
+ if (!acc.tools) acc.tools = {};
292
+ acc.tools[name] = tool;
293
+ }
294
+ }
295
+ return acc;
296
+ }, {});
297
+ };
298
+
299
+ // src/utils/ProxyConfigProvider.ts
300
+ var ProxyConfigProvider = class {
301
+ _providers = /* @__PURE__ */ new Set();
302
+ getModelConfig() {
303
+ return mergeModelConfigs(this._providers);
304
+ }
305
+ registerModelConfigProvider(provider) {
306
+ this._providers.add(provider);
307
+ return () => {
308
+ this._providers.delete(provider);
309
+ };
310
+ }
311
+ };
312
+
313
+ // src/context/stores/AssistantModelConfig.ts
314
+ var makeAssistantModelConfigStore = () => (0, import_zustand.create)(() => {
315
+ const proxy = new ProxyConfigProvider();
316
+ return Object.freeze({
317
+ getModelConfig: () => {
318
+ return proxy.getModelConfig();
319
+ },
320
+ registerModelConfigProvider: (provider) => {
321
+ return proxy.registerModelConfigProvider(provider);
322
+ }
323
+ });
324
+ });
325
+
326
+ // src/context/stores/AssistantToolUIs.ts
327
+ var import_zustand2 = require("zustand");
328
+ var makeAssistantToolUIsStore = () => (0, import_zustand2.create)((set) => {
329
+ const renderers = /* @__PURE__ */ new Map();
330
+ return Object.freeze({
331
+ getToolUI: (name) => {
332
+ const arr = renderers.get(name);
333
+ const last = arr?.at(-1);
334
+ if (last) return last;
335
+ return null;
336
+ },
337
+ setToolUI: (name, render) => {
338
+ let arr = renderers.get(name);
339
+ if (!arr) {
340
+ arr = [];
341
+ renderers.set(name, arr);
342
+ }
343
+ arr.push(render);
344
+ set({});
345
+ return () => {
346
+ const index = arr.indexOf(render);
347
+ if (index !== -1) {
348
+ arr.splice(index, 1);
349
+ }
350
+ if (index === arr.length) {
351
+ set({});
352
+ }
353
+ };
354
+ }
355
+ });
356
+ });
357
+
358
+ // src/context/providers/ThreadProvider.tsx
251
359
  var import_react11 = require("react");
360
+
361
+ // src/context/stores/Composer.ts
362
+ var import_zustand3 = require("zustand");
363
+
364
+ // src/context/stores/BaseComposer.ts
365
+ var makeBaseComposer = (set) => ({
366
+ value: "",
367
+ setValue: (value) => {
368
+ set({ value });
369
+ }
370
+ });
371
+
372
+ // src/context/stores/Composer.ts
373
+ var makeComposerStore = (useThread, useThreadActions) => {
374
+ const focusListeners = /* @__PURE__ */ new Set();
375
+ return (0, import_zustand3.create)()((set, get, store) => {
376
+ return {
377
+ ...makeBaseComposer(set, get, store),
378
+ isEditing: true,
379
+ send: () => {
380
+ const { setValue, value } = get();
381
+ setValue("");
382
+ useThreadActions.getState().append({
383
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
384
+ role: "user",
385
+ content: [{ type: "text", text: value }]
386
+ });
387
+ },
388
+ cancel: () => {
389
+ const thread = useThread.getState();
390
+ if (!thread.isRunning) return false;
391
+ useThreadActions.getState().cancelRun();
392
+ return true;
393
+ },
394
+ focus: () => {
395
+ for (const listener of focusListeners) {
396
+ listener();
397
+ }
398
+ },
399
+ onFocus: (listener) => {
400
+ focusListeners.add(listener);
401
+ return () => {
402
+ focusListeners.delete(listener);
403
+ };
404
+ }
405
+ };
406
+ });
407
+ };
408
+
409
+ // src/context/stores/Thread.ts
410
+ var import_zustand4 = require("zustand");
411
+ var makeThreadStore = (runtimeRef) => {
412
+ return (0, import_zustand4.create)(() => ({
413
+ messages: runtimeRef.current.messages,
414
+ isRunning: runtimeRef.current.isRunning
415
+ }));
416
+ };
417
+
418
+ // src/context/stores/ThreadViewport.tsx
419
+ var import_zustand5 = require("zustand");
420
+ var makeThreadViewportStore = () => {
421
+ const scrollToBottomListeners = /* @__PURE__ */ new Set();
422
+ return (0, import_zustand5.create)(() => ({
423
+ isAtBottom: true,
424
+ scrollToBottom: () => {
425
+ for (const listener of scrollToBottomListeners) {
426
+ listener();
427
+ }
428
+ },
429
+ onScrollToBottom: (callback) => {
430
+ scrollToBottomListeners.add(callback);
431
+ return () => {
432
+ scrollToBottomListeners.delete(callback);
433
+ };
434
+ }
435
+ }));
436
+ };
437
+
438
+ // src/context/stores/ThreadActions.ts
439
+ var import_zustand6 = require("zustand");
440
+ var makeThreadActionStore = (runtimeRef) => {
441
+ return (0, import_zustand6.create)(
442
+ () => Object.freeze({
443
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
444
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
445
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
446
+ append: (message) => runtimeRef.current.append(message),
447
+ cancelRun: () => runtimeRef.current.cancelRun(),
448
+ addToolResult: (toolCallId, result) => runtimeRef.current.addToolResult(toolCallId, result)
449
+ })
450
+ );
451
+ };
452
+
453
+ // src/context/providers/ThreadProvider.tsx
454
+ var import_jsx_runtime = require("react/jsx-runtime");
455
+ var ThreadProvider = ({
456
+ children,
457
+ runtime
458
+ }) => {
459
+ const runtimeRef = (0, import_react11.useRef)(runtime);
460
+ (0, import_react11.useInsertionEffect)(() => {
461
+ runtimeRef.current = runtime;
462
+ });
463
+ const [context] = (0, import_react11.useState)(() => {
464
+ const useThread = makeThreadStore(runtimeRef);
465
+ const useThreadActions = makeThreadActionStore(runtimeRef);
466
+ const useViewport = makeThreadViewportStore();
467
+ const useComposer = makeComposerStore(useThread, useThreadActions);
468
+ return {
469
+ useThread,
470
+ useThreadActions,
471
+ useComposer,
472
+ useViewport
473
+ };
474
+ });
475
+ (0, import_react11.useEffect)(() => {
476
+ const onRuntimeUpdate = () => {
477
+ context.useThread.setState(
478
+ Object.freeze({
479
+ messages: runtimeRef.current.messages,
480
+ isRunning: runtimeRef.current.isRunning
481
+ }),
482
+ true
483
+ );
484
+ };
485
+ onRuntimeUpdate();
486
+ return runtime.subscribe(onRuntimeUpdate);
487
+ }, [context, runtime]);
488
+ const RuntimeSynchronizer = runtime.unstable_synchronizer;
489
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ThreadContext.Provider, { value: context, children: [
490
+ RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RuntimeSynchronizer, {}),
491
+ children
492
+ ] });
493
+ };
494
+
495
+ // src/context/providers/AssistantProvider.tsx
496
+ var import_jsx_runtime2 = require("react/jsx-runtime");
497
+ var AssistantProvider = ({ children, runtime }) => {
498
+ const runtimeRef = (0, import_react12.useRef)(runtime);
499
+ (0, import_react12.useInsertionEffect)(() => {
500
+ runtimeRef.current = runtime;
501
+ });
502
+ const [context] = (0, import_react12.useState)(() => {
503
+ const useModelConfig = makeAssistantModelConfigStore();
504
+ const useToolUIs = makeAssistantToolUIsStore();
505
+ return { useModelConfig, useToolUIs };
506
+ });
507
+ const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
508
+ (0, import_react12.useEffect)(() => {
509
+ return runtime.registerModelConfigProvider(getModelCOnfig);
510
+ }, [runtime, getModelCOnfig]);
511
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThreadProvider, { runtime, children }) });
512
+ };
513
+
514
+ // src/context/providers/AssistantRuntimeProvider.tsx
515
+ var import_jsx_runtime3 = require("react/jsx-runtime");
516
+ var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
517
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AssistantProvider, { runtime, children });
518
+ };
519
+ var AssistantRuntimeProvider = (0, import_react13.memo)(AssistantRuntimeProviderImpl);
520
+
521
+ // src/context/react/ComposerContext.ts
522
+ var import_react14 = require("react");
252
523
  var useComposerContext = () => {
253
524
  const { useComposer } = useThreadContext();
254
- const { useEditComposer } = (0, import_react11.useContext)(MessageContext) ?? {};
255
- return (0, import_react11.useMemo)(
525
+ const { useEditComposer } = (0, import_react14.useContext)(MessageContext) ?? {};
526
+ return (0, import_react14.useMemo)(
256
527
  () => ({
257
528
  useComposer: useEditComposer ?? useComposer,
258
529
  type: useEditComposer ? "edit" : "new"
@@ -262,12 +533,12 @@ var useComposerContext = () => {
262
533
  };
263
534
 
264
535
  // src/context/react/ContentPartContext.ts
265
- var import_react12 = require("react");
266
- var ContentPartContext = (0, import_react12.createContext)(
536
+ var import_react15 = require("react");
537
+ var ContentPartContext = (0, import_react15.createContext)(
267
538
  null
268
539
  );
269
540
  var useContentPartContext = () => {
270
- const context = (0, import_react12.useContext)(ContentPartContext);
541
+ const context = (0, import_react15.useContext)(ContentPartContext);
271
542
  if (!context)
272
543
  throw new Error(
273
544
  "This component can only be used inside a component passed to <MessagePrimitive.Content components={...} >."
@@ -279,7 +550,7 @@ var useContentPartContext = () => {
279
550
  var useComposerCancel = () => {
280
551
  const { useComposer } = useComposerContext();
281
552
  const disabled = useComposer((c) => !c.isEditing);
282
- const callback = (0, import_react13.useCallback)(() => {
553
+ const callback = (0, import_react16.useCallback)(() => {
283
554
  const { cancel } = useComposer.getState();
284
555
  cancel();
285
556
  }, [useComposer]);
@@ -298,17 +569,18 @@ var useComposerIf = (props) => {
298
569
  };
299
570
 
300
571
  // src/primitive-hooks/composer/useComposerSend.tsx
301
- var import_react14 = require("react");
572
+ var import_react17 = require("react");
302
573
  var useComposerSend = () => {
303
- const { useViewport } = useThreadContext();
574
+ const { useViewport, useComposer: useNewComposer } = useThreadContext();
304
575
  const { useComposer } = useComposerContext();
305
576
  const disabled = useComposer((c) => !c.isEditing || c.value.length === 0);
306
- const callback = (0, import_react14.useCallback)(() => {
577
+ const callback = (0, import_react17.useCallback)(() => {
307
578
  const composerState = useComposer.getState();
308
579
  if (!composerState.isEditing) return;
309
580
  composerState.send();
310
581
  useViewport.getState().scrollToBottom();
311
- }, [useComposer, useViewport]);
582
+ useNewComposer.getState().focus();
583
+ }, [useNewComposer, useComposer, useViewport]);
312
584
  if (disabled) return null;
313
585
  return callback;
314
586
  };
@@ -398,27 +670,27 @@ var useThreadEmpty = () => {
398
670
  };
399
671
 
400
672
  // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
401
- var import_react15 = require("react");
673
+ var import_react18 = require("react");
402
674
  var useThreadScrollToBottom = () => {
403
- const { useViewport } = useThreadContext();
675
+ const { useComposer, useViewport } = useThreadContext();
404
676
  const isAtBottom = useViewport((s) => s.isAtBottom);
405
- const handleScrollToBottom = (0, import_react15.useCallback)(() => {
406
- const { scrollToBottom } = useViewport.getState();
407
- scrollToBottom();
408
- }, [useViewport]);
677
+ const handleScrollToBottom = (0, import_react18.useCallback)(() => {
678
+ useViewport.getState().scrollToBottom();
679
+ useComposer.getState().focus();
680
+ }, [useViewport, useComposer]);
409
681
  if (isAtBottom) return null;
410
682
  return handleScrollToBottom;
411
683
  };
412
684
 
413
685
  // src/primitive-hooks/thread/useThreadSuggestion.tsx
414
- var import_react16 = require("react");
686
+ var import_react19 = require("react");
415
687
  var useThreadSuggestion = ({
416
688
  prompt,
417
689
  autoSend
418
690
  }) => {
419
691
  const { useThread, useComposer } = useThreadContext();
420
692
  const disabled = useThread((t) => t.isRunning);
421
- const callback = (0, import_react16.useCallback)(() => {
693
+ const callback = (0, import_react19.useCallback)(() => {
422
694
  const thread = useThread.getState();
423
695
  const composer = useComposer.getState();
424
696
  composer.setValue(prompt);
@@ -430,330 +702,279 @@ var useThreadSuggestion = ({
430
702
  return callback;
431
703
  };
432
704
 
433
- // src/primitives/thread/index.ts
434
- var thread_exports = {};
435
- __export(thread_exports, {
436
- Empty: () => ThreadEmpty,
437
- If: () => ThreadIf,
438
- Messages: () => ThreadMessages,
439
- Root: () => ThreadRoot,
440
- ScrollToBottom: () => ThreadScrollToBottom,
441
- Suggestion: () => ThreadSuggestion,
442
- Viewport: () => ThreadViewport
705
+ // src/primitives/actionBar/index.ts
706
+ var actionBar_exports = {};
707
+ __export(actionBar_exports, {
708
+ Copy: () => ActionBarCopy,
709
+ Edit: () => ActionBarEdit,
710
+ Reload: () => ActionBarReload,
711
+ Root: () => ActionBarRoot
443
712
  });
444
713
 
445
- // src/primitives/thread/ThreadRoot.tsx
714
+ // src/primitives/actionBar/ActionBarRoot.tsx
446
715
  var import_react_primitive = require("@radix-ui/react-primitive");
447
- var import_react17 = require("react");
448
- var import_jsx_runtime = require("react/jsx-runtime");
449
- var ThreadRoot = (0, import_react17.forwardRef)(
450
- (props, ref) => {
451
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
452
- }
453
- );
454
- ThreadRoot.displayName = "ThreadRoot";
455
-
456
- // src/primitives/thread/ThreadEmpty.tsx
457
- var ThreadEmpty = ({ children }) => {
458
- const empty = useThreadEmpty();
459
- return empty ? children : null;
716
+ var import_react20 = require("react");
717
+ var import_jsx_runtime4 = require("react/jsx-runtime");
718
+ var useActionBarFloatStatus = ({
719
+ hideWhenRunning,
720
+ autohide,
721
+ autohideFloat
722
+ }) => {
723
+ const { useThread } = useThreadContext();
724
+ const { useMessage, useMessageUtils } = useMessageContext();
725
+ return useCombinedStore(
726
+ [useThread, useMessage, useMessageUtils],
727
+ (t, m, mu) => {
728
+ if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
729
+ const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
730
+ if (!autohideEnabled) return "normal" /* Normal */;
731
+ if (!mu.isHovering) return "hidden" /* Hidden */;
732
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
733
+ return "floating" /* Floating */;
734
+ return "normal" /* Normal */;
735
+ }
736
+ );
460
737
  };
738
+ var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
739
+ const hideAndfloatStatus = useActionBarFloatStatus({
740
+ hideWhenRunning,
741
+ autohide,
742
+ autohideFloat
743
+ });
744
+ if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
745
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
746
+ import_react_primitive.Primitive.div,
747
+ {
748
+ ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
749
+ ...rest,
750
+ ref
751
+ }
752
+ );
753
+ });
754
+ ActionBarRoot.displayName = "ActionBarRoot";
461
755
 
462
- // src/primitives/thread/ThreadIf.tsx
463
- var ThreadIf = ({ children, ...query }) => {
464
- const result = useThreadIf(query);
465
- return result ? children : null;
756
+ // src/utils/createActionButton.tsx
757
+ var import_primitive = require("@radix-ui/primitive");
758
+ var import_react_primitive2 = require("@radix-ui/react-primitive");
759
+ var import_react21 = require("react");
760
+ var import_jsx_runtime5 = require("react/jsx-runtime");
761
+ var createActionButton = (displayName, useActionButton) => {
762
+ const ActionButton = (0, import_react21.forwardRef)((props, forwardedRef) => {
763
+ const callback = useActionButton(props);
764
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
765
+ import_react_primitive2.Primitive.button,
766
+ {
767
+ type: "button",
768
+ disabled: !callback,
769
+ ...props,
770
+ ref: forwardedRef,
771
+ onClick: (0, import_primitive.composeEventHandlers)(props.onClick, () => {
772
+ callback?.();
773
+ })
774
+ }
775
+ );
776
+ });
777
+ ActionButton.displayName = displayName;
778
+ return ActionButton;
466
779
  };
467
780
 
468
- // src/primitives/thread/ThreadViewport.tsx
469
- var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
470
- var import_react_primitive2 = require("@radix-ui/react-primitive");
471
- var import_react22 = require("react");
781
+ // src/primitives/actionBar/ActionBarCopy.tsx
782
+ var ActionBarCopy = createActionButton(
783
+ "ActionBarCopy",
784
+ useActionBarCopy
785
+ );
472
786
 
473
- // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
474
- var import_react_compose_refs = require("@radix-ui/react-compose-refs");
475
- var import_react21 = require("react");
787
+ // src/primitives/actionBar/ActionBarReload.tsx
788
+ var ActionBarReload = createActionButton(
789
+ "ActionBarReload",
790
+ useActionBarReload
791
+ );
476
792
 
477
- // src/utils/hooks/useOnResizeContent.tsx
478
- var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
479
- var import_react19 = require("react");
793
+ // src/primitives/actionBar/ActionBarEdit.tsx
794
+ var ActionBarEdit = createActionButton(
795
+ "ActionBarEdit",
796
+ useActionBarEdit
797
+ );
480
798
 
481
- // src/utils/hooks/useManagedRef.ts
482
- var import_react18 = require("react");
483
- var useManagedRef = (callback) => {
484
- const cleanupRef = (0, import_react18.useRef)();
485
- const ref = (0, import_react18.useCallback)(
486
- (el) => {
487
- if (cleanupRef.current) {
488
- cleanupRef.current();
489
- }
490
- if (el) {
491
- cleanupRef.current = callback(el);
492
- }
493
- },
494
- [callback]
495
- );
496
- return ref;
497
- };
799
+ // src/primitives/assistantModal/index.ts
800
+ var assistantModal_exports = {};
801
+ __export(assistantModal_exports, {
802
+ Content: () => AssistantModalContent,
803
+ Root: () => AssistantModalRoot,
804
+ Trigger: () => AssistantModalTrigger
805
+ });
498
806
 
499
- // src/utils/hooks/useOnResizeContent.tsx
500
- var useOnResizeContent = (callback) => {
501
- const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
502
- const refCallback = (0, import_react19.useCallback)(
503
- (el) => {
504
- const resizeObserver = new ResizeObserver(() => {
505
- callbackRef();
506
- });
507
- const mutationObserver = new MutationObserver((mutations) => {
508
- for (const mutation of mutations) {
509
- for (const node of mutation.addedNodes) {
510
- if (node instanceof Element) {
511
- resizeObserver.observe(node);
512
- }
513
- }
514
- for (const node of mutation.removedNodes) {
515
- if (node instanceof Element) {
516
- resizeObserver.unobserve(node);
517
- }
518
- }
519
- }
520
- callbackRef();
521
- });
522
- resizeObserver.observe(el);
523
- mutationObserver.observe(el, { childList: true });
524
- for (const child of el.children) {
525
- resizeObserver.observe(child);
526
- }
527
- return () => {
528
- resizeObserver.disconnect();
529
- mutationObserver.disconnect();
530
- };
531
- },
532
- [callbackRef]
533
- );
534
- return useManagedRef(refCallback);
535
- };
807
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
808
+ var import_react23 = require("react");
809
+ var PopoverPrimitive = __toESM(require("@radix-ui/react-popover"));
810
+ var import_primitive2 = require("@radix-ui/primitive");
536
811
 
537
- // src/utils/hooks/useOnScrollToBottom.tsx
538
- var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
539
- var import_react20 = require("react");
540
- var useOnScrollToBottom = (callback) => {
541
- const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
542
- const { useViewport } = useThreadContext();
543
- (0, import_react20.useEffect)(() => {
544
- return useViewport.getState().onScrollToBottom(() => {
812
+ // src/utils/hooks/useOnComposerFocus.tsx
813
+ var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
814
+ var import_react22 = require("react");
815
+ var useOnComposerFocus = (callback) => {
816
+ const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
817
+ const { useComposer } = useThreadContext();
818
+ (0, import_react22.useEffect)(() => {
819
+ return useComposer.getState().onFocus(() => {
545
820
  callbackRef();
546
821
  });
547
- }, [useViewport, callbackRef]);
822
+ }, [useComposer, callbackRef]);
548
823
  };
549
824
 
550
- // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
551
- var useThreadViewportAutoScroll = ({
552
- autoScroll = true
825
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
826
+ var import_jsx_runtime6 = require("react/jsx-runtime");
827
+ var usePopoverScope = PopoverPrimitive.createPopoverScope();
828
+ var useAssistantModalOpenState = (defaultOpen = false) => {
829
+ const state = (0, import_react23.useState)(defaultOpen);
830
+ const [, setOpen] = state;
831
+ useOnComposerFocus(() => {
832
+ setOpen(true);
833
+ });
834
+ return state;
835
+ };
836
+ var AssistantModalRoot = ({
837
+ __scopeAssistantModal,
838
+ defaultOpen,
839
+ open,
840
+ onOpenChange,
841
+ ...rest
553
842
  }) => {
554
- const divRef = (0, import_react21.useRef)(null);
555
- const { useViewport } = useThreadContext();
556
- const firstRenderRef = (0, import_react21.useRef)(true);
557
- const lastScrollTop = (0, import_react21.useRef)(0);
558
- const isScrollingToBottomRef = (0, import_react21.useRef)(false);
559
- const scrollToBottom = () => {
560
- const div = divRef.current;
561
- if (!div || !autoScroll) return;
562
- const behavior = firstRenderRef.current ? "instant" : "auto";
563
- firstRenderRef.current = false;
564
- isScrollingToBottomRef.current = true;
565
- div.scrollTo({ top: div.scrollHeight, behavior });
566
- };
567
- const handleScroll = () => {
568
- const div = divRef.current;
569
- if (!div) return;
570
- const isAtBottom = useViewport.getState().isAtBottom;
571
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
572
- if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
573
- } else {
574
- isScrollingToBottomRef.current = newIsAtBottom;
575
- if (newIsAtBottom !== isAtBottom) {
576
- useViewport.setState({
577
- isAtBottom: newIsAtBottom
578
- });
579
- }
580
- }
581
- lastScrollTop.current = div.scrollTop;
582
- };
583
- const resizeRef = useOnResizeContent(() => {
584
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
585
- handleScroll();
586
- } else {
587
- scrollToBottom();
843
+ const scope = usePopoverScope(__scopeAssistantModal);
844
+ const [modalOpen, setOpen] = useAssistantModalOpenState(defaultOpen);
845
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
846
+ PopoverPrimitive.Root,
847
+ {
848
+ ...scope,
849
+ open: open === void 0 ? modalOpen : open,
850
+ onOpenChange: (0, import_primitive2.composeEventHandlers)(onOpenChange, setOpen),
851
+ ...rest
588
852
  }
589
- });
590
- const scrollRef = useManagedRef((el) => {
591
- el.addEventListener("scroll", handleScroll);
592
- return () => {
593
- el.removeEventListener("scroll", handleScroll);
594
- };
595
- });
596
- const autoScrollRef = (0, import_react_compose_refs.useComposedRefs)(resizeRef, scrollRef, divRef);
597
- useOnScrollToBottom(() => {
598
- scrollToBottom();
599
- });
600
- return autoScrollRef;
853
+ );
601
854
  };
855
+ AssistantModalRoot.displayName = "AssistantModalRoot";
602
856
 
603
- // src/primitives/thread/ThreadViewport.tsx
604
- var import_jsx_runtime2 = require("react/jsx-runtime");
605
- var ThreadViewport = (0, import_react22.forwardRef)(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
606
- const autoScrollRef = useThreadViewportAutoScroll({
607
- autoScroll
608
- });
609
- const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, autoScrollRef);
610
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_primitive2.Primitive.div, { ...rest, ref, children });
611
- });
612
- ThreadViewport.displayName = "ThreadViewport";
613
-
614
- // src/primitives/thread/ThreadMessages.tsx
857
+ // src/primitives/assistantModal/AssistantModalTrigger.tsx
615
858
  var import_react24 = require("react");
859
+ var PopoverPrimitive2 = __toESM(require("@radix-ui/react-popover"));
860
+ var import_jsx_runtime7 = require("react/jsx-runtime");
861
+ var AssistantModalTrigger = (0, import_react24.forwardRef)(
862
+ ({ __scopeAssistantModal, ...rest }, ref) => {
863
+ const scope = usePopoverScope(__scopeAssistantModal);
864
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PopoverPrimitive2.Trigger, { ...scope, ...rest, ref });
865
+ }
866
+ );
867
+ AssistantModalTrigger.displayName = "AssistantModalTrigger";
616
868
 
617
- // src/context/providers/MessageProvider.tsx
618
- var import_react23 = require("react");
619
- var import_zustand3 = require("zustand");
620
-
621
- // src/context/stores/EditComposer.ts
622
- var import_zustand = require("zustand");
623
-
624
- // src/context/stores/BaseComposer.ts
625
- var makeBaseComposer = (set) => ({
626
- value: "",
627
- setValue: (value) => {
628
- set({ value });
869
+ // src/primitives/assistantModal/AssistantModalContent.tsx
870
+ var import_react25 = require("react");
871
+ var PopoverPrimitive3 = __toESM(require("@radix-ui/react-popover"));
872
+ var import_primitive3 = require("@radix-ui/primitive");
873
+ var import_jsx_runtime8 = require("react/jsx-runtime");
874
+ var AssistantModalContent = (0, import_react25.forwardRef)(
875
+ ({
876
+ __scopeAssistantModal,
877
+ side,
878
+ align,
879
+ onInteractOutside,
880
+ dissmissOnInteractOutside = false,
881
+ ...props
882
+ }, forwardedRef) => {
883
+ const scope = usePopoverScope(__scopeAssistantModal);
884
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PopoverPrimitive3.Portal, { ...scope, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
885
+ PopoverPrimitive3.Content,
886
+ {
887
+ ...scope,
888
+ ...props,
889
+ ref: forwardedRef,
890
+ side: side ?? "top",
891
+ align: align ?? "end",
892
+ onInteractOutside: (0, import_primitive3.composeEventHandlers)(
893
+ onInteractOutside,
894
+ dissmissOnInteractOutside ? void 0 : (e) => e.preventDefault()
895
+ )
896
+ }
897
+ ) });
629
898
  }
899
+ );
900
+ AssistantModalContent.displayName = "AssistantModalContent";
901
+
902
+ // src/primitives/branchPicker/index.ts
903
+ var branchPicker_exports = {};
904
+ __export(branchPicker_exports, {
905
+ Count: () => BranchPickerCount,
906
+ Next: () => BranchPickerNext,
907
+ Number: () => BranchPickerNumber,
908
+ Previous: () => BranchPickerPrevious,
909
+ Root: () => BranchPickerRoot
630
910
  });
631
911
 
632
- // src/context/stores/EditComposer.ts
633
- var makeEditComposerStore = ({
634
- onEdit,
635
- onSend
636
- }) => (0, import_zustand.create)()((set, get, store) => ({
637
- ...makeBaseComposer(set, get, store),
638
- isEditing: false,
639
- edit: () => {
640
- const value = onEdit();
641
- set({ isEditing: true, value });
642
- },
643
- send: () => {
644
- const value = get().value;
645
- set({ isEditing: false });
646
- onSend(value);
647
- },
648
- cancel: () => {
649
- if (!get().isEditing) return false;
650
- set({ isEditing: false });
651
- return true;
652
- }
653
- }));
912
+ // src/primitives/branchPicker/BranchPickerNext.tsx
913
+ var BranchPickerNext = createActionButton(
914
+ "BranchPickerNext",
915
+ useBranchPickerNext
916
+ );
654
917
 
655
- // src/context/stores/MessageUtils.ts
656
- var import_zustand2 = require("zustand");
657
- var makeMessageUtilsStore = () => (0, import_zustand2.create)((set) => ({
658
- inProgressIndicator: null,
659
- setInProgressIndicator: (value) => {
660
- set({ inProgressIndicator: value });
661
- },
662
- isCopied: false,
663
- setIsCopied: (value) => {
664
- set({ isCopied: value });
665
- },
666
- isHovering: false,
667
- setIsHovering: (value) => {
668
- set({ isHovering: value });
669
- }
670
- }));
918
+ // src/primitives/branchPicker/BranchPickerPrevious.tsx
919
+ var BranchPickerPrevious = createActionButton(
920
+ "BranchPickerPrevious",
921
+ useBranchPickerPrevious
922
+ );
671
923
 
672
- // src/context/providers/MessageProvider.tsx
673
- var import_jsx_runtime3 = require("react/jsx-runtime");
674
- var getIsLast = (thread, message) => {
675
- return thread.messages[thread.messages.length - 1]?.id === message.id;
924
+ // src/primitives/branchPicker/BranchPickerCount.tsx
925
+ var import_jsx_runtime9 = require("react/jsx-runtime");
926
+ var BranchPickerCount = () => {
927
+ const branchCount = useBranchPickerCount();
928
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: branchCount });
676
929
  };
677
- var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
678
- const parentId = thread.messages[messageIndex - 1]?.id ?? null;
679
- const message = thread.messages[messageIndex];
680
- if (!message) return;
681
- const isLast = getIsLast(thread, message);
682
- const branches = getBranches(message.id);
683
- const currentState = useMessage.getState();
684
- if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
685
- return;
686
- useMessage.setState({
687
- message,
688
- parentId,
689
- branches,
690
- isLast
691
- });
930
+
931
+ // src/primitives/branchPicker/BranchPickerNumber.tsx
932
+ var import_jsx_runtime10 = require("react/jsx-runtime");
933
+ var BranchPickerNumber = () => {
934
+ const branchNumber = useBranchPickerNumber();
935
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: branchNumber });
692
936
  };
693
- var useMessageContext2 = (messageIndex) => {
694
- const { useThread, useThreadActions } = useThreadContext();
695
- const [context] = (0, import_react23.useState)(() => {
696
- const useMessage = (0, import_zustand3.create)(() => ({}));
697
- const useMessageUtils = makeMessageUtilsStore();
698
- const useEditComposer = makeEditComposerStore({
699
- onEdit: () => {
700
- const message = useMessage.getState().message;
701
- if (message.role !== "user")
702
- throw new Error(
703
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
704
- );
705
- const text = getMessageText(message);
706
- return text;
707
- },
708
- onSend: (text) => {
709
- const { message, parentId } = useMessage.getState();
710
- if (message.role !== "user")
711
- throw new Error(
712
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
713
- );
714
- const nonTextParts = message.content.filter(
715
- (part) => part.type !== "text" && part.type !== "ui"
716
- );
717
- useThreadActions.getState().append({
718
- parentId,
719
- role: "user",
720
- content: [{ type: "text", text }, ...nonTextParts]
721
- });
937
+
938
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
939
+ var import_react_primitive6 = require("@radix-ui/react-primitive");
940
+ var import_react31 = require("react");
941
+
942
+ // src/primitives/message/index.ts
943
+ var message_exports = {};
944
+ __export(message_exports, {
945
+ Content: () => MessageContent,
946
+ If: () => MessageIf,
947
+ InProgress: () => MessageInProgress,
948
+ Root: () => MessageRoot
949
+ });
950
+
951
+ // src/primitives/message/MessageRoot.tsx
952
+ var import_primitive4 = require("@radix-ui/primitive");
953
+ var import_react_primitive3 = require("@radix-ui/react-primitive");
954
+ var import_react26 = require("react");
955
+ var import_jsx_runtime11 = require("react/jsx-runtime");
956
+ var MessageRoot = (0, import_react26.forwardRef)(
957
+ ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
958
+ const { useMessageUtils } = useMessageContext();
959
+ const setIsHovering = useMessageUtils((s) => s.setIsHovering);
960
+ const handleMouseEnter = () => {
961
+ setIsHovering(true);
962
+ };
963
+ const handleMouseLeave = () => {
964
+ setIsHovering(false);
965
+ };
966
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
967
+ import_react_primitive3.Primitive.div,
968
+ {
969
+ ...rest,
970
+ ref,
971
+ onMouseEnter: (0, import_primitive4.composeEventHandlers)(onMouseEnter, handleMouseEnter),
972
+ onMouseLeave: (0, import_primitive4.composeEventHandlers)(onMouseLeave, handleMouseLeave)
722
973
  }
723
- });
724
- syncMessage(
725
- useThread.getState(),
726
- useThreadActions.getState().getBranches,
727
- useMessage,
728
- messageIndex
729
974
  );
730
- return { useMessage, useMessageUtils, useEditComposer };
731
- });
732
- (0, import_react23.useEffect)(() => {
733
- return useThread.subscribe((thread) => {
734
- syncMessage(
735
- thread,
736
- useThreadActions.getState().getBranches,
737
- context.useMessage,
738
- messageIndex
739
- );
740
- });
741
- }, [useThread, useThreadActions, context, messageIndex]);
742
- return context;
743
- };
744
- var MessageProvider = ({
745
- messageIndex,
746
- children
747
- }) => {
748
- const context = useMessageContext2(messageIndex);
749
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MessageContext.Provider, { value: context, children });
750
- };
751
-
752
- // src/primitives/composer/ComposerIf.tsx
753
- var ComposerIf = ({ children, ...query }) => {
754
- const result = useComposerIf(query);
755
- return result ? children : null;
756
- };
975
+ }
976
+ );
977
+ MessageRoot.displayName = "MessageRoot";
757
978
 
758
979
  // src/primitives/message/MessageIf.tsx
759
980
  var MessageIf = ({ children, ...query }) => {
@@ -761,85 +982,166 @@ var MessageIf = ({ children, ...query }) => {
761
982
  return result ? children : null;
762
983
  };
763
984
 
764
- // src/primitives/thread/ThreadMessages.tsx
765
- var import_jsx_runtime4 = require("react/jsx-runtime");
766
- var getComponents = (components) => {
767
- return {
768
- EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
769
- UserMessage: components.UserMessage ?? components.Message,
770
- AssistantMessage: components.AssistantMessage ?? components.Message
771
- };
772
- };
773
- var ThreadMessageImpl = ({
774
- messageIndex,
775
- components
776
- }) => {
777
- const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
778
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MessageProvider, { messageIndex, children: [
779
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MessageIf, { user: true, children: [
780
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UserMessage, {}) }),
781
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EditComposer, {}) })
782
- ] }),
783
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AssistantMessage, {}) })
784
- ] });
985
+ // src/primitives/message/MessageContent.tsx
986
+ var import_react29 = require("react");
987
+
988
+ // src/context/providers/ContentPartProvider.tsx
989
+ var import_react27 = require("react");
990
+ var import_zustand7 = require("zustand");
991
+ var import_jsx_runtime12 = require("react/jsx-runtime");
992
+ var syncContentPart = ({ message }, useContentPart, partIndex) => {
993
+ const part = message.content[partIndex];
994
+ if (!part) return;
995
+ const messageStatus = message.role === "assistant" ? message.status : "done";
996
+ const status = partIndex === message.content.length - 1 ? messageStatus : "done";
997
+ const currentState = useContentPart.getState();
998
+ if (currentState.part === part && currentState.status === status) return;
999
+ useContentPart.setState(
1000
+ Object.freeze({
1001
+ part,
1002
+ status
1003
+ })
1004
+ );
785
1005
  };
786
- var ThreadMessage = (0, import_react24.memo)(
787
- ThreadMessageImpl,
788
- (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
789
- );
790
- var ThreadMessages = ({ components }) => {
791
- const { useThread } = useThreadContext();
792
- const messagesLength = useThread((t) => t.messages.length);
793
- if (messagesLength === 0) return null;
794
- return new Array(messagesLength).fill(null).map((_, idx) => {
795
- const messageIndex = idx;
796
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
797
- ThreadMessage,
798
- {
799
- messageIndex,
800
- components
801
- },
802
- messageIndex
1006
+ var useContentPartContext2 = (partIndex) => {
1007
+ const { useMessage } = useMessageContext();
1008
+ const [context] = (0, import_react27.useState)(() => {
1009
+ const useContentPart = (0, import_zustand7.create)(
1010
+ () => ({})
803
1011
  );
1012
+ syncContentPart(useMessage.getState(), useContentPart, partIndex);
1013
+ return { useContentPart };
804
1014
  });
1015
+ (0, import_react27.useEffect)(() => {
1016
+ syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
1017
+ return useMessage.subscribe((message) => {
1018
+ syncContentPart(message, context.useContentPart, partIndex);
1019
+ });
1020
+ }, [context, useMessage, partIndex]);
1021
+ return context;
1022
+ };
1023
+ var ContentPartProvider = ({
1024
+ partIndex,
1025
+ children
1026
+ }) => {
1027
+ const context = useContentPartContext2(partIndex);
1028
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartContext.Provider, { value: context, children });
805
1029
  };
806
1030
 
807
- // src/utils/createActionButton.tsx
808
- var import_primitive = require("@radix-ui/primitive");
809
- var import_react_primitive3 = require("@radix-ui/react-primitive");
810
- var import_react25 = require("react");
811
- var import_jsx_runtime5 = require("react/jsx-runtime");
812
- var createActionButton = (displayName, useActionButton) => {
813
- const ActionButton = (0, import_react25.forwardRef)((props, forwardedRef) => {
814
- const callback = useActionButton(props);
815
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
816
- import_react_primitive3.Primitive.button,
817
- {
818
- type: "button",
819
- disabled: !callback,
820
- ...props,
821
- ref: forwardedRef,
822
- onClick: (0, import_primitive.composeEventHandlers)(props.onClick, () => {
823
- callback?.();
824
- })
825
- }
826
- );
827
- });
828
- ActionButton.displayName = displayName;
829
- return ActionButton;
1031
+ // src/primitives/contentPart/ContentPartDisplay.tsx
1032
+ var ContentPartDisplay = () => {
1033
+ const display = useContentPartDisplay();
1034
+ return display ?? null;
830
1035
  };
831
1036
 
832
- // src/primitives/thread/ThreadScrollToBottom.tsx
833
- var ThreadScrollToBottom = createActionButton(
834
- "ThreadScrollToBottom",
835
- useThreadScrollToBottom
836
- );
1037
+ // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
1038
+ var ContentPartInProgressIndicator = () => {
1039
+ const indicator = useContentPartInProgressIndicator();
1040
+ return indicator;
1041
+ };
837
1042
 
838
- // src/primitives/thread/ThreadSuggestion.tsx
839
- var ThreadSuggestion = createActionButton(
840
- "ThreadSuggestion",
841
- useThreadSuggestion
1043
+ // src/primitives/contentPart/ContentPartText.tsx
1044
+ var import_react_primitive4 = require("@radix-ui/react-primitive");
1045
+ var import_react28 = require("react");
1046
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1047
+ var ContentPartText = (0, import_react28.forwardRef)((props, forwardedRef) => {
1048
+ const text = useContentPartText();
1049
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_primitive4.Primitive.p, { ...props, ref: forwardedRef, children: text });
1050
+ });
1051
+ ContentPartText.displayName = "ContentPartText";
1052
+
1053
+ // src/primitives/message/MessageContent.tsx
1054
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1055
+ var defaultComponents = {
1056
+ Text: () => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1057
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartText, { style: { whiteSpace: "pre-line" } }),
1058
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartInProgressIndicator, {})
1059
+ ] }),
1060
+ Image: () => null,
1061
+ UI: () => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartDisplay, {}),
1062
+ tools: {
1063
+ Fallback: (props) => {
1064
+ const { useToolUIs } = useAssistantContext();
1065
+ const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
1066
+ if (!Render) return null;
1067
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Render, { ...props });
1068
+ }
1069
+ }
1070
+ };
1071
+ var MessageContentPartComponent = ({
1072
+ components: {
1073
+ Text = defaultComponents.Text,
1074
+ Image = defaultComponents.Image,
1075
+ UI = defaultComponents.UI,
1076
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
1077
+ } = {}
1078
+ }) => {
1079
+ const { useThreadActions } = useThreadContext();
1080
+ const addToolResult = useThreadActions((t) => t.addToolResult);
1081
+ const { useContentPart } = useContentPartContext();
1082
+ const { part, status } = useContentPart();
1083
+ const type = part.type;
1084
+ switch (type) {
1085
+ case "text":
1086
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { part, status });
1087
+ case "image":
1088
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Image, { part, status });
1089
+ case "ui":
1090
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(UI, { part, status });
1091
+ case "tool-call": {
1092
+ const Tool = by_name[part.toolName] || Fallback;
1093
+ const addResult = (result) => addToolResult(part.toolCallId, result);
1094
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Tool, { part, status, addResult });
1095
+ }
1096
+ default:
1097
+ throw new Error(`Unknown content part type: ${type}`);
1098
+ }
1099
+ };
1100
+ var MessageContentPartImpl = ({
1101
+ partIndex,
1102
+ components
1103
+ }) => {
1104
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ContentPartProvider, { partIndex, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageContentPartComponent, { components }) });
1105
+ };
1106
+ var MessageContentPart = (0, import_react29.memo)(
1107
+ MessageContentPartImpl,
1108
+ (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Image === next.components?.Image && prev.components?.UI === next.components?.UI && prev.components?.tools === next.components?.tools
842
1109
  );
1110
+ var MessageContent = ({ components }) => {
1111
+ const { useMessage } = useMessageContext();
1112
+ const contentLength = useMessage((s) => s.message.content.length);
1113
+ return new Array(contentLength).fill(null).map((_, idx) => {
1114
+ const partIndex = idx;
1115
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1116
+ MessageContentPart,
1117
+ {
1118
+ partIndex,
1119
+ components
1120
+ },
1121
+ partIndex
1122
+ );
1123
+ });
1124
+ };
1125
+
1126
+ // src/primitives/message/MessageInProgress.tsx
1127
+ var import_react_primitive5 = require("@radix-ui/react-primitive");
1128
+ var import_react30 = require("react");
1129
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1130
+ var MessageInProgress = (0, import_react30.forwardRef)((props, ref) => {
1131
+ const { useMessageUtils } = useMessageContext();
1132
+ (0, import_react30.useMemo)(() => {
1133
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_primitive5.Primitive.span, { ...props, ref }));
1134
+ }, [useMessageUtils, props, ref]);
1135
+ return null;
1136
+ });
1137
+ MessageInProgress.displayName = "MessageInProgress";
1138
+
1139
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
1140
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1141
+ var BranchPickerRoot = (0, import_react31.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
1142
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive6.Primitive.div, { ...rest, ref }) });
1143
+ });
1144
+ BranchPickerRoot.displayName = "BranchPickerRoot";
843
1145
 
844
1146
  // src/primitives/composer/index.ts
845
1147
  var composer_exports = {};
@@ -852,11 +1154,11 @@ __export(composer_exports, {
852
1154
  });
853
1155
 
854
1156
  // src/primitives/composer/ComposerRoot.tsx
855
- var import_primitive2 = require("@radix-ui/primitive");
856
- var import_react_primitive4 = require("@radix-ui/react-primitive");
857
- var import_react26 = require("react");
858
- var import_jsx_runtime6 = require("react/jsx-runtime");
859
- var ComposerRoot = (0, import_react26.forwardRef)(
1157
+ var import_primitive5 = require("@radix-ui/primitive");
1158
+ var import_react_primitive7 = require("@radix-ui/react-primitive");
1159
+ var import_react32 = require("react");
1160
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1161
+ var ComposerRoot = (0, import_react32.forwardRef)(
860
1162
  ({ onSubmit, ...rest }, forwardedRef) => {
861
1163
  const send = useComposerSend();
862
1164
  const handleSubmit = (e) => {
@@ -864,12 +1166,12 @@ var ComposerRoot = (0, import_react26.forwardRef)(
864
1166
  e.preventDefault();
865
1167
  send();
866
1168
  };
867
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
868
- import_react_primitive4.Primitive.form,
1169
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1170
+ import_react_primitive7.Primitive.form,
869
1171
  {
870
1172
  ...rest,
871
1173
  ref: forwardedRef,
872
- onSubmit: (0, import_primitive2.composeEventHandlers)(onSubmit, handleSubmit)
1174
+ onSubmit: (0, import_primitive5.composeEventHandlers)(onSubmit, handleSubmit)
873
1175
  }
874
1176
  );
875
1177
  }
@@ -877,14 +1179,14 @@ var ComposerRoot = (0, import_react26.forwardRef)(
877
1179
  ComposerRoot.displayName = "ComposerRoot";
878
1180
 
879
1181
  // src/primitives/composer/ComposerInput.tsx
880
- var import_primitive3 = require("@radix-ui/primitive");
881
- var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
1182
+ var import_primitive6 = require("@radix-ui/primitive");
1183
+ var import_react_compose_refs = require("@radix-ui/react-compose-refs");
882
1184
  var import_react_slot = require("@radix-ui/react-slot");
883
- var import_react27 = require("react");
1185
+ var import_react33 = require("react");
884
1186
  var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
885
1187
  var import_react_use_escape_keydown = require("@radix-ui/react-use-escape-keydown");
886
- var import_jsx_runtime7 = require("react/jsx-runtime");
887
- var ComposerInput = (0, import_react27.forwardRef)(
1188
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1189
+ var ComposerInput = (0, import_react33.forwardRef)(
888
1190
  ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
889
1191
  const { useThread } = useThreadContext();
890
1192
  const { useComposer, type } = useComposerContext();
@@ -893,8 +1195,8 @@ var ComposerInput = (0, import_react27.forwardRef)(
893
1195
  return c.value;
894
1196
  });
895
1197
  const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
896
- const textareaRef = (0, import_react27.useRef)(null);
897
- const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
1198
+ const textareaRef = (0, import_react33.useRef)(null);
1199
+ const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, textareaRef);
898
1200
  (0, import_react_use_escape_keydown.useEscapeKeydown)((e) => {
899
1201
  const composer = useComposer.getState();
900
1202
  if (composer.cancel()) {
@@ -912,35 +1214,34 @@ var ComposerInput = (0, import_react27.forwardRef)(
912
1214
  }
913
1215
  };
914
1216
  const autoFocusEnabled = autoFocus && !disabled;
915
- const focus = (0, import_react27.useCallback)(() => {
1217
+ const focus = (0, import_react33.useCallback)(() => {
916
1218
  const textarea = textareaRef.current;
917
1219
  if (!textarea || !autoFocusEnabled) return;
918
- textarea.focus();
1220
+ textarea.focus({ preventScroll: true });
919
1221
  textarea.setSelectionRange(
920
1222
  textareaRef.current.value.length,
921
1223
  textareaRef.current.value.length
922
1224
  );
923
1225
  }, [autoFocusEnabled]);
924
- (0, import_react27.useEffect)(() => focus(), [focus]);
925
- useOnScrollToBottom(() => {
1226
+ (0, import_react33.useEffect)(() => focus(), [focus]);
1227
+ useOnComposerFocus(() => {
926
1228
  if (type === "new") {
927
1229
  focus();
928
1230
  }
929
1231
  });
930
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1232
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
931
1233
  Component,
932
1234
  {
933
1235
  value,
934
1236
  ...rest,
935
1237
  ref,
936
- autoFocus,
937
1238
  disabled,
938
- onChange: (0, import_primitive3.composeEventHandlers)(onChange, (e) => {
1239
+ onChange: (0, import_primitive6.composeEventHandlers)(onChange, (e) => {
939
1240
  const composerState = useComposer.getState();
940
1241
  if (!composerState.isEditing) return;
941
1242
  return composerState.setValue(e.target.value);
942
1243
  }),
943
- onKeyDown: (0, import_primitive3.composeEventHandlers)(onKeyDown, handleKeyPress)
1244
+ onKeyDown: (0, import_primitive6.composeEventHandlers)(onKeyDown, handleKeyPress)
944
1245
  }
945
1246
  );
946
1247
  }
@@ -948,15 +1249,15 @@ var ComposerInput = (0, import_react27.forwardRef)(
948
1249
  ComposerInput.displayName = "ComposerInput";
949
1250
 
950
1251
  // src/primitives/composer/ComposerSend.tsx
951
- var import_react28 = require("react");
952
- var import_react_primitive5 = require("@radix-ui/react-primitive");
953
- var import_jsx_runtime8 = require("react/jsx-runtime");
954
- var ComposerSend = (0, import_react28.forwardRef)(
1252
+ var import_react34 = require("react");
1253
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
1254
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1255
+ var ComposerSend = (0, import_react34.forwardRef)(
955
1256
  ({ disabled, ...rest }, ref) => {
956
1257
  const { useComposer } = useComposerContext();
957
1258
  const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
958
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
959
- import_react_primitive5.Primitive.button,
1259
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1260
+ import_react_primitive8.Primitive.button,
960
1261
  {
961
1262
  type: "submit",
962
1263
  ...rest,
@@ -974,360 +1275,397 @@ var ComposerCancel = createActionButton(
974
1275
  useComposerCancel
975
1276
  );
976
1277
 
977
- // src/primitives/message/index.ts
978
- var message_exports = {};
979
- __export(message_exports, {
980
- Content: () => MessageContent,
981
- If: () => MessageIf,
982
- InProgress: () => MessageInProgress,
983
- Root: () => MessageRoot
1278
+ // src/primitives/composer/ComposerIf.tsx
1279
+ var ComposerIf = ({ children, ...query }) => {
1280
+ const result = useComposerIf(query);
1281
+ return result ? children : null;
1282
+ };
1283
+
1284
+ // src/primitives/contentPart/index.ts
1285
+ var contentPart_exports = {};
1286
+ __export(contentPart_exports, {
1287
+ Display: () => ContentPartDisplay,
1288
+ Image: () => ContentPartImage,
1289
+ InProgressIndicator: () => ContentPartInProgressIndicator,
1290
+ Text: () => ContentPartText
984
1291
  });
985
1292
 
986
- // src/primitives/message/MessageRoot.tsx
987
- var import_primitive4 = require("@radix-ui/primitive");
988
- var import_react_primitive6 = require("@radix-ui/react-primitive");
989
- var import_react29 = require("react");
990
- var import_jsx_runtime9 = require("react/jsx-runtime");
991
- var MessageRoot = (0, import_react29.forwardRef)(
992
- ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
993
- const { useMessageUtils } = useMessageContext();
994
- const setIsHovering = useMessageUtils((s) => s.setIsHovering);
995
- const handleMouseEnter = () => {
996
- setIsHovering(true);
997
- };
998
- const handleMouseLeave = () => {
999
- setIsHovering(false);
1000
- };
1001
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1002
- import_react_primitive6.Primitive.div,
1003
- {
1004
- ...rest,
1005
- ref,
1006
- onMouseEnter: (0, import_primitive4.composeEventHandlers)(onMouseEnter, handleMouseEnter),
1007
- onMouseLeave: (0, import_primitive4.composeEventHandlers)(onMouseLeave, handleMouseLeave)
1008
- }
1009
- );
1293
+ // src/primitives/contentPart/ContentPartImage.tsx
1294
+ var import_react_primitive9 = require("@radix-ui/react-primitive");
1295
+ var import_react35 = require("react");
1296
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1297
+ var ContentPartImage = (0, import_react35.forwardRef)((props, forwardedRef) => {
1298
+ const image = useContentPartImage();
1299
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_primitive9.Primitive.img, { src: image, ...props, ref: forwardedRef });
1300
+ });
1301
+ ContentPartImage.displayName = "ContentPartImage";
1302
+
1303
+ // src/primitives/thread/index.ts
1304
+ var thread_exports = {};
1305
+ __export(thread_exports, {
1306
+ Empty: () => ThreadEmpty,
1307
+ If: () => ThreadIf,
1308
+ Messages: () => ThreadMessages,
1309
+ Root: () => ThreadRoot,
1310
+ ScrollToBottom: () => ThreadScrollToBottom,
1311
+ Suggestion: () => ThreadSuggestion,
1312
+ Viewport: () => ThreadViewport
1313
+ });
1314
+
1315
+ // src/primitives/thread/ThreadRoot.tsx
1316
+ var import_react_primitive10 = require("@radix-ui/react-primitive");
1317
+ var import_react36 = require("react");
1318
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1319
+ var ThreadRoot = (0, import_react36.forwardRef)(
1320
+ (props, ref) => {
1321
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_primitive10.Primitive.div, { ...props, ref });
1010
1322
  }
1011
1323
  );
1012
- MessageRoot.displayName = "MessageRoot";
1013
-
1014
- // src/primitives/message/MessageContent.tsx
1015
- var import_react32 = require("react");
1324
+ ThreadRoot.displayName = "ThreadRoot";
1016
1325
 
1017
- // src/context/providers/ContentPartProvider.tsx
1018
- var import_react30 = require("react");
1019
- var import_zustand4 = require("zustand");
1020
- var import_jsx_runtime10 = require("react/jsx-runtime");
1021
- var syncContentPart = ({ message }, useContentPart, partIndex) => {
1022
- const part = message.content[partIndex];
1023
- if (!part) return;
1024
- const messageStatus = message.role === "assistant" ? message.status : "done";
1025
- const status = partIndex === message.content.length - 1 ? messageStatus : "done";
1026
- const currentState = useContentPart.getState();
1027
- if (currentState.part === part && currentState.status === status) return;
1028
- useContentPart.setState(
1029
- Object.freeze({
1030
- part,
1031
- status
1032
- })
1033
- );
1034
- };
1035
- var useContentPartContext2 = (partIndex) => {
1036
- const { useMessage } = useMessageContext();
1037
- const [context] = (0, import_react30.useState)(() => {
1038
- const useContentPart = (0, import_zustand4.create)(
1039
- () => ({})
1040
- );
1041
- syncContentPart(useMessage.getState(), useContentPart, partIndex);
1042
- return { useContentPart };
1043
- });
1044
- (0, import_react30.useEffect)(() => {
1045
- syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
1046
- return useMessage.subscribe((message) => {
1047
- syncContentPart(message, context.useContentPart, partIndex);
1048
- });
1049
- }, [context, useMessage, partIndex]);
1050
- return context;
1051
- };
1052
- var ContentPartProvider = ({
1053
- partIndex,
1054
- children
1055
- }) => {
1056
- const context = useContentPartContext2(partIndex);
1057
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ContentPartContext.Provider, { value: context, children });
1326
+ // src/primitives/thread/ThreadEmpty.tsx
1327
+ var ThreadEmpty = ({ children }) => {
1328
+ const empty = useThreadEmpty();
1329
+ return empty ? children : null;
1058
1330
  };
1059
1331
 
1060
- // src/primitives/contentPart/ContentPartDisplay.tsx
1061
- var ContentPartDisplay = () => {
1062
- const display = useContentPartDisplay();
1063
- return display ?? null;
1332
+ // src/primitives/thread/ThreadIf.tsx
1333
+ var ThreadIf = ({ children, ...query }) => {
1334
+ const result = useThreadIf(query);
1335
+ return result ? children : null;
1064
1336
  };
1065
1337
 
1066
- // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
1067
- var ContentPartInProgressIndicator = () => {
1068
- const indicator = useContentPartInProgressIndicator();
1069
- return indicator;
1070
- };
1338
+ // src/primitives/thread/ThreadViewport.tsx
1339
+ var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
1340
+ var import_react_primitive11 = require("@radix-ui/react-primitive");
1341
+ var import_react41 = require("react");
1071
1342
 
1072
- // src/primitives/contentPart/ContentPartText.tsx
1073
- var import_react_primitive7 = require("@radix-ui/react-primitive");
1074
- var import_react31 = require("react");
1075
- var import_jsx_runtime11 = require("react/jsx-runtime");
1076
- var ContentPartText = (0, import_react31.forwardRef)((props, forwardedRef) => {
1077
- const text = useContentPartText();
1078
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_primitive7.Primitive.span, { ...props, ref: forwardedRef, children: text });
1079
- });
1080
- ContentPartText.displayName = "ContentPartText";
1343
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1344
+ var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
1345
+ var import_react40 = require("react");
1081
1346
 
1082
- // src/primitives/message/MessageContent.tsx
1083
- var import_jsx_runtime12 = require("react/jsx-runtime");
1084
- var defaultComponents = {
1085
- Text: () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1086
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartText, {}),
1087
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartInProgressIndicator, {})
1088
- ] }),
1089
- Image: () => null,
1090
- UI: () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartDisplay, {}),
1091
- tools: {
1092
- Fallback: (props) => {
1093
- const { useToolUIs } = useAssistantContext();
1094
- const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
1095
- if (!Render) return null;
1096
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Render, { ...props });
1097
- }
1098
- }
1347
+ // src/utils/hooks/useOnResizeContent.tsx
1348
+ var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
1349
+ var import_react38 = require("react");
1350
+
1351
+ // src/utils/hooks/useManagedRef.ts
1352
+ var import_react37 = require("react");
1353
+ var useManagedRef = (callback) => {
1354
+ const cleanupRef = (0, import_react37.useRef)();
1355
+ const ref = (0, import_react37.useCallback)(
1356
+ (el) => {
1357
+ if (cleanupRef.current) {
1358
+ cleanupRef.current();
1359
+ }
1360
+ if (el) {
1361
+ cleanupRef.current = callback(el);
1362
+ }
1363
+ },
1364
+ [callback]
1365
+ );
1366
+ return ref;
1099
1367
  };
1100
- var MessageContentPartComponent = ({
1101
- components: {
1102
- Text = defaultComponents.Text,
1103
- Image = defaultComponents.Image,
1104
- UI = defaultComponents.UI,
1105
- tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
1106
- } = {}
1107
- }) => {
1108
- const { useThreadActions } = useThreadContext();
1109
- const addToolResult = useThreadActions((t) => t.addToolResult);
1110
- const { useContentPart } = useContentPartContext();
1111
- const { part, status } = useContentPart();
1112
- const type = part.type;
1113
- switch (type) {
1114
- case "text":
1115
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { part, status });
1116
- case "image":
1117
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Image, { part, status });
1118
- case "ui":
1119
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(UI, { part, status });
1120
- case "tool-call": {
1121
- const Tool = by_name[part.toolName] || Fallback;
1122
- const addResult = (result) => addToolResult(part.toolCallId, result);
1123
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Tool, { part, status, addResult });
1124
- }
1125
- default:
1126
- throw new Error(`Unknown content part type: ${type}`);
1127
- }
1368
+
1369
+ // src/utils/hooks/useOnResizeContent.tsx
1370
+ var useOnResizeContent = (callback) => {
1371
+ const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
1372
+ const refCallback = (0, import_react38.useCallback)(
1373
+ (el) => {
1374
+ const resizeObserver = new ResizeObserver(() => {
1375
+ callbackRef();
1376
+ });
1377
+ const mutationObserver = new MutationObserver((mutations) => {
1378
+ for (const mutation of mutations) {
1379
+ for (const node of mutation.addedNodes) {
1380
+ if (node instanceof Element) {
1381
+ resizeObserver.observe(node);
1382
+ }
1383
+ }
1384
+ for (const node of mutation.removedNodes) {
1385
+ if (node instanceof Element) {
1386
+ resizeObserver.unobserve(node);
1387
+ }
1388
+ }
1389
+ }
1390
+ callbackRef();
1391
+ });
1392
+ resizeObserver.observe(el);
1393
+ mutationObserver.observe(el, { childList: true });
1394
+ for (const child of el.children) {
1395
+ resizeObserver.observe(child);
1396
+ }
1397
+ return () => {
1398
+ resizeObserver.disconnect();
1399
+ mutationObserver.disconnect();
1400
+ };
1401
+ },
1402
+ [callbackRef]
1403
+ );
1404
+ return useManagedRef(refCallback);
1128
1405
  };
1129
- var MessageContentPartImpl = ({
1130
- partIndex,
1131
- components
1132
- }) => {
1133
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartProvider, { partIndex, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MessageContentPartComponent, { components }) });
1406
+
1407
+ // src/utils/hooks/useOnScrollToBottom.tsx
1408
+ var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
1409
+ var import_react39 = require("react");
1410
+ var useOnScrollToBottom = (callback) => {
1411
+ const callbackRef = (0, import_react_use_callback_ref3.useCallbackRef)(callback);
1412
+ const { useViewport } = useThreadContext();
1413
+ (0, import_react39.useEffect)(() => {
1414
+ return useViewport.getState().onScrollToBottom(() => {
1415
+ callbackRef();
1416
+ });
1417
+ }, [useViewport, callbackRef]);
1134
1418
  };
1135
- var MessageContentPart = (0, import_react32.memo)(
1136
- MessageContentPartImpl,
1137
- (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Image === next.components?.Image && prev.components?.UI === next.components?.UI && prev.components?.tools === next.components?.tools
1138
- );
1139
- var MessageContent = ({ components }) => {
1140
- const { useMessage } = useMessageContext();
1141
- const contentLength = useMessage((s) => s.message.content.length);
1142
- return new Array(contentLength).fill(null).map((_, idx) => {
1143
- const partIndex = idx;
1144
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1145
- MessageContentPart,
1146
- {
1147
- partIndex,
1148
- components
1149
- },
1150
- partIndex
1151
- );
1419
+
1420
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1421
+ var useThreadViewportAutoScroll = ({
1422
+ autoScroll = true
1423
+ }) => {
1424
+ const divRef = (0, import_react40.useRef)(null);
1425
+ const { useViewport } = useThreadContext();
1426
+ const firstRenderRef = (0, import_react40.useRef)(true);
1427
+ const lastScrollTop = (0, import_react40.useRef)(0);
1428
+ const isScrollingToBottomRef = (0, import_react40.useRef)(false);
1429
+ const scrollToBottom = () => {
1430
+ const div = divRef.current;
1431
+ if (!div || !autoScroll) return;
1432
+ const behavior = firstRenderRef.current ? "instant" : "auto";
1433
+ firstRenderRef.current = false;
1434
+ isScrollingToBottomRef.current = true;
1435
+ div.scrollTo({ top: div.scrollHeight, behavior });
1436
+ };
1437
+ const handleScroll = () => {
1438
+ const div = divRef.current;
1439
+ if (!div) return;
1440
+ const isAtBottom = useViewport.getState().isAtBottom;
1441
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1442
+ if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1443
+ } else {
1444
+ isScrollingToBottomRef.current = newIsAtBottom;
1445
+ if (newIsAtBottom !== isAtBottom) {
1446
+ useViewport.setState({
1447
+ isAtBottom: newIsAtBottom
1448
+ });
1449
+ }
1450
+ }
1451
+ lastScrollTop.current = div.scrollTop;
1452
+ };
1453
+ const resizeRef = useOnResizeContent(() => {
1454
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
1455
+ handleScroll();
1456
+ } else {
1457
+ scrollToBottom();
1458
+ }
1459
+ });
1460
+ const scrollRef = useManagedRef((el) => {
1461
+ el.addEventListener("scroll", handleScroll);
1462
+ return () => {
1463
+ el.removeEventListener("scroll", handleScroll);
1464
+ };
1465
+ });
1466
+ const autoScrollRef = (0, import_react_compose_refs2.useComposedRefs)(resizeRef, scrollRef, divRef);
1467
+ useOnScrollToBottom(() => {
1468
+ scrollToBottom();
1152
1469
  });
1470
+ return autoScrollRef;
1153
1471
  };
1154
1472
 
1155
- // src/primitives/message/MessageInProgress.tsx
1156
- var import_react_primitive8 = require("@radix-ui/react-primitive");
1157
- var import_react33 = require("react");
1158
- var import_jsx_runtime13 = require("react/jsx-runtime");
1159
- var MessageInProgress = (0, import_react33.forwardRef)((props, ref) => {
1160
- const { useMessageUtils } = useMessageContext();
1161
- (0, import_react33.useMemo)(() => {
1162
- useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_primitive8.Primitive.span, { ...props, ref }));
1163
- }, [useMessageUtils, props, ref]);
1164
- return null;
1473
+ // src/primitives/thread/ThreadViewport.tsx
1474
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1475
+ var ThreadViewport = (0, import_react41.forwardRef)(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
1476
+ const autoScrollRef = useThreadViewportAutoScroll({
1477
+ autoScroll
1478
+ });
1479
+ const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, autoScrollRef);
1480
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_primitive11.Primitive.div, { ...rest, ref, children });
1165
1481
  });
1166
- MessageInProgress.displayName = "MessageInProgress";
1482
+ ThreadViewport.displayName = "ThreadViewport";
1167
1483
 
1168
- // src/primitives/branchPicker/index.ts
1169
- var branchPicker_exports = {};
1170
- __export(branchPicker_exports, {
1171
- Count: () => BranchPickerCount,
1172
- Next: () => BranchPickerNext,
1173
- Number: () => BranchPickerNumber,
1174
- Previous: () => BranchPickerPrevious,
1175
- Root: () => BranchPickerRoot
1176
- });
1484
+ // src/primitives/thread/ThreadMessages.tsx
1485
+ var import_react43 = require("react");
1177
1486
 
1178
- // src/primitives/branchPicker/BranchPickerNext.tsx
1179
- var BranchPickerNext = createActionButton(
1180
- "BranchPickerNext",
1181
- useBranchPickerNext
1182
- );
1487
+ // src/context/providers/MessageProvider.tsx
1488
+ var import_react42 = require("react");
1489
+ var import_zustand10 = require("zustand");
1183
1490
 
1184
- // src/primitives/branchPicker/BranchPickerPrevious.tsx
1185
- var BranchPickerPrevious = createActionButton(
1186
- "BranchPickerPrevious",
1187
- useBranchPickerPrevious
1188
- );
1491
+ // src/context/stores/EditComposer.ts
1492
+ var import_zustand8 = require("zustand");
1493
+ var makeEditComposerStore = ({
1494
+ onEdit,
1495
+ onSend
1496
+ }) => (0, import_zustand8.create)()((set, get, store) => ({
1497
+ ...makeBaseComposer(set, get, store),
1498
+ isEditing: false,
1499
+ edit: () => {
1500
+ const value = onEdit();
1501
+ set({ isEditing: true, value });
1502
+ },
1503
+ send: () => {
1504
+ const value = get().value;
1505
+ set({ isEditing: false });
1506
+ onSend(value);
1507
+ },
1508
+ cancel: () => {
1509
+ if (!get().isEditing) return false;
1510
+ set({ isEditing: false });
1511
+ return true;
1512
+ }
1513
+ }));
1189
1514
 
1190
- // src/primitives/branchPicker/BranchPickerCount.tsx
1191
- var import_jsx_runtime14 = require("react/jsx-runtime");
1192
- var BranchPickerCount = () => {
1193
- const branchCount = useBranchPickerCount();
1194
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: branchCount });
1195
- };
1515
+ // src/context/stores/MessageUtils.ts
1516
+ var import_zustand9 = require("zustand");
1517
+ var makeMessageUtilsStore = () => (0, import_zustand9.create)((set) => ({
1518
+ inProgressIndicator: null,
1519
+ setInProgressIndicator: (value) => {
1520
+ set({ inProgressIndicator: value });
1521
+ },
1522
+ isCopied: false,
1523
+ setIsCopied: (value) => {
1524
+ set({ isCopied: value });
1525
+ },
1526
+ isHovering: false,
1527
+ setIsHovering: (value) => {
1528
+ set({ isHovering: value });
1529
+ }
1530
+ }));
1196
1531
 
1197
- // src/primitives/branchPicker/BranchPickerNumber.tsx
1198
- var import_jsx_runtime15 = require("react/jsx-runtime");
1199
- var BranchPickerNumber = () => {
1200
- const branchNumber = useBranchPickerNumber();
1201
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: branchNumber });
1532
+ // src/context/providers/MessageProvider.tsx
1533
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1534
+ var getIsLast = (thread, message) => {
1535
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
1202
1536
  };
1203
-
1204
- // src/primitives/branchPicker/BranchPickerRoot.tsx
1205
- var import_react_primitive9 = require("@radix-ui/react-primitive");
1206
- var import_react34 = require("react");
1207
- var import_jsx_runtime16 = require("react/jsx-runtime");
1208
- var BranchPickerRoot = (0, import_react34.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
1209
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive9.Primitive.div, { ...rest, ref }) });
1210
- });
1211
- BranchPickerRoot.displayName = "BranchPickerRoot";
1212
-
1213
- // src/primitives/actionBar/index.ts
1214
- var actionBar_exports = {};
1215
- __export(actionBar_exports, {
1216
- Copy: () => ActionBarCopy,
1217
- Edit: () => ActionBarEdit,
1218
- Reload: () => ActionBarReload,
1219
- Root: () => ActionBarRoot
1220
- });
1221
-
1222
- // src/primitives/actionBar/ActionBarRoot.tsx
1223
- var import_react_primitive10 = require("@radix-ui/react-primitive");
1224
- var import_react35 = require("react");
1225
- var import_jsx_runtime17 = require("react/jsx-runtime");
1226
- var useActionBarFloatStatus = ({
1227
- hideWhenRunning,
1228
- autohide,
1229
- autohideFloat
1230
- }) => {
1231
- const { useThread } = useThreadContext();
1232
- const { useMessage, useMessageUtils } = useMessageContext();
1233
- return useCombinedStore(
1234
- [useThread, useMessage, useMessageUtils],
1235
- (t, m, mu) => {
1236
- if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1237
- const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1238
- if (!autohideEnabled) return "normal" /* Normal */;
1239
- if (!mu.isHovering) return "hidden" /* Hidden */;
1240
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1241
- return "floating" /* Floating */;
1242
- return "normal" /* Normal */;
1243
- }
1244
- );
1537
+ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
1538
+ const parentId = thread.messages[messageIndex - 1]?.id ?? null;
1539
+ const message = thread.messages[messageIndex];
1540
+ if (!message) return;
1541
+ const isLast = getIsLast(thread, message);
1542
+ const branches = getBranches(message.id);
1543
+ const currentState = useMessage.getState();
1544
+ if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
1545
+ return;
1546
+ useMessage.setState({
1547
+ message,
1548
+ parentId,
1549
+ branches,
1550
+ isLast
1551
+ });
1245
1552
  };
1246
- var ActionBarRoot = (0, import_react35.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1247
- const hideAndfloatStatus = useActionBarFloatStatus({
1248
- hideWhenRunning,
1249
- autohide,
1250
- autohideFloat
1553
+ var useMessageContext2 = (messageIndex) => {
1554
+ const { useThread, useThreadActions } = useThreadContext();
1555
+ const [context] = (0, import_react42.useState)(() => {
1556
+ const useMessage = (0, import_zustand10.create)(() => ({}));
1557
+ const useMessageUtils = makeMessageUtilsStore();
1558
+ const useEditComposer = makeEditComposerStore({
1559
+ onEdit: () => {
1560
+ const message = useMessage.getState().message;
1561
+ if (message.role !== "user")
1562
+ throw new Error(
1563
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
1564
+ );
1565
+ const text = getMessageText(message);
1566
+ return text;
1567
+ },
1568
+ onSend: (text) => {
1569
+ const { message, parentId } = useMessage.getState();
1570
+ if (message.role !== "user")
1571
+ throw new Error(
1572
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
1573
+ );
1574
+ const nonTextParts = message.content.filter(
1575
+ (part) => part.type !== "text" && part.type !== "ui"
1576
+ );
1577
+ useThreadActions.getState().append({
1578
+ parentId,
1579
+ role: "user",
1580
+ content: [{ type: "text", text }, ...nonTextParts]
1581
+ });
1582
+ }
1583
+ });
1584
+ syncMessage(
1585
+ useThread.getState(),
1586
+ useThreadActions.getState().getBranches,
1587
+ useMessage,
1588
+ messageIndex
1589
+ );
1590
+ return { useMessage, useMessageUtils, useEditComposer };
1251
1591
  });
1252
- if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
1253
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1254
- import_react_primitive10.Primitive.div,
1255
- {
1256
- ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
1257
- ...rest,
1258
- ref
1259
- }
1260
- );
1261
- });
1262
- ActionBarRoot.displayName = "ActionBarRoot";
1592
+ (0, import_react42.useEffect)(() => {
1593
+ return useThread.subscribe((thread) => {
1594
+ syncMessage(
1595
+ thread,
1596
+ useThreadActions.getState().getBranches,
1597
+ context.useMessage,
1598
+ messageIndex
1599
+ );
1600
+ });
1601
+ }, [useThread, useThreadActions, context, messageIndex]);
1602
+ return context;
1603
+ };
1604
+ var MessageProvider = ({
1605
+ messageIndex,
1606
+ children
1607
+ }) => {
1608
+ const context = useMessageContext2(messageIndex);
1609
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MessageContext.Provider, { value: context, children });
1610
+ };
1263
1611
 
1264
- // src/primitives/actionBar/ActionBarCopy.tsx
1265
- var ActionBarCopy = createActionButton(
1266
- "ActionBarCopy",
1267
- useActionBarCopy
1612
+ // src/primitives/thread/ThreadMessages.tsx
1613
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1614
+ var getComponents = (components) => {
1615
+ return {
1616
+ EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
1617
+ UserMessage: components.UserMessage ?? components.Message,
1618
+ AssistantMessage: components.AssistantMessage ?? components.Message
1619
+ };
1620
+ };
1621
+ var ThreadMessageImpl = ({
1622
+ messageIndex,
1623
+ components
1624
+ }) => {
1625
+ const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
1626
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(MessageProvider, { messageIndex, children: [
1627
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(MessageIf, { user: true, children: [
1628
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(UserMessage, {}) }),
1629
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EditComposer, {}) })
1630
+ ] }),
1631
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AssistantMessage, {}) })
1632
+ ] });
1633
+ };
1634
+ var ThreadMessage = (0, import_react43.memo)(
1635
+ ThreadMessageImpl,
1636
+ (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
1268
1637
  );
1638
+ var ThreadMessages = ({ components }) => {
1639
+ const { useThread } = useThreadContext();
1640
+ const messagesLength = useThread((t) => t.messages.length);
1641
+ if (messagesLength === 0) return null;
1642
+ return new Array(messagesLength).fill(null).map((_, idx) => {
1643
+ const messageIndex = idx;
1644
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1645
+ ThreadMessage,
1646
+ {
1647
+ messageIndex,
1648
+ components
1649
+ },
1650
+ messageIndex
1651
+ );
1652
+ });
1653
+ };
1269
1654
 
1270
- // src/primitives/actionBar/ActionBarReload.tsx
1271
- var ActionBarReload = createActionButton(
1272
- "ActionBarReload",
1273
- useActionBarReload
1655
+ // src/primitives/thread/ThreadScrollToBottom.tsx
1656
+ var ThreadScrollToBottom = createActionButton(
1657
+ "ThreadScrollToBottom",
1658
+ useThreadScrollToBottom
1274
1659
  );
1275
1660
 
1276
- // src/primitives/actionBar/ActionBarEdit.tsx
1277
- var ActionBarEdit = createActionButton(
1278
- "ActionBarEdit",
1279
- useActionBarEdit
1661
+ // src/primitives/thread/ThreadSuggestion.tsx
1662
+ var ThreadSuggestion = createActionButton(
1663
+ "ThreadSuggestion",
1664
+ useThreadSuggestion
1280
1665
  );
1281
1666
 
1282
- // src/primitives/contentPart/index.ts
1283
- var contentPart_exports = {};
1284
- __export(contentPart_exports, {
1285
- Display: () => ContentPartDisplay,
1286
- Image: () => ContentPartImage,
1287
- InProgressIndicator: () => ContentPartInProgressIndicator,
1288
- Text: () => ContentPartText
1289
- });
1290
-
1291
- // src/primitives/contentPart/ContentPartImage.tsx
1292
- var import_react_primitive11 = require("@radix-ui/react-primitive");
1293
- var import_react36 = require("react");
1294
- var import_jsx_runtime18 = require("react/jsx-runtime");
1295
- var ContentPartImage = (0, import_react36.forwardRef)((props, forwardedRef) => {
1296
- const image = useContentPartImage();
1297
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_primitive11.Primitive.img, { src: image, ...props, ref: forwardedRef });
1298
- });
1299
- ContentPartImage.displayName = "ContentPartImage";
1300
-
1301
1667
  // src/runtime/local/useLocalRuntime.tsx
1302
- var import_react37 = require("react");
1303
-
1304
- // src/utils/ModelConfigTypes.ts
1305
- var mergeModelConfigs = (configSet) => {
1306
- const configs = Array.from(configSet).map((c) => c()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
1307
- return configs.reduce((acc, config) => {
1308
- if (config.system) {
1309
- if (acc.system) {
1310
- acc.system += `
1311
-
1312
- ${config.system}`;
1313
- } else {
1314
- acc.system = config.system;
1315
- }
1316
- }
1317
- if (config.tools) {
1318
- for (const [name, tool] of Object.entries(config.tools)) {
1319
- if (acc.tools?.[name]) {
1320
- throw new Error(
1321
- `You tried to define a tool with the name ${name}, but it already exists.`
1322
- );
1323
- }
1324
- if (!acc.tools) acc.tools = {};
1325
- acc.tools[name] = tool;
1326
- }
1327
- }
1328
- return acc;
1329
- }, {});
1330
- };
1668
+ var import_react44 = require("react");
1331
1669
 
1332
1670
  // src/runtime/utils/idUtils.tsx
1333
1671
  var import_non_secure = require("nanoid/non-secure");
@@ -1585,219 +1923,81 @@ var LocalRuntime = class {
1585
1923
 
1586
1924
  // src/runtime/local/useLocalRuntime.tsx
1587
1925
  var useLocalRuntime = (adapter) => {
1588
- const [runtime] = (0, import_react37.useState)(() => new LocalRuntime(adapter));
1589
- (0, import_react37.useInsertionEffect)(() => {
1926
+ const [runtime] = (0, import_react44.useState)(() => new LocalRuntime(adapter));
1927
+ (0, import_react44.useInsertionEffect)(() => {
1590
1928
  runtime.adapter = adapter;
1591
1929
  });
1592
1930
  return runtime;
1593
1931
  };
1594
1932
 
1595
- // src/context/providers/AssistantRuntimeProvider.tsx
1596
- var import_react40 = require("react");
1597
-
1598
- // src/context/providers/AssistantProvider.tsx
1599
- var import_react39 = require("react");
1600
-
1601
- // src/context/stores/AssistantModelConfig.ts
1602
- var import_zustand5 = require("zustand");
1603
-
1604
- // src/utils/ProxyConfigProvider.ts
1605
- var ProxyConfigProvider = class {
1606
- _providers = /* @__PURE__ */ new Set();
1607
- getModelConfig() {
1608
- return mergeModelConfigs(this._providers);
1609
- }
1610
- registerModelConfigProvider(provider) {
1611
- this._providers.add(provider);
1933
+ // src/model-config/useAssistantTool.tsx
1934
+ var import_react45 = require("react");
1935
+ var useAssistantTool = (tool) => {
1936
+ const { useModelConfig, useToolUIs } = useAssistantContext();
1937
+ const registerModelConfigProvider = useModelConfig(
1938
+ (s) => s.registerModelConfigProvider
1939
+ );
1940
+ const setToolUI = useToolUIs((s) => s.setToolUI);
1941
+ (0, import_react45.useEffect)(() => {
1942
+ const { toolName, render, ...rest } = tool;
1943
+ const config = {
1944
+ tools: {
1945
+ [tool.toolName]: rest
1946
+ }
1947
+ };
1948
+ const unsub1 = registerModelConfigProvider(() => config);
1949
+ const unsub2 = render ? setToolUI(toolName, render) : void 0;
1612
1950
  return () => {
1613
- this._providers.delete(provider);
1951
+ unsub1();
1952
+ unsub2?.();
1614
1953
  };
1615
- }
1954
+ }, [registerModelConfigProvider, setToolUI, tool]);
1616
1955
  };
1617
1956
 
1618
- // src/context/stores/AssistantModelConfig.ts
1619
- var makeAssistantModelConfigStore = () => (0, import_zustand5.create)(() => {
1620
- const proxy = new ProxyConfigProvider();
1621
- return Object.freeze({
1622
- getModelConfig: () => {
1623
- return proxy.getModelConfig();
1624
- },
1625
- registerModelConfigProvider: (provider) => {
1626
- return proxy.registerModelConfigProvider(provider);
1627
- }
1628
- });
1629
- });
1630
-
1631
- // src/context/stores/AssistantToolUIs.ts
1632
- var import_zustand6 = require("zustand");
1633
- var makeAssistantToolUIsStore = () => (0, import_zustand6.create)((set) => {
1634
- const renderers = /* @__PURE__ */ new Map();
1635
- return Object.freeze({
1636
- getToolUI: (name) => {
1637
- const arr = renderers.get(name);
1638
- const last = arr?.at(-1);
1639
- if (last) return last;
1640
- return null;
1641
- },
1642
- setToolUI: (name, render) => {
1643
- let arr = renderers.get(name);
1644
- if (!arr) {
1645
- arr = [];
1646
- renderers.set(name, arr);
1647
- }
1648
- arr.push(render);
1649
- set({});
1650
- return () => {
1651
- const index = arr.indexOf(render);
1652
- if (index !== -1) {
1653
- arr.splice(index, 1);
1654
- }
1655
- if (index === arr.length) {
1656
- set({});
1657
- }
1658
- };
1659
- }
1660
- });
1661
- });
1662
-
1663
- // src/context/providers/ThreadProvider.tsx
1664
- var import_react38 = require("react");
1665
-
1666
- // src/context/stores/Composer.ts
1667
- var import_zustand7 = require("zustand");
1668
- var makeComposerStore = (useThread, useThreadActions) => (0, import_zustand7.create)()((set, get, store) => {
1669
- return {
1670
- ...makeBaseComposer(set, get, store),
1671
- isEditing: true,
1672
- send: () => {
1673
- const { setValue, value } = get();
1674
- setValue("");
1675
- useThreadActions.getState().append({
1676
- parentId: useThread.getState().messages.at(-1)?.id ?? null,
1677
- role: "user",
1678
- content: [{ type: "text", text: value }]
1679
- });
1680
- },
1681
- cancel: () => {
1682
- const thread = useThread.getState();
1683
- if (!thread.isRunning) return false;
1684
- useThreadActions.getState().cancelRun();
1685
- return true;
1686
- }
1957
+ // src/model-config/makeAssistantTool.tsx
1958
+ var makeAssistantTool = (tool) => {
1959
+ const Tool = () => {
1960
+ useAssistantTool(tool);
1961
+ return null;
1687
1962
  };
1688
- });
1689
-
1690
- // src/context/stores/Thread.ts
1691
- var import_zustand8 = require("zustand");
1692
- var makeThreadStore = (runtimeRef) => {
1693
- return (0, import_zustand8.create)(() => ({
1694
- messages: runtimeRef.current.messages,
1695
- isRunning: runtimeRef.current.isRunning
1696
- }));
1697
- };
1698
-
1699
- // src/context/stores/ThreadViewport.tsx
1700
- var import_zustand9 = require("zustand");
1701
- var makeThreadViewportStore = () => {
1702
- const scrollToBottomListeners = /* @__PURE__ */ new Set();
1703
- return (0, import_zustand9.create)(() => ({
1704
- isAtBottom: true,
1705
- scrollToBottom: () => {
1706
- for (const listener of scrollToBottomListeners) {
1707
- listener();
1708
- }
1709
- },
1710
- onScrollToBottom: (callback) => {
1711
- scrollToBottomListeners.add(callback);
1712
- return () => {
1713
- scrollToBottomListeners.delete(callback);
1714
- };
1715
- }
1716
- }));
1963
+ return Tool;
1964
+ };
1965
+
1966
+ // src/model-config/useAssistantToolUI.tsx
1967
+ var import_react46 = require("react");
1968
+ var useAssistantToolUI = (tool) => {
1969
+ const { useToolUIs } = useAssistantContext();
1970
+ const setToolUI = useToolUIs((s) => s.setToolUI);
1971
+ (0, import_react46.useEffect)(() => {
1972
+ if (!tool) return;
1973
+ const { toolName, render } = tool;
1974
+ return setToolUI(toolName, render);
1975
+ }, [setToolUI, tool]);
1976
+ };
1977
+
1978
+ // src/model-config/makeAssistantToolUI.tsx
1979
+ var makeAssistantToolUI = (tool) => {
1980
+ const ToolUI = () => {
1981
+ useAssistantToolUI(tool);
1982
+ return null;
1983
+ };
1984
+ return ToolUI;
1717
1985
  };
1718
1986
 
1719
- // src/context/stores/ThreadActions.ts
1720
- var import_zustand10 = require("zustand");
1721
- var makeThreadActionStore = (runtimeRef) => {
1722
- return (0, import_zustand10.create)(
1723
- () => Object.freeze({
1724
- getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1725
- switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1726
- startRun: (parentId) => runtimeRef.current.startRun(parentId),
1727
- append: (message) => runtimeRef.current.append(message),
1728
- cancelRun: () => runtimeRef.current.cancelRun(),
1729
- addToolResult: (toolCallId, result) => runtimeRef.current.addToolResult(toolCallId, result)
1730
- })
1987
+ // src/model-config/useAssistantInstructions.tsx
1988
+ var import_react47 = require("react");
1989
+ var useAssistantInstructions = (instruction) => {
1990
+ const { useModelConfig } = useAssistantContext();
1991
+ const registerModelConfigProvider = useModelConfig(
1992
+ (s) => s.registerModelConfigProvider
1731
1993
  );
1732
- };
1733
-
1734
- // src/context/providers/ThreadProvider.tsx
1735
- var import_jsx_runtime19 = require("react/jsx-runtime");
1736
- var ThreadProvider = ({
1737
- children,
1738
- runtime
1739
- }) => {
1740
- const runtimeRef = (0, import_react38.useRef)(runtime);
1741
- (0, import_react38.useInsertionEffect)(() => {
1742
- runtimeRef.current = runtime;
1743
- });
1744
- const [context] = (0, import_react38.useState)(() => {
1745
- const useThread = makeThreadStore(runtimeRef);
1746
- const useThreadActions = makeThreadActionStore(runtimeRef);
1747
- const useViewport = makeThreadViewportStore();
1748
- const useComposer = makeComposerStore(useThread, useThreadActions);
1749
- return {
1750
- useThread,
1751
- useThreadActions,
1752
- useComposer,
1753
- useViewport
1754
- };
1755
- });
1756
- (0, import_react38.useEffect)(() => {
1757
- const onRuntimeUpdate = () => {
1758
- context.useThread.setState(
1759
- Object.freeze({
1760
- messages: runtimeRef.current.messages,
1761
- isRunning: runtimeRef.current.isRunning
1762
- }),
1763
- true
1764
- );
1994
+ (0, import_react47.useEffect)(() => {
1995
+ const config = {
1996
+ system: instruction
1765
1997
  };
1766
- onRuntimeUpdate();
1767
- return runtime.subscribe(onRuntimeUpdate);
1768
- }, [context, runtime]);
1769
- const RuntimeSynchronizer = runtime.unstable_synchronizer;
1770
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ThreadContext.Provider, { value: context, children: [
1771
- RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(RuntimeSynchronizer, {}),
1772
- children
1773
- ] });
1774
- };
1775
-
1776
- // src/context/providers/AssistantProvider.tsx
1777
- var import_jsx_runtime20 = require("react/jsx-runtime");
1778
- var AssistantProvider = ({ children, runtime }) => {
1779
- const runtimeRef = (0, import_react39.useRef)(runtime);
1780
- (0, import_react39.useInsertionEffect)(() => {
1781
- runtimeRef.current = runtime;
1782
- });
1783
- const [context] = (0, import_react39.useState)(() => {
1784
- const useModelConfig = makeAssistantModelConfigStore();
1785
- const useToolUIs = makeAssistantToolUIsStore();
1786
- return { useModelConfig, useToolUIs };
1787
- });
1788
- const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1789
- (0, import_react39.useEffect)(() => {
1790
- return runtime.registerModelConfigProvider(getModelCOnfig);
1791
- }, [runtime, getModelCOnfig]);
1792
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ThreadProvider, { runtime, children }) });
1793
- };
1794
-
1795
- // src/context/providers/AssistantRuntimeProvider.tsx
1796
- var import_jsx_runtime21 = require("react/jsx-runtime");
1797
- var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1798
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantProvider, { runtime, children });
1998
+ return registerModelConfigProvider(() => config);
1999
+ }, [registerModelConfigProvider, instruction]);
1799
2000
  };
1800
- var AssistantRuntimeProvider = (0, import_react40.memo)(AssistantRuntimeProviderImpl);
1801
2001
 
1802
2002
  // src/internal.ts
1803
2003
  var internal_exports = {};
@@ -1808,6 +2008,7 @@ __export(internal_exports, {
1808
2008
  // Annotate the CommonJS export names for ESM import in node:
1809
2009
  0 && (module.exports = {
1810
2010
  ActionBarPrimitive,
2011
+ AssistantModalPrimitive,
1811
2012
  AssistantRuntimeProvider,
1812
2013
  BranchPickerPrimitive,
1813
2014
  ComposerPrimitive,
@@ -1815,22 +2016,32 @@ __export(internal_exports, {
1815
2016
  INTERNAL,
1816
2017
  MessagePrimitive,
1817
2018
  ThreadPrimitive,
2019
+ makeAssistantTool,
2020
+ makeAssistantToolUI,
1818
2021
  useActionBarCopy,
1819
2022
  useActionBarEdit,
1820
2023
  useActionBarReload,
2024
+ useAssistantContext,
2025
+ useAssistantInstructions,
2026
+ useAssistantTool,
2027
+ useAssistantToolUI,
1821
2028
  useBranchPickerCount,
1822
2029
  useBranchPickerNext,
1823
2030
  useBranchPickerNumber,
1824
2031
  useBranchPickerPrevious,
1825
2032
  useComposerCancel,
2033
+ useComposerContext,
1826
2034
  useComposerIf,
1827
2035
  useComposerSend,
2036
+ useContentPartContext,
1828
2037
  useContentPartDisplay,
1829
2038
  useContentPartImage,
1830
2039
  useContentPartInProgressIndicator,
1831
2040
  useContentPartText,
1832
2041
  useLocalRuntime,
2042
+ useMessageContext,
1833
2043
  useMessageIf,
2044
+ useThreadContext,
1834
2045
  useThreadEmpty,
1835
2046
  useThreadIf,
1836
2047
  useThreadScrollToBottom,