@assistant-ui/react 0.0.17 → 0.0.19

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
@@ -38,8 +38,11 @@ __export(src_exports, {
38
38
  ThreadPrimitive: () => thread_exports,
39
39
  VercelAIAssistantProvider: () => VercelAIAssistantProvider,
40
40
  VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
41
+ unstable_AssistantProvider: () => AssistantProvider,
42
+ unstable_VercelModelAdapter: () => VercelModelAdapter,
41
43
  unstable_getVercelMessage: () => getVercelMessage,
42
44
  unstable_getVercelRSCMessage: () => getVercelRSCMessage,
45
+ unstable_useLocalRuntime: () => useLocalRuntime,
43
46
  unstable_useMessageContext: () => useMessageContext,
44
47
  useBeginMessageEdit: () => useBeginMessageEdit,
45
48
  useCopyMessage: () => useCopyMessage,
@@ -170,18 +173,22 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
170
173
  const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, divRef);
171
174
  const { useViewport } = useAssistantContext();
172
175
  const firstRenderRef = (0, import_react5.useRef)(true);
176
+ const isScrollingToBottomRef = (0, import_react5.useRef)(false);
173
177
  const lastScrollTop = (0, import_react5.useRef)(0);
174
178
  const scrollToBottom = () => {
175
179
  const div = messagesEndRef.current;
176
180
  if (!div || !autoScroll) return;
177
181
  const behavior = firstRenderRef.current ? "instant" : "auto";
178
182
  firstRenderRef.current = false;
179
- useViewport.setState({ isAtBottom: true });
183
+ isScrollingToBottomRef.current = true;
180
184
  div.scrollIntoView({ behavior });
181
185
  };
182
186
  useOnResizeContent(divRef, () => {
183
- if (!useViewport.getState().isAtBottom) return;
184
- scrollToBottom();
187
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
188
+ handleScroll();
189
+ } else {
190
+ scrollToBottom();
191
+ }
185
192
  });
