@assistant-ui/react 0.0.19 → 0.0.20

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
@@ -1046,7 +1046,7 @@ __export(contentPart_exports, {
1046
1046
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1047
1047
  var import_react31 = require("react");
1048
1048
 
1049
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1049
+ // src/adapters/core/AssistantProvider.tsx
1050
1050
  var import_react29 = require("react");
1051
1051
  var import_zustand5 = require("zustand");
1052
1052
 
@@ -1070,42 +1070,80 @@ var makeViewportStore = () => {
1070
1070
  }));
1071
1071
  };
1072
1072
 
1073
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1074
- var makeDummyThreadStore = () => {
1075
- return (0, import_zustand5.create)(() => ({
1076
- messages: [],
1077
- isRunning: false,
1078
- getBranches: () => {
1079
- return [];
1080
- },
1081
- switchToBranch: () => {
1082
- throw new Error("Not implemented");
1083
- },
1084
- append: () => {
1085
- throw new Error("Not implemented");
1086
- },
1087
- startRun: () => {
1088
- throw new Error("Not implemented");
1089
- },
1090
- cancelRun: () => {
1091
- throw new Error("Not implemented");
1092
- }
1073
+ // src/adapters/core/AssistantProvider.tsx
1074
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1075
+ var makeThreadStore = (runtimeRef) => {
1076
+ const useThread = (0, import_zustand5.create)(() => ({
1077
+ messages: runtimeRef.current.messages,
1078
+ isRunning: runtimeRef.current.isRunning,
1079
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1080
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1081
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1082
+ append: (message) => runtimeRef.current.append(message),
1083
+ cancelRun: () => runtimeRef.current.cancelRun()
1093
1084
  }));
1085
+ const onRuntimeUpdate = () => {
1086
+ useThread.setState({
1087
+ messages: runtimeRef.current.messages,
1088
+ isRunning: runtimeRef.current.isRunning
1089
+ });
1090
+ };
1091
+ return {
1092
+ useThread,
1093
+ onRuntimeUpdate
1094
+ };
1094
1095
  };
1095
- var useDummyAIAssistantContext = () => {
1096
- const [context] = (0, import_react29.useState)(() => {
1097
- const useThread = makeDummyThreadStore();
1096
+ var AssistantProvider = ({ children, runtime }) => {
1097
+ const runtimeRef = (0, import_react29.useRef)(runtime);
1098
+ (0, import_react29.useInsertionEffect)(() => {
1099
+ runtimeRef.current = runtime;
1100
+ });
1101
+ const [{ context, onRuntimeUpdate }] = (0, import_react29.useState)(() => {
1102
+ const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1098
1103
  const useViewport = makeViewportStore();
1099
1104
  const useComposer = makeThreadComposerStore(useThread);
1100
- return { useThread, useViewport, useComposer };
1105
+ return {
1106
+ context: {
1107
+ useViewport,
1108
+ useThread,
1109
+ useComposer
1110
+ },
1111
+ onRuntimeUpdate: onRuntimeUpdate2
1112
+ };
1101
1113
  });
1102
- return context;
1114
+ (0, import_react29.useEffect)(() => {
1115
+ onRuntimeUpdate();
1116
+ return runtime.subscribe(onRuntimeUpdate);
1117
+ }, [onRuntimeUpdate, runtime]);
1118
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantContext.Provider, { value: context, children });
1103
1119
  };
1104
1120
 
1105
- // src/adapters/vercel/useVercelAIThreadState.tsx
1106
- var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
1121
+ // src/adapters/core/vercel-use-chat/useVercelUseChatRuntime.tsx
1107
1122
  var import_react30 = require("react");
1108
1123
 
1124
+ // src/adapters/ThreadMessageConverter.ts
1125
+ var ThreadMessageConverter = class {
1126
+ cache = /* @__PURE__ */ new WeakMap();
1127
+ convertMessages(converter, messages) {
1128
+ return messages.map((m) => {
1129
+ const cached = this.cache.get(m);
1130
+ const newMessage = converter(m, cached);
1131
+ this.cache.set(m, newMessage);
1132
+ return newMessage;
1133
+ });
1134
+ }
1135
+ };
1136
+
1137
+ // src/adapters/vercel/VercelThreadMessage.tsx
1138
+ var symbolInnerMessage = Symbol("innerMessage");
1139
+ var symbolInnerRSCMessage = Symbol("innerRSCMessage");
1140
+ var getVercelMessage = (message) => {
1141
+ return message[symbolInnerMessage];
1142
+ };
1143
+ var getVercelRSCMessage = (message) => {
1144
+ return message[symbolInnerRSCMessage];
1145
+ };
1146
+
1109
1147
  // src/adapters/idUtils.tsx
1110
1148
  var import_non_secure = require("nanoid/non-secure");
1111
1149
  var generateId = (0, import_non_secure.customAlphabet)(
@@ -1266,30 +1304,104 @@ var MessageRepository = class {
1266
1304
  }
1267
1305
  };
1268
1306
 
1269
- // src/adapters/ThreadMessageConverter.ts
1270
- var ThreadMessageConverter = class {
1271
- cache = /* @__PURE__ */ new WeakMap();
1272
- convertMessages(converter, messages) {
1273
- return messages.map((m) => {
1274
- const cached = this.cache.get(m);
1275
- const newMessage = converter(m, cached);
1276
- this.cache.set(m, newMessage);
1277
- return newMessage;
1307
+ // src/adapters/core/vercel-use-chat/VercelUseChatRuntime.tsx
1308
+ var sliceMessagesUntil = (messages, messageId) => {
1309
+ if (messageId == null) return [];
1310
+ const messageIdx = messages.findIndex((m) => m.id === messageId);
1311
+ if (messageIdx === -1)
1312
+ throw new Error(
1313
+ "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1314
+ );
1315
+ return messages.slice(0, messageIdx + 1);
1316
+ };
1317
+ var hasUpcomingMessage = (isRunning, messages) => {
1318
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
1319
+ };
1320
+ var VercelUseChatRuntime = class {
1321
+ constructor(vercel) {
1322
+ this.vercel = vercel;
1323
+ }
1324
+ _subscriptions = /* @__PURE__ */ new Set();
1325
+ repository = new MessageRepository();
1326
+ assistantOptimisticId = null;
1327
+ messages = [];
1328
+ isRunning = false;
1329
+ getBranches(messageId) {
1330
+ return this.repository.getBranches(messageId);
1331
+ }
1332
+ switchToBranch(branchId) {
1333
+ this.repository.switchToBranch(branchId);
1334
+ this.vercel.setMessages(
1335
+ this.repository.getMessages().map(getVercelMessage).filter((m) => m != null)
1336
+ );
1337
+ }
1338
+ async append(message) {
1339
+ if (message.content.length !== 1 || message.content[0]?.type !== "text")
1340
+ throw new Error("Only text content is supported by Vercel AI SDK.");
1341
+ const newMessages = sliceMessagesUntil(
1342
+ this.vercel.messages,
1343
+ message.parentId
1344
+ );
1345
+ this.vercel.setMessages(newMessages);
1346
+ await this.vercel.append({
1347
+ role: "user",
1348
+ content: message.content[0].text
1278
1349
  });
1279
1350
  }
1351
+ async startRun(parentId) {
1352
+ const reloadMaybe = "reload" in this.vercel ? this.vercel.reload : void 0;
1353
+ if (!reloadMaybe)
1354
+ throw new Error(
1355
+ "Reload is not supported by Vercel AI SDK's useAssistant."
1356
+ );
1357
+ const newMessages = sliceMessagesUntil(this.vercel.messages, parentId);
1358
+ this.vercel.setMessages(newMessages);
1359
+ await reloadMaybe();
1360
+ }
1361
+ cancelRun() {
1362
+ const lastMessage = this.vercel.messages.at(-1);
1363
+ this.vercel.stop();
1364
+ if (lastMessage?.role === "user") {
1365
+ this.vercel.setInput(lastMessage.content);
1366
+ }
1367
+ }
1368
+ updateData(isRunning, vm) {
1369
+ for (let i = 0; i < vm.length; i++) {
1370
+ const message = vm[i];
1371
+ const parent = vm[i - 1];
1372
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
1373
+ }
1374
+ if (this.assistantOptimisticId) {
1375
+ this.repository.deleteMessage(this.assistantOptimisticId, null);
1376
+ this.assistantOptimisticId = null;
1377
+ }
1378
+ if (hasUpcomingMessage(isRunning, vm)) {
1379
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
1380
+ vm.at(-1)?.id ?? null,
1381
+ {
1382
+ role: "assistant",
1383
+ content: [{ type: "text", text: "" }]
1384
+ }
1385
+ );
1386
+ }
1387
+ this.repository.resetHead(
1388
+ this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
1389
+ );
1390
+ this.messages = this.repository.getMessages();
1391
+ this.isRunning = isRunning;
1392
+ for (const callback of this._subscriptions) callback();
1393
+ }
1394
+ subscribe(callback) {
1395
+ this._subscriptions.add(callback);
1396
+ return () => this._subscriptions.delete(callback);
1397
+ }
1280
1398
  };
1281
1399
 
1282
- // src/adapters/vercel/VercelThreadMessage.tsx
1283
- var symbolInnerMessage = Symbol("innerMessage");
1284
- var symbolInnerRSCMessage = Symbol("innerRSCMessage");
1285
- var getVercelMessage = (message) => {
1286
- return message[symbolInnerMessage];
1287
- };
1288
- var getVercelRSCMessage = (message) => {
1289
- return message[symbolInnerRSCMessage];
1400
+ // src/adapters/core/vercel-use-chat/useVercelUseChatRuntime.tsx
1401
+ var getIsRunning = (vercel) => {
1402
+ if ("isLoading" in vercel) return vercel.isLoading;
1403
+ return vercel.status === "in_progress";
1290
1404
  };
1291
-
1292
- // src/adapters/vercel/useVercelAIThreadState.tsx
1293
1405
  var vercelToThreadMessage = (message, status) => {
1294
1406
  const common = {
1295
1407
  id: message.id,
@@ -1326,27 +1438,13 @@ var vercelToThreadMessage = (message, status) => {
1326
1438
  );
1327
1439
  }
1328
1440
  };
1329
- var sliceMessagesUntil = (messages, messageId) => {
1330
- if (messageId == null) return [];
1331
- const messageIdx = messages.findIndex((m) => m.id === messageId);
1332
- if (messageIdx === -1)
1333
- throw new Error(
1334
- "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1335
- );
1336
- return messages.slice(0, messageIdx + 1);
1337
- };
1338
- var hasUpcomingMessage = (isRunning, messages) => {
1339
- return isRunning && messages[messages.length - 1]?.role !== "assistant";
1340
- };
1341
- var getIsRunning = (vercel) => {
1342
- if ("isLoading" in vercel) return vercel.isLoading;
1343
- return vercel.status === "in_progress";
1344
- };
1345
- var useVercelAIThreadState = (vercel) => {
1346
- const [data] = (0, import_react30.useState)(() => new MessageRepository());
1441
+ var useVercelUseChatRuntime = (vercel) => {
1442
+ const [runtime] = (0, import_react30.useState)(() => new VercelUseChatRuntime(vercel));
1443
+ (0, import_react30.useInsertionEffect)(() => {
1444
+ runtime.vercel = vercel;
1445
+ });
1347
1446
  const isRunning = getIsRunning(vercel);
1348
1447
  const converter = (0, import_react30.useMemo)(() => new ThreadMessageConverter(), []);
1349
- const assistantOptimisticIdRef = (0, import_react30.useRef)(null);
1350
1448
  const messages = (0, import_react30.useMemo)(() => {
1351
1449
  const lastMessageId = vercel.messages.at(-1)?.id;
1352
1450
  const convertCallback = (message, cache) => {
@@ -1355,113 +1453,102 @@ var useVercelAIThreadState = (vercel) => {
1355
1453
  return cache;
1356
1454
  return vercelToThreadMessage(message, status);
1357
1455
  };
1358
- const vm = converter.convertMessages(convertCallback, vercel.messages);
1359
- for (let i = 0; i < vm.length; i++) {
1360
- const message = vm[i];
1361
- const parent = vm[i - 1];
1362
- data.addOrUpdateMessage(parent?.id ?? null, message);
1363
- }
1364
- if (assistantOptimisticIdRef.current) {
1365
- data.deleteMessage(assistantOptimisticIdRef.current, null);
1366
- assistantOptimisticIdRef.current = null;
1367
- }
1368
- if (hasUpcomingMessage(isRunning, vm)) {
1369
- assistantOptimisticIdRef.current = data.appendOptimisticMessage(
1370
- vm.at(-1)?.id ?? null,
1371
- {
1372
- role: "assistant",
1373
- content: [{ type: "text", text: "" }]
1374
- }
1375
- );
1376
- }
1377
- data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
1378
- return data.getMessages();
1379
- }, [converter, data, isRunning, vercel.messages]);
1380
- const getBranches2 = (0, import_react30.useCallback)(
1381
- (messageId) => {
1382
- return data.getBranches(messageId);
1383
- },
1384
- [data]
1385
- );
1386
- const switchToBranch2 = (0, import_react_use_callback_ref3.useCallbackRef)((messageId) => {
1387
- data.switchToBranch(messageId);
1388
- vercel.setMessages(
1389
- data.getMessages().map(getVercelMessage).filter((m) => m != null)
1390
- );
1391
- });
1392
- const startRun = (0, import_react_use_callback_ref3.useCallbackRef)(async (parentId) => {
1393
- const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
1394
- if (!reloadMaybe)
1395
- throw new Error(
1396
- "Reload is not supported by Vercel AI SDK's useAssistant."
1397
- );
1398
- const newMessages = sliceMessagesUntil(vercel.messages, parentId);
1399
- vercel.setMessages(newMessages);
1400
- await reloadMaybe();
1401
- });
1402
- const append = (0, import_react_use_callback_ref3.useCallbackRef)(async (message) => {
1403
- if (message.content.length !== 1 || message.content[0]?.type !== "text")
1404
- throw new Error("Only text content is supported by Vercel AI SDK.");
1405
- const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
1406
- vercel.setMessages(newMessages);
1407
- await vercel.append({
1408
- role: "user",
1409
- content: message.content[0].text
1410
- });
1411
- });
1412
- const cancelRun2 = (0, import_react_use_callback_ref3.useCallbackRef)(() => {
1413
- const lastMessage = vercel.messages.at(-1);
1414
- vercel.stop();
1415
- if (lastMessage?.role === "user") {
1416
- vercel.setInput(lastMessage.content);
1417
- }
1418
- });
1419
- return (0, import_react30.useMemo)(
1420
- () => ({
1421
- isRunning,
1422
- messages,
1423
- getBranches: getBranches2,
1424
- switchToBranch: switchToBranch2,
1425
- append,
1426
- startRun,
1427
- cancelRun: cancelRun2
1428
- }),
1429
- [
1430
- isRunning,
1431
- messages,
1432
- getBranches2,
1433
- switchToBranch2,
1434
- append,
1435
- startRun,
1436
- cancelRun2
1437
- ]
1438
- );
1456
+ return converter.convertMessages(convertCallback, vercel.messages);
1457
+ }, [isRunning, vercel.messages, converter]);
1458
+ (0, import_react30.useEffect)(() => {
1459
+ runtime.updateData(isRunning, messages);
1460
+ }, [runtime, isRunning, messages]);
1461
+ return runtime;
1439
1462
  };
1440
1463
 
1441
1464
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1442
- var import_jsx_runtime21 = require("react/jsx-runtime");
1465
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1443
1466
  var VercelAIAssistantProvider = ({
1444
1467
  children,
1445
1468
  ...rest
1446
1469
  }) => {
1447
- const context = useDummyAIAssistantContext();
1448
1470
  const vercel = "chat" in rest ? rest.chat : rest.assistant;
1449
- const threadState = useVercelAIThreadState(vercel);
1450
- (0, import_react31.useMemo)(() => {
1451
- context.useThread.setState(threadState, true);
1452
- }, [context, threadState]);
1453
- (0, import_react31.useMemo)(() => {
1454
- context.useComposer.setState({
1471
+ const runtime = useVercelUseChatRuntime(vercel);
1472
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(AssistantProvider, { runtime, children: [
1473
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ComposerSync, { vercel }),
1474
+ children
1475
+ ] });
1476
+ };
1477
+ var ComposerSync = ({
1478
+ vercel
1479
+ }) => {
1480
+ const { useComposer } = useAssistantContext();
1481
+ (0, import_react31.useEffect)(() => {
1482
+ useComposer.setState({
1455
1483
  value: vercel.input,
1456
1484
  setValue: vercel.setInput
1457
1485
  });
1458
- }, [context, vercel.input, vercel.setInput]);
1459
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantContext.Provider, { value: context, children });
1486
+ }, [useComposer, vercel.input, vercel.setInput]);
1487
+ return null;
1460
1488
  };
1461
1489
 
1462
- // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1490
+ // src/adapters/core/vercel-rsc/useVercelRSCRuntime.tsx
1463
1491
  var import_react32 = require("react");
1464
- var import_jsx_runtime22 = require("react/jsx-runtime");
1492
+
1493
+ // src/adapters/core/vercel-rsc/VercelRSCRuntime.tsx
1494
+ var EMPTY_BRANCHES = Object.freeze([]);
1495
+ var VercelRSCRuntime = class {
1496
+ constructor(adapter) {
1497
+ this.adapter = adapter;
1498
+ }
1499
+ _subscriptions = /* @__PURE__ */ new Set();
1500
+ isRunning = false;
1501
+ messages = [];
1502
+ withRunning = (callback) => {
1503
+ this.isRunning = true;
1504
+ return callback.finally(() => {
1505
+ this.isRunning = false;
1506
+ });
1507
+ };
1508
+ getBranches() {
1509
+ return EMPTY_BRANCHES;
1510
+ }
1511
+ switchToBranch() {
1512
+ throw new Error(
1513
+ "Branch switching is not supported by VercelRSCAssistantProvider."
1514
+ );
1515
+ }
1516
+ async append(message) {
1517
+ if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
1518
+ if (!this.adapter.edit)
1519
+ throw new Error(
1520
+ "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1521
+ );
1522
+ await this.withRunning(this.adapter.edit(message));
1523
+ } else {
1524
+ await this.withRunning(this.adapter.append(message));
1525
+ }
1526
+ }
1527
+ async startRun(parentId) {
1528
+ if (!this.adapter.reload)
1529
+ throw new Error(
1530
+ "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1531
+ );
1532
+ await this.withRunning(this.adapter.reload(parentId));
1533
+ }
1534
+ cancelRun() {
1535
+ if (process.env["NODE_ENV"] === "development") {
1536
+ console.warn(
1537
+ "Run cancellation is not supported by VercelRSCAssistantProvider."
1538
+ );
1539
+ }
1540
+ }
1541
+ updateData(messages) {
1542
+ this.messages = messages;
1543
+ for (const callback of this._subscriptions) callback();
1544
+ }
1545
+ subscribe(callback) {
1546
+ this._subscriptions.add(callback);
1547
+ return () => this._subscriptions.delete(callback);
1548
+ }
1549
+ };
1550
+
1551
+ // src/adapters/core/vercel-rsc/useVercelRSCRuntime.tsx
1465
1552
  var vercelToThreadMessage2 = (converter, rawMessage) => {
1466
1553
  const message = converter(rawMessage);
1467
1554
  return {
@@ -1473,222 +1560,61 @@ var vercelToThreadMessage2 = (converter, rawMessage) => {
1473
1560
  [symbolInnerRSCMessage]: rawMessage
1474
1561
  };
1475
1562
  };
1476
- var EMPTY_BRANCHES = [];
1477
- var getBranches = () => {
1478
- return EMPTY_BRANCHES;
1479
- };
1480
- var switchToBranch = () => {
1481
- throw new Error(
1482
- "Branch switching is not supported by VercelRSCAssistantProvider."
1483
- );
1484
- };
1485
- var cancelRun = () => {
1486
- if (process.env["NODE_ENV"] === "development") {
1487
- console.warn(
1488
- "Run cancellation is not supported by VercelRSCAssistantProvider."
1489
- );
1490
- }
1491
- };
1492
- var VercelRSCAssistantProvider = ({
1493
- children,
1494
- convertMessage,
1495
- messages: vercelMessages,
1496
- append: appendCallback,
1497
- edit,
1498
- reload
1499
- }) => {
1500
- const context = useDummyAIAssistantContext();
1501
- const [isRunning, setIsRunning] = (0, import_react32.useState)(false);
1502
- const withRunning = (0, import_react32.useCallback)((callback) => {
1503
- setIsRunning(true);
1504
- return callback.finally(() => setIsRunning(false));
1505
- }, []);
1563
+ var useVercelRSCRuntime = (adapter) => {
1564
+ const [runtime] = (0, import_react32.useState)(() => new VercelRSCRuntime(adapter));
1565
+ (0, import_react32.useInsertionEffect)(() => {
1566
+ runtime.adapter = adapter;
1567
+ });
1506
1568
  const [converter, convertCallback] = (0, import_react32.useMemo)(() => {
1507
- const rscConverter = convertMessage ?? ((m) => m);
1569
+ const rscConverter = adapter.convertMessage ?? ((m) => m);
1508
1570
  const convertCallback2 = (m, cache) => {
1509
1571
  if (cache) return cache;
1510
1572
  return vercelToThreadMessage2(rscConverter, m);
1511
1573
  };
1512
1574
  return [new ThreadMessageConverter(), convertCallback2];
1513
- }, [convertMessage]);
1514
- const messages = (0, import_react32.useMemo)(() => {
1515
- return converter.convertMessages(convertCallback, vercelMessages);
1516
- }, [converter, convertCallback, vercelMessages]);
1517
- const append = (0, import_react32.useCallback)(
1518
- async (message) => {
1519
- if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
1520
- if (!edit)
1521
- throw new Error(
1522
- "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1523
- );
1524
- await withRunning(edit(message));
1525
- } else {
1526
- await withRunning(appendCallback(message));
1527
- }
1528
- },
1529
- [context, withRunning, appendCallback, edit]
1530
- );
1531
- const startRun = (0, import_react32.useCallback)(
1532
- async (parentId) => {
1533
- if (!reload)
1534
- throw new Error(
1535
- "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1536
- );
1537
- await withRunning(reload(parentId));
1538
- },
1539
- [withRunning, reload]
1540
- );
1541
- (0, import_react32.useMemo)(() => {
1542
- context.useThread.setState(
1543
- {
1544
- messages,
1545
- isRunning,
1546
- getBranches,
1547
- switchToBranch,
1548
- append,
1549
- startRun,
1550
- cancelRun
1551
- },
1552
- true
1575
+ }, [adapter.convertMessage]);
1576
+ (0, import_react32.useEffect)(() => {
1577
+ runtime.updateData(
1578
+ converter.convertMessages(convertCallback, adapter.messages)
1553
1579
  );
1554
- }, [context, messages, isRunning, append, startRun]);
1555
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AssistantContext.Provider, { value: context, children });
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;
1580
+ }, [runtime, converter, convertCallback, adapter.messages]);
1581
+ return runtime;
1671
1582
  };
1672
1583
 
1673
- // src/adapters/core/AssistantProvider.tsx
1584
+ // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1674
1585
  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 });
1586
+ var VercelRSCAssistantProvider = ({
1587
+ children,
1588
+ ...adapter
1589
+ }) => {
1590
+ const runtime = useVercelRSCRuntime(adapter);
1591
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantProvider, { runtime, children });
1678
1592
  };
1679
1593
 
1680
1594
  // src/adapters/core/local/useLocalRuntime.tsx
1681
- var import_react34 = require("react");
1595
+ var import_react33 = require("react");
1682
1596
 
1683
1597
  // src/adapters/core/local/LocalRuntime.tsx
1684
1598
  var LocalRuntime = class {
1685
1599
  constructor(adapter) {
1686
1600
  this.adapter = adapter;
1687
1601
  }
1688
- _messageUpdateCallbacks = /* @__PURE__ */ new Set();
1689
- _statusUpdateCallbacks = /* @__PURE__ */ new Set();
1602
+ _subscriptions = /* @__PURE__ */ new Set();
1690
1603
  abortController = null;
1691
1604
  repository = new MessageRepository();
1605
+ get messages() {
1606
+ return this.repository.getMessages();
1607
+ }
1608
+ get isRunning() {
1609
+ return this.abortController != null;
1610
+ }
1611
+ getBranches(messageId) {
1612
+ return this.repository.getBranches(messageId);
1613
+ }
1614
+ switchToBranch(branchId) {
1615
+ this.repository.switchToBranch(branchId);
1616
+ this.notifySubscribers();
1617
+ }
1692
1618
  async append(message) {
1693
1619
  const userMessageId = generateId();
1694
1620
  const userMessage = {
@@ -1697,9 +1623,8 @@ var LocalRuntime = class {
1697
1623
  content: message.content,
1698
1624
  createdAt: /* @__PURE__ */ new Date()
1699
1625
  };
1700
- this.addOrUpdateMessage(message.parentId, userMessage);
1701
- const { id } = await this.startRun(userMessageId);
1702
- return { parentId: userMessageId, id };
1626
+ this.repository.addOrUpdateMessage(message.parentId, userMessage);
1627
+ await this.startRun(userMessageId);
1703
1628
  }
1704
1629
  async startRun(parentId) {
1705
1630
  const id = generateId();
@@ -1712,59 +1637,52 @@ var LocalRuntime = class {
1712
1637
  content: [{ type: "text", text: "" }],
1713
1638
  createdAt: /* @__PURE__ */ new Date()
1714
1639
  };
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);
1640
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1641
+ this.abortController?.abort();
1728
1642
  this.abortController = new AbortController();
1643
+ this.notifySubscribers();
1729
1644
  try {
1730
1645
  await this.adapter.run({
1731
1646
  messages,
1732
1647
  abortSignal: this.abortController.signal,
1733
1648
  onUpdate: ({ content }) => {
1734
1649
  message.content = content;
1735
- this.addOrUpdateMessage(parentId, message);
1650
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1651
+ this.notifySubscribers();
1736
1652
  }
1737
1653
  });
1738
1654
  message.status = "done";
1739
- this.addOrUpdateMessage(parentId, message);
1655
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1740
1656
  } catch (e) {
1741
1657
  message.status = "error";
1742
- this.addOrUpdateMessage(parentId, message);
1658
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1743
1659
  console.error(e);
1744
1660
  } finally {
1745
- this.cancelRun();
1661
+ this.abortController = null;
1662
+ this.notifySubscribers();
1746
1663
  }
1747
1664
  }
1748
1665
  cancelRun() {
1749
1666
  if (!this.abortController) return;
1750
1667
  this.abortController.abort();
1751
1668
  this.abortController = null;
1752
- for (const callback of this._statusUpdateCallbacks) callback(false);
1669
+ this.notifySubscribers();
1753
1670
  }
1754
- subscribeToMessageUpdates(callback) {
1755
- this._messageUpdateCallbacks.add(callback);
1756
- return () => this._messageUpdateCallbacks.delete(callback);
1671
+ notifySubscribers() {
1672
+ for (const callback of this._subscriptions) callback();
1757
1673
  }
1758
- subscribeToStatusUpdates(callback) {
1759
- this._statusUpdateCallbacks.add(callback);
1760
- return () => this._statusUpdateCallbacks.delete(callback);
1674
+ subscribe(callback) {
1675
+ this._subscriptions.add(callback);
1676
+ return () => this._subscriptions.delete(callback);
1761
1677
  }
1762
1678
  };
1763
1679
 
1764
1680
  // src/adapters/core/local/useLocalRuntime.tsx
1765
1681
  var useLocalRuntime = (adapter) => {
1766
- const [runtime] = (0, import_react34.useState)(() => new LocalRuntime(adapter));
1767
- runtime.adapter = adapter;
1682
+ const [runtime] = (0, import_react33.useState)(() => new LocalRuntime(adapter));
1683
+ (0, import_react33.useInsertionEffect)(() => {
1684
+ runtime.adapter = adapter;
1685
+ });
1768
1686
  return runtime;
1769
1687
  };
1770
1688