@assistant-ui/react 0.0.17 → 0.0.19

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