@assistant-ui/react 0.0.16 → 0.0.18
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.d.mts +78 -9
- package/dist/index.d.ts +78 -9
- package/dist/index.js +403 -123
- package/dist/index.mjs +411 -136
- package/package.json +2 -1
package/dist/index.js
CHANGED
@@ -38,6 +38,11 @@ __export(src_exports, {
|
|
38
38
|
ThreadPrimitive: () => thread_exports,
|
39
39
|
VercelAIAssistantProvider: () => VercelAIAssistantProvider,
|
40
40
|
VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
|
41
|
+
unstable_AssistantProvider: () => AssistantProvider,
|
42
|
+
unstable_VercelModelAdapter: () => VercelModelAdapter,
|
43
|
+
unstable_getVercelMessage: () => getVercelMessage,
|
44
|
+
unstable_getVercelRSCMessage: () => getVercelRSCMessage,
|
45
|
+
unstable_useLocalRuntime: () => useLocalRuntime,
|
41
46
|
unstable_useMessageContext: () => useMessageContext,
|
42
47
|
useBeginMessageEdit: () => useBeginMessageEdit,
|
43
48
|
useCopyMessage: () => useCopyMessage,
|
@@ -110,15 +115,15 @@ var import_react_primitive2 = require("@radix-ui/react-primitive");
|
|
110
115
|
var import_react5 = require("react");
|
111
116
|
|
112
117
|
// src/utils/hooks/useOnResizeContent.tsx
|
118
|
+
var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
|
113
119
|
var import_react3 = require("react");
|
114
120
|
var useOnResizeContent = (ref, callback) => {
|
115
|
-
const callbackRef = (0,
|
116
|
-
callbackRef.current = callback;
|
121
|
+
const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
|
117
122
|
(0, import_react3.useEffect)(() => {
|
118
123
|
const el = ref.current;
|
119
124
|
if (!el) return;
|
120
125
|
const resizeObserver = new ResizeObserver(() => {
|
121
|
-
callbackRef
|
126
|
+
callbackRef();
|
122
127
|
});
|
123
128
|
const mutationObserver = new MutationObserver((mutations) => {
|
124
129
|
for (const mutation of mutations) {
|
@@ -133,7 +138,7 @@ var useOnResizeContent = (ref, callback) => {
|
|
133
138
|
}
|
134
139
|
}
|
135
140
|
}
|
136
|
-
callbackRef
|
141
|
+
callbackRef();
|
137
142
|
});
|
138
143
|
resizeObserver.observe(el);
|
139
144
|
mutationObserver.observe(el, { childList: true });
|
@@ -144,20 +149,20 @@ var useOnResizeContent = (ref, callback) => {
|
|
144
149
|
resizeObserver.disconnect();
|
145
150
|
mutationObserver.disconnect();
|
146
151
|
};
|
147
|
-
}, [ref.current]);
|
152
|
+
}, [ref.current, callbackRef]);
|
148
153
|
};
|
149
154
|
|
150
155
|
// src/utils/hooks/useOnScrollToBottom.tsx
|
156
|
+
var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
|
151
157
|
var import_react4 = require("react");
|
152
158
|
var useOnScrollToBottom = (callback) => {
|
153
|
-
const callbackRef = (0,
|
154
|
-
callbackRef.current = callback;
|
159
|
+
const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
|
155
160
|
const { useViewport } = useAssistantContext();
|
156
161
|
(0, import_react4.useEffect)(() => {
|
157
162
|
return useViewport.getState().onScrollToBottom(() => {
|
158
|
-
callbackRef
|
163
|
+
callbackRef();
|
159
164
|
});
|
160
|
-
}, [useViewport]);
|
165
|
+
}, [useViewport, callbackRef]);
|
161
166
|
};
|
162
167
|
|
163
168
|
// src/primitives/thread/ThreadViewport.tsx
|
@@ -253,7 +258,7 @@ var message_exports = {};
|
|
253
258
|
__export(message_exports, {
|
254
259
|
Content: () => MessageContent,
|
255
260
|
If: () => MessageIf,
|
256
|
-
|
261
|
+
InProgress: () => MessageInProgress,
|
257
262
|
Provider: () => MessageProvider,
|
258
263
|
Root: () => MessageRoot
|
259
264
|
});
|
@@ -333,11 +338,11 @@ var useMessageContext2 = () => {
|
|
333
338
|
parentId: null,
|
334
339
|
branches: [],
|
335
340
|
isLast: false,
|
336
|
-
|
341
|
+
inProgressIndicator: null,
|
337
342
|
isCopied: false,
|
338
343
|
isHovering: false,
|
339
|
-
|
340
|
-
set({
|
344
|
+
setInProgressIndicator: (value) => {
|
345
|
+
set({ inProgressIndicator: value });
|
341
346
|
},
|
342
347
|
setIsCopied: (value) => {
|
343
348
|
set({ isCopied: value });
|
@@ -478,15 +483,15 @@ var useContentPartContext = () => {
|
|
478
483
|
return context;
|
479
484
|
};
|
480
485
|
|
481
|
-
// src/primitives/contentPart/
|
482
|
-
var
|
486
|
+
// src/primitives/contentPart/ContentPartInProgressIndicator.tsx
|
487
|
+
var ContentPartInProgressIndicator = () => {
|
483
488
|
const { useMessage } = useMessageContext();
|
484
489
|
const { useContentPart } = useContentPartContext();
|
485
|
-
const
|
490
|
+
const indicator = useCombinedStore(
|
486
491
|
[useMessage, useContentPart],
|
487
|
-
(m, c) => c.
|
492
|
+
(m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
|
488
493
|
);
|
489
|
-
return
|
494
|
+
return indicator;
|
490
495
|
};
|
491
496
|
|
492
497
|
// src/primitives/contentPart/ContentPartProvider.tsx
|
@@ -497,7 +502,7 @@ var useContentPartContext2 = () => {
|
|
497
502
|
const [context] = (0, import_react13.useState)(() => {
|
498
503
|
const useContentPart = (0, import_zustand3.create)(() => ({
|
499
504
|
part: null,
|
500
|
-
|
505
|
+
status: "done"
|
501
506
|
}));
|
502
507
|
return { useContentPart };
|
503
508
|
});
|
@@ -505,7 +510,7 @@ var useContentPartContext2 = () => {
|
|
505
510
|
};
|
506
511
|
var ContentPartProvider = ({
|
507
512
|
part,
|
508
|
-
|
513
|
+
status,
|
509
514
|
children
|
510
515
|
}) => {
|
511
516
|
const context = useContentPartContext2();
|
@@ -513,11 +518,11 @@ var ContentPartProvider = ({
|
|
513
518
|
context.useContentPart.setState(
|
514
519
|
{
|
515
520
|
part,
|
516
|
-
|
521
|
+
status
|
517
522
|
},
|
518
523
|
true
|
519
524
|
);
|
520
|
-
}, [context, part,
|
525
|
+
}, [context, part, status]);
|
521
526
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ContentPartContext.Provider, { value: context, children });
|
522
527
|
};
|
523
528
|
|
@@ -526,7 +531,7 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
526
531
|
var defaultComponents = {
|
527
532
|
Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
528
533
|
part.text,
|
529
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
534
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContentPartInProgressIndicator, {})
|
530
535
|
] }),
|
531
536
|
Image: () => null,
|
532
537
|
UI: ({ part }) => part.display,
|
@@ -542,13 +547,10 @@ var MessageContent = ({
|
|
542
547
|
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
543
548
|
} = {}
|
544
549
|
}) => {
|
545
|
-
const { useThread } = useAssistantContext();
|
546
550
|
const { useMessage } = useMessageContext();
|
547
|
-
const
|
548
|
-
const
|
549
|
-
|
550
|
-
(t, s) => s.isLast && t.isRunning
|
551
|
-
);
|
551
|
+
const message = useMessage((s) => s.message);
|
552
|
+
const content = message.content;
|
553
|
+
const status = message.role === "assistant" ? message.status : "done";
|
552
554
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: content.map((part, i) => {
|
553
555
|
const key = i;
|
554
556
|
const type = part.type;
|
@@ -575,7 +577,7 @@ var MessageContent = ({
|
|
575
577
|
ContentPartProvider,
|
576
578
|
{
|
577
579
|
part,
|
578
|
-
|
580
|
+
status: i === content.length - 1 ? status : "done",
|
579
581
|
children: component
|
580
582
|
},
|
581
583
|
key
|
@@ -583,14 +585,14 @@ var MessageContent = ({
|
|
583
585
|
}) });
|
584
586
|
};
|
585
587
|
|
586
|
-
// src/primitives/message/
|
588
|
+
// src/primitives/message/MessageInProgress.tsx
|
587
589
|
var import_react_primitive4 = require("@radix-ui/react-primitive");
|
588
590
|
var import_react14 = require("react");
|
589
591
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
590
|
-
var
|
592
|
+
var MessageInProgress = (0, import_react14.forwardRef)((props, ref) => {
|
591
593
|
const { useMessage } = useMessageContext();
|
592
594
|
(0, import_react14.useMemo)(() => {
|
593
|
-
useMessage.getState().
|
595
|
+
useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_primitive4.Primitive.div, { ...props, ref }));
|
594
596
|
}, [useMessage, props, ref]);
|
595
597
|
return null;
|
596
598
|
});
|
@@ -892,7 +894,6 @@ var useGoToPreviousBranch = () => {
|
|
892
894
|
const { message, branches } = useMessage.getState();
|
893
895
|
useThread.getState().switchToBranch(
|
894
896
|
branches[branches.indexOf(message.id) - 1]
|
895
|
-
// TODO probably there's a more elegant way to do this
|
896
897
|
);
|
897
898
|
};
|
898
899
|
};
|
@@ -1025,7 +1026,7 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
|
1025
1026
|
// src/primitives/contentPart/index.ts
|
1026
1027
|
var contentPart_exports = {};
|
1027
1028
|
__export(contentPart_exports, {
|
1028
|
-
|
1029
|
+
InProgressIndicator: () => ContentPartInProgressIndicator,
|
1029
1030
|
Provider: () => ContentPartProvider
|
1030
1031
|
});
|
1031
1032
|
|
@@ -1089,9 +1090,10 @@ var useDummyAIAssistantContext = () => {
|
|
1089
1090
|
};
|
1090
1091
|
|
1091
1092
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1093
|
+
var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
|
1092
1094
|
var import_react25 = require("react");
|
1093
1095
|
|
1094
|
-
// src/adapters/
|
1096
|
+
// src/adapters/idUtils.tsx
|
1095
1097
|
var import_non_secure = require("nanoid/non-secure");
|
1096
1098
|
var generateId = (0, import_non_secure.customAlphabet)(
|
1097
1099
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
@@ -1099,7 +1101,8 @@ var generateId = (0, import_non_secure.customAlphabet)(
|
|
1099
1101
|
);
|
1100
1102
|
var optimisticPrefix = "__optimistic__";
|
1101
1103
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1102
|
-
|
1104
|
+
|
1105
|
+
// src/adapters/MessageRepository.tsx
|
1103
1106
|
var findHead = (message) => {
|
1104
1107
|
if (message.next) return findHead(message.next);
|
1105
1108
|
return message;
|
@@ -1111,15 +1114,6 @@ var MessageRepository = class {
|
|
1111
1114
|
root = {
|
1112
1115
|
children: []
|
1113
1116
|
};
|
1114
|
-
getFallbackChild(p) {
|
1115
|
-
const childId = p.children.at(-1);
|
1116
|
-
const child = childId ? this.messages.get(childId) : null;
|
1117
|
-
if (child === void 0)
|
1118
|
-
throw new Error(
|
1119
|
-
"MessageRepository(getFallbackChild): Child message not found. This is likely an internal bug in assistant-ui."
|
1120
|
-
);
|
1121
|
-
return child;
|
1122
|
-
}
|
1123
1117
|
performOp(newParent, child, operation) {
|
1124
1118
|
const parentOrRoot = child.prev ?? this.root;
|
1125
1119
|
const newParentOrRoot = newParent ?? this.root;
|
@@ -1129,7 +1123,14 @@ var MessageRepository = class {
|
|
1129
1123
|
(m) => m !== child.current.id
|
1130
1124
|
);
|
1131
1125
|
if (child.prev?.next === child) {
|
1132
|
-
child.prev.
|
1126
|
+
const fallbackId = child.prev.children.at(-1);
|
1127
|
+
const fallback = fallbackId ? this.messages.get(fallbackId) : null;
|
1128
|
+
if (fallback === void 0) {
|
1129
|
+
throw new Error(
|
1130
|
+
"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
|
1131
|
+
);
|
1132
|
+
}
|
1133
|
+
child.prev.next = fallback;
|
1133
1134
|
}
|
1134
1135
|
}
|
1135
1136
|
if (operation !== "cut") {
|
@@ -1183,18 +1184,19 @@ var MessageRepository = class {
|
|
1183
1184
|
this.addOrUpdateMessage(parentId, {
|
1184
1185
|
...message,
|
1185
1186
|
id: optimisticId,
|
1186
|
-
createdAt: /* @__PURE__ */ new Date()
|
1187
|
+
createdAt: /* @__PURE__ */ new Date(),
|
1188
|
+
...message.role === "assistant" ? { status: "in_progress" } : void 0
|
1187
1189
|
});
|
1188
1190
|
return optimisticId;
|
1189
1191
|
}
|
1190
|
-
deleteMessage(messageId,
|
1192
|
+
deleteMessage(messageId, replacementId) {
|
1191
1193
|
const message = this.messages.get(messageId);
|
1192
|
-
const
|
1194
|
+
const replacement = replacementId ? this.messages.get(replacementId) : null;
|
1193
1195
|
if (!message)
|
1194
1196
|
throw new Error(
|
1195
1197
|
"MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
|
1196
1198
|
);
|
1197
|
-
if (
|
1199
|
+
if (replacement === void 0)
|
1198
1200
|
throw new Error(
|
1199
1201
|
"MessageRepository(deleteMessage): New message not found. This is likely an internal bug in assistant-ui."
|
1200
1202
|
);
|
@@ -1204,11 +1206,11 @@ var MessageRepository = class {
|
|
1204
1206
|
throw new Error(
|
1205
1207
|
"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
|
1206
1208
|
);
|
1207
|
-
this.performOp(
|
1209
|
+
this.performOp(replacement, childMessage, "relink");
|
1208
1210
|
}
|
1209
1211
|
this.messages.delete(messageId);
|
1210
1212
|
if (this.head === message) {
|
1211
|
-
this.head =
|
1213
|
+
this.head = replacement;
|
1212
1214
|
}
|
1213
1215
|
this.performOp(null, message, "cut");
|
1214
1216
|
}
|
@@ -1251,50 +1253,68 @@ var MessageRepository = class {
|
|
1251
1253
|
}
|
1252
1254
|
};
|
1253
1255
|
|
1254
|
-
// src/adapters/ThreadMessageConverter.
|
1256
|
+
// src/adapters/ThreadMessageConverter.ts
|
1255
1257
|
var ThreadMessageConverter = class {
|
1256
|
-
constructor(converter2) {
|
1257
|
-
this.converter = converter2;
|
1258
|
-
}
|
1259
1258
|
cache = /* @__PURE__ */ new WeakMap();
|
1260
|
-
convertMessages(messages) {
|
1259
|
+
convertMessages(converter, messages) {
|
1261
1260
|
return messages.map((m) => {
|
1262
1261
|
const cached = this.cache.get(m);
|
1263
|
-
|
1264
|
-
const newMessage = this.converter(m);
|
1262
|
+
const newMessage = converter(m, cached);
|
1265
1263
|
this.cache.set(m, newMessage);
|
1266
1264
|
return newMessage;
|
1267
1265
|
});
|
1268
1266
|
}
|
1269
1267
|
};
|
1270
1268
|
|
1269
|
+
// src/adapters/vercel/VercelThreadMessage.tsx
|
1270
|
+
var symbolInnerMessage = Symbol("innerMessage");
|
1271
|
+
var symbolInnerRSCMessage = Symbol("innerRSCMessage");
|
1272
|
+
var getVercelMessage = (message) => {
|
1273
|
+
return message[symbolInnerMessage];
|
1274
|
+
};
|
1275
|
+
var getVercelRSCMessage = (message) => {
|
1276
|
+
return message[symbolInnerRSCMessage];
|
1277
|
+
};
|
1278
|
+
|
1271
1279
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1272
|
-
var vercelToThreadMessage = (message) => {
|
1273
|
-
|
1274
|
-
throw new Error(
|
1275
|
-
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1276
|
-
);
|
1277
|
-
return {
|
1280
|
+
var vercelToThreadMessage = (message, status) => {
|
1281
|
+
const common = {
|
1278
1282
|
id: message.id,
|
1279
|
-
role: message.role,
|
1280
|
-
content: [
|
1281
|
-
...message.content ? [{ type: "text", text: message.content }] : [],
|
1282
|
-
...message.toolInvocations?.map((t) => ({
|
1283
|
-
type: "tool-call",
|
1284
|
-
name: t.toolName,
|
1285
|
-
args: t.args,
|
1286
|
-
result: "result" in t ? t.result : void 0
|
1287
|
-
})) ?? []
|
1288
|
-
],
|
1289
|
-
// ignore type mismatch for now
|
1290
1283
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1291
|
-
|
1284
|
+
[symbolInnerMessage]: message
|
1292
1285
|
};
|
1286
|
+
switch (message.role) {
|
1287
|
+
case "user":
|
1288
|
+
return {
|
1289
|
+
...common,
|
1290
|
+
role: "user",
|
1291
|
+
content: [{ type: "text", text: message.content }]
|
1292
|
+
};
|
1293
|
+
case "assistant":
|
1294
|
+
return {
|
1295
|
+
...common,
|
1296
|
+
role: "assistant",
|
1297
|
+
content: [
|
1298
|
+
...message.content ? [{ type: "text", text: message.content }] : [],
|
1299
|
+
...message.toolInvocations?.map(
|
1300
|
+
(t) => ({
|
1301
|
+
type: "tool-call",
|
1302
|
+
name: t.toolName,
|
1303
|
+
args: t.args,
|
1304
|
+
result: "result" in t ? t.result : void 0
|
1305
|
+
})
|
1306
|
+
) ?? []
|
1307
|
+
],
|
1308
|
+
status
|
1309
|
+
};
|
1310
|
+
default:
|
1311
|
+
throw new Error(
|
1312
|
+
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1313
|
+
);
|
1314
|
+
}
|
1293
1315
|
};
|
1294
|
-
var converter = new ThreadMessageConverter(vercelToThreadMessage);
|
1295
1316
|
var sliceMessagesUntil = (messages, messageId) => {
|
1296
1317
|
if (messageId == null) return [];
|
1297
|
-
if (isOptimisticId(messageId)) return messages;
|
1298
1318
|
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1299
1319
|
if (messageIdx === -1)
|
1300
1320
|
throw new Error(
|
@@ -1311,12 +1331,18 @@ var getIsRunning = (vercel) => {
|
|
1311
1331
|
};
|
1312
1332
|
var useVercelAIThreadState = (vercel) => {
|
1313
1333
|
const [data] = (0, import_react25.useState)(() => new MessageRepository());
|
1314
|
-
const
|
1315
|
-
|
1316
|
-
const isRunning = getIsRunning(vercelRef.current);
|
1334
|
+
const isRunning = getIsRunning(vercel);
|
1335
|
+
const converter = (0, import_react25.useMemo)(() => new ThreadMessageConverter(), []);
|
1317
1336
|
const assistantOptimisticIdRef = (0, import_react25.useRef)(null);
|
1318
1337
|
const messages = (0, import_react25.useMemo)(() => {
|
1319
|
-
const
|
1338
|
+
const lastMessageId = vercel.messages.at(-1)?.id;
|
1339
|
+
const convertCallback = (message, cache) => {
|
1340
|
+
const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
|
1341
|
+
if (cache && (cache.role === "user" || cache.status === status))
|
1342
|
+
return cache;
|
1343
|
+
return vercelToThreadMessage(message, status);
|
1344
|
+
};
|
1345
|
+
const vm = converter.convertMessages(convertCallback, vercel.messages);
|
1320
1346
|
for (let i = 0; i < vm.length; i++) {
|
1321
1347
|
const message = vm[i];
|
1322
1348
|
const parent = vm[i - 1];
|
@@ -1337,55 +1363,46 @@ var useVercelAIThreadState = (vercel) => {
|
|
1337
1363
|
}
|
1338
1364
|
data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
|
1339
1365
|
return data.getMessages();
|
1340
|
-
}, [data, isRunning, vercel.messages]);
|
1366
|
+
}, [converter, data, isRunning, vercel.messages]);
|
1341
1367
|
const getBranches2 = (0, import_react25.useCallback)(
|
1342
1368
|
(messageId) => {
|
1343
1369
|
return data.getBranches(messageId);
|
1344
1370
|
},
|
1345
1371
|
[data]
|
1346
1372
|
);
|
1347
|
-
const switchToBranch2 = (0,
|
1348
|
-
(messageId)
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
);
|
1356
|
-
const startRun = (0, import_react25.useCallback)(async (parentId) => {
|
1357
|
-
const reloadMaybe = "reload" in vercelRef.current ? vercelRef.current.reload : void 0;
|
1373
|
+
const switchToBranch2 = (0, import_react_use_callback_ref3.useCallbackRef)((messageId) => {
|
1374
|
+
data.switchToBranch(messageId);
|
1375
|
+
vercel.setMessages(
|
1376
|
+
data.getMessages().map(getVercelMessage).filter((m) => m != null)
|
1377
|
+
);
|
1378
|
+
});
|
1379
|
+
const startRun = (0, import_react_use_callback_ref3.useCallbackRef)(async (parentId) => {
|
1380
|
+
const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
|
1358
1381
|
if (!reloadMaybe)
|
1359
1382
|
throw new Error(
|
1360
1383
|
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1361
1384
|
);
|
1362
|
-
const newMessages = sliceMessagesUntil(
|
1363
|
-
|
1364
|
-
parentId
|
1365
|
-
);
|
1366
|
-
vercelRef.current.setMessages(newMessages);
|
1385
|
+
const newMessages = sliceMessagesUntil(vercel.messages, parentId);
|
1386
|
+
vercel.setMessages(newMessages);
|
1367
1387
|
await reloadMaybe();
|
1368
|
-
}
|
1369
|
-
const append = (0,
|
1388
|
+
});
|
1389
|
+
const append = (0, import_react_use_callback_ref3.useCallbackRef)(async (message) => {
|
1370
1390
|
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1371
1391
|
throw new Error("Only text content is supported by Vercel AI SDK.");
|
1372
|
-
const newMessages = sliceMessagesUntil(
|
1373
|
-
|
1374
|
-
|
1375
|
-
);
|
1376
|
-
vercelRef.current.setMessages(newMessages);
|
1377
|
-
await vercelRef.current.append({
|
1392
|
+
const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
|
1393
|
+
vercel.setMessages(newMessages);
|
1394
|
+
await vercel.append({
|
1378
1395
|
role: "user",
|
1379
1396
|
content: message.content[0].text
|
1380
1397
|
});
|
1381
|
-
}
|
1382
|
-
const cancelRun2 = (0,
|
1383
|
-
const lastMessage =
|
1384
|
-
|
1398
|
+
});
|
1399
|
+
const cancelRun2 = (0, import_react_use_callback_ref3.useCallbackRef)(() => {
|
1400
|
+
const lastMessage = vercel.messages.at(-1);
|
1401
|
+
vercel.stop();
|
1385
1402
|
if (lastMessage?.role === "user") {
|
1386
|
-
|
1403
|
+
vercel.setInput(lastMessage.content);
|
1387
1404
|
}
|
1388
|
-
}
|
1405
|
+
});
|
1389
1406
|
return (0, import_react25.useMemo)(
|
1390
1407
|
() => ({
|
1391
1408
|
isRunning,
|
@@ -1432,12 +1449,15 @@ var VercelAIAssistantProvider = ({
|
|
1432
1449
|
// src/adapters/vercel/VercelRSCAssistantProvider.tsx
|
1433
1450
|
var import_react27 = require("react");
|
1434
1451
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
1435
|
-
var vercelToThreadMessage2 = (
|
1452
|
+
var vercelToThreadMessage2 = (converter, rawMessage) => {
|
1453
|
+
const message = converter(rawMessage);
|
1436
1454
|
return {
|
1437
1455
|
id: message.id,
|
1438
1456
|
role: message.role,
|
1439
1457
|
content: [{ type: "ui", display: message.display }],
|
1440
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1458
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1459
|
+
...{ status: "done" },
|
1460
|
+
[symbolInnerRSCMessage]: rawMessage
|
1441
1461
|
};
|
1442
1462
|
};
|
1443
1463
|
var EMPTY_BRANCHES = [];
|
@@ -1470,15 +1490,17 @@ var VercelRSCAssistantProvider = ({
|
|
1470
1490
|
setIsRunning(true);
|
1471
1491
|
return callback.finally(() => setIsRunning(false));
|
1472
1492
|
}, []);
|
1473
|
-
const
|
1493
|
+
const [converter, convertCallback] = (0, import_react27.useMemo)(() => {
|
1474
1494
|
const rscConverter = convertMessage ?? ((m) => m);
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1495
|
+
const convertCallback2 = (m, cache) => {
|
1496
|
+
if (cache) return cache;
|
1497
|
+
return vercelToThreadMessage2(rscConverter, m);
|
1498
|
+
};
|
1499
|
+
return [new ThreadMessageConverter(), convertCallback2];
|
1478
1500
|
}, [convertMessage]);
|
1479
1501
|
const messages = (0, import_react27.useMemo)(() => {
|
1480
|
-
return
|
1481
|
-
}, [
|
1502
|
+
return converter.convertMessages(convertCallback, vercelMessages);
|
1503
|
+
}, [converter, convertCallback, vercelMessages]);
|
1482
1504
|
const append = (0, import_react27.useCallback)(
|
1483
1505
|
async (message) => {
|
1484
1506
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
@@ -1519,6 +1541,259 @@ var VercelRSCAssistantProvider = ({
|
|
1519
1541
|
}, [context, messages, isRunning, append, startRun]);
|
1520
1542
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AssistantContext.Provider, { value: context, children });
|
1521
1543
|
};
|
1544
|
+
|
1545
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1546
|
+
var import_react28 = require("react");
|
1547
|
+
var import_zustand6 = require("zustand");
|
1548
|
+
|
1549
|
+
// src/adapters/core/utils/AssistantMessageRepository.tsx
|
1550
|
+
var AssistantMessageRepository = class {
|
1551
|
+
constructor(flushCallback) {
|
1552
|
+
this.flushCallback = flushCallback;
|
1553
|
+
}
|
1554
|
+
repository = new MessageRepository();
|
1555
|
+
getBranches(messageId) {
|
1556
|
+
return this.repository.getBranches(messageId);
|
1557
|
+
}
|
1558
|
+
withModifications(callback) {
|
1559
|
+
const res = callback(this.repository);
|
1560
|
+
this.flushCallback(this.repository.getMessages());
|
1561
|
+
return res;
|
1562
|
+
}
|
1563
|
+
};
|
1564
|
+
|
1565
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1566
|
+
var makeThreadStore = (runtimeRef) => {
|
1567
|
+
const repository = new AssistantMessageRepository((messages) => {
|
1568
|
+
useThread.setState({ messages });
|
1569
|
+
});
|
1570
|
+
const useThread = (0, import_zustand6.create)(() => ({
|
1571
|
+
messages: [],
|
1572
|
+
isRunning: false,
|
1573
|
+
getBranches: (messageId) => repository.getBranches(messageId),
|
1574
|
+
switchToBranch: (branchId) => {
|
1575
|
+
repository.withModifications((repository2) => {
|
1576
|
+
repository2.switchToBranch(branchId);
|
1577
|
+
});
|
1578
|
+
},
|
1579
|
+
startRun: async (parentId) => {
|
1580
|
+
const optimisticId = repository.withModifications((repository2) => {
|
1581
|
+
const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
|
1582
|
+
role: "assistant",
|
1583
|
+
content: [{ type: "text", text: "" }]
|
1584
|
+
});
|
1585
|
+
repository2.resetHead(optimisticId2);
|
1586
|
+
return optimisticId2;
|
1587
|
+
});
|
1588
|
+
const { id } = await runtimeRef.current.startRun(parentId);
|
1589
|
+
repository.withModifications((repository2) => {
|
1590
|
+
repository2.deleteMessage(optimisticId, id);
|
1591
|
+
});
|
1592
|
+
},
|
1593
|
+
append: async (message) => {
|
1594
|
+
const [parentOptimisticId, optimisticId] = repository.withModifications(
|
1595
|
+
(repository2) => {
|
1596
|
+
const parentOptimisticId2 = repository2.appendOptimisticMessage(
|
1597
|
+
message.parentId,
|
1598
|
+
{
|
1599
|
+
role: "user",
|
1600
|
+
content: message.content
|
1601
|
+
}
|
1602
|
+
);
|
1603
|
+
const optimisticId2 = repository2.appendOptimisticMessage(
|
1604
|
+
parentOptimisticId2,
|
1605
|
+
{
|
1606
|
+
role: "assistant",
|
1607
|
+
content: [{ type: "text", text: "" }]
|
1608
|
+
}
|
1609
|
+
);
|
1610
|
+
repository2.resetHead(optimisticId2);
|
1611
|
+
return [parentOptimisticId2, optimisticId2];
|
1612
|
+
}
|
1613
|
+
);
|
1614
|
+
const { parentId, id } = await runtimeRef.current.append(message);
|
1615
|
+
repository.withModifications((repository2) => {
|
1616
|
+
repository2.deleteMessage(parentOptimisticId, parentId);
|
1617
|
+
repository2.deleteMessage(optimisticId, id);
|
1618
|
+
});
|
1619
|
+
},
|
1620
|
+
cancelRun: () => runtimeRef.current.cancelRun()
|
1621
|
+
}));
|
1622
|
+
const onNewMessage = (parentId, message) => {
|
1623
|
+
repository.withModifications((repository2) => {
|
1624
|
+
repository2.addOrUpdateMessage(parentId, message);
|
1625
|
+
});
|
1626
|
+
};
|
1627
|
+
const onRunningChange = (isRunning) => {
|
1628
|
+
useThread.setState({ isRunning });
|
1629
|
+
};
|
1630
|
+
return {
|
1631
|
+
useThread,
|
1632
|
+
onNewMessage,
|
1633
|
+
onRunningChange
|
1634
|
+
};
|
1635
|
+
};
|
1636
|
+
var useAssistantContext2 = (runtime) => {
|
1637
|
+
const runtimeRef = (0, import_react28.useRef)(runtime);
|
1638
|
+
runtimeRef.current = runtime;
|
1639
|
+
const [{ context, onNewMessage, onRunningChange }] = (0, import_react28.useState)(() => {
|
1640
|
+
const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
|
1641
|
+
const useViewport = makeViewportStore();
|
1642
|
+
const useComposer = makeThreadComposerStore(useThread);
|
1643
|
+
return {
|
1644
|
+
context: { useViewport, useThread, useComposer },
|
1645
|
+
onNewMessage: onNewMessage2,
|
1646
|
+
onRunningChange: onRunningChange2
|
1647
|
+
};
|
1648
|
+
});
|
1649
|
+
(0, import_react28.useEffect)(() => {
|
1650
|
+
return runtime.subscribeToMessageUpdates(onNewMessage);
|
1651
|
+
}, [runtime, onNewMessage]);
|
1652
|
+
(0, import_react28.useEffect)(() => {
|
1653
|
+
return runtime.subscribeToStatusUpdates(onRunningChange);
|
1654
|
+
}, [runtime, onRunningChange]);
|
1655
|
+
return context;
|
1656
|
+
};
|
1657
|
+
|
1658
|
+
// src/adapters/core/AssistantProvider.tsx
|
1659
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
1660
|
+
var AssistantProvider = ({ children, runtime }) => {
|
1661
|
+
const context = useAssistantContext2(runtime);
|
1662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantContext.Provider, { value: context, children });
|
1663
|
+
};
|
1664
|
+
|
1665
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1666
|
+
var import_react29 = require("react");
|
1667
|
+
|
1668
|
+
// src/adapters/core/local/LocalRuntime.tsx
|
1669
|
+
var LocalRuntime = class {
|
1670
|
+
constructor(adapter) {
|
1671
|
+
this.adapter = adapter;
|
1672
|
+
}
|
1673
|
+
_messageUpdateCallbacks = /* @__PURE__ */ new Set();
|
1674
|
+
_statusUpdateCallbacks = /* @__PURE__ */ new Set();
|
1675
|
+
abortController = null;
|
1676
|
+
repository = new MessageRepository();
|
1677
|
+
async append(message) {
|
1678
|
+
const userMessageId = generateId();
|
1679
|
+
const userMessage = {
|
1680
|
+
id: userMessageId,
|
1681
|
+
role: "user",
|
1682
|
+
content: message.content,
|
1683
|
+
createdAt: /* @__PURE__ */ new Date()
|
1684
|
+
};
|
1685
|
+
this.addOrUpdateMessage(message.parentId, userMessage);
|
1686
|
+
const { id } = await this.startRun(userMessageId);
|
1687
|
+
return { parentId: userMessageId, id };
|
1688
|
+
}
|
1689
|
+
async startRun(parentId) {
|
1690
|
+
const id = generateId();
|
1691
|
+
this.repository.resetHead(parentId);
|
1692
|
+
const messages = this.repository.getMessages();
|
1693
|
+
const message = {
|
1694
|
+
id,
|
1695
|
+
role: "assistant",
|
1696
|
+
status: "in_progress",
|
1697
|
+
content: [{ type: "text", text: "" }],
|
1698
|
+
createdAt: /* @__PURE__ */ new Date()
|
1699
|
+
};
|
1700
|
+
this.addOrUpdateMessage(parentId, message);
|
1701
|
+
void this.run(parentId, messages, message);
|
1702
|
+
return { id };
|
1703
|
+
}
|
1704
|
+
addOrUpdateMessage(parentId, message) {
|
1705
|
+
const clone = { ...message };
|
1706
|
+
this.repository.addOrUpdateMessage(parentId, clone);
|
1707
|
+
for (const callback of this._messageUpdateCallbacks)
|
1708
|
+
callback(parentId, clone);
|
1709
|
+
}
|
1710
|
+
async run(parentId, messages, message) {
|
1711
|
+
this.cancelRun();
|
1712
|
+
for (const callback of this._statusUpdateCallbacks) callback(true);
|
1713
|
+
this.abortController = new AbortController();
|
1714
|
+
try {
|
1715
|
+
await this.adapter.run({
|
1716
|
+
messages,
|
1717
|
+
abortSignal: this.abortController.signal,
|
1718
|
+
onUpdate: ({ content }) => {
|
1719
|
+
message.content = content;
|
1720
|
+
this.addOrUpdateMessage(parentId, message);
|
1721
|
+
}
|
1722
|
+
});
|
1723
|
+
message.status = "done";
|
1724
|
+
this.addOrUpdateMessage(parentId, message);
|
1725
|
+
} catch (e) {
|
1726
|
+
message.status = "error";
|
1727
|
+
this.addOrUpdateMessage(parentId, message);
|
1728
|
+
console.error(e);
|
1729
|
+
} finally {
|
1730
|
+
this.cancelRun();
|
1731
|
+
}
|
1732
|
+
}
|
1733
|
+
cancelRun() {
|
1734
|
+
if (!this.abortController) return;
|
1735
|
+
this.abortController.abort();
|
1736
|
+
this.abortController = null;
|
1737
|
+
for (const callback of this._statusUpdateCallbacks) callback(false);
|
1738
|
+
}
|
1739
|
+
subscribeToMessageUpdates(callback) {
|
1740
|
+
this._messageUpdateCallbacks.add(callback);
|
1741
|
+
return () => this._messageUpdateCallbacks.delete(callback);
|
1742
|
+
}
|
1743
|
+
subscribeToStatusUpdates(callback) {
|
1744
|
+
this._statusUpdateCallbacks.add(callback);
|
1745
|
+
return () => this._statusUpdateCallbacks.delete(callback);
|
1746
|
+
}
|
1747
|
+
};
|
1748
|
+
|
1749
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1750
|
+
var useLocalRuntime = (adapter) => {
|
1751
|
+
const [runtime] = (0, import_react29.useState)(() => new LocalRuntime(adapter));
|
1752
|
+
runtime.adapter = adapter;
|
1753
|
+
return runtime;
|
1754
|
+
};
|
1755
|
+
|
1756
|
+
// src/adapters/core/local/vercel/VercelModelAdapter.tsx
|
1757
|
+
var import_ai = require("ai");
|
1758
|
+
var VercelModelAdapter = class {
|
1759
|
+
constructor(model) {
|
1760
|
+
this.model = model;
|
1761
|
+
}
|
1762
|
+
async run({ messages, abortSignal, onUpdate }) {
|
1763
|
+
const { fullStream } = await (0, import_ai.streamText)({
|
1764
|
+
model: this.model,
|
1765
|
+
abortSignal,
|
1766
|
+
messages: messages.map((m) => ({
|
1767
|
+
role: m.role,
|
1768
|
+
content: m.content.filter((c) => c.type !== "ui")
|
1769
|
+
}))
|
1770
|
+
});
|
1771
|
+
const content = [];
|
1772
|
+
for await (const aiPart of fullStream) {
|
1773
|
+
switch (aiPart.type) {
|
1774
|
+
case "text-delta": {
|
1775
|
+
let part = content.at(-1);
|
1776
|
+
if (!part || part.type !== "text") {
|
1777
|
+
part = { type: "text", text: "" };
|
1778
|
+
content.push(part);
|
1779
|
+
}
|
1780
|
+
part.text += aiPart.textDelta;
|
1781
|
+
break;
|
1782
|
+
}
|
1783
|
+
case "tool-call": {
|
1784
|
+
content.push({
|
1785
|
+
type: "tool-call",
|
1786
|
+
name: aiPart.toolName,
|
1787
|
+
args: aiPart.args
|
1788
|
+
});
|
1789
|
+
break;
|
1790
|
+
}
|
1791
|
+
}
|
1792
|
+
onUpdate({ content });
|
1793
|
+
}
|
1794
|
+
return { content };
|
1795
|
+
}
|
1796
|
+
};
|
1522
1797
|
// Annotate the CommonJS export names for ESM import in node:
|
1523
1798
|
0 && (module.exports = {
|
1524
1799
|
ActionBarPrimitive,
|
@@ -1529,6 +1804,11 @@ var VercelRSCAssistantProvider = ({
|
|
1529
1804
|
ThreadPrimitive,
|
1530
1805
|
VercelAIAssistantProvider,
|
1531
1806
|
VercelRSCAssistantProvider,
|
1807
|
+
unstable_AssistantProvider,
|
1808
|
+
unstable_VercelModelAdapter,
|
1809
|
+
unstable_getVercelMessage,
|
1810
|
+
unstable_getVercelRSCMessage,
|
1811
|
+
unstable_useLocalRuntime,
|
1532
1812
|
unstable_useMessageContext,
|
1533
1813
|
useBeginMessageEdit,
|
1534
1814
|
useCopyMessage,
|