@assistant-ui/react 0.0.19 → 0.0.20

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