@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.mjs CHANGED
@@ -1027,10 +1027,15 @@ __export(contentPart_exports, {
1027
1027
  });
1028
1028
 
1029
1029
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1030
- import { useMemo as useMemo6 } from "react";
1030
+ import { useEffect as useEffect6 } from "react";
1031
1031
 
1032
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1033
- import { useState as useState3 } from "react";
1032
+ // src/adapters/core/AssistantProvider.tsx
1033
+ import {
1034
+ useEffect as useEffect4,
1035
+ useInsertionEffect,
1036
+ useRef as useRef4,
1037
+ useState as useState3
1038
+ } from "react";
1034
1039
  import { create as create5 } from "zustand";
1035
1040
 
1036
1041
  // src/utils/context/stores/ViewportStore.tsx
@@ -1053,41 +1058,79 @@ var makeViewportStore = () => {
1053
1058
  }));
1054
1059
  };
1055
1060
 
1056
- // src/adapters/vercel/useDummyAIAssistantContext.tsx
1057
- var makeDummyThreadStore = () => {
1058
- return create5(() => ({
1059
- messages: [],
1060
- isRunning: false,
1061
- getBranches: () => {
1062
- return [];
1063
- },
1064
- switchToBranch: () => {
1065
- throw new Error("Not implemented");
1066
- },
1067
- append: () => {
1068
- throw new Error("Not implemented");
1069
- },
1070
- startRun: () => {
1071
- throw new Error("Not implemented");
1072
- },
1073
- cancelRun: () => {
1074
- throw new Error("Not implemented");
1075
- }
1061
+ // src/adapters/core/AssistantProvider.tsx
1062
+ import { jsx as jsx21 } from "react/jsx-runtime";
1063
+ var makeThreadStore = (runtimeRef) => {
1064
+ const useThread = create5(() => ({
1065
+ messages: runtimeRef.current.messages,
1066
+ isRunning: runtimeRef.current.isRunning,
1067
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1068
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1069
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1070
+ append: (message) => runtimeRef.current.append(message),
1071
+ cancelRun: () => runtimeRef.current.cancelRun()
1076
1072
  }));
1073
+ const onRuntimeUpdate = () => {
1074
+ useThread.setState({
1075
+ messages: runtimeRef.current.messages,
1076
+ isRunning: runtimeRef.current.isRunning
1077
+ });
1078
+ };
1079
+ return {
1080
+ useThread,
1081
+ onRuntimeUpdate
1082
+ };
1077
1083
  };
1078
- var useDummyAIAssistantContext = () => {
1079
- const [context] = useState3(() => {
1080
- const useThread = makeDummyThreadStore();
1084
+ var AssistantProvider = ({ children, runtime }) => {
1085
+ const runtimeRef = useRef4(runtime);
1086
+ useInsertionEffect(() => {
1087
+ runtimeRef.current = runtime;
1088
+ });
1089
+ const [{ context, onRuntimeUpdate }] = useState3(() => {
1090
+ const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1081
1091
  const useViewport = makeViewportStore();
1082
1092
  const useComposer = makeThreadComposerStore(useThread);
1083
- return { useThread, useViewport, useComposer };
1093
+ return {
1094
+ context: {
1095
+ useViewport,
1096
+ useThread,
1097
+ useComposer
1098
+ },
1099
+ onRuntimeUpdate: onRuntimeUpdate2
1100
+ };
1084
1101
  });
1085
- return context;
1102
+ useEffect4(() => {
1103
+ onRuntimeUpdate();
1104
+ return runtime.subscribe(onRuntimeUpdate);
1105
+ }, [onRuntimeUpdate, runtime]);
1106
+ return /* @__PURE__ */ jsx21(AssistantContext.Provider, { value: context, children });
1107
+ };
1108
+
1109
+ // src/adapters/core/vercel-use-chat/useVercelUseChatRuntime.tsx
1110
+ import { useEffect as useEffect5, useInsertionEffect as useInsertionEffect2, useMemo as useMemo5, useState as useState4 } from "react";
1111
+
1112
+ // src/adapters/ThreadMessageConverter.ts
1113
+ var ThreadMessageConverter = class {
1114
+ cache = /* @__PURE__ */ new WeakMap();
1115
+ convertMessages(converter, messages) {
1116
+ return messages.map((m) => {
1117
+ const cached = this.cache.get(m);
1118
+ const newMessage = converter(m, cached);
1119
+ this.cache.set(m, newMessage);
1120
+ return newMessage;
1121
+ });
1122
+ }
1086
1123
  };
1087
1124
 
1088
- // src/adapters/vercel/useVercelAIThreadState.tsx
1089
- import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
1090
- import { useCallback as useCallback7, useMemo as useMemo5, useRef as useRef4, useState as useState4 } from "react";
1125
+ // src/adapters/vercel/VercelThreadMessage.tsx
1126
+ var symbolInnerMessage = Symbol("innerMessage");
1127
+ var symbolInnerRSCMessage = Symbol("innerRSCMessage");
1128
+ var getVercelMessage = (message) => {
1129
+ return message[symbolInnerMessage];
1130
+ };
1131
+ var getVercelRSCMessage = (message) => {
1132
+ return message[symbolInnerRSCMessage];
1133
+ };
1091
1134
 
1092
1135
  // src/adapters/idUtils.tsx
1093
1136
  import { customAlphabet } from "nanoid/non-secure";
@@ -1249,30 +1292,104 @@ var MessageRepository = class {
1249
1292
  }
1250
1293
  };
1251
1294
 
1252
- // src/adapters/ThreadMessageConverter.ts
1253
- var ThreadMessageConverter = class {
1254
- cache = /* @__PURE__ */ new WeakMap();
1255
- convertMessages(converter, messages) {
1256
- return messages.map((m) => {
1257
- const cached = this.cache.get(m);
1258
- const newMessage = converter(m, cached);
1259
- this.cache.set(m, newMessage);
1260
- return newMessage;
1295
+ // src/adapters/core/vercel-use-chat/VercelUseChatRuntime.tsx
1296
+ var sliceMessagesUntil = (messages, messageId) => {
1297
+ if (messageId == null) return [];
1298
+ const messageIdx = messages.findIndex((m) => m.id === messageId);
1299
+ if (messageIdx === -1)
1300
+ throw new Error(
1301
+ "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1302
+ );
1303
+ return messages.slice(0, messageIdx + 1);
1304
+ };
1305
+ var hasUpcomingMessage = (isRunning, messages) => {
1306
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
1307
+ };
1308
+ var VercelUseChatRuntime = class {
1309
+ constructor(vercel) {
1310
+ this.vercel = vercel;
1311
+ }
1312
+ _subscriptions = /* @__PURE__ */ new Set();
1313
+ repository = new MessageRepository();
1314
+ assistantOptimisticId = null;
1315
+ messages = [];
1316
+ isRunning = false;
1317
+ getBranches(messageId) {
1318
+ return this.repository.getBranches(messageId);
1319
+ }
1320
+ switchToBranch(branchId) {
1321
+ this.repository.switchToBranch(branchId);
1322
+ this.vercel.setMessages(
1323
+ this.repository.getMessages().map(getVercelMessage).filter((m) => m != null)
1324
+ );
1325
+ }
1326
+ async append(message) {
1327
+ if (message.content.length !== 1 || message.content[0]?.type !== "text")
1328
+ throw new Error("Only text content is supported by Vercel AI SDK.");
1329
+ const newMessages = sliceMessagesUntil(
1330
+ this.vercel.messages,
1331
+ message.parentId
1332
+ );
1333
+ this.vercel.setMessages(newMessages);
1334
+ await this.vercel.append({
1335
+ role: "user",
1336
+ content: message.content[0].text
1261
1337
  });
1262
1338
  }
1339
+ async startRun(parentId) {
1340
+ const reloadMaybe = "reload" in this.vercel ? this.vercel.reload : void 0;
1341
+ if (!reloadMaybe)
1342
+ throw new Error(
1343
+ "Reload is not supported by Vercel AI SDK's useAssistant."
1344
+ );
1345
+ const newMessages = sliceMessagesUntil(this.vercel.messages, parentId);
1346
+ this.vercel.setMessages(newMessages);
1347
+ await reloadMaybe();
1348
+ }
1349
+ cancelRun() {
1350
+ const lastMessage = this.vercel.messages.at(-1);
1351
+ this.vercel.stop();
1352
+ if (lastMessage?.role === "user") {
1353
+ this.vercel.setInput(lastMessage.content);
1354
+ }
1355
+ }
1356
+ updateData(isRunning, vm) {
1357
+ for (let i = 0; i < vm.length; i++) {
1358
+ const message = vm[i];
1359
+ const parent = vm[i - 1];
1360
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
1361
+ }
1362
+ if (this.assistantOptimisticId) {
1363
+ this.repository.deleteMessage(this.assistantOptimisticId, null);
1364
+ this.assistantOptimisticId = null;
1365
+ }
1366
+ if (hasUpcomingMessage(isRunning, vm)) {
1367
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
1368
+ vm.at(-1)?.id ?? null,
1369
+ {
1370
+ role: "assistant",
1371
+ content: [{ type: "text", text: "" }]
1372
+ }
1373
+ );
1374
+ }
1375
+ this.repository.resetHead(
1376
+ this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
1377
+ );
1378
+ this.messages = this.repository.getMessages();
1379
+ this.isRunning = isRunning;
1380
+ for (const callback of this._subscriptions) callback();
1381
+ }
1382
+ subscribe(callback) {
1383
+ this._subscriptions.add(callback);
1384
+ return () => this._subscriptions.delete(callback);
1385
+ }
1263
1386
  };
1264
1387
 
1265
- // src/adapters/vercel/VercelThreadMessage.tsx
1266
- var symbolInnerMessage = Symbol("innerMessage");
1267
- var symbolInnerRSCMessage = Symbol("innerRSCMessage");
1268
- var getVercelMessage = (message) => {
1269
- return message[symbolInnerMessage];
1270
- };
1271
- var getVercelRSCMessage = (message) => {
1272
- return message[symbolInnerRSCMessage];
1388
+ // src/adapters/core/vercel-use-chat/useVercelUseChatRuntime.tsx
1389
+ var getIsRunning = (vercel) => {
1390
+ if ("isLoading" in vercel) return vercel.isLoading;
1391
+ return vercel.status === "in_progress";
1273
1392
  };
1274
-
1275
- // src/adapters/vercel/useVercelAIThreadState.tsx
1276
1393
  var vercelToThreadMessage = (message, status) => {
1277
1394
  const common = {
1278
1395
  id: message.id,
@@ -1309,27 +1426,13 @@ var vercelToThreadMessage = (message, status) => {
1309
1426
  );
1310
1427
  }
1311
1428
  };
1312
- var sliceMessagesUntil = (messages, messageId) => {
1313
- if (messageId == null) return [];
1314
- const messageIdx = messages.findIndex((m) => m.id === messageId);
1315
- if (messageIdx === -1)
1316
- throw new Error(
1317
- "useVercelAIThreadState: Message not found. This is liekly an internal bug in assistant-ui."
1318
- );
1319
- return messages.slice(0, messageIdx + 1);
1320
- };
1321
- var hasUpcomingMessage = (isRunning, messages) => {
1322
- return isRunning && messages[messages.length - 1]?.role !== "assistant";
1323
- };
1324
- var getIsRunning = (vercel) => {
1325
- if ("isLoading" in vercel) return vercel.isLoading;
1326
- return vercel.status === "in_progress";
1327
- };
1328
- var useVercelAIThreadState = (vercel) => {
1329
- const [data] = useState4(() => new MessageRepository());
1429
+ var useVercelUseChatRuntime = (vercel) => {
1430
+ const [runtime] = useState4(() => new VercelUseChatRuntime(vercel));
1431
+ useInsertionEffect2(() => {
1432
+ runtime.vercel = vercel;
1433
+ });
1330
1434
  const isRunning = getIsRunning(vercel);
1331
1435
  const converter = useMemo5(() => new ThreadMessageConverter(), []);
1332
- const assistantOptimisticIdRef = useRef4(null);
1333
1436
  const messages = useMemo5(() => {
1334
1437
  const lastMessageId = vercel.messages.at(-1)?.id;
1335
1438
  const convertCallback = (message, cache) => {
@@ -1338,117 +1441,102 @@ var useVercelAIThreadState = (vercel) => {
1338
1441
  return cache;
1339
1442
  return vercelToThreadMessage(message, status);
1340
1443
  };
1341
- const vm = converter.convertMessages(convertCallback, vercel.messages);
1342
- for (let i = 0; i < vm.length; i++) {
1343
- const message = vm[i];
1344
- const parent = vm[i - 1];
1345
- data.addOrUpdateMessage(parent?.id ?? null, message);
1346
- }
1347
- if (assistantOptimisticIdRef.current) {
1348
- data.deleteMessage(assistantOptimisticIdRef.current, null);
1349
- assistantOptimisticIdRef.current = null;
1350
- }
1351
- if (hasUpcomingMessage(isRunning, vm)) {
1352
- assistantOptimisticIdRef.current = data.appendOptimisticMessage(
1353
- vm.at(-1)?.id ?? null,
1354
- {
1355
- role: "assistant",
1356
- content: [{ type: "text", text: "" }]
1357
- }
1358
- );
1359
- }
1360
- data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
1361
- return data.getMessages();
1362
- }, [converter, data, isRunning, vercel.messages]);
1363
- const getBranches2 = useCallback7(
1364
- (messageId) => {
1365
- return data.getBranches(messageId);
1366
- },
1367
- [data]
1368
- );
1369
- const switchToBranch2 = useCallbackRef3((messageId) => {
1370
- data.switchToBranch(messageId);
1371
- vercel.setMessages(
1372
- data.getMessages().map(getVercelMessage).filter((m) => m != null)
1373
- );
1374
- });
1375
- const startRun = useCallbackRef3(async (parentId) => {
1376
- const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
1377
- if (!reloadMaybe)
1378
- throw new Error(
1379
- "Reload is not supported by Vercel AI SDK's useAssistant."
1380
- );
1381
- const newMessages = sliceMessagesUntil(vercel.messages, parentId);
1382
- vercel.setMessages(newMessages);
1383
- await reloadMaybe();
1384
- });
1385
- const append = useCallbackRef3(async (message) => {
1386
- if (message.content.length !== 1 || message.content[0]?.type !== "text")
1387
- throw new Error("Only text content is supported by Vercel AI SDK.");
1388
- const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
1389
- vercel.setMessages(newMessages);
1390
- await vercel.append({
1391
- role: "user",
1392
- content: message.content[0].text
1393
- });
1394
- });
1395
- const cancelRun2 = useCallbackRef3(() => {
1396
- const lastMessage = vercel.messages.at(-1);
1397
- vercel.stop();
1398
- if (lastMessage?.role === "user") {
1399
- vercel.setInput(lastMessage.content);
1400
- }
1401
- });
1402
- return useMemo5(
1403
- () => ({
1404
- isRunning,
1405
- messages,
1406
- getBranches: getBranches2,
1407
- switchToBranch: switchToBranch2,
1408
- append,
1409
- startRun,
1410
- cancelRun: cancelRun2
1411
- }),
1412
- [
1413
- isRunning,
1414
- messages,
1415
- getBranches2,
1416
- switchToBranch2,
1417
- append,
1418
- startRun,
1419
- cancelRun2
1420
- ]
1421
- );
1444
+ return converter.convertMessages(convertCallback, vercel.messages);
1445
+ }, [isRunning, vercel.messages, converter]);
1446
+ useEffect5(() => {
1447
+ runtime.updateData(isRunning, messages);
1448
+ }, [runtime, isRunning, messages]);
1449
+ return runtime;
1422
1450
  };
1423
1451
 
1424
1452
  // src/adapters/vercel/VercelAIAssistantProvider.tsx
1425
- import { jsx as jsx21 } from "react/jsx-runtime";
1453
+ import { jsx as jsx22, jsxs as jsxs4 } from "react/jsx-runtime";
1426
1454
  var VercelAIAssistantProvider = ({
1427
1455
  children,
1428
1456
  ...rest
1429
1457
  }) => {
1430
- const context = useDummyAIAssistantContext();
1431
1458
  const vercel = "chat" in rest ? rest.chat : rest.assistant;
1432
- const threadState = useVercelAIThreadState(vercel);
1433
- useMemo6(() => {
1434
- context.useThread.setState(threadState, true);
1435
- }, [context, threadState]);
1436
- useMemo6(() => {
1437
- context.useComposer.setState({
1459
+ const runtime = useVercelUseChatRuntime(vercel);
1460
+ return /* @__PURE__ */ jsxs4(AssistantProvider, { runtime, children: [
1461
+ /* @__PURE__ */ jsx22(ComposerSync, { vercel }),
1462
+ children
1463
+ ] });
1464
+ };
1465
+ var ComposerSync = ({
1466
+ vercel
1467
+ }) => {
1468
+ const { useComposer } = useAssistantContext();
1469
+ useEffect6(() => {
1470
+ useComposer.setState({
1438
1471
  value: vercel.input,
1439
1472
  setValue: vercel.setInput
1440
1473
  });
1441
- }, [context, vercel.input, vercel.setInput]);
1442
- return /* @__PURE__ */ jsx21(AssistantContext.Provider, { value: context, children });
1474
+ }, [useComposer, vercel.input, vercel.setInput]);
1475
+ return null;
1443
1476
  };
1444
1477
 
1445
- // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1446
- import {
1447
- useCallback as useCallback8,
1448
- useMemo as useMemo7,
1449
- useState as useState5
1450
- } from "react";
1451
- import { jsx as jsx22 } from "react/jsx-runtime";
1478
+ // src/adapters/core/vercel-rsc/useVercelRSCRuntime.tsx
1479
+ import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useMemo as useMemo6, useState as useState5 } from "react";
1480
+
1481
+ // src/adapters/core/vercel-rsc/VercelRSCRuntime.tsx
1482
+ var EMPTY_BRANCHES = Object.freeze([]);
1483
+ var VercelRSCRuntime = class {
1484
+ constructor(adapter) {
1485
+ this.adapter = adapter;
1486
+ }
1487
+ _subscriptions = /* @__PURE__ */ new Set();
1488
+ isRunning = false;
1489
+ messages = [];
1490
+ withRunning = (callback) => {
1491
+ this.isRunning = true;
1492
+ return callback.finally(() => {
1493
+ this.isRunning = false;
1494
+ });
1495
+ };
1496
+ getBranches() {
1497
+ return EMPTY_BRANCHES;
1498
+ }
1499
+ switchToBranch() {
1500
+ throw new Error(
1501
+ "Branch switching is not supported by VercelRSCAssistantProvider."
1502
+ );
1503
+ }
1504
+ async append(message) {
1505
+ if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
1506
+ if (!this.adapter.edit)
1507
+ throw new Error(
1508
+ "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1509
+ );
1510
+ await this.withRunning(this.adapter.edit(message));
1511
+ } else {
1512
+ await this.withRunning(this.adapter.append(message));
1513
+ }
1514
+ }
1515
+ async startRun(parentId) {
1516
+ if (!this.adapter.reload)
1517
+ throw new Error(
1518
+ "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1519
+ );
1520
+ await this.withRunning(this.adapter.reload(parentId));
1521
+ }
1522
+ cancelRun() {
1523
+ if (process.env["NODE_ENV"] === "development") {
1524
+ console.warn(
1525
+ "Run cancellation is not supported by VercelRSCAssistantProvider."
1526
+ );
1527
+ }
1528
+ }
1529
+ updateData(messages) {
1530
+ this.messages = messages;
1531
+ for (const callback of this._subscriptions) callback();
1532
+ }
1533
+ subscribe(callback) {
1534
+ this._subscriptions.add(callback);
1535
+ return () => this._subscriptions.delete(callback);
1536
+ }
1537
+ };
1538
+
1539
+ // src/adapters/core/vercel-rsc/useVercelRSCRuntime.tsx
1452
1540
  var vercelToThreadMessage2 = (converter, rawMessage) => {
1453
1541
  const message = converter(rawMessage);
1454
1542
  return {
@@ -1460,227 +1548,61 @@ var vercelToThreadMessage2 = (converter, rawMessage) => {
1460
1548
  [symbolInnerRSCMessage]: rawMessage
1461
1549
  };
1462
1550
  };
1463
- var EMPTY_BRANCHES = [];
1464
- var getBranches = () => {
1465
- return EMPTY_BRANCHES;
1466
- };
1467
- var switchToBranch = () => {
1468
- throw new Error(
1469
- "Branch switching is not supported by VercelRSCAssistantProvider."
1470
- );
1471
- };
1472
- var cancelRun = () => {
1473
- if (process.env["NODE_ENV"] === "development") {
1474
- console.warn(
1475
- "Run cancellation is not supported by VercelRSCAssistantProvider."
1476
- );
1477
- }
1478
- };
1479
- var VercelRSCAssistantProvider = ({
1480
- children,
1481
- convertMessage,
1482
- messages: vercelMessages,
1483
- append: appendCallback,
1484
- edit,
1485
- reload
1486
- }) => {
1487
- const context = useDummyAIAssistantContext();
1488
- const [isRunning, setIsRunning] = useState5(false);
1489
- const withRunning = useCallback8((callback) => {
1490
- setIsRunning(true);
1491
- return callback.finally(() => setIsRunning(false));
1492
- }, []);
1493
- const [converter, convertCallback] = useMemo7(() => {
1494
- const rscConverter = convertMessage ?? ((m) => m);
1551
+ var useVercelRSCRuntime = (adapter) => {
1552
+ const [runtime] = useState5(() => new VercelRSCRuntime(adapter));
1553
+ useInsertionEffect3(() => {
1554
+ runtime.adapter = adapter;
1555
+ });
1556
+ const [converter, convertCallback] = useMemo6(() => {
1557
+ const rscConverter = adapter.convertMessage ?? ((m) => m);
1495
1558
  const convertCallback2 = (m, cache) => {
1496
1559
  if (cache) return cache;
1497
1560
  return vercelToThreadMessage2(rscConverter, m);
1498
1561
  };
1499
1562
  return [new ThreadMessageConverter(), convertCallback2];
1500
- }, [convertMessage]);
1501
- const messages = useMemo7(() => {
1502
- return converter.convertMessages(convertCallback, vercelMessages);
1503
- }, [converter, convertCallback, vercelMessages]);
1504
- const append = useCallback8(
1505
- async (message) => {
1506
- if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
1507
- if (!edit)
1508
- throw new Error(
1509
- "Message editing is not enabled, please provide an edit callback to VercelRSCAssistantProvider."
1510
- );
1511
- await withRunning(edit(message));
1512
- } else {
1513
- await withRunning(appendCallback(message));
1514
- }
1515
- },
1516
- [context, withRunning, appendCallback, edit]
1517
- );
1518
- const startRun = useCallback8(
1519
- async (parentId) => {
1520
- if (!reload)
1521
- throw new Error(
1522
- "Message reloading is not enabled, please provide a reload callback to VercelRSCAssistantProvider."
1523
- );
1524
- await withRunning(reload(parentId));
1525
- },
1526
- [withRunning, reload]
1527
- );
1528
- useMemo7(() => {
1529
- context.useThread.setState(
1530
- {
1531
- messages,
1532
- isRunning,
1533
- getBranches,
1534
- switchToBranch,
1535
- append,
1536
- startRun,
1537
- cancelRun
1538
- },
1539
- true
1563
+ }, [adapter.convertMessage]);
1564
+ useEffect7(() => {
1565
+ runtime.updateData(
1566
+ converter.convertMessages(convertCallback, adapter.messages)
1540
1567
  );
1541
- }, [context, messages, isRunning, append, startRun]);
1542
- return /* @__PURE__ */ jsx22(AssistantContext.Provider, { value: context, children });
1543
- };
1544
-
1545
- // src/adapters/core/utils/useAssistantContext.tsx
1546
- import {
1547
- useEffect as useEffect4,
1548
- useInsertionEffect,
1549
- useRef as useRef5,
1550
- useState as useState6
1551
- } from "react";
1552
- import { create as create6 } from "zustand";
1553
-
1554
- // src/adapters/core/utils/AssistantMessageRepository.tsx
1555
- var AssistantMessageRepository = class {
1556
- constructor(flushCallback) {
1557
- this.flushCallback = flushCallback;
1558
- }
1559
- repository = new MessageRepository();
1560
- getBranches(messageId) {
1561
- return this.repository.getBranches(messageId);
1562
- }
1563
- withModifications(callback) {
1564
- const res = callback(this.repository);
1565
- this.flushCallback(this.repository.getMessages());
1566
- return res;
1567
- }
1568
- };
1569
-
1570
- // src/adapters/core/utils/useAssistantContext.tsx
1571
- var makeThreadStore = (runtimeRef) => {
1572
- const repository = new AssistantMessageRepository((messages) => {
1573
- useThread.setState({ messages });
1574
- });
1575
- const useThread = create6(() => ({
1576
- messages: [],
1577
- isRunning: false,
1578
- getBranches: (messageId) => repository.getBranches(messageId),
1579
- switchToBranch: (branchId) => {
1580
- repository.withModifications((repository2) => {
1581
- repository2.switchToBranch(branchId);
1582
- });
1583
- },
1584
- startRun: async (parentId) => {
1585
- const optimisticId = repository.withModifications((repository2) => {
1586
- const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
1587
- role: "assistant",
1588
- content: [{ type: "text", text: "" }]
1589
- });
1590
- repository2.resetHead(optimisticId2);
1591
- return optimisticId2;
1592
- });
1593
- const { id } = await runtimeRef.current.startRun(parentId);
1594
- repository.withModifications((repository2) => {
1595
- repository2.deleteMessage(optimisticId, id);
1596
- });
1597
- },
1598
- append: async (message) => {
1599
- const [parentOptimisticId, optimisticId] = repository.withModifications(
1600
- (repository2) => {
1601
- const parentOptimisticId2 = repository2.appendOptimisticMessage(
1602
- message.parentId,
1603
- {
1604
- role: "user",
1605
- content: message.content
1606
- }
1607
- );
1608
- const optimisticId2 = repository2.appendOptimisticMessage(
1609
- parentOptimisticId2,
1610
- {
1611
- role: "assistant",
1612
- content: [{ type: "text", text: "" }]
1613
- }
1614
- );
1615
- repository2.resetHead(optimisticId2);
1616
- return [parentOptimisticId2, optimisticId2];
1617
- }
1618
- );
1619
- const { parentId, id } = await runtimeRef.current.append(message);
1620
- repository.withModifications((repository2) => {
1621
- repository2.deleteMessage(parentOptimisticId, parentId);
1622
- repository2.deleteMessage(optimisticId, id);
1623
- });
1624
- },
1625
- cancelRun: () => runtimeRef.current.cancelRun()
1626
- }));
1627
- const onNewMessage = (parentId, message) => {
1628
- repository.withModifications((repository2) => {
1629
- repository2.addOrUpdateMessage(parentId, message);
1630
- });
1631
- };
1632
- const onRunningChange = (isRunning) => {
1633
- useThread.setState({ isRunning });
1634
- };
1635
- return {
1636
- useThread,
1637
- onNewMessage,
1638
- onRunningChange
1639
- };
1640
- };
1641
- var useAssistantContext2 = (runtime) => {
1642
- const runtimeRef = useRef5(runtime);
1643
- useInsertionEffect(() => {
1644
- runtimeRef.current = runtime;
1645
- });
1646
- const [{ context, onNewMessage, onRunningChange }] = useState6(() => {
1647
- const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
1648
- const useViewport = makeViewportStore();
1649
- const useComposer = makeThreadComposerStore(useThread);
1650
- return {
1651
- context: { useViewport, useThread, useComposer },
1652
- onNewMessage: onNewMessage2,
1653
- onRunningChange: onRunningChange2
1654
- };
1655
- });
1656
- useEffect4(() => {
1657
- return runtime.subscribeToMessageUpdates(onNewMessage);
1658
- }, [runtime, onNewMessage]);
1659
- useEffect4(() => {
1660
- return runtime.subscribeToStatusUpdates(onRunningChange);
1661
- }, [runtime, onRunningChange]);
1662
- return context;
1568
+ }, [runtime, converter, convertCallback, adapter.messages]);
1569
+ return runtime;
1663
1570
  };
1664
1571
 
1665
- // src/adapters/core/AssistantProvider.tsx
1572
+ // src/adapters/vercel/VercelRSCAssistantProvider.tsx
1666
1573
  import { jsx as jsx23 } from "react/jsx-runtime";
1667
- var AssistantProvider = ({ children, runtime }) => {
1668
- const context = useAssistantContext2(runtime);
1669
- return /* @__PURE__ */ jsx23(AssistantContext.Provider, { value: context, children });
1574
+ var VercelRSCAssistantProvider = ({
1575
+ children,
1576
+ ...adapter
1577
+ }) => {
1578
+ const runtime = useVercelRSCRuntime(adapter);
1579
+ return /* @__PURE__ */ jsx23(AssistantProvider, { runtime, children });
1670
1580
  };
1671
1581
 
1672
1582
  // src/adapters/core/local/useLocalRuntime.tsx
1673
- import { useState as useState7 } from "react";
1583
+ import { useInsertionEffect as useInsertionEffect4, useState as useState6 } from "react";
1674
1584
 
1675
1585
  // src/adapters/core/local/LocalRuntime.tsx
1676
1586
  var LocalRuntime = class {
1677
1587
  constructor(adapter) {
1678
1588
  this.adapter = adapter;
1679
1589
  }
1680
- _messageUpdateCallbacks = /* @__PURE__ */ new Set();
1681
- _statusUpdateCallbacks = /* @__PURE__ */ new Set();
1590
+ _subscriptions = /* @__PURE__ */ new Set();
1682
1591
  abortController = null;
1683
1592
  repository = new MessageRepository();
1593
+ get messages() {
1594
+ return this.repository.getMessages();
1595
+ }
1596
+ get isRunning() {
1597
+ return this.abortController != null;
1598
+ }
1599
+ getBranches(messageId) {
1600
+ return this.repository.getBranches(messageId);
1601
+ }
1602
+ switchToBranch(branchId) {
1603
+ this.repository.switchToBranch(branchId);
1604
+ this.notifySubscribers();
1605
+ }
1684
1606
  async append(message) {
1685
1607
  const userMessageId = generateId();
1686
1608
  const userMessage = {
@@ -1689,9 +1611,8 @@ var LocalRuntime = class {
1689
1611
  content: message.content,
1690
1612
  createdAt: /* @__PURE__ */ new Date()
1691
1613
  };
1692
- this.addOrUpdateMessage(message.parentId, userMessage);
1693
- const { id } = await this.startRun(userMessageId);
1694
- return { parentId: userMessageId, id };
1614
+ this.repository.addOrUpdateMessage(message.parentId, userMessage);
1615
+ await this.startRun(userMessageId);
1695
1616
  }
1696
1617
  async startRun(parentId) {
1697
1618
  const id = generateId();
@@ -1704,59 +1625,52 @@ var LocalRuntime = class {
1704
1625
  content: [{ type: "text", text: "" }],
1705
1626
  createdAt: /* @__PURE__ */ new Date()
1706
1627
  };
1707
- this.addOrUpdateMessage(parentId, message);
1708
- void this.run(parentId, messages, message);
1709
- return { id };
1710
- }
1711
- addOrUpdateMessage(parentId, message) {
1712
- const clone = { ...message };
1713
- this.repository.addOrUpdateMessage(parentId, clone);
1714
- for (const callback of this._messageUpdateCallbacks)
1715
- callback(parentId, clone);
1716
- }
1717
- async run(parentId, messages, message) {
1718
- this.cancelRun();
1719
- for (const callback of this._statusUpdateCallbacks) callback(true);
1628
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1629
+ this.abortController?.abort();
1720
1630
  this.abortController = new AbortController();
1631
+ this.notifySubscribers();
1721
1632
  try {
1722
1633
  await this.adapter.run({
1723
1634
  messages,
1724
1635
  abortSignal: this.abortController.signal,
1725
1636
  onUpdate: ({ content }) => {
1726
1637
  message.content = content;
1727
- this.addOrUpdateMessage(parentId, message);
1638
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1639
+ this.notifySubscribers();
1728
1640
  }
1729
1641
  });
1730
1642
  message.status = "done";
1731
- this.addOrUpdateMessage(parentId, message);
1643
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1732
1644
  } catch (e) {
1733
1645
  message.status = "error";
1734
- this.addOrUpdateMessage(parentId, message);
1646
+ this.repository.addOrUpdateMessage(parentId, { ...message });
1735
1647
  console.error(e);
1736
1648
  } finally {
1737
- this.cancelRun();
1649
+ this.abortController = null;
1650
+ this.notifySubscribers();
1738
1651
  }
1739
1652
  }
1740
1653
  cancelRun() {
1741
1654
  if (!this.abortController) return;
1742
1655
  this.abortController.abort();
1743
1656
  this.abortController = null;
1744
- for (const callback of this._statusUpdateCallbacks) callback(false);
1657
+ this.notifySubscribers();
1745
1658
  }
1746
- subscribeToMessageUpdates(callback) {
1747
- this._messageUpdateCallbacks.add(callback);
1748
- return () => this._messageUpdateCallbacks.delete(callback);
1659
+ notifySubscribers() {
1660
+ for (const callback of this._subscriptions) callback();
1749
1661
  }
1750
- subscribeToStatusUpdates(callback) {
1751
- this._statusUpdateCallbacks.add(callback);
1752
- return () => this._statusUpdateCallbacks.delete(callback);
1662
+ subscribe(callback) {
1663
+ this._subscriptions.add(callback);
1664
+ return () => this._subscriptions.delete(callback);
1753
1665
  }
1754
1666
  };
1755
1667
 
1756
1668
  // src/adapters/core/local/useLocalRuntime.tsx
1757
1669
  var useLocalRuntime = (adapter) => {
1758
- const [runtime] = useState7(() => new LocalRuntime(adapter));
1759
- runtime.adapter = adapter;
1670
+ const [runtime] = useState6(() => new LocalRuntime(adapter));
1671
+ useInsertionEffect4(() => {
1672
+ runtime.adapter = adapter;
1673
+ });
1760
1674
  return runtime;
1761
1675
  };
1762
1676