@assistant-ui/react 0.1.11 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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,