@assistant-ui/react 0.0.10 → 0.0.11
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 +20 -18
- package/dist/index.d.ts +20 -18
- package/dist/index.js +455 -339
- package/dist/index.mjs +429 -313
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -58,11 +58,12 @@ __export(thread_exports, {
|
|
58
58
|
});
|
59
59
|
|
60
60
|
// src/primitives/thread/ThreadRoot.tsx
|
61
|
-
var import_react = require("react");
|
62
61
|
var import_react_primitive = require("@radix-ui/react-primitive");
|
62
|
+
var import_react = require("react");
|
63
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
63
64
|
var ThreadRoot = (0, import_react.forwardRef)(
|
64
65
|
(props, ref) => {
|
65
|
-
return /* @__PURE__ */
|
66
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
|
66
67
|
}
|
67
68
|
);
|
68
69
|
|
@@ -99,8 +100,9 @@ var ThreadIf = ({ children, ...query }) => {
|
|
99
100
|
};
|
100
101
|
|
101
102
|
// src/primitives/thread/ThreadEmpty.tsx
|
103
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
102
104
|
var ThreadEmpty = ({ children }) => {
|
103
|
-
return /* @__PURE__ */
|
105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThreadIf, { empty: true, children });
|
104
106
|
};
|
105
107
|
|
106
108
|
// src/primitives/thread/ThreadViewport.tsx
|
@@ -162,6 +164,7 @@ var useOnScrollToBottom = (callback) => {
|
|
162
164
|
};
|
163
165
|
|
164
166
|
// src/primitives/thread/ThreadViewport.tsx
|
167
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
165
168
|
var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
|
166
169
|
const messagesEndRef = (0, import_react5.useRef)(null);
|
167
170
|
const divRef = (0, import_react5.useRef)(null);
|
@@ -198,165 +201,28 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
|
|
198
201
|
}
|
199
202
|
lastScrollTop.current = div.scrollTop;
|
200
203
|
};
|
201
|
-
return /* @__PURE__ */
|
204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
202
205
|
import_react_primitive2.Primitive.div,
|
203
206
|
{
|
204
207
|
...rest,
|
205
208
|
onScroll: (0, import_primitive.composeEventHandlers)(onScroll, handleScroll),
|
206
|
-
ref
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
});
|
212
|
-
|
213
|
-
// src/adapters/vercel/useVercelAIBranches.tsx
|
214
|
-
var import_react6 = require("react");
|
215
|
-
|
216
|
-
// src/utils/context/stores/AssistantTypes.ts
|
217
|
-
var ROOT_PARENT_ID = "__ROOT_ID__";
|
218
|
-
|
219
|
-
// src/adapters/vercel/useVercelAIBranches.tsx
|
220
|
-
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
221
|
-
var updateBranchData = (data, messages) => {
|
222
|
-
for (let i = 0; i < messages.length; i++) {
|
223
|
-
const child = messages[i];
|
224
|
-
const childId = child.id;
|
225
|
-
const parentId = messages[i - 1]?.id ?? ROOT_PARENT_ID;
|
226
|
-
data.parentMap.set(childId, parentId);
|
227
|
-
const parentArray = data.branchMap.get(parentId);
|
228
|
-
if (!parentArray) {
|
229
|
-
data.branchMap.set(parentId, [childId]);
|
230
|
-
} else if (!parentArray.includes(childId)) {
|
231
|
-
parentArray.push(childId);
|
209
|
+
ref,
|
210
|
+
children: [
|
211
|
+
children,
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
|
213
|
+
]
|
232
214
|
}
|
233
|
-
data.snapshots.set(childId, messages);
|
234
|
-
}
|
235
|
-
};
|
236
|
-
var getParentId = (data, messages, messageId) => {
|
237
|
-
if (messageId === UPCOMING_MESSAGE_ID) {
|
238
|
-
const parent = messages.at(-1);
|
239
|
-
if (!parent)
|
240
|
-
return ROOT_PARENT_ID;
|
241
|
-
return parent.id;
|
242
|
-
}
|
243
|
-
const parentId = data.parentMap.get(messageId);
|
244
|
-
if (!parentId)
|
245
|
-
throw new Error("Unexpected: Message parent not found");
|
246
|
-
return parentId;
|
247
|
-
};
|
248
|
-
var getBranchStateImpl = (data, messages, messageId) => {
|
249
|
-
const parentId = getParentId(data, messages, messageId);
|
250
|
-
const branches = data.branchMap.get(parentId) ?? [];
|
251
|
-
const branchId = messageId === UPCOMING_MESSAGE_ID ? branches.length : branches.indexOf(messageId);
|
252
|
-
if (branchId === -1)
|
253
|
-
throw new Error("Unexpected: Message not found in parent children");
|
254
|
-
const upcomingOffset = messageId === UPCOMING_MESSAGE_ID ? 1 : 0;
|
255
|
-
return {
|
256
|
-
branchId,
|
257
|
-
branchCount: branches.length + upcomingOffset
|
258
|
-
};
|
259
|
-
};
|
260
|
-
var switchToBranchImpl = (data, messages, messageId, branchId) => {
|
261
|
-
const parentId = getParentId(data, messages, messageId);
|
262
|
-
const branches = data.branchMap.get(parentId);
|
263
|
-
if (!branches)
|
264
|
-
throw new Error("Unexpected: Parent children not found");
|
265
|
-
const newMessageId = branches[branchId];
|
266
|
-
if (!newMessageId)
|
267
|
-
throw new Error("Unexpected: Requested branch not found");
|
268
|
-
if (branchId < 0 || branchId >= branches.length)
|
269
|
-
throw new Error("Switch to branch called with a branch index out of range");
|
270
|
-
if (newMessageId === messageId)
|
271
|
-
return messages;
|
272
|
-
const snapshot = data.snapshots.get(newMessageId);
|
273
|
-
if (!snapshot)
|
274
|
-
throw new Error("Unexpected: Branch snapshot not found");
|
275
|
-
return snapshot;
|
276
|
-
};
|
277
|
-
var sliceMessagesUntil = (messages, messageId) => {
|
278
|
-
if (messageId === ROOT_PARENT_ID)
|
279
|
-
return [];
|
280
|
-
if (messageId === UPCOMING_MESSAGE_ID)
|
281
|
-
return messages;
|
282
|
-
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
283
|
-
if (messageIdx === -1)
|
284
|
-
throw new Error("Unexpected: Message not found");
|
285
|
-
return messages.slice(0, messageIdx + 1);
|
286
|
-
};
|
287
|
-
var useVercelAIBranches = (chat, context) => {
|
288
|
-
const data = (0, import_react6.useRef)({
|
289
|
-
parentMap: /* @__PURE__ */ new Map(),
|
290
|
-
branchMap: /* @__PURE__ */ new Map(),
|
291
|
-
snapshots: /* @__PURE__ */ new Map()
|
292
|
-
}).current;
|
293
|
-
updateBranchData(data, chat.messages);
|
294
|
-
const getBranchState = (0, import_react6.useCallback)(
|
295
|
-
(messageId) => {
|
296
|
-
return getBranchStateImpl(data, chat.messages, messageId);
|
297
|
-
},
|
298
|
-
[data, chat.messages]
|
299
215
|
);
|
300
|
-
|
301
|
-
(messageId, branchId) => {
|
302
|
-
const newMessages = switchToBranchImpl(
|
303
|
-
data,
|
304
|
-
chat.messages,
|
305
|
-
messageId,
|
306
|
-
branchId
|
307
|
-
);
|
308
|
-
chat.setMessages(newMessages);
|
309
|
-
},
|
310
|
-
[data, chat.messages, chat.setMessages]
|
311
|
-
);
|
312
|
-
const reloadMaybe = "reload" in chat ? chat.reload : void 0;
|
313
|
-
const startRun = (0, import_react6.useCallback)(
|
314
|
-
async (parentId) => {
|
315
|
-
if (!reloadMaybe)
|
316
|
-
throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
|
317
|
-
const newMessages = sliceMessagesUntil(chat.messages, parentId);
|
318
|
-
chat.setMessages(newMessages);
|
319
|
-
context.useViewport.getState().scrollToBottom();
|
320
|
-
await reloadMaybe();
|
321
|
-
},
|
322
|
-
[context, chat.messages, chat.setMessages, reloadMaybe]
|
323
|
-
);
|
324
|
-
const append = (0, import_react6.useCallback)(
|
325
|
-
async (message) => {
|
326
|
-
const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
|
327
|
-
chat.setMessages(newMessages);
|
328
|
-
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
329
|
-
throw new Error("Only text content is currently supported");
|
330
|
-
context.useViewport.getState().scrollToBottom();
|
331
|
-
await chat.append({
|
332
|
-
role: "user",
|
333
|
-
content: message.content[0].text
|
334
|
-
});
|
335
|
-
},
|
336
|
-
[context, chat.messages, chat.setMessages, chat.append]
|
337
|
-
);
|
338
|
-
return (0, import_react6.useMemo)(
|
339
|
-
() => ({
|
340
|
-
getBranchState,
|
341
|
-
switchToBranch,
|
342
|
-
append,
|
343
|
-
startRun
|
344
|
-
}),
|
345
|
-
[getBranchState, switchToBranch, append, startRun]
|
346
|
-
);
|
347
|
-
};
|
348
|
-
var hasUpcomingMessage = (thread) => {
|
349
|
-
return thread.isRunning && thread.messages[thread.messages.length - 1]?.role !== "assistant";
|
350
|
-
};
|
216
|
+
});
|
351
217
|
|
352
218
|
// src/utils/context/useComposerContext.ts
|
353
|
-
var
|
219
|
+
var import_react7 = require("react");
|
354
220
|
|
355
221
|
// src/utils/context/useMessageContext.ts
|
356
|
-
var
|
357
|
-
var MessageContext = (0,
|
222
|
+
var import_react6 = require("react");
|
223
|
+
var MessageContext = (0, import_react6.createContext)(null);
|
358
224
|
var useMessageContext = () => {
|
359
|
-
const context = (0,
|
225
|
+
const context = (0, import_react6.useContext)(MessageContext);
|
360
226
|
if (!context)
|
361
227
|
throw new Error("useMessageContext must be used within a MessageProvider");
|
362
228
|
return context;
|
@@ -365,7 +231,7 @@ var useMessageContext = () => {
|
|
365
231
|
// src/utils/context/useComposerContext.ts
|
366
232
|
var useComposerContext = () => {
|
367
233
|
const { useComposer: useAssisstantComposer } = useAssistantContext();
|
368
|
-
const { useComposer: useMessageComposer } = (0,
|
234
|
+
const { useComposer: useMessageComposer } = (0, import_react7.useContext)(MessageContext) ?? {};
|
369
235
|
return {
|
370
236
|
useComposer: useMessageComposer ?? useAssisstantComposer,
|
371
237
|
type: useMessageComposer ? "message" : "assistant"
|
@@ -398,7 +264,7 @@ __export(message_exports, {
|
|
398
264
|
});
|
399
265
|
|
400
266
|
// src/primitives/message/MessageProvider.tsx
|
401
|
-
var
|
267
|
+
var import_react8 = require("react");
|
402
268
|
var import_zustand2 = require("zustand");
|
403
269
|
|
404
270
|
// src/utils/context/stores/ComposerStore.ts
|
@@ -414,7 +280,6 @@ var makeMessageComposerStore = ({
|
|
414
280
|
onSend
|
415
281
|
}) => (0, import_zustand.create)()((set, get, store) => ({
|
416
282
|
...makeBaseComposer(set, get, store),
|
417
|
-
canCancel: true,
|
418
283
|
isEditing: false,
|
419
284
|
edit: () => {
|
420
285
|
const value = onEdit();
|
@@ -423,39 +288,48 @@ var makeMessageComposerStore = ({
|
|
423
288
|
send: () => {
|
424
289
|
const value = get().value;
|
425
290
|
set({ isEditing: false });
|
426
|
-
|
291
|
+
onSend(value);
|
427
292
|
},
|
428
293
|
cancel: () => {
|
294
|
+
if (!get().isEditing)
|
295
|
+
return false;
|
429
296
|
set({ isEditing: false });
|
297
|
+
return true;
|
430
298
|
}
|
431
299
|
}));
|
432
|
-
var makeThreadComposerStore = ({
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
300
|
+
var makeThreadComposerStore = (useThread) => (0, import_zustand.create)()((set, get, store) => {
|
301
|
+
return {
|
302
|
+
...makeBaseComposer(set, get, store),
|
303
|
+
isEditing: true,
|
304
|
+
send: () => {
|
305
|
+
const { value } = get();
|
306
|
+
set({ value: "" });
|
307
|
+
useThread.getState().append({
|
308
|
+
parentId: useThread.getState().messages.at(-1)?.id ?? null,
|
309
|
+
content: [{ type: "text", text: value }]
|
310
|
+
});
|
311
|
+
},
|
312
|
+
cancel: () => {
|
313
|
+
const thread = useThread.getState();
|
314
|
+
if (!thread.isRunning)
|
315
|
+
return false;
|
316
|
+
useThread.getState().cancelRun();
|
317
|
+
return true;
|
318
|
+
}
|
319
|
+
};
|
320
|
+
});
|
448
321
|
|
449
322
|
// src/primitives/message/MessageProvider.tsx
|
323
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
450
324
|
var getIsLast = (thread, message) => {
|
451
|
-
|
452
|
-
return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
|
325
|
+
return thread.messages[thread.messages.length - 1]?.id === message.id;
|
453
326
|
};
|
454
327
|
var useMessageContext2 = () => {
|
455
|
-
const
|
456
|
-
|
328
|
+
const { useThread } = useAssistantContext();
|
329
|
+
const [context] = (0, import_react8.useState)(() => {
|
457
330
|
const useMessage = (0, import_zustand2.create)(() => ({
|
458
331
|
message: null,
|
332
|
+
branches: [],
|
459
333
|
isLast: false,
|
460
334
|
isCopied: false,
|
461
335
|
isHovering: false,
|
@@ -475,7 +349,7 @@ var useMessageContext2 = () => {
|
|
475
349
|
},
|
476
350
|
onSend: (text) => {
|
477
351
|
const message = useMessage.getState().message;
|
478
|
-
|
352
|
+
useThread.getState().append({
|
479
353
|
parentId: message.parentId,
|
480
354
|
content: [{ type: "text", text }]
|
481
355
|
});
|
@@ -492,12 +366,14 @@ var MessageProvider = ({
|
|
492
366
|
const { useThread } = useAssistantContext();
|
493
367
|
const context = useMessageContext2();
|
494
368
|
const isLast = useThread((thread) => getIsLast(thread, message));
|
495
|
-
const
|
496
|
-
const [
|
497
|
-
(0,
|
369
|
+
const branches = useThread((thread) => thread.getBranches(message.id));
|
370
|
+
const [isCopied, setIsCopied] = (0, import_react8.useState)(false);
|
371
|
+
const [isHovering, setIsHovering] = (0, import_react8.useState)(false);
|
372
|
+
(0, import_react8.useMemo)(() => {
|
498
373
|
context.useMessage.setState(
|
499
374
|
{
|
500
375
|
message,
|
376
|
+
branches,
|
501
377
|
isLast,
|
502
378
|
isCopied,
|
503
379
|
isHovering,
|
@@ -506,15 +382,16 @@ var MessageProvider = ({
|
|
506
382
|
},
|
507
383
|
true
|
508
384
|
);
|
509
|
-
}, [context, message, isLast, isCopied, isHovering]);
|
510
|
-
return /* @__PURE__ */
|
385
|
+
}, [context, message, branches, isLast, isCopied, isHovering]);
|
386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
|
511
387
|
};
|
512
388
|
|
513
389
|
// src/primitives/message/MessageRoot.tsx
|
514
390
|
var import_primitive2 = require("@radix-ui/primitive");
|
515
391
|
var import_react_primitive3 = require("@radix-ui/react-primitive");
|
516
|
-
var
|
517
|
-
var
|
392
|
+
var import_react9 = require("react");
|
393
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
394
|
+
var MessageRoot = (0, import_react9.forwardRef)(
|
518
395
|
({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
|
519
396
|
const { useMessage } = useMessageContext();
|
520
397
|
const setIsHovering = useMessage((s) => s.setIsHovering);
|
@@ -524,7 +401,7 @@ var MessageRoot = (0, import_react10.forwardRef)(
|
|
524
401
|
const handleMouseLeave = () => {
|
525
402
|
setIsHovering(false);
|
526
403
|
};
|
527
|
-
return /* @__PURE__ */
|
404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
528
405
|
import_react_primitive3.Primitive.div,
|
529
406
|
{
|
530
407
|
...rest,
|
@@ -539,8 +416,8 @@ var MessageRoot = (0, import_react10.forwardRef)(
|
|
539
416
|
// src/primitives/message/MessageIf.tsx
|
540
417
|
var useMessageIf = (props) => {
|
541
418
|
const { useMessage } = useMessageContext();
|
542
|
-
return useMessage(({ message, isLast, isCopied, isHovering }) => {
|
543
|
-
if (props.hasBranches === true &&
|
419
|
+
return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
|
420
|
+
if (props.hasBranches === true && branches.length < 2)
|
544
421
|
return false;
|
545
422
|
if (props.user && message.role !== "user")
|
546
423
|
return false;
|
@@ -561,8 +438,9 @@ var MessageIf = ({ children, ...query }) => {
|
|
561
438
|
};
|
562
439
|
|
563
440
|
// src/primitives/message/MessageContent.tsx
|
441
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
564
442
|
var defaultComponents = {
|
565
|
-
Text: ({ part }) => /* @__PURE__ */
|
443
|
+
Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: part.text }),
|
566
444
|
Image: () => null,
|
567
445
|
UI: ({ part }) => part.display,
|
568
446
|
tools: {
|
@@ -579,26 +457,27 @@ var MessageContent = ({
|
|
579
457
|
}) => {
|
580
458
|
const { useMessage } = useMessageContext();
|
581
459
|
const content = useMessage((s) => s.message.content);
|
582
|
-
return /* @__PURE__ */
|
460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: content.map((part, i) => {
|
583
461
|
const key = i;
|
584
462
|
switch (part.type) {
|
585
463
|
case "text":
|
586
|
-
return /* @__PURE__ */
|
464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { part }, key);
|
587
465
|
case "image":
|
588
|
-
return /* @__PURE__ */
|
466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Image, { part }, key);
|
589
467
|
case "ui":
|
590
|
-
return /* @__PURE__ */
|
468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(UI, { part }, key);
|
591
469
|
case "tool-call": {
|
592
470
|
const Tool = by_name[part.name] || Fallback;
|
593
|
-
return /* @__PURE__ */
|
471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tool, { part }, key);
|
594
472
|
}
|
595
473
|
default:
|
596
474
|
return null;
|
597
475
|
}
|
598
|
-
}));
|
476
|
+
}) });
|
599
477
|
};
|
600
478
|
|
601
479
|
// src/primitives/thread/ThreadMessages.tsx
|
480
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
602
481
|
var getComponents = (components) => {
|
603
482
|
return {
|
604
483
|
EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
|
@@ -613,40 +492,32 @@ var ThreadMessages = ({ components }) => {
|
|
613
492
|
const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
|
614
493
|
if (messages.length === 0)
|
615
494
|
return null;
|
616
|
-
return /* @__PURE__ */
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: messages.map((message, idx) => {
|
617
496
|
return (
|
618
497
|
// biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
|
619
|
-
/* @__PURE__ */
|
498
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(MessageProvider, { message, children: [
|
499
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(MessageIf, { user: true, children: [
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserMessage, {}) }),
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EditComposer, {}) })
|
502
|
+
] }),
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AssistantMessage, {}) })
|
504
|
+
] }, idx)
|
620
505
|
);
|
621
|
-
})
|
622
|
-
MessageProvider,
|
623
|
-
{
|
624
|
-
message: {
|
625
|
-
id: UPCOMING_MESSAGE_ID,
|
626
|
-
role: "assistant",
|
627
|
-
content: [{ type: "text", text: "..." }],
|
628
|
-
parentId: messages.at(-1)?.id ?? ROOT_PARENT_ID,
|
629
|
-
// TODO fix these (move upcoming message to AssistantContext)
|
630
|
-
branchId: 0,
|
631
|
-
branchCount: 1,
|
632
|
-
createdAt: /* @__PURE__ */ new Date()
|
633
|
-
}
|
634
|
-
},
|
635
|
-
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
636
|
-
));
|
506
|
+
}) });
|
637
507
|
};
|
638
508
|
|
639
509
|
// src/primitives/thread/ThreadScrollToBottom.tsx
|
640
510
|
var import_primitive3 = require("@radix-ui/primitive");
|
641
511
|
var import_react_primitive4 = require("@radix-ui/react-primitive");
|
642
|
-
var
|
643
|
-
var
|
512
|
+
var import_react10 = require("react");
|
513
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
514
|
+
var ThreadScrollToBottom = (0, import_react10.forwardRef)(({ onClick, ...rest }, ref) => {
|
644
515
|
const { useViewport } = useAssistantContext();
|
645
516
|
const isAtBottom = useViewport((s) => s.isAtBottom);
|
646
517
|
const handleScrollToBottom = () => {
|
647
518
|
useViewport.getState().scrollToBottom();
|
648
519
|
};
|
649
|
-
return /* @__PURE__ */
|
520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
650
521
|
import_react_primitive4.Primitive.button,
|
651
522
|
{
|
652
523
|
...rest,
|
@@ -671,11 +542,13 @@ __export(composer_exports, {
|
|
671
542
|
var import_primitive4 = require("@radix-ui/primitive");
|
672
543
|
var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
|
673
544
|
var import_react_primitive5 = require("@radix-ui/react-primitive");
|
674
|
-
var
|
675
|
-
var
|
545
|
+
var import_react11 = require("react");
|
546
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
547
|
+
var ComposerRoot = (0, import_react11.forwardRef)(
|
676
548
|
({ onSubmit, ...rest }, forwardedRef) => {
|
549
|
+
const { useViewport } = useAssistantContext();
|
677
550
|
const { useComposer } = useComposerContext();
|
678
|
-
const formRef = (0,
|
551
|
+
const formRef = (0, import_react11.useRef)(null);
|
679
552
|
const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
|
680
553
|
const handleSubmit = (e) => {
|
681
554
|
const composerState = useComposer.getState();
|
@@ -683,8 +556,9 @@ var ComposerRoot = (0, import_react12.forwardRef)(
|
|
683
556
|
return;
|
684
557
|
e.preventDefault();
|
685
558
|
composerState.send();
|
559
|
+
useViewport.getState().scrollToBottom();
|
686
560
|
};
|
687
|
-
return /* @__PURE__ */
|
561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
688
562
|
import_react_primitive5.Primitive.form,
|
689
563
|
{
|
690
564
|
...rest,
|
@@ -699,11 +573,12 @@ var ComposerRoot = (0, import_react12.forwardRef)(
|
|
699
573
|
var import_primitive5 = require("@radix-ui/primitive");
|
700
574
|
var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
|
701
575
|
var import_react_slot = require("@radix-ui/react-slot");
|
702
|
-
var
|
576
|
+
var import_react12 = require("react");
|
703
577
|
var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
|
704
|
-
var
|
578
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
579
|
+
var ComposerInput = (0, import_react12.forwardRef)(
|
705
580
|
({ autoFocus, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
|
706
|
-
const { useThread } = useAssistantContext();
|
581
|
+
const { useThread, useViewport } = useAssistantContext();
|
707
582
|
const { useComposer, type } = useComposerContext();
|
708
583
|
const value = useComposer((c) => {
|
709
584
|
if (!c.isEditing)
|
@@ -715,22 +590,23 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
715
590
|
if (disabled)
|
716
591
|
return;
|
717
592
|
const composer = useComposer.getState();
|
718
|
-
if (e.key === "Escape"
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
if (e.key === "Enter" && e.shiftKey === false) {
|
593
|
+
if (e.key === "Escape") {
|
594
|
+
if (useComposer.getState().cancel()) {
|
595
|
+
e.preventDefault();
|
596
|
+
}
|
597
|
+
} else if (e.key === "Enter" && e.shiftKey === false) {
|
723
598
|
const isRunning = useThread.getState().isRunning;
|
724
599
|
if (!isRunning) {
|
725
600
|
e.preventDefault();
|
726
601
|
composer.send();
|
602
|
+
useViewport.getState().scrollToBottom();
|
727
603
|
}
|
728
604
|
}
|
729
605
|
};
|
730
|
-
const textareaRef = (0,
|
606
|
+
const textareaRef = (0, import_react12.useRef)(null);
|
731
607
|
const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
|
732
608
|
const autoFocusEnabled = autoFocus !== false && !disabled;
|
733
|
-
const focus = (0,
|
609
|
+
const focus = (0, import_react12.useCallback)(() => {
|
734
610
|
const textarea = textareaRef.current;
|
735
611
|
if (!textarea || !autoFocusEnabled)
|
736
612
|
return;
|
@@ -740,13 +616,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
740
616
|
textareaRef.current.value.length
|
741
617
|
);
|
742
618
|
}, [autoFocusEnabled]);
|
743
|
-
(0,
|
619
|
+
(0, import_react12.useEffect)(() => focus(), [focus]);
|
744
620
|
useOnScrollToBottom(() => {
|
745
621
|
if (type === "assistant") {
|
746
622
|
focus();
|
747
623
|
}
|
748
624
|
});
|
749
|
-
return /* @__PURE__ */
|
625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
750
626
|
Component,
|
751
627
|
{
|
752
628
|
value,
|
@@ -767,12 +643,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
767
643
|
|
768
644
|
// src/primitives/composer/ComposerSend.tsx
|
769
645
|
var import_react_primitive6 = require("@radix-ui/react-primitive");
|
770
|
-
var
|
771
|
-
var
|
646
|
+
var import_react13 = require("react");
|
647
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
648
|
+
var ComposerSend = (0, import_react13.forwardRef)(
|
772
649
|
({ disabled, ...rest }, ref) => {
|
773
650
|
const { useComposer } = useComposerContext();
|
774
651
|
const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
|
775
|
-
return /* @__PURE__ */
|
652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
776
653
|
import_react_primitive6.Primitive.button,
|
777
654
|
{
|
778
655
|
type: "submit",
|
@@ -787,21 +664,20 @@ var ComposerSend = (0, import_react14.forwardRef)(
|
|
787
664
|
// src/primitives/composer/ComposerCancel.tsx
|
788
665
|
var import_primitive6 = require("@radix-ui/primitive");
|
789
666
|
var import_react_primitive7 = require("@radix-ui/react-primitive");
|
790
|
-
var
|
791
|
-
var
|
667
|
+
var import_react14 = require("react");
|
668
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
669
|
+
var ComposerCancel = (0, import_react14.forwardRef)(({ onClick, ...rest }, ref) => {
|
792
670
|
const { useComposer } = useComposerContext();
|
793
|
-
const
|
794
|
-
const handleClose = () => {
|
671
|
+
const handleCancel = () => {
|
795
672
|
useComposer.getState().cancel();
|
796
673
|
};
|
797
|
-
return /* @__PURE__ */
|
674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
798
675
|
import_react_primitive7.Primitive.button,
|
799
676
|
{
|
800
677
|
type: "button",
|
801
678
|
...rest,
|
802
679
|
ref,
|
803
|
-
onClick: (0, import_primitive6.composeEventHandlers)(onClick,
|
804
|
-
disabled: disabled || !hasValue
|
680
|
+
onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleCancel)
|
805
681
|
}
|
806
682
|
);
|
807
683
|
});
|
@@ -817,10 +693,10 @@ __export(branchPicker_exports, {
|
|
817
693
|
});
|
818
694
|
|
819
695
|
// src/utils/context/combined/useCombinedStore.ts
|
820
|
-
var
|
696
|
+
var import_react16 = require("react");
|
821
697
|
|
822
698
|
// src/utils/context/combined/createCombinedStore.ts
|
823
|
-
var
|
699
|
+
var import_react15 = require("react");
|
824
700
|
var createCombinedStore = (stores) => {
|
825
701
|
const subscribe = (callback) => {
|
826
702
|
const unsubscribes = stores.map((store) => store.subscribe(callback));
|
@@ -832,41 +708,42 @@ var createCombinedStore = (stores) => {
|
|
832
708
|
};
|
833
709
|
return (selector) => {
|
834
710
|
const getSnapshot = () => selector(...stores.map((store) => store.getState()));
|
835
|
-
return (0,
|
711
|
+
return (0, import_react15.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
836
712
|
};
|
837
713
|
};
|
838
714
|
|
839
715
|
// src/utils/context/combined/useCombinedStore.ts
|
840
716
|
var useCombinedStore = (stores, selector) => {
|
841
|
-
const useCombined = (0,
|
717
|
+
const useCombined = (0, import_react16.useMemo)(() => createCombinedStore(stores), stores);
|
842
718
|
return useCombined(selector);
|
843
719
|
};
|
844
720
|
|
845
721
|
// src/actions/useGoToNextBranch.tsx
|
846
722
|
var useGoToNextBranch = () => {
|
847
723
|
const { useThread } = useAssistantContext();
|
848
|
-
const {
|
724
|
+
const { useMessage, useComposer } = useMessageContext();
|
849
725
|
const disabled = useCombinedStore(
|
850
|
-
[
|
851
|
-
(
|
726
|
+
[useMessage, useComposer],
|
727
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
|
852
728
|
);
|
853
729
|
if (disabled)
|
854
730
|
return null;
|
855
731
|
return () => {
|
856
|
-
const { message } = useMessage.getState();
|
857
|
-
useThread.getState().switchToBranch(message.id
|
732
|
+
const { message, branches } = useMessage.getState();
|
733
|
+
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
|
858
734
|
};
|
859
735
|
};
|
860
736
|
|
861
737
|
// src/utils/createActionButton.tsx
|
862
|
-
var import_react18 = require("react");
|
863
|
-
var import_react_primitive8 = require("@radix-ui/react-primitive");
|
864
738
|
var import_primitive7 = require("@radix-ui/primitive");
|
739
|
+
var import_react_primitive8 = require("@radix-ui/react-primitive");
|
740
|
+
var import_react17 = require("react");
|
741
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
865
742
|
var createActionButton = (useActionButton) => {
|
866
|
-
return (0,
|
743
|
+
return (0, import_react17.forwardRef)(
|
867
744
|
(props, forwardedRef) => {
|
868
745
|
const onClick = useActionButton(props);
|
869
|
-
return /* @__PURE__ */
|
746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
870
747
|
import_react_primitive8.Primitive.button,
|
871
748
|
{
|
872
749
|
type: "button",
|
@@ -886,16 +763,19 @@ var BranchPickerNext = createActionButton(useGoToNextBranch);
|
|
886
763
|
// src/actions/useGoToPreviousBranch.tsx
|
887
764
|
var useGoToPreviousBranch = () => {
|
888
765
|
const { useThread } = useAssistantContext();
|
889
|
-
const {
|
766
|
+
const { useMessage, useComposer } = useMessageContext();
|
890
767
|
const disabled = useCombinedStore(
|
891
|
-
[
|
892
|
-
(
|
768
|
+
[useMessage, useComposer],
|
769
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
|
893
770
|
);
|
894
771
|
if (disabled)
|
895
772
|
return null;
|
896
773
|
return () => {
|
897
|
-
const { message } = useMessage.getState();
|
898
|
-
useThread.getState().switchToBranch(
|
774
|
+
const { message, branches } = useMessage.getState();
|
775
|
+
useThread.getState().switchToBranch(
|
776
|
+
branches[branches.indexOf(message.id) - 1]
|
777
|
+
// TODO probably there's a more elegant way to do this
|
778
|
+
);
|
899
779
|
};
|
900
780
|
};
|
901
781
|
|
@@ -903,24 +783,27 @@ var useGoToPreviousBranch = () => {
|
|
903
783
|
var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
|
904
784
|
|
905
785
|
// src/primitives/branchPicker/BranchPickerCount.tsx
|
786
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
906
787
|
var BranchPickerCount = () => {
|
907
788
|
const { useMessage } = useMessageContext();
|
908
|
-
const branchCount = useMessage((s) => s.
|
909
|
-
return /* @__PURE__ */
|
789
|
+
const branchCount = useMessage((s) => s.branches.length);
|
790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: branchCount });
|
910
791
|
};
|
911
792
|
|
912
793
|
// src/primitives/branchPicker/BranchPickerNumber.tsx
|
794
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
913
795
|
var BranchPickerNumber = () => {
|
914
796
|
const { useMessage } = useMessageContext();
|
915
|
-
const
|
916
|
-
return /* @__PURE__ */
|
797
|
+
const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
|
798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: branchIdx + 1 });
|
917
799
|
};
|
918
800
|
|
919
801
|
// src/primitives/branchPicker/BranchPickerRoot.tsx
|
920
802
|
var import_react_primitive9 = require("@radix-ui/react-primitive");
|
921
|
-
var
|
922
|
-
var
|
923
|
-
|
803
|
+
var import_react18 = require("react");
|
804
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
805
|
+
var BranchPickerRoot = (0, import_react18.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
|
806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive9.Primitive.div, { ...rest, ref }) });
|
924
807
|
});
|
925
808
|
|
926
809
|
// src/primitives/actionBar/index.ts
|
@@ -934,8 +817,9 @@ __export(actionBar_exports, {
|
|
934
817
|
|
935
818
|
// src/primitives/actionBar/ActionBarRoot.tsx
|
936
819
|
var import_react_primitive10 = require("@radix-ui/react-primitive");
|
937
|
-
var
|
938
|
-
var
|
820
|
+
var import_react19 = require("react");
|
821
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
822
|
+
var ActionBarRoot = (0, import_react19.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
|
939
823
|
const { useThread } = useAssistantContext();
|
940
824
|
const { useMessage } = useMessageContext();
|
941
825
|
const hideAndfloatStatus = useCombinedStore(
|
@@ -948,14 +832,14 @@ var ActionBarRoot = (0, import_react20.forwardRef)(({ hideWhenRunning, autohide,
|
|
948
832
|
return "normal" /* Normal */;
|
949
833
|
if (!m.isHovering)
|
950
834
|
return "hidden" /* Hidden */;
|
951
|
-
if (autohideFloat === "always" || autohideFloat === "single-branch" && m.
|
835
|
+
if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
|
952
836
|
return "floating" /* Floating */;
|
953
837
|
return "normal" /* Normal */;
|
954
838
|
}
|
955
839
|
);
|
956
840
|
if (hideAndfloatStatus === "hidden" /* Hidden */)
|
957
841
|
return null;
|
958
|
-
return /* @__PURE__ */
|
842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
959
843
|
import_react_primitive10.Primitive.div,
|
960
844
|
{
|
961
845
|
"data-floating": hideAndfloatStatus === "floating" /* Floating */,
|
@@ -986,7 +870,7 @@ var ActionBarCopy = createActionButton(useCopyMessage);
|
|
986
870
|
|
987
871
|
// src/actions/useReloadMessage.tsx
|
988
872
|
var useReloadMessage = () => {
|
989
|
-
const { useThread } = useAssistantContext();
|
873
|
+
const { useThread, useViewport } = useAssistantContext();
|
990
874
|
const { useMessage } = useMessageContext();
|
991
875
|
const disabled = useCombinedStore(
|
992
876
|
[useThread, useMessage],
|
@@ -999,6 +883,7 @@ var useReloadMessage = () => {
|
|
999
883
|
if (message.role !== "assistant")
|
1000
884
|
throw new Error("Reloading is only supported on assistant messages");
|
1001
885
|
useThread.getState().startRun(message.parentId);
|
886
|
+
useViewport.getState().scrollToBottom();
|
1002
887
|
};
|
1003
888
|
};
|
1004
889
|
|
@@ -1027,7 +912,7 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
|
1027
912
|
var import_react22 = require("react");
|
1028
913
|
|
1029
914
|
// src/adapters/vercel/useDummyAIAssistantContext.tsx
|
1030
|
-
var
|
915
|
+
var import_react20 = require("react");
|
1031
916
|
var import_zustand4 = require("zustand");
|
1032
917
|
|
1033
918
|
// src/utils/context/stores/ViewportStore.tsx
|
@@ -1051,45 +936,285 @@ var makeViewportStore = () => {
|
|
1051
936
|
};
|
1052
937
|
|
1053
938
|
// src/adapters/vercel/useDummyAIAssistantContext.tsx
|
939
|
+
var makeDummyThreadStore = () => {
|
940
|
+
return (0, import_zustand4.create)(() => ({
|
941
|
+
messages: [],
|
942
|
+
isRunning: false,
|
943
|
+
getBranches: () => {
|
944
|
+
return [];
|
945
|
+
},
|
946
|
+
switchToBranch: () => {
|
947
|
+
throw new Error("Not implemented");
|
948
|
+
},
|
949
|
+
append: async () => {
|
950
|
+
throw new Error("Not implemented");
|
951
|
+
},
|
952
|
+
cancelRun: () => {
|
953
|
+
throw new Error("Not implemented");
|
954
|
+
},
|
955
|
+
startRun: async () => {
|
956
|
+
throw new Error("Not implemented");
|
957
|
+
}
|
958
|
+
}));
|
959
|
+
};
|
1054
960
|
var useDummyAIAssistantContext = () => {
|
1055
|
-
const [context] = (0,
|
1056
|
-
const useThread = (
|
1057
|
-
id: "",
|
1058
|
-
messages: [],
|
1059
|
-
isRunning: false,
|
1060
|
-
append: async () => {
|
1061
|
-
throw new Error("Not implemented");
|
1062
|
-
},
|
1063
|
-
cancelRun: () => {
|
1064
|
-
throw new Error("Not implemented");
|
1065
|
-
},
|
1066
|
-
switchToBranch: () => {
|
1067
|
-
throw new Error("Not implemented");
|
1068
|
-
},
|
1069
|
-
startRun: async () => {
|
1070
|
-
throw new Error("Not implemented");
|
1071
|
-
}
|
1072
|
-
}));
|
961
|
+
const [context] = (0, import_react20.useState)(() => {
|
962
|
+
const useThread = makeDummyThreadStore();
|
1073
963
|
const useViewport = makeViewportStore();
|
1074
|
-
const useComposer = makeThreadComposerStore(
|
1075
|
-
onSend: async (text) => {
|
1076
|
-
await useThread.getState().append({
|
1077
|
-
parentId: useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID,
|
1078
|
-
content: [{ type: "text", text }]
|
1079
|
-
});
|
1080
|
-
},
|
1081
|
-
onCancel: () => {
|
1082
|
-
useThread.getState().cancelRun();
|
1083
|
-
}
|
1084
|
-
});
|
964
|
+
const useComposer = makeThreadComposerStore(useThread);
|
1085
965
|
return { useThread, useViewport, useComposer };
|
1086
966
|
});
|
1087
967
|
return context;
|
1088
968
|
};
|
1089
969
|
|
970
|
+
// src/adapters/vercel/useVercelAIBranches.tsx
|
971
|
+
var import_react21 = require("react");
|
972
|
+
|
973
|
+
// ../../node_modules/nanoid/non-secure/index.js
|
974
|
+
var customAlphabet = (alphabet, defaultSize = 21) => {
|
975
|
+
return (size = defaultSize) => {
|
976
|
+
let id = "";
|
977
|
+
let i = size;
|
978
|
+
while (i--) {
|
979
|
+
id += alphabet[Math.random() * alphabet.length | 0];
|
980
|
+
}
|
981
|
+
return id;
|
982
|
+
};
|
983
|
+
};
|
984
|
+
|
985
|
+
// src/adapters/MessageRepository.tsx
|
986
|
+
var generateId = customAlphabet(
|
987
|
+
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
988
|
+
7
|
989
|
+
);
|
990
|
+
var optimisticPrefix = "__optimistic__";
|
991
|
+
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
992
|
+
var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
993
|
+
var findHead = (message) => {
|
994
|
+
if (message.next)
|
995
|
+
return findHead(message.next);
|
996
|
+
return message;
|
997
|
+
};
|
998
|
+
var MessageRepository = class {
|
999
|
+
messages = /* @__PURE__ */ new Map();
|
1000
|
+
// message_id -> item
|
1001
|
+
head = null;
|
1002
|
+
rootChildren = [];
|
1003
|
+
getMessages() {
|
1004
|
+
const messages = new Array(this.head?.level ?? 0);
|
1005
|
+
for (let current = this.head; current; current = current.prev) {
|
1006
|
+
messages[current.level] = current.current;
|
1007
|
+
}
|
1008
|
+
return messages;
|
1009
|
+
}
|
1010
|
+
addOrUpdateMessage(message) {
|
1011
|
+
const item = this.messages.get(message.id);
|
1012
|
+
if (item) {
|
1013
|
+
if (item.current.parentId !== message.parentId) {
|
1014
|
+
this.deleteMessage(message.id);
|
1015
|
+
} else {
|
1016
|
+
item.current = message;
|
1017
|
+
return;
|
1018
|
+
}
|
1019
|
+
}
|
1020
|
+
const prev = message.parentId ? this.messages.get(message.parentId) : null;
|
1021
|
+
if (prev === void 0)
|
1022
|
+
throw new Error("Unexpected: Parent message not found");
|
1023
|
+
const newItem = {
|
1024
|
+
prev,
|
1025
|
+
current: message,
|
1026
|
+
next: null,
|
1027
|
+
children: [],
|
1028
|
+
level: prev ? prev.level + 1 : 0
|
1029
|
+
};
|
1030
|
+
this.messages.set(message.id, newItem);
|
1031
|
+
if (prev) {
|
1032
|
+
prev.children = [...prev.children, message.id];
|
1033
|
+
prev.next = newItem;
|
1034
|
+
} else {
|
1035
|
+
this.rootChildren = [...this.rootChildren, message.id];
|
1036
|
+
}
|
1037
|
+
if (this.head === prev) {
|
1038
|
+
this.head = newItem;
|
1039
|
+
}
|
1040
|
+
}
|
1041
|
+
deleteMessage(messageId) {
|
1042
|
+
const message = this.messages.get(messageId);
|
1043
|
+
if (!message)
|
1044
|
+
throw new Error("Unexpected: Message not found");
|
1045
|
+
if (message.children.length > 0) {
|
1046
|
+
for (const child of message.children) {
|
1047
|
+
this.deleteMessage(child);
|
1048
|
+
}
|
1049
|
+
}
|
1050
|
+
this.messages.delete(messageId);
|
1051
|
+
if (message.prev) {
|
1052
|
+
message.prev.children = message.prev.children.filter(
|
1053
|
+
(m) => m !== messageId
|
1054
|
+
);
|
1055
|
+
if (message.prev.next === message) {
|
1056
|
+
const childId = message.prev.children.at(-1);
|
1057
|
+
const child = childId ? this.messages.get(childId) : null;
|
1058
|
+
if (child === void 0)
|
1059
|
+
throw new Error("Unexpected: Child message not found");
|
1060
|
+
message.prev.next = child;
|
1061
|
+
}
|
1062
|
+
} else {
|
1063
|
+
this.rootChildren = this.rootChildren.filter((m) => m !== messageId);
|
1064
|
+
}
|
1065
|
+
if (this.head === message) {
|
1066
|
+
this.head = message.prev ? findHead(message.prev) : null;
|
1067
|
+
}
|
1068
|
+
}
|
1069
|
+
getOptimisticId = () => {
|
1070
|
+
let optimisticId;
|
1071
|
+
do {
|
1072
|
+
optimisticId = generateOptimisticId();
|
1073
|
+
} while (this.messages.has(optimisticId));
|
1074
|
+
return optimisticId;
|
1075
|
+
};
|
1076
|
+
commitOptimisticRun(parentId) {
|
1077
|
+
const optimisticId = this.getOptimisticId();
|
1078
|
+
this.addOrUpdateMessage({
|
1079
|
+
id: optimisticId,
|
1080
|
+
role: "assistant",
|
1081
|
+
content: [
|
1082
|
+
{
|
1083
|
+
type: "text",
|
1084
|
+
text: ""
|
1085
|
+
}
|
1086
|
+
],
|
1087
|
+
parentId,
|
1088
|
+
createdAt: /* @__PURE__ */ new Date()
|
1089
|
+
});
|
1090
|
+
return optimisticId;
|
1091
|
+
}
|
1092
|
+
getBranches(messageId) {
|
1093
|
+
const message = this.messages.get(messageId);
|
1094
|
+
if (!message)
|
1095
|
+
throw new Error("Unexpected: Message not found");
|
1096
|
+
if (message.prev) {
|
1097
|
+
return message.prev.children;
|
1098
|
+
}
|
1099
|
+
return this.rootChildren;
|
1100
|
+
}
|
1101
|
+
switchToBranch(messageId) {
|
1102
|
+
const message = this.messages.get(messageId);
|
1103
|
+
if (!message)
|
1104
|
+
throw new Error("Unexpected: Branch not found");
|
1105
|
+
if (message.prev) {
|
1106
|
+
message.prev.next = message;
|
1107
|
+
}
|
1108
|
+
this.head = findHead(message);
|
1109
|
+
}
|
1110
|
+
resetHead(messageId) {
|
1111
|
+
if (messageId) {
|
1112
|
+
const message = this.messages.get(messageId);
|
1113
|
+
if (!message)
|
1114
|
+
throw new Error("Unexpected: Branch not found");
|
1115
|
+
this.head = message;
|
1116
|
+
for (let current = message; current; current = current.prev) {
|
1117
|
+
if (current.prev) {
|
1118
|
+
current.prev.next = current;
|
1119
|
+
}
|
1120
|
+
}
|
1121
|
+
} else {
|
1122
|
+
this.head = null;
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
};
|
1126
|
+
|
1127
|
+
// src/adapters/vercel/useVercelAIBranches.tsx
|
1128
|
+
var sliceMessagesUntil = (messages, messageId) => {
|
1129
|
+
if (messageId == null)
|
1130
|
+
return [];
|
1131
|
+
if (isOptimisticId(messageId))
|
1132
|
+
return messages;
|
1133
|
+
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1134
|
+
if (messageIdx === -1)
|
1135
|
+
throw new Error("Unexpected: Message not found");
|
1136
|
+
return messages.slice(0, messageIdx + 1);
|
1137
|
+
};
|
1138
|
+
var hasUpcomingMessage = (isRunning, messages) => {
|
1139
|
+
return isRunning && messages[messages.length - 1]?.role !== "assistant";
|
1140
|
+
};
|
1141
|
+
var useVercelAIBranches = (chat, messages) => {
|
1142
|
+
const [data] = (0, import_react21.useState)(() => new MessageRepository());
|
1143
|
+
const isRunning = "isLoading" in chat ? chat.isLoading : chat.status === "in_progress";
|
1144
|
+
const assistantOptimisticIdRef = (0, import_react21.useRef)(null);
|
1145
|
+
const messagesEx = (0, import_react21.useMemo)(() => {
|
1146
|
+
for (const message of messages) {
|
1147
|
+
data.addOrUpdateMessage(message);
|
1148
|
+
}
|
1149
|
+
if (assistantOptimisticIdRef.current) {
|
1150
|
+
data.deleteMessage(assistantOptimisticIdRef.current);
|
1151
|
+
assistantOptimisticIdRef.current = null;
|
1152
|
+
}
|
1153
|
+
if (hasUpcomingMessage(isRunning, messages)) {
|
1154
|
+
assistantOptimisticIdRef.current = data.commitOptimisticRun(
|
1155
|
+
messages.at(-1)?.id ?? null
|
1156
|
+
);
|
1157
|
+
}
|
1158
|
+
data.resetHead(
|
1159
|
+
assistantOptimisticIdRef.current ?? messages.at(-1)?.id ?? null
|
1160
|
+
);
|
1161
|
+
return data.getMessages();
|
1162
|
+
}, [data, isRunning, messages]);
|
1163
|
+
const getBranches = (0, import_react21.useCallback)(
|
1164
|
+
(messageId) => {
|
1165
|
+
return data.getBranches(messageId);
|
1166
|
+
},
|
1167
|
+
[data]
|
1168
|
+
);
|
1169
|
+
const switchToBranch = (0, import_react21.useCallback)(
|
1170
|
+
(messageId) => {
|
1171
|
+
data.switchToBranch(messageId);
|
1172
|
+
chat.setMessages(
|
1173
|
+
data.getMessages().filter((m) => !isOptimisticId(m.id)).map((m) => m.innerMessage)
|
1174
|
+
);
|
1175
|
+
},
|
1176
|
+
[data, chat.setMessages]
|
1177
|
+
);
|
1178
|
+
const reloadMaybe = "reload" in chat ? chat.reload : void 0;
|
1179
|
+
const startRun = (0, import_react21.useCallback)(
|
1180
|
+
async (parentId) => {
|
1181
|
+
if (!reloadMaybe)
|
1182
|
+
throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
|
1183
|
+
const newMessages = sliceMessagesUntil(chat.messages, parentId);
|
1184
|
+
chat.setMessages(newMessages);
|
1185
|
+
await reloadMaybe();
|
1186
|
+
},
|
1187
|
+
[chat.messages, chat.setMessages, reloadMaybe]
|
1188
|
+
);
|
1189
|
+
const append = (0, import_react21.useCallback)(
|
1190
|
+
async (message) => {
|
1191
|
+
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1192
|
+
throw new Error("Only text content is supported by Vercel AI SDK");
|
1193
|
+
const newMessages = sliceMessagesUntil(chat.messages, message.parentId);
|
1194
|
+
chat.setMessages(newMessages);
|
1195
|
+
await chat.append({
|
1196
|
+
role: "user",
|
1197
|
+
content: message.content[0].text
|
1198
|
+
});
|
1199
|
+
},
|
1200
|
+
[chat.messages, chat.setMessages, chat.append]
|
1201
|
+
);
|
1202
|
+
return (0, import_react21.useMemo)(
|
1203
|
+
() => ({
|
1204
|
+
messages: messagesEx,
|
1205
|
+
getBranches,
|
1206
|
+
switchToBranch,
|
1207
|
+
append,
|
1208
|
+
startRun
|
1209
|
+
}),
|
1210
|
+
[messagesEx, getBranches, switchToBranch, append, startRun]
|
1211
|
+
);
|
1212
|
+
};
|
1213
|
+
|
1090
1214
|
// src/adapters/vercel/VercelAIAssistantProvider.tsx
|
1215
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
1091
1216
|
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
1092
|
-
var vercelToThreadMessage = (message, parentId
|
1217
|
+
var vercelToThreadMessage = (message, parentId) => {
|
1093
1218
|
if (message.role !== "user" && message.role !== "assistant")
|
1094
1219
|
throw new Error("Unsupported role");
|
1095
1220
|
return {
|
@@ -1097,24 +1222,17 @@ var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
|
|
1097
1222
|
id: message.id,
|
1098
1223
|
role: message.role,
|
1099
1224
|
content: [{ type: "text", text: message.content }],
|
1100
|
-
|
1101
|
-
|
1102
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1225
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1226
|
+
innerMessage: message
|
1103
1227
|
};
|
1104
1228
|
};
|
1105
|
-
var vercelToCachedThreadMessages = (messages
|
1229
|
+
var vercelToCachedThreadMessages = (messages) => {
|
1106
1230
|
return messages.map((m, idx) => {
|
1107
1231
|
const cached = ThreadMessageCache.get(m);
|
1108
|
-
const parentId = messages[idx - 1]?.id ??
|
1109
|
-
|
1110
|
-
if (cached && cached.parentId === parentId && cached.branchId === branchId && cached.branchCount === branchCount)
|
1232
|
+
const parentId = messages[idx - 1]?.id ?? null;
|
1233
|
+
if (cached && cached.parentId === parentId)
|
1111
1234
|
return cached;
|
1112
|
-
const newMessage = vercelToThreadMessage(
|
1113
|
-
m,
|
1114
|
-
parentId,
|
1115
|
-
branchId,
|
1116
|
-
branchCount
|
1117
|
-
);
|
1235
|
+
const newMessage = vercelToThreadMessage(m, parentId);
|
1118
1236
|
ThreadMessageCache.set(m, newMessage);
|
1119
1237
|
return newMessage;
|
1120
1238
|
});
|
@@ -1125,13 +1243,10 @@ var VercelAIAssistantProvider = ({
|
|
1125
1243
|
}) => {
|
1126
1244
|
const context = useDummyAIAssistantContext();
|
1127
1245
|
const vercel = "chat" in rest ? rest.chat : rest.assistant;
|
1128
|
-
const branches = useVercelAIBranches(vercel, context);
|
1129
1246
|
const messages = (0, import_react22.useMemo)(() => {
|
1130
|
-
return vercelToCachedThreadMessages(
|
1131
|
-
|
1132
|
-
|
1133
|
-
);
|
1134
|
-
}, [vercel.messages, branches.getBranchState]);
|
1247
|
+
return vercelToCachedThreadMessages(vercel.messages);
|
1248
|
+
}, [vercel.messages]);
|
1249
|
+
const branches = useVercelAIBranches(vercel, messages);
|
1135
1250
|
const cancelRun = (0, import_react22.useCallback)(() => {
|
1136
1251
|
const lastMessage = vercel.messages.at(-1);
|
1137
1252
|
vercel.stop();
|
@@ -1141,27 +1256,31 @@ var VercelAIAssistantProvider = ({
|
|
1141
1256
|
}, [vercel.messages, vercel.stop, vercel.setInput]);
|
1142
1257
|
const isRunning = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
|
1143
1258
|
(0, import_react22.useMemo)(() => {
|
1144
|
-
context.useThread.setState(
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1259
|
+
context.useThread.setState(
|
1260
|
+
{
|
1261
|
+
messages: branches.messages,
|
1262
|
+
isRunning,
|
1263
|
+
getBranches: branches.getBranches,
|
1264
|
+
switchToBranch: branches.switchToBranch,
|
1265
|
+
append: branches.append,
|
1266
|
+
startRun: branches.startRun,
|
1267
|
+
cancelRun
|
1268
|
+
},
|
1269
|
+
true
|
1270
|
+
);
|
1271
|
+
}, [context, isRunning, cancelRun, branches]);
|
1153
1272
|
(0, import_react22.useMemo)(() => {
|
1154
1273
|
context.useComposer.setState({
|
1155
|
-
canCancel: isRunning,
|
1156
1274
|
value: vercel.input,
|
1157
1275
|
setValue: vercel.setInput
|
1158
1276
|
});
|
1159
|
-
}, [context,
|
1160
|
-
return /* @__PURE__ */
|
1277
|
+
}, [context, vercel.input, vercel.setInput]);
|
1278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AssistantContext.Provider, { value: context, children });
|
1161
1279
|
};
|
1162
1280
|
|
1163
1281
|
// src/adapters/vercel/VercelRSCAssistantProvider.tsx
|
1164
1282
|
var import_react23 = require("react");
|
1283
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
1165
1284
|
var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
|
1166
1285
|
var vercelToThreadMessage2 = (parentId, message) => {
|
1167
1286
|
if (message.role !== "user" && message.role !== "assistant")
|
@@ -1171,15 +1290,13 @@ var vercelToThreadMessage2 = (parentId, message) => {
|
|
1171
1290
|
id: message.id,
|
1172
1291
|
role: message.role,
|
1173
1292
|
content: [{ type: "ui", display: message.display }],
|
1174
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1175
|
-
branchId: 0,
|
1176
|
-
branchCount: 1
|
1293
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1177
1294
|
};
|
1178
1295
|
};
|
1179
1296
|
var vercelToCachedThreadMessages2 = (messages) => {
|
1180
1297
|
return messages.map((m, idx) => {
|
1181
1298
|
const cached = ThreadMessageCache2.get(m);
|
1182
|
-
const parentId = messages[idx - 1]?.id ??
|
1299
|
+
const parentId = messages[idx - 1]?.id ?? null;
|
1183
1300
|
if (cached && cached.parentId === parentId)
|
1184
1301
|
return cached;
|
1185
1302
|
const newMessage = vercelToThreadMessage2(parentId, m);
|
@@ -1198,12 +1315,11 @@ var VercelRSCAssistantProvider = ({
|
|
1198
1315
|
}, [vercelMessages]);
|
1199
1316
|
const append = (0, import_react23.useCallback)(
|
1200
1317
|
async (message) => {
|
1201
|
-
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ??
|
1318
|
+
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null))
|
1202
1319
|
throw new Error("Unexpected: Message editing is not supported");
|
1203
1320
|
if (message.content[0]?.type !== "text") {
|
1204
1321
|
throw new Error("Only text content is currently supported");
|
1205
1322
|
}
|
1206
|
-
context.useViewport.getState().scrollToBottom();
|
1207
1323
|
await vercelAppend(message);
|
1208
1324
|
},
|
1209
1325
|
[context, vercelAppend]
|
@@ -1214,7 +1330,7 @@ var VercelRSCAssistantProvider = ({
|
|
1214
1330
|
append
|
1215
1331
|
});
|
1216
1332
|
}, [context, messages, append]);
|
1217
|
-
return /* @__PURE__ */
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AssistantContext.Provider, { value: context, children });
|
1218
1334
|
};
|
1219
1335
|
// Annotate the CommonJS export names for ESM import in node:
|
1220
1336
|
0 && (module.exports = {
|