186
193
  useOnScrollToBottom(() => {
187
194
  scrollToBottom();
@@ -193,6 +200,7 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
193
200
  const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
194
201
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
195
202
  } else if (newIsAtBottom !== isAtBottom) {
203
+ isScrollingToBottomRef.current = false;
196
204
  useViewport.setState({ isAtBottom: newIsAtBottom });
197
205
  }
198
206
  lastScrollTop.current = div.scrollTop;
@@ -838,6 +846,7 @@ __export(branchPicker_exports, {
838
846
  });
839
847
 
840
848
  // src/actions/useGoToNextBranch.tsx
849
+ var import_react21 = require("react");
841
850
  var useGoToNextBranch = () => {
842
851
  const { useThread } = useAssistantContext();
843
852
  const { useMessage, useComposer } = useMessageContext();
@@ -845,20 +854,21 @@ var useGoToNextBranch = () => {
845
854
  [useMessage, useComposer],
846
855
  (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
847
856
  );
848
- if (disabled) return null;
849
- return () => {
857
+ const callback = (0, import_react21.useCallback)(() => {
850
858
  const { message, branches } = useMessage.getState();
851
859
  useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
852
- };
860
+ }, [useMessage, useThread]);
861
+ if (disabled) return null;
862
+ return callback;
853
863
  };
854
864
 
855
865
  // src/utils/createActionButton.tsx
856
866
  var import_primitive8 = require("@radix-ui/primitive");
857
867
  var import_react_primitive10 = require("@radix-ui/react-primitive");
858
- var import_react21 = require("react");
868
+ var import_react22 = require("react");
859
869
  var import_jsx_runtime16 = require("react/jsx-runtime");
860
870
  var createActionButton = (useActionButton) => {
861
- return (0, import_react21.forwardRef)(
871
+ return (0, import_react22.forwardRef)(
862
872
  (props, forwardedRef) => {
863
873
  const onClick = useActionButton(props);
864
874
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -879,6 +889,7 @@ var createActionButton = (useActionButton) => {
879
889
  var BranchPickerNext = createActionButton(useGoToNextBranch);
880
890
 
881
891
  // src/actions/useGoToPreviousBranch.tsx
892
+ var import_react23 = require("react");
882
893
  var useGoToPreviousBranch = () => {
883
894
  const { useThread } = useAssistantContext();
884
895
  const { useMessage, useComposer } = useMessageContext();
@@ -886,13 +897,12 @@ var useGoToPreviousBranch = () => {
886
897
  [useMessage, useComposer],
887
898
  (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
888
899
  );
889
- if (disabled) return null;
890
- return () => {
900
+ const callback = (0, import_react23.useCallback)(() => {
891
901
  const { message, branches } = useMessage.getState();
892
- useThread.getState().switchToBranch(
893
- branches[branches.indexOf(message.id) - 1]
894
- );
895
- };
902
+ useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
903
+ }, [useMessage, useThread]);
904
+ if (disabled) return null;
905
+ return callback;
896
906
  };
897
907
 
898
908
  // src/primitives/branchPicker/BranchPickerPrevious.tsx
@@ -916,9 +926,9 @@ var BranchPickerNumber = () => {
916
926
 
917
927
  // src/primitives/branchPicker/BranchPickerRoot.tsx
918
928
  var import_react_primitive11 = require("@radix-ui/react-primitive");
919
- var import_react22 = require("react");
929
+ var import_react24 = require("react");
920
930
  var import_jsx_runtime19 = require("react/jsx-runtime");
921
- var BranchPickerRoot = (0, import_react22.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
931
+ var BranchPickerRoot = (0, import_react24.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
922
932
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_primitive11.Primitive.div, { ...rest, ref }) });
923
933
  });
924
934
 
@@ -933,9 +943,9 @@ __export(actionBar_exports, {
933
943
 
934
944
  // src/primitives/actionBar/ActionBarRoot.tsx
935
945
  var import_react_primitive12 = require("@radix-ui/react-primitive");
936
- var import_react23 = require("react");
946
+ var import_react25 = require("react");
937
947
  var import_jsx_runtime20 = require("react/jsx-runtime");
938
- var ActionBarRoot = (0, import_react23.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
948
+ var ActionBarRoot = (0, import_react25.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
939
949
  const { useThread } = useAssistantContext();
940
950
  const { useMessage } = useMessageContext();
941
951
  const hideAndfloatStatus = useCombinedStore(
@@ -962,6 +972,7 @@ var ActionBarRoot = (0, import_react23.forwardRef)(({ hideWhenRunning, autohide,
962
972
  });
963
973
 
964
974
  // src/actions/useCopyMessage.tsx
975
+ var import_react26 = require("react");
965
976
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
966
977
  const { useMessage, useComposer } = useMessageContext();
967
978
  const hasCopyableContent = useCombinedStore(
@@ -970,21 +981,23 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
970
981
  return c.isEditing || m.message.content.some((c2) => c2.type === "text");
971
982
  }
972
983
  );
973
- if (!hasCopyableContent) return null;
974
- return () => {
984
+ const callback = (0, import_react26.useCallback)(() => {
975
985
  const { isEditing, value: composerValue } = useComposer.getState();
976
986
  const { message, setIsCopied } = useMessage.getState();
977
987
  const valueToCopy = isEditing ? composerValue : getMessageText(message);
978
988
  navigator.clipboard.writeText(valueToCopy);
979
989
  setIsCopied(true);
980
990
  setTimeout(() => setIsCopied(false), copiedDuration);
981
- };
991
+ }, [useComposer, useMessage, copiedDuration]);
992
+ if (!hasCopyableContent) return null;
993
+ return callback;
982
994
  };
983
995
 
984
996
  // src/primitives/actionBar/ActionBarCopy.tsx
985
997
  var ActionBarCopy = createActionButton(useCopyMessage);
986
998
 
987
999
  // src/actions/useReloadMessage.tsx
1000
+ var import_react27 = require("react");
988
1001
  var useReloadMessage = () => {
989
1002
  const { useThread, useViewport } = useAssistantContext();
990
1003
  const { useMessage } = useMessageContext();
@@ -992,29 +1005,32 @@ var useReloadMessage = () => {
992
1005
  [useThread, useMessage],
993
1006
  (t, m) => t.isRunning || m.message.role !== "assistant"
994
1007
  );
995
- if (disabled) return null;
996
- return () => {
1008
+ const callback = (0, import_react27.useCallback)(() => {
997
1009
  const { parentId } = useMessage.getState();
998
1010
  useThread.getState().startRun(parentId);
999
1011
  useViewport.getState().scrollToBottom();
1000
- };
1012
+ }, [useMessage, useThread, useViewport]);
1013
+ if (disabled) return null;
1014
+ return callback;
1001
1015
  };
1002
1016
 
1003
1017
  // src/primitives/actionBar/ActionBarReload.tsx
1004
1018
  var ActionBarReload = createActionButton(useReloadMessage);
1005
1019
 
1006
1020
  // src/actions/useBeginMessageEdit.tsx
1021
+ var import_react28 = require("react");
1007
1022
  var useBeginMessageEdit = () => {
1008
1023
  const { useMessage, useComposer } = useMessageContext();
1009
1024
  const disabled = useCombinedStore(
1010
1025
  [useMessage, useComposer],
1011
1026
  (m, c) => m.message.role !== "user" || c.isEditing
1012
1027
  );
1013
- if (disabled) return null;
1014
- return () => {
1028
+ const callback = (0, import_react28.useCallback)(() => {
1015
1029
  const { edit } = useComposer.getState();
1016
1030
  edit();
1017
- };
1031
+ }, [useComposer]);
1032
+ if (disabled) return null;
1033
+ return callback;
1018
1034
  };
1019
1035
 
1020
1036
  // src/primitives/actionBar/ActionBarEdit.tsx
@@ -1028,10 +1044,10 @@ __export(contentPart_exports, {
1028
1044
  });
1029
1045
 
1030
1046
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1031
- var import_react26 = require("react");
1047
+ var import_react31 = require("react");
1032
1048
 
1033
1049
  // src/adapters/vercel/useDummyAIAssistantContext.tsx
1034
- var import_react24 = require("react");
1050
+ var import_react29 = require("react");
1035
1051
  var import_zustand5 = require("zustand");
1036
1052
 
1037
1053
  // src/utils/context/stores/ViewportStore.tsx
@@ -1077,7 +1093,7 @@ var makeDummyThreadStore = () => {
1077
1093
  }));
1078
1094
  };
1079
1095
  var useDummyAIAssistantContext = () => {
1080
- const [context] = (0, import_react24.useState)(() => {
1096
+ const [context] = (0, import_react29.useState)(() => {
1081
1097
  const useThread = makeDummyThreadStore();
1082
1098
  const useViewport = makeViewportStore();
1083
1099
  const useComposer = makeThreadComposerStore(useThread);
@@ -1088,9 +1104,9 @@ var useDummyAIAssistantContext = () => {
1088
1104
 
1089
1105
  // src/adapters/vercel/useVercelAIThreadState.tsx
1090
1106
  var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
1091
- var import_react25 = require("react");
1107
+ var import_react30 = require("react");
1092
1108
 
1093
- // src/adapters/MessageRepository.tsx
1109
+ // src/adapters/idUtils.tsx
1094
1110
  var import_non_secure = require("nanoid/non-secure");
1095
1111
  var generateId = (0, import_non_secure.customAlphabet)(
1096
1112
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
@@ -1098,6 +1114,8 @@ var generateId = (0, import_non_secure.customAlphabet)(
1098
1114
  );
1099
1115
  var optimisticPrefix = "__optimistic__";
1100
1116
  var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
1117
+
1118
+ // src/adapters/MessageRepository.tsx
1101
1119
  var findHead = (message) => {
1102
1120
  if (message.next) return findHead(message.next);
1103
1121
  return message;
@@ -1109,15 +1127,6 @@ var MessageRepository = class {
1109
1127
  root = {
1110
1128
  children: []
1111
1129
  };
1112
- getFallbackChild(p) {
1113
- const childId = p.children.at(-1);
1114
- const child = childId ? this.messages.get(childId) : null;
1115
- if (child === void 0)
1116
- throw new Error(
1117
- "MessageRepository(getFallbackChild): Child message not found. This is likely an internal bug in assistant-ui."
1118
- );
1119
- return child;
1120
- }
1121
1130
  performOp(newParent, child, operation) {
1122
1131
  const parentOrRoot = child.prev ?? this.root;
1123
1132
  const newParentOrRoot = newParent ?? this.root;
@@ -1127,7 +1136,14 @@ var MessageRepository = class {
1127
1136
  (m) => m !== child.current.id
1128
1137
  );
1129
1138
  if (child.prev?.next === child) {
1130
- child.prev.next = this.getFallbackChild(child.prev);
1139
+ const fallbackId = child.prev.children.at(-1);
1140
+ const fallback = fallbackId ? this.messages.get(fallbackId) : null;
1141
+ if (fallback === void 0) {
1142
+ throw new Error(
1143
+ "MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
1144
+ );
1145
+ }
1146
+ child.prev.next = fallback;
1131
1147
  }
1132
1148
  }
1133
1149
  if (operation !== "cut") {
@@ -1186,14 +1202,14 @@ var MessageRepository = class {
1186
1202
  });
1187
1203
  return optimisticId;
1188
1204
  }
1189
- deleteMessage(messageId, newParentId) {
1205
+ deleteMessage(messageId, replacementId) {
1190
1206
  const message = this.messages.get(messageId);
1191
- const newParent = newParentId ? this.messages.get(newParentId) : null;
1207
+ const replacement = replacementId ? this.messages.get(replacementId) : null;
1192
1208
  if (!message)
1193
1209
  throw new Error(
1194
1210
  "MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
1195
1211
  );
1196
- if (newParent === void 0)
1212
+ if (replacement === void 0)
1197
1213
  throw new Error(
1198
1214
  "MessageRepository(deleteMessage): New message not found. This is likely an internal bug in assistant-ui."
1199
1215
  );
@@ -1203,11 +1219,11 @@ var MessageRepository = class {
1203
1219
  throw new Error(
1204
1220
  "MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
1205
1221
  );
1206
- this.performOp(newParent, childMessage, "relink");
1222
+ this.performOp(replacement, childMessage, "relink");
1207
1223
  }
1208
1224
  this.messages.delete(messageId);
1209
1225
  if (this.head === message) {
1210
- this.head = this.getFallbackChild(message.prev ?? this.root);
1226
+ this.head = replacement;
1211
1227
  }
1212
1228
  this.performOp(null, message, "cut");
1213
1229
  }
@@ -1250,17 +1266,13 @@ var MessageRepository = class {
1250
1266
  }
1251
1267
  };
1252
1268
 
1253
- // src/adapters/ThreadMessageConverter.tsx
1269
+ // src/adapters/ThreadMessageConverter.ts
1254
1270
  var ThreadMessageConverter = class {
1255
- constructor(converter) {
1256
- this.converter = converter;
1257
- }
1258
1271
  cache = /* @__PURE__ */ new WeakMap();
1259
- convertMessages(messages) {
1272
+ convertMessages(converter, messages) {
1260
1273
  return messages.map((m) => {
1261
1274
  const cached = this.cache.get(m);
1262
- if (cached) return cached;
1263
- const newMessage = this.converter(m);
1275
+ const newMessage = converter(m, cached);
1264
1276
  this.cache.set(m, newMessage);
1265
1277
  return newMessage;
1266
1278
  });
@@ -1331,18 +1343,19 @@ var getIsRunning = (vercel) => {
1331
1343
  return vercel.status === "in_progress";
1332
1344
  };
1333
1345
  var useVercelAIThreadState = (vercel) => {
1334
- const [data] = (0, import_react25.useState)(() => new MessageRepository());
1346
+ const [data] = (0, import_react30.useState)(() => new MessageRepository());
1335
1347
  const isRunning = getIsRunning(vercel);
1336
- const convertCallback = (0, import_react_use_callback_ref3.useCallbackRef)((message) => {
1337
- return vercelToThreadMessage(
1338
- message,
1339
- vercel.messages.at(-1) === message && isRunning ? "in_progress" : "done"
1340
- );
1341
- });
1342
- const converter = new ThreadMessageConverter(convertCallback);
1343
- const assistantOptimisticIdRef = (0, import_react25.useRef)(null);
1344
- const messages = (0, import_react25.useMemo)(() => {
1345
- const vm = converter.convertMessages(vercel.messages);
1348
+ const converter = (0, import_react30.useMemo)(() => new ThreadMessageConverter(), []);
1349
+ const assistantOptimisticIdRef = (0, import_react30.useRef)(null);
1350
+ const messages = (0, import_react30.useMemo)(() => {
1351
+ const lastMessageId = vercel.messages.at(-1)?.id;
1352
+ const convertCallback = (message, cache) => {
1353
+ const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
1354
+ if (cache && (cache.role === "user" || cache.status === status))
1355
+ return cache;
1356
+ return vercelToThreadMessage(message, status);
1357
+ };
1358
+ const vm = converter.convertMessages(convertCallback, vercel.messages);
1346
1359
  for (let i = 0; i < vm.length; i++) {
1347
1360
  const message = vm[i];
1348
1361
  const parent = vm[i - 1];
@@ -1364,7 +1377,7 @@ var useVercelAIThreadState = (vercel) => {
1364
1377
  data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
1365
1378
  return data.getMessages();
1366
1379
  }, [converter, data, isRunning, vercel.messages]);
1367
- const getBranches2 = (0, import_react25.useCallback)(
1380
+ const getBranches2 = (0, import_react30.useCallback)(
1368
1381
  (messageId) => {
1369
1382
  return data.getBranches(messageId);
1370
1383
  },
@@ -1403,7 +1416,7 @@ var useVercelAIThreadState = (vercel) => {
1403
1416
  vercel.setInput(lastMessage.content);
1404
1417
  }
1405
1418
  });
1406
- return (0, import_react25.useMemo)(
1419
+ return (0, import_react30.useMemo)(
1407
1420
  () => ({
1408
1421
  isRunning,
1409
1422
  messages,
@@ -1434,10 +1447,10 @@ var VercelAIAssistantProvider = ({
1434
1447
  const context = useDummyAIAssistantContext();
1435
1448
  const vercel = "chat" in rest ? rest.chat : rest.assistant;
1436
1449
  const threadState = useVercelAIThreadState(vercel);
1437
- (0, import_react26.useMemo)(() => {
1450
+ (0, import_react31.useMemo)(() => {
1438
1451
  context.useThread.setState(threadState, true);
1439
1452
  }, [context, threadState]);
1440
- (0, import_react26.useMemo)(() => {
1453
+ (0, import_react31.useMemo)(() => {
1441
1454
  context.useComposer.setState({
1442
1455
  value: vercel.input,
1443
1456
  setValue: vercel.setInput
@@ -1447,7 +1460,7 @@ var VercelAIAssistantProvider = ({
1447
1460
  };
1448
1461
 
1449
1462
  // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1450
- var import_react27 = require("react");
1463
+ var import_react32 = require("react");
1451
1464
  var import_jsx_runtime22 = require("react/jsx-runtime");
1452
1465
  var vercelToThreadMessage2 = (converter, rawMessage) => {
1453
1466
  const message = converter(rawMessage);
@@ -1485,21 +1498,23 @@ var VercelRSCAssistantProvider = ({
1485
1498
  reload
1486
1499
  }) => {
1487
1500
  const context = useDummyAIAssistantContext();
1488
- const [isRunning, setIsRunning] = (0, import_react27.useState)(false);
1489
- const withRunning = (0, import_react27.useCallback)((callback) => {
1501
+ const [isRunning, setIsRunning] = (0, import_react32.useState)(false);
1502
+ const withRunning = (0, import_react32.useCallback)((callback) => {
1490
1503
  setIsRunning(true);
1491
1504
  return callback.finally(() => setIsRunning(false));
1492
1505
  }, []);
1493
- const converter = (0, import_react27.useMemo)(() => {
1506
+ const [converter, convertCallback] = (0, import_react32.useMemo)(() => {
1494
1507
  const rscConverter = convertMessage ?? ((m) => m);
1495
- return new ThreadMessageConverter((m) => {
1508
+ const convertCallback2 = (m, cache) => {
1509
+ if (cache) return cache;
1496
1510
  return vercelToThreadMessage2(rscConverter, m);
1497
- });
1511
+ };
1512
+ return [new ThreadMessageConverter(), convertCallback2];
1498
1513
  }, [convertMessage]);
1499
- const messages = (0, import_react27.useMemo)(() => {
1500
- return converter.convertMessages(vercelMessages);
1501
- }, [converter, vercelMessages]);
1502
- const append = (0, import_react27.useCallback)(
1514
+ const messages = (0, import_react32.useMemo)(() => {
1515
+ return converter.convertMessages(convertCallback, vercelMessages);
1516
+ }, [converter, convertCallback, vercelMessages]);
1517
+ const append = (0, import_react32.useCallback)(
1503
1518
  async (message) => {
1504
1519
  if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
1505
1520
  if (!edit)
@@ -1513,7 +1528,7 @@ var VercelRSCAssistantProvider = ({
1513
1528
  },
1514
1529
  [context, withRunning, appendCallback, edit]
1515
1530
  );
1516
- const startRun = (0, import_react27.useCallback)(
1531
+ const startRun = (0, import_react32.useCallback)(
1517
1532
  async (parentId) => {
1518
1533
  if (!reload)
1519
1534
  throw new Error(
@@ -1523,7 +1538,7 @@ var VercelRSCAssistantProvider = ({
1523
1538
  },
1524
1539
  [withRunning, reload]
1525
1540
  );
1526
- (0, import_react27.useMemo)(() => {
1541
+ (0, import_react32.useMemo)(() => {
1527
1542
  context.useThread.setState(
1528
1543
  {
1529
1544
  messages,
@@ -1539,6 +1554,261 @@ var VercelRSCAssistantProvider = ({
1539
1554
  }, [context, messages, isRunning, append, startRun]);
1540
1555
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AssistantContext.Provider, { value: context, children });
1541
1556
  };
1557
+
1558
+ // src/adapters/core/utils/useAssistantContext.tsx
1559
+ var import_react33 = require("react");
1560
+ var import_zustand6 = require("zustand");
1561
+
1562
+ // src/adapters/core/utils/AssistantMessageRepository.tsx
1563
+ var AssistantMessageRepository = class {
1564
+ constructor(flushCallback) {
1565
+ this.flushCallback = flushCallback;
1566
+ }
1567
+ repository = new MessageRepository();
1568
+ getBranches(messageId) {
1569
+ return this.repository.getBranches(messageId);
1570
+ }
1571
+ withModifications(callback) {
1572
+ const res = callback(this.repository);
1573
+ this.flushCallback(this.repository.getMessages());
1574
+ return res;
1575
+ }
1576
+ };
1577
+
1578
+ // src/adapters/core/utils/useAssistantContext.tsx
1579
+ var makeThreadStore = (runtimeRef) => {
1580
+ const repository = new AssistantMessageRepository((messages) => {
1581
+ useThread.setState({ messages });
1582
+ });
1583
+ const useThread = (0, import_zustand6.create)(() => ({
1584
+ messages: [],
1585
+ isRunning: false,
1586
+ getBranches: (messageId) => repository.getBranches(messageId),
1587
+ switchToBranch: (branchId) => {
1588
+ repository.withModifications((repository2) => {
1589
+ repository2.switchToBranch(branchId);
1590
+ });
1591
+ },
1592
+ startRun: async (parentId) => {
1593
+ const optimisticId = repository.withModifications((repository2) => {
1594
+ const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
1595
+ role: "assistant",
1596
+ content: [{ type: "text", text: "" }]
1597
+ });
1598
+ repository2.resetHead(optimisticId2);
1599
+ return optimisticId2;
1600
+ });
1601
+ const { id } = await runtimeRef.current.startRun(parentId);
1602
+ repository.withModifications((repository2) => {
1603
+ repository2.deleteMessage(optimisticId, id);
1604
+ });
1605
+ },
1606
+ append: async (message) => {
1607
+ const [parentOptimisticId, optimisticId] = repository.withModifications(
1608
+ (repository2) => {
1609
+ const parentOptimisticId2 = repository2.appendOptimisticMessage(
1610
+ message.parentId,
1611
+ {
1612
+ role: "user",
1613
+ content: message.content
1614
+ }
1615
+ );
1616
+ const optimisticId2 = repository2.appendOptimisticMessage(
1617
+ parentOptimisticId2,
1618
+ {
1619
+ role: "assistant",
1620
+ content: [{ type: "text", text: "" }]
1621
+ }
1622
+ );
1623
+ repository2.resetHead(optimisticId2);
1624
+ return [parentOptimisticId2, optimisticId2];
1625
+ }
1626
+ );
1627
+ const { parentId, id } = await runtimeRef.current.append(message);
1628
+ repository.withModifications((repository2) => {
1629
+ repository2.deleteMessage(parentOptimisticId, parentId);
1630
+ repository2.deleteMessage(optimisticId, id);
1631
+ });
1632
+ },
1633
+ cancelRun: () => runtimeRef.current.cancelRun()
1634
+ }));
1635
+ const onNewMessage = (parentId, message) => {
1636
+ repository.withModifications((repository2) => {
1637
+ repository2.addOrUpdateMessage(parentId, message);
1638
+ });
1639
+ };
1640
+ const onRunningChange = (isRunning) => {
1641
+ useThread.setState({ isRunning });
1642
+ };
1643
+ return {
1644
+ useThread,
1645
+ onNewMessage,
1646
+ onRunningChange
1647
+ };
1648
+ };
1649
+ var useAssistantContext2 = (runtime) => {
1650
+ const runtimeRef = (0, import_react33.useRef)(runtime);
1651
+ (0, import_react33.useInsertionEffect)(() => {
1652
+ runtimeRef.current = runtime;
1653
+ });
1654
+ const [{ context, onNewMessage, onRunningChange }] = (0, import_react33.useState)(() => {
1655
+ const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
1656
+ const useViewport = makeViewportStore();
1657
+ const useComposer = makeThreadComposerStore(useThread);
1658
+ return {
1659
+ context: { useViewport, useThread, useComposer },
1660
+ onNewMessage: onNewMessage2,
1661
+ onRunningChange: onRunningChange2
1662
+ };
1663
+ });
1664
+ (0, import_react33.useEffect)(() => {
1665
+ return runtime.subscribeToMessageUpdates(onNewMessage);
1666
+ }, [runtime, onNewMessage]);
1667
+ (0, import_react33.useEffect)(() => {
1668
+ return runtime.subscribeToStatusUpdates(onRunningChange);
1669
+ }, [runtime, onRunningChange]);
1670
+ return context;
1671
+ };
1672
+
1673
+ // src/adapters/core/AssistantProvider.tsx
1674
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1675
+ var AssistantProvider = ({ children, runtime }) => {
1676
+ const context = useAssistantContext2(runtime);
1677
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantContext.Provider, { value: context, children });
1678
+ };
1679
+
1680
+ // src/adapters/core/local/useLocalRuntime.tsx
1681
+ var import_react34 = require("react");
1682
+
1683
+ // src/adapters/core/local/LocalRuntime.tsx
1684
+ var LocalRuntime = class {
1685
+ constructor(adapter) {
1686
+ this.adapter = adapter;
1687
+ }
1688
+ _messageUpdateCallbacks = /* @__PURE__ */ new Set();
1689
+ _statusUpdateCallbacks = /* @__PURE__ */ new Set();
1690
+ abortController = null;
1691
+ repository = new MessageRepository();
1692
+ async append(message) {
1693
+ const userMessageId = generateId();
1694
+ const userMessage = {
1695
+ id: userMessageId,
1696
+ role: "user",
1697
+ content: message.content,
1698
+ createdAt: /* @__PURE__ */ new Date()
1699
+ };
1700
+ this.addOrUpdateMessage(message.parentId, userMessage);
1701
+ const { id } = await this.startRun(userMessageId);
1702
+ return { parentId: userMessageId, id };
1703
+ }
1704
+ async startRun(parentId) {
1705
+ const id = generateId();
1706
+ this.repository.resetHead(parentId);
1707
+ const messages = this.repository.getMessages();
1708
+ const message = {
1709
+ id,
1710
+ role: "assistant",
1711
+ status: "in_progress",
1712
+ content: [{ type: "text", text: "" }],
1713
+ createdAt: /* @__PURE__ */ new Date()
1714
+ };
1715
+ this.addOrUpdateMessage(parentId, message);
1716
+ void this.run(parentId, messages, message);
1717
+ return { id };
1718
+ }
1719
+ addOrUpdateMessage(parentId, message) {
1720
+ const clone = { ...message };
1721
+ this.repository.addOrUpdateMessage(parentId, clone);
1722
+ for (const callback of this._messageUpdateCallbacks)
1723
+ callback(parentId, clone);
1724
+ }
1725
+ async run(parentId, messages, message) {
1726
+ this.cancelRun();
1727
+ for (const callback of this._statusUpdateCallbacks) callback(true);
1728
+ this.abortController = new AbortController();
1729
+ try {
1730
+ await this.adapter.run({
1731
+ messages,
1732
+ abortSignal: this.abortController.signal,
1733
+ onUpdate: ({ content }) => {
1734
+ message.content = content;
1735
+ this.addOrUpdateMessage(parentId, message);
1736
+ }
1737
+ });
1738
+ message.status = "done";
1739
+ this.addOrUpdateMessage(parentId, message);
1740
+ } catch (e) {
1741
+ message.status = "error";
1742
+ this.addOrUpdateMessage(parentId, message);
1743
+ console.error(e);
1744
+ } finally {
1745
+ this.cancelRun();
1746
+ }
1747
+ }
1748
+ cancelRun() {
1749
+ if (!this.abortController) return;
1750
+ this.abortController.abort();
1751
+ this.abortController = null;
1752
+ for (const callback of this._statusUpdateCallbacks) callback(false);
1753
+ }
1754
+ subscribeToMessageUpdates(callback) {
1755
+ this._messageUpdateCallbacks.add(callback);
1756
+ return () => this._messageUpdateCallbacks.delete(callback);
1757
+ }
1758
+ subscribeToStatusUpdates(callback) {
1759
+ this._statusUpdateCallbacks.add(callback);
1760
+ return () => this._statusUpdateCallbacks.delete(callback);
1761
+ }
1762
+ };
1763
+
1764
+ // src/adapters/core/local/useLocalRuntime.tsx
1765
+ var useLocalRuntime = (adapter) => {
1766
+ const [runtime] = (0, import_react34.useState)(() => new LocalRuntime(adapter));
1767
+ runtime.adapter = adapter;
1768
+ return runtime;
1769
+ };
1770
+
1771
+ // src/adapters/core/local/vercel/VercelModelAdapter.tsx
1772
+ var import_ai = require("ai");
1773
+ var VercelModelAdapter = class {
1774
+ constructor(model) {
1775
+ this.model = model;
1776
+ }
1777
+ async run({ messages, abortSignal, onUpdate }) {
1778
+ const { fullStream } = await (0, import_ai.streamText)({
1779
+ model: this.model,
1780
+ abortSignal,
1781
+ messages: messages.map((m) => ({
1782
+ role: m.role,
1783
+ content: m.content.filter((c) => c.type !== "ui")
1784
+ }))
1785
+ });
1786
+ const content = [];
1787
+ for await (const aiPart of fullStream) {
1788
+ switch (aiPart.type) {
1789
+ case "text-delta": {
1790
+ let part = content.at(-1);
1791
+ if (!part || part.type !== "text") {
1792
+ part = { type: "text", text: "" };
1793
+ content.push(part);
1794
+ }
1795
+ part.text += aiPart.textDelta;
1796
+ break;
1797
+ }
1798
+ case "tool-call": {
1799
+ content.push({
1800
+ type: "tool-call",
1801
+ name: aiPart.toolName,
1802
+ args: aiPart.args
1803
+ });
1804
+ break;
1805
+ }
1806
+ }
1807
+ onUpdate({ content });
1808
+ }
1809
+ return { content };
1810
+ }
1811
+ };
1542
1812
  // Annotate the CommonJS export names for ESM import in node:
1543
1813
  0 && (module.exports = {
1544
1814
  ActionBarPrimitive,
@@ -1549,8 +1819,11 @@ var VercelRSCAssistantProvider = ({
1549
1819
  ThreadPrimitive,
1550
1820
  VercelAIAssistantProvider,
1551
1821
  VercelRSCAssistantProvider,
1822
+ unstable_AssistantProvider,
1823
+ unstable_VercelModelAdapter,
1552
1824
  unstable_getVercelMessage,
1553
1825
  unstable_getVercelRSCMessage,
1826
+ unstable_useLocalRuntime,
1554
1827
  unstable_useMessageContext,
1555
1828
  useBeginMessageEdit,
1556
1829
  useCopyMessage,