@assistant-ui/react 0.0.9 → 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 +29 -27
- package/dist/index.d.ts +29 -27
- package/dist/index.js +536 -384
- package/dist/index.mjs +514 -360
- 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
|
|
@@ -86,9 +87,9 @@ var useThreadIf = (props) => {
|
|
86
87
|
return false;
|
87
88
|
if (props.empty === false && thread.messages.length === 0)
|
88
89
|
return false;
|
89
|
-
if (props.
|
90
|
+
if (props.running === true && !thread.isRunning)
|
90
91
|
return false;
|
91
|
-
if (props.
|
92
|
+
if (props.running === false && thread.isRunning)
|
92
93
|
return false;
|
93
94
|
return true;
|
94
95
|
});
|
@@ -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
|
@@ -153,20 +155,21 @@ var import_react4 = require("react");
|
|
153
155
|
var useOnScrollToBottom = (callback) => {
|
154
156
|
const callbackRef = (0, import_react4.useRef)(callback);
|
155
157
|
callbackRef.current = callback;
|
156
|
-
const {
|
158
|
+
const { useViewport } = useAssistantContext();
|
157
159
|
(0, import_react4.useEffect)(() => {
|
158
|
-
return
|
160
|
+
return useViewport.getState().onScrollToBottom(() => {
|
159
161
|
callbackRef.current();
|
160
162
|
});
|
161
|
-
}, [
|
163
|
+
}, [useViewport]);
|
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);
|
168
171
|
const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, divRef);
|
169
|
-
const {
|
172
|
+
const { useViewport } = useAssistantContext();
|
170
173
|
const firstRenderRef = (0, import_react5.useRef)(true);
|
171
174
|
const lastScrollTop = (0, import_react5.useRef)(0);
|
172
175
|
const scrollToBottom = () => {
|
@@ -175,11 +178,11 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
|
|
175
178
|
return;
|
176
179
|
const behavior = firstRenderRef.current ? "instant" : "auto";
|
177
180
|
firstRenderRef.current = false;
|
178
|
-
|
181
|
+
useViewport.setState({ isAtBottom: true });
|
179
182
|
div.scrollIntoView({ behavior });
|
180
183
|
};
|
181
184
|
useOnResizeContent(divRef, () => {
|
182
|
-
if (!
|
185
|
+
if (!useViewport.getState().isAtBottom)
|
183
186
|
return;
|
184
187
|
scrollToBottom();
|
185
188
|
});
|
@@ -190,173 +193,36 @@ var ThreadViewport = (0, import_react5.forwardRef)(({ autoScroll = true, onScrol
|
|
190
193
|
const div = divRef.current;
|
191
194
|
if (!div)
|
192
195
|
return;
|
193
|
-
const isAtBottom =
|
196
|
+
const isAtBottom = useViewport.getState().isAtBottom;
|
194
197
|
const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
|
195
198
|
if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
|
196
199
|
} else if (newIsAtBottom !== isAtBottom) {
|
197
|
-
|
200
|
+
useViewport.setState({ isAtBottom: newIsAtBottom });
|
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 reload = (0, import_react6.useCallback)(
|
314
|
-
async (messageId) => {
|
315
|
-
if (!reloadMaybe)
|
316
|
-
throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
|
317
|
-
const newMessages = sliceMessagesUntil(chat.messages, messageId);
|
318
|
-
chat.setMessages(newMessages);
|
319
|
-
context.useThread.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.useThread.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
|
-
reload
|
344
|
-
}),
|
345
|
-
[getBranchState, switchToBranch, append, reload]
|
346
|
-
);
|
347
|
-
};
|
348
|
-
var hasUpcomingMessage = (thread) => {
|
349
|
-
return thread.isLoading && 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,17 +264,72 @@ __export(message_exports, {
|
|
398
264
|
});
|
399
265
|
|
400
266
|
// src/primitives/message/MessageProvider.tsx
|
401
|
-
var
|
267
|
+
var import_react8 = require("react");
|
268
|
+
var import_zustand2 = require("zustand");
|
269
|
+
|
270
|
+
// src/utils/context/stores/ComposerStore.ts
|
402
271
|
var import_zustand = require("zustand");
|
272
|
+
var makeBaseComposer = (set) => ({
|
273
|
+
value: "",
|
274
|
+
setValue: (value) => {
|
275
|
+
set({ value });
|
276
|
+
}
|
277
|
+
});
|
278
|
+
var makeMessageComposerStore = ({
|
279
|
+
onEdit,
|
280
|
+
onSend
|
281
|
+
}) => (0, import_zustand.create)()((set, get, store) => ({
|
282
|
+
...makeBaseComposer(set, get, store),
|
283
|
+
isEditing: false,
|
284
|
+
edit: () => {
|
285
|
+
const value = onEdit();
|
286
|
+
set({ isEditing: true, value });
|
287
|
+
},
|
288
|
+
send: () => {
|
289
|
+
const value = get().value;
|
290
|
+
set({ isEditing: false });
|
291
|
+
onSend(value);
|
292
|
+
},
|
293
|
+
cancel: () => {
|
294
|
+
if (!get().isEditing)
|
295
|
+
return false;
|
296
|
+
set({ isEditing: false });
|
297
|
+
return true;
|
298
|
+
}
|
299
|
+
}));
|
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
|
+
});
|
321
|
+
|
322
|
+
// src/primitives/message/MessageProvider.tsx
|
323
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
403
324
|
var getIsLast = (thread, message) => {
|
404
|
-
|
405
|
-
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;
|
406
326
|
};
|
407
327
|
var useMessageContext2 = () => {
|
408
|
-
const
|
409
|
-
|
410
|
-
const useMessage = (0,
|
328
|
+
const { useThread } = useAssistantContext();
|
329
|
+
const [context] = (0, import_react8.useState)(() => {
|
330
|
+
const useMessage = (0, import_zustand2.create)(() => ({
|
411
331
|
message: null,
|
332
|
+
branches: [],
|
412
333
|
isLast: false,
|
413
334
|
isCopied: false,
|
414
335
|
isHovering: false,
|
@@ -417,34 +338,23 @@ var useMessageContext2 = () => {
|
|
417
338
|
setIsHovering: () => {
|
418
339
|
}
|
419
340
|
}));
|
420
|
-
const useComposer = (
|
421
|
-
|
422
|
-
canCancel: true,
|
423
|
-
edit: () => {
|
341
|
+
const useComposer = makeMessageComposerStore({
|
342
|
+
onEdit: () => {
|
424
343
|
const message = useMessage.getState().message;
|
425
344
|
if (message.role !== "user")
|
426
345
|
throw new Error("Editing is only supported for user messages");
|
427
346
|
if (message.content[0]?.type !== "text")
|
428
347
|
throw new Error("Editing is only supported for text-only messages");
|
429
|
-
return
|
430
|
-
isEditing: true,
|
431
|
-
value: message.content[0].text
|
432
|
-
});
|
348
|
+
return message.content[0].text;
|
433
349
|
},
|
434
|
-
|
435
|
-
send: () => {
|
350
|
+
onSend: (text) => {
|
436
351
|
const message = useMessage.getState().message;
|
437
|
-
if (message.role !== "user")
|
438
|
-
throw new Error("Editing is only supported for user messages");
|
439
352
|
useThread.getState().append({
|
440
353
|
parentId: message.parentId,
|
441
|
-
content: [{ type: "text", text
|
354
|
+
content: [{ type: "text", text }]
|
442
355
|
});
|
443
|
-
|
444
|
-
|
445
|
-
value: "",
|
446
|
-
setValue: (value) => set({ value })
|
447
|
-
}));
|
356
|
+
}
|
357
|
+
});
|
448
358
|
return { useMessage, useComposer };
|
449
359
|
});
|
450
360
|
return context;
|
@@ -456,12 +366,14 @@ var MessageProvider = ({
|
|
456
366
|
const { useThread } = useAssistantContext();
|
457
367
|
const context = useMessageContext2();
|
458
368
|
const isLast = useThread((thread) => getIsLast(thread, message));
|
459
|
-
const
|
460
|
-
const [
|
461
|
-
(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)(() => {
|
462
373
|
context.useMessage.setState(
|
463
374
|
{
|
464
375
|
message,
|
376
|
+
branches,
|
465
377
|
isLast,
|
466
378
|
isCopied,
|
467
379
|
isHovering,
|
@@ -470,15 +382,16 @@ var MessageProvider = ({
|
|
470
382
|
},
|
471
383
|
true
|
472
384
|
);
|
473
|
-
}, [context, message, isLast, isCopied, isHovering]);
|
474
|
-
return /* @__PURE__ */
|
385
|
+
}, [context, message, branches, isLast, isCopied, isHovering]);
|
386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
|
475
387
|
};
|
476
388
|
|
477
389
|
// src/primitives/message/MessageRoot.tsx
|
478
390
|
var import_primitive2 = require("@radix-ui/primitive");
|
479
391
|
var import_react_primitive3 = require("@radix-ui/react-primitive");
|
480
|
-
var
|
481
|
-
var
|
392
|
+
var import_react9 = require("react");
|
393
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
394
|
+
var MessageRoot = (0, import_react9.forwardRef)(
|
482
395
|
({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
|
483
396
|
const { useMessage } = useMessageContext();
|
484
397
|
const setIsHovering = useMessage((s) => s.setIsHovering);
|
@@ -488,7 +401,7 @@ var MessageRoot = (0, import_react10.forwardRef)(
|
|
488
401
|
const handleMouseLeave = () => {
|
489
402
|
setIsHovering(false);
|
490
403
|
};
|
491
|
-
return /* @__PURE__ */
|
404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
492
405
|
import_react_primitive3.Primitive.div,
|
493
406
|
{
|
494
407
|
...rest,
|
@@ -503,8 +416,8 @@ var MessageRoot = (0, import_react10.forwardRef)(
|
|
503
416
|
// src/primitives/message/MessageIf.tsx
|
504
417
|
var useMessageIf = (props) => {
|
505
418
|
const { useMessage } = useMessageContext();
|
506
|
-
return useMessage(({ message, isLast, isCopied, isHovering }) => {
|
507
|
-
if (props.hasBranches === true &&
|
419
|
+
return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
|
420
|
+
if (props.hasBranches === true && branches.length < 2)
|
508
421
|
return false;
|
509
422
|
if (props.user && message.role !== "user")
|
510
423
|
return false;
|
@@ -525,8 +438,9 @@ var MessageIf = ({ children, ...query }) => {
|
|
525
438
|
};
|
526
439
|
|
527
440
|
// src/primitives/message/MessageContent.tsx
|
441
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
528
442
|
var defaultComponents = {
|
529
|
-
Text: ({ part }) => /* @__PURE__ */
|
443
|
+
Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: part.text }),
|
530
444
|
Image: () => null,
|
531
445
|
UI: ({ part }) => part.display,
|
532
446
|
tools: {
|
@@ -543,26 +457,27 @@ var MessageContent = ({
|
|
543
457
|
}) => {
|
544
458
|
const { useMessage } = useMessageContext();
|
545
459
|
const content = useMessage((s) => s.message.content);
|
546
|
-
return /* @__PURE__ */
|
460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: content.map((part, i) => {
|
547
461
|
const key = i;
|
548
462
|
switch (part.type) {
|
549
463
|
case "text":
|
550
|
-
return /* @__PURE__ */
|
464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { part }, key);
|
551
465
|
case "image":
|
552
|
-
return /* @__PURE__ */
|
466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Image, { part }, key);
|
553
467
|
case "ui":
|
554
|
-
return /* @__PURE__ */
|
468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(UI, { part }, key);
|
555
469
|
case "tool-call": {
|
556
470
|
const Tool = by_name[part.name] || Fallback;
|
557
|
-
return /* @__PURE__ */
|
471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tool, { part }, key);
|
558
472
|
}
|
559
473
|
default:
|
560
474
|
return null;
|
561
475
|
}
|
562
|
-
}));
|
476
|
+
}) });
|
563
477
|
};
|
564
478
|
|
565
479
|
// src/primitives/thread/ThreadMessages.tsx
|
480
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
566
481
|
var getComponents = (components) => {
|
567
482
|
return {
|
568
483
|
EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
|
@@ -577,41 +492,32 @@ var ThreadMessages = ({ components }) => {
|
|
577
492
|
const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
|
578
493
|
if (messages.length === 0)
|
579
494
|
return null;
|
580
|
-
return /* @__PURE__ */
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: messages.map((message, idx) => {
|
581
496
|
return (
|
582
497
|
// biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
|
583
|
-
/* @__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)
|
584
505
|
);
|
585
|
-
})
|
586
|
-
MessageProvider,
|
587
|
-
{
|
588
|
-
message: {
|
589
|
-
id: UPCOMING_MESSAGE_ID,
|
590
|
-
role: "assistant",
|
591
|
-
content: [{ type: "text", text: "..." }],
|
592
|
-
parentId: messages.at(-1)?.id ?? ROOT_PARENT_ID,
|
593
|
-
// TODO fix these (move upcoming message to AssistantContext)
|
594
|
-
branchId: 0,
|
595
|
-
branchCount: 1,
|
596
|
-
createdAt: /* @__PURE__ */ new Date()
|
597
|
-
}
|
598
|
-
},
|
599
|
-
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
600
|
-
));
|
506
|
+
}) });
|
601
507
|
};
|
602
508
|
|
603
509
|
// src/primitives/thread/ThreadScrollToBottom.tsx
|
604
510
|
var import_primitive3 = require("@radix-ui/primitive");
|
605
511
|
var import_react_primitive4 = require("@radix-ui/react-primitive");
|
606
|
-
var
|
607
|
-
var
|
608
|
-
|
609
|
-
const
|
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) => {
|
515
|
+
const { useViewport } = useAssistantContext();
|
516
|
+
const isAtBottom = useViewport((s) => s.isAtBottom);
|
610
517
|
const handleScrollToBottom = () => {
|
611
|
-
|
612
|
-
thread.scrollToBottom();
|
518
|
+
useViewport.getState().scrollToBottom();
|
613
519
|
};
|
614
|
-
return /* @__PURE__ */
|
520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
615
521
|
import_react_primitive4.Primitive.button,
|
616
522
|
{
|
617
523
|
...rest,
|
@@ -636,11 +542,13 @@ __export(composer_exports, {
|
|
636
542
|
var import_primitive4 = require("@radix-ui/primitive");
|
637
543
|
var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
|
638
544
|
var import_react_primitive5 = require("@radix-ui/react-primitive");
|
639
|
-
var
|
640
|
-
var
|
545
|
+
var import_react11 = require("react");
|
546
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
547
|
+
var ComposerRoot = (0, import_react11.forwardRef)(
|
641
548
|
({ onSubmit, ...rest }, forwardedRef) => {
|
549
|
+
const { useViewport } = useAssistantContext();
|
642
550
|
const { useComposer } = useComposerContext();
|
643
|
-
const formRef = (0,
|
551
|
+
const formRef = (0, import_react11.useRef)(null);
|
644
552
|
const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
|
645
553
|
const handleSubmit = (e) => {
|
646
554
|
const composerState = useComposer.getState();
|
@@ -648,8 +556,9 @@ var ComposerRoot = (0, import_react12.forwardRef)(
|
|
648
556
|
return;
|
649
557
|
e.preventDefault();
|
650
558
|
composerState.send();
|
559
|
+
useViewport.getState().scrollToBottom();
|
651
560
|
};
|
652
|
-
return /* @__PURE__ */
|
561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
653
562
|
import_react_primitive5.Primitive.form,
|
654
563
|
{
|
655
564
|
...rest,
|
@@ -664,11 +573,12 @@ var ComposerRoot = (0, import_react12.forwardRef)(
|
|
664
573
|
var import_primitive5 = require("@radix-ui/primitive");
|
665
574
|
var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
|
666
575
|
var import_react_slot = require("@radix-ui/react-slot");
|
667
|
-
var
|
576
|
+
var import_react12 = require("react");
|
668
577
|
var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
|
669
|
-
var
|
578
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
579
|
+
var ComposerInput = (0, import_react12.forwardRef)(
|
670
580
|
({ autoFocus, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
|
671
|
-
const { useThread } = useAssistantContext();
|
581
|
+
const { useThread, useViewport } = useAssistantContext();
|
672
582
|
const { useComposer, type } = useComposerContext();
|
673
583
|
const value = useComposer((c) => {
|
674
584
|
if (!c.isEditing)
|
@@ -680,22 +590,23 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
680
590
|
if (disabled)
|
681
591
|
return;
|
682
592
|
const composer = useComposer.getState();
|
683
|
-
if (e.key === "Escape"
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
if (e.key === "Enter" && e.shiftKey === false) {
|
688
|
-
const
|
689
|
-
if (!
|
593
|
+
if (e.key === "Escape") {
|
594
|
+
if (useComposer.getState().cancel()) {
|
595
|
+
e.preventDefault();
|
596
|
+
}
|
597
|
+
} else if (e.key === "Enter" && e.shiftKey === false) {
|
598
|
+
const isRunning = useThread.getState().isRunning;
|
599
|
+
if (!isRunning) {
|
690
600
|
e.preventDefault();
|
691
601
|
composer.send();
|
602
|
+
useViewport.getState().scrollToBottom();
|
692
603
|
}
|
693
604
|
}
|
694
605
|
};
|
695
|
-
const textareaRef = (0,
|
606
|
+
const textareaRef = (0, import_react12.useRef)(null);
|
696
607
|
const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
|
697
608
|
const autoFocusEnabled = autoFocus !== false && !disabled;
|
698
|
-
const focus = (0,
|
609
|
+
const focus = (0, import_react12.useCallback)(() => {
|
699
610
|
const textarea = textareaRef.current;
|
700
611
|
if (!textarea || !autoFocusEnabled)
|
701
612
|
return;
|
@@ -705,13 +616,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
705
616
|
textareaRef.current.value.length
|
706
617
|
);
|
707
618
|
}, [autoFocusEnabled]);
|
708
|
-
(0,
|
619
|
+
(0, import_react12.useEffect)(() => focus(), [focus]);
|
709
620
|
useOnScrollToBottom(() => {
|
710
621
|
if (type === "assistant") {
|
711
622
|
focus();
|
712
623
|
}
|
713
624
|
});
|
714
|
-
return /* @__PURE__ */
|
625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
715
626
|
Component,
|
716
627
|
{
|
717
628
|
value,
|
@@ -732,12 +643,13 @@ var ComposerInput = (0, import_react13.forwardRef)(
|
|
732
643
|
|
733
644
|
// src/primitives/composer/ComposerSend.tsx
|
734
645
|
var import_react_primitive6 = require("@radix-ui/react-primitive");
|
735
|
-
var
|
736
|
-
var
|
646
|
+
var import_react13 = require("react");
|
647
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
648
|
+
var ComposerSend = (0, import_react13.forwardRef)(
|
737
649
|
({ disabled, ...rest }, ref) => {
|
738
650
|
const { useComposer } = useComposerContext();
|
739
651
|
const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
|
740
|
-
return /* @__PURE__ */
|
652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
741
653
|
import_react_primitive6.Primitive.button,
|
742
654
|
{
|
743
655
|
type: "submit",
|
@@ -752,21 +664,20 @@ var ComposerSend = (0, import_react14.forwardRef)(
|
|
752
664
|
// src/primitives/composer/ComposerCancel.tsx
|
753
665
|
var import_primitive6 = require("@radix-ui/primitive");
|
754
666
|
var import_react_primitive7 = require("@radix-ui/react-primitive");
|
755
|
-
var
|
756
|
-
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) => {
|
757
670
|
const { useComposer } = useComposerContext();
|
758
|
-
const
|
759
|
-
const handleClose = () => {
|
671
|
+
const handleCancel = () => {
|
760
672
|
useComposer.getState().cancel();
|
761
673
|
};
|
762
|
-
return /* @__PURE__ */
|
674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
763
675
|
import_react_primitive7.Primitive.button,
|
764
676
|
{
|
765
677
|
type: "button",
|
766
678
|
...rest,
|
767
679
|
ref,
|
768
|
-
onClick: (0, import_primitive6.composeEventHandlers)(onClick,
|
769
|
-
disabled: disabled || !hasValue
|
680
|
+
onClick: (0, import_primitive6.composeEventHandlers)(onClick, handleCancel)
|
770
681
|
}
|
771
682
|
);
|
772
683
|
});
|
@@ -782,10 +693,10 @@ __export(branchPicker_exports, {
|
|
782
693
|
});
|
783
694
|
|
784
695
|
// src/utils/context/combined/useCombinedStore.ts
|
785
|
-
var
|
696
|
+
var import_react16 = require("react");
|
786
697
|
|
787
698
|
// src/utils/context/combined/createCombinedStore.ts
|
788
|
-
var
|
699
|
+
var import_react15 = require("react");
|
789
700
|
var createCombinedStore = (stores) => {
|
790
701
|
const subscribe = (callback) => {
|
791
702
|
const unsubscribes = stores.map((store) => store.subscribe(callback));
|
@@ -797,41 +708,42 @@ var createCombinedStore = (stores) => {
|
|
797
708
|
};
|
798
709
|
return (selector) => {
|
799
710
|
const getSnapshot = () => selector(...stores.map((store) => store.getState()));
|
800
|
-
return (0,
|
711
|
+
return (0, import_react15.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
801
712
|
};
|
802
713
|
};
|
803
714
|
|
804
715
|
// src/utils/context/combined/useCombinedStore.ts
|
805
716
|
var useCombinedStore = (stores, selector) => {
|
806
|
-
const useCombined = (0,
|
717
|
+
const useCombined = (0, import_react16.useMemo)(() => createCombinedStore(stores), stores);
|
807
718
|
return useCombined(selector);
|
808
719
|
};
|
809
720
|
|
810
721
|
// src/actions/useGoToNextBranch.tsx
|
811
722
|
var useGoToNextBranch = () => {
|
812
723
|
const { useThread } = useAssistantContext();
|
813
|
-
const {
|
724
|
+
const { useMessage, useComposer } = useMessageContext();
|
814
725
|
const disabled = useCombinedStore(
|
815
|
-
[
|
816
|
-
(
|
726
|
+
[useMessage, useComposer],
|
727
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
|
817
728
|
);
|
818
729
|
if (disabled)
|
819
730
|
return null;
|
820
731
|
return () => {
|
821
|
-
const { message } = useMessage.getState();
|
822
|
-
useThread.getState().switchToBranch(message.id
|
732
|
+
const { message, branches } = useMessage.getState();
|
733
|
+
useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
|
823
734
|
};
|
824
735
|
};
|
825
736
|
|
826
737
|
// src/utils/createActionButton.tsx
|
827
|
-
var import_react18 = require("react");
|
828
|
-
var import_react_primitive8 = require("@radix-ui/react-primitive");
|
829
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");
|
830
742
|
var createActionButton = (useActionButton) => {
|
831
|
-
return (0,
|
743
|
+
return (0, import_react17.forwardRef)(
|
832
744
|
(props, forwardedRef) => {
|
833
745
|
const onClick = useActionButton(props);
|
834
|
-
return /* @__PURE__ */
|
746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
835
747
|
import_react_primitive8.Primitive.button,
|
836
748
|
{
|
837
749
|
type: "button",
|
@@ -851,16 +763,19 @@ var BranchPickerNext = createActionButton(useGoToNextBranch);
|
|
851
763
|
// src/actions/useGoToPreviousBranch.tsx
|
852
764
|
var useGoToPreviousBranch = () => {
|
853
765
|
const { useThread } = useAssistantContext();
|
854
|
-
const {
|
766
|
+
const { useMessage, useComposer } = useMessageContext();
|
855
767
|
const disabled = useCombinedStore(
|
856
|
-
[
|
857
|
-
(
|
768
|
+
[useMessage, useComposer],
|
769
|
+
(m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
|
858
770
|
);
|
859
771
|
if (disabled)
|
860
772
|
return null;
|
861
773
|
return () => {
|
862
|
-
const { message } = useMessage.getState();
|
863
|
-
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
|
+
);
|
864
779
|
};
|
865
780
|
};
|
866
781
|
|
@@ -868,24 +783,27 @@ var useGoToPreviousBranch = () => {
|
|
868
783
|
var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
|
869
784
|
|
870
785
|
// src/primitives/branchPicker/BranchPickerCount.tsx
|
786
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
871
787
|
var BranchPickerCount = () => {
|
872
788
|
const { useMessage } = useMessageContext();
|
873
|
-
const branchCount = useMessage((s) => s.
|
874
|
-
return /* @__PURE__ */
|
789
|
+
const branchCount = useMessage((s) => s.branches.length);
|
790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: branchCount });
|
875
791
|
};
|
876
792
|
|
877
793
|
// src/primitives/branchPicker/BranchPickerNumber.tsx
|
794
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
878
795
|
var BranchPickerNumber = () => {
|
879
796
|
const { useMessage } = useMessageContext();
|
880
|
-
const
|
881
|
-
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 });
|
882
799
|
};
|
883
800
|
|
884
801
|
// src/primitives/branchPicker/BranchPickerRoot.tsx
|
885
802
|
var import_react_primitive9 = require("@radix-ui/react-primitive");
|
886
|
-
var
|
887
|
-
var
|
888
|
-
|
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 }) });
|
889
807
|
});
|
890
808
|
|
891
809
|
// src/primitives/actionBar/index.ts
|
@@ -899,28 +817,29 @@ __export(actionBar_exports, {
|
|
899
817
|
|
900
818
|
// src/primitives/actionBar/ActionBarRoot.tsx
|
901
819
|
var import_react_primitive10 = require("@radix-ui/react-primitive");
|
902
|
-
var
|
903
|
-
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) => {
|
904
823
|
const { useThread } = useAssistantContext();
|
905
824
|
const { useMessage } = useMessageContext();
|
906
825
|
const hideAndfloatStatus = useCombinedStore(
|
907
826
|
[useThread, useMessage],
|
908
827
|
(t, m) => {
|
909
|
-
if (
|
828
|
+
if (hideWhenRunning && t.isRunning)
|
910
829
|
return "hidden" /* Hidden */;
|
911
830
|
const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
|
912
831
|
if (!autohideEnabled)
|
913
832
|
return "normal" /* Normal */;
|
914
833
|
if (!m.isHovering)
|
915
834
|
return "hidden" /* Hidden */;
|
916
|
-
if (autohideFloat === "always" || autohideFloat === "single-branch" && m.
|
835
|
+
if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
|
917
836
|
return "floating" /* Floating */;
|
918
837
|
return "normal" /* Normal */;
|
919
838
|
}
|
920
839
|
);
|
921
840
|
if (hideAndfloatStatus === "hidden" /* Hidden */)
|
922
841
|
return null;
|
923
|
-
return /* @__PURE__ */
|
842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
924
843
|
import_react_primitive10.Primitive.div,
|
925
844
|
{
|
926
845
|
"data-floating": hideAndfloatStatus === "floating" /* Floating */,
|
@@ -951,11 +870,11 @@ var ActionBarCopy = createActionButton(useCopyMessage);
|
|
951
870
|
|
952
871
|
// src/actions/useReloadMessage.tsx
|
953
872
|
var useReloadMessage = () => {
|
954
|
-
const { useThread } = useAssistantContext();
|
873
|
+
const { useThread, useViewport } = useAssistantContext();
|
955
874
|
const { useMessage } = useMessageContext();
|
956
875
|
const disabled = useCombinedStore(
|
957
876
|
[useThread, useMessage],
|
958
|
-
(t, m) => t.
|
877
|
+
(t, m) => t.isRunning || m.message.role !== "assistant"
|
959
878
|
);
|
960
879
|
if (disabled)
|
961
880
|
return null;
|
@@ -963,7 +882,8 @@ var useReloadMessage = () => {
|
|
963
882
|
const message = useMessage.getState().message;
|
964
883
|
if (message.role !== "assistant")
|
965
884
|
throw new Error("Reloading is only supported on assistant messages");
|
966
|
-
useThread.getState().
|
885
|
+
useThread.getState().startRun(message.parentId);
|
886
|
+
useViewport.getState().scrollToBottom();
|
967
887
|
};
|
968
888
|
};
|
969
889
|
|
@@ -992,68 +912,309 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
|
992
912
|
var import_react22 = require("react");
|
993
913
|
|
994
914
|
// src/adapters/vercel/useDummyAIAssistantContext.tsx
|
995
|
-
var
|
996
|
-
var
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
throw new Error("Not implemented");
|
1008
|
-
},
|
1009
|
-
switchToBranch: () => {
|
1010
|
-
throw new Error("Not implemented");
|
1011
|
-
},
|
1012
|
-
reload: async () => {
|
1013
|
-
throw new Error("Not implemented");
|
1014
|
-
},
|
1015
|
-
isAtBottom: true,
|
1016
|
-
scrollToBottom: () => {
|
1017
|
-
for (const listener of scrollToBottomListeners) {
|
1018
|
-
listener();
|
1019
|
-
}
|
1020
|
-
},
|
1021
|
-
onScrollToBottom: (callback) => {
|
1022
|
-
scrollToBottomListeners.add(callback);
|
1023
|
-
return () => {
|
1024
|
-
scrollToBottomListeners.delete(callback);
|
1025
|
-
};
|
1026
|
-
}
|
1027
|
-
}));
|
1028
|
-
const useComposer = (0, import_zustand2.create)()(() => ({
|
1029
|
-
isEditing: true,
|
1030
|
-
canCancel: false,
|
1031
|
-
value: "",
|
1032
|
-
setValue: (value) => {
|
1033
|
-
useComposer.setState({ value });
|
1034
|
-
},
|
1035
|
-
edit: () => {
|
1036
|
-
throw new Error("Not implemented");
|
1037
|
-
},
|
1038
|
-
send: () => {
|
1039
|
-
useThread.getState().append({
|
1040
|
-
parentId: useThread.getState().messages.at(-1)?.id ?? ROOT_PARENT_ID,
|
1041
|
-
content: [{ type: "text", text: useComposer.getState().value }]
|
1042
|
-
});
|
1043
|
-
useComposer.getState().setValue("");
|
1044
|
-
},
|
1045
|
-
cancel: () => {
|
1046
|
-
useThread.getState().stop();
|
915
|
+
var import_react20 = require("react");
|
916
|
+
var import_zustand4 = require("zustand");
|
917
|
+
|
918
|
+
// src/utils/context/stores/ViewportStore.tsx
|
919
|
+
var import_zustand3 = require("zustand");
|
920
|
+
var makeViewportStore = () => {
|
921
|
+
const scrollToBottomListeners = /* @__PURE__ */ new Set();
|
922
|
+
return (0, import_zustand3.create)(() => ({
|
923
|
+
isAtBottom: true,
|
924
|
+
scrollToBottom: () => {
|
925
|
+
for (const listener of scrollToBottomListeners) {
|
926
|
+
listener();
|
1047
927
|
}
|
1048
|
-
}
|
1049
|
-
|
928
|
+
},
|
929
|
+
onScrollToBottom: (callback) => {
|
930
|
+
scrollToBottomListeners.add(callback);
|
931
|
+
return () => {
|
932
|
+
scrollToBottomListeners.delete(callback);
|
933
|
+
};
|
934
|
+
}
|
935
|
+
}));
|
936
|
+
};
|
937
|
+
|
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
|
+
};
|
960
|
+
var useDummyAIAssistantContext = () => {
|
961
|
+
const [context] = (0, import_react20.useState)(() => {
|
962
|
+
const useThread = makeDummyThreadStore();
|
963
|
+
const useViewport = makeViewportStore();
|
964
|
+
const useComposer = makeThreadComposerStore(useThread);
|
965
|
+
return { useThread, useViewport, useComposer };
|
1050
966
|
});
|
1051
967
|
return context;
|
1052
968
|
};
|
1053
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
|
+
|
1054
1214
|
// src/adapters/vercel/VercelAIAssistantProvider.tsx
|
1215
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
1055
1216
|
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
1056
|
-
var vercelToThreadMessage = (message, parentId
|
1217
|
+
var vercelToThreadMessage = (message, parentId) => {
|
1057
1218
|
if (message.role !== "user" && message.role !== "assistant")
|
1058
1219
|
throw new Error("Unsupported role");
|
1059
1220
|
return {
|
@@ -1061,24 +1222,17 @@ var vercelToThreadMessage = (message, parentId, branchId, branchCount) => {
|
|
1061
1222
|
id: message.id,
|
1062
1223
|
role: message.role,
|
1063
1224
|
content: [{ type: "text", text: message.content }],
|
1064
|
-
|
1065
|
-
|
1066
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1225
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1226
|
+
innerMessage: message
|
1067
1227
|
};
|
1068
1228
|
};
|
1069
|
-
var vercelToCachedThreadMessages = (messages
|
1229
|
+
var vercelToCachedThreadMessages = (messages) => {
|
1070
1230
|
return messages.map((m, idx) => {
|
1071
1231
|
const cached = ThreadMessageCache.get(m);
|
1072
|
-
const parentId = messages[idx - 1]?.id ??
|
1073
|
-
|
1074
|
-
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)
|
1075
1234
|
return cached;
|
1076
|
-
const newMessage = vercelToThreadMessage(
|
1077
|
-
m,
|
1078
|
-
parentId,
|
1079
|
-
branchId,
|
1080
|
-
branchCount
|
1081
|
-
);
|
1235
|
+
const newMessage = vercelToThreadMessage(m, parentId);
|
1082
1236
|
ThreadMessageCache.set(m, newMessage);
|
1083
1237
|
return newMessage;
|
1084
1238
|
});
|
@@ -1089,43 +1243,44 @@ var VercelAIAssistantProvider = ({
|
|
1089
1243
|
}) => {
|
1090
1244
|
const context = useDummyAIAssistantContext();
|
1091
1245
|
const vercel = "chat" in rest ? rest.chat : rest.assistant;
|
1092
|
-
const branches = useVercelAIBranches(vercel, context);
|
1093
1246
|
const messages = (0, import_react22.useMemo)(() => {
|
1094
|
-
return vercelToCachedThreadMessages(
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
}, [vercel.messages, branches.getBranchState]);
|
1099
|
-
const stop = (0, import_react22.useCallback)(() => {
|
1247
|
+
return vercelToCachedThreadMessages(vercel.messages);
|
1248
|
+
}, [vercel.messages]);
|
1249
|
+
const branches = useVercelAIBranches(vercel, messages);
|
1250
|
+
const cancelRun = (0, import_react22.useCallback)(() => {
|
1100
1251
|
const lastMessage = vercel.messages.at(-1);
|
1101
1252
|
vercel.stop();
|
1102
1253
|
if (lastMessage?.role === "user") {
|
1103
1254
|
vercel.setInput(lastMessage.content);
|
1104
1255
|
}
|
1105
1256
|
}, [vercel.messages, vercel.stop, vercel.setInput]);
|
1106
|
-
const
|
1257
|
+
const isRunning = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
|
1107
1258
|
(0, import_react22.useMemo)(() => {
|
1108
|
-
context.useThread.setState(
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
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]);
|
1117
1272
|
(0, import_react22.useMemo)(() => {
|
1118
1273
|
context.useComposer.setState({
|
1119
|
-
canCancel: isLoading,
|
1120
1274
|
value: vercel.input,
|
1121
1275
|
setValue: vercel.setInput
|
1122
1276
|
});
|
1123
|
-
}, [context,
|
1124
|
-
return /* @__PURE__ */
|
1277
|
+
}, [context, vercel.input, vercel.setInput]);
|
1278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AssistantContext.Provider, { value: context, children });
|
1125
1279
|
};
|
1126
1280
|
|
1127
1281
|
// src/adapters/vercel/VercelRSCAssistantProvider.tsx
|
1128
1282
|
var import_react23 = require("react");
|
1283
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
1129
1284
|
var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
|
1130
1285
|
var vercelToThreadMessage2 = (parentId, message) => {
|
1131
1286
|
if (message.role !== "user" && message.role !== "assistant")
|
@@ -1135,15 +1290,13 @@ var vercelToThreadMessage2 = (parentId, message) => {
|
|
1135
1290
|
id: message.id,
|
1136
1291
|
role: message.role,
|
1137
1292
|
content: [{ type: "ui", display: message.display }],
|
1138
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1139
|
-
branchId: 0,
|
1140
|
-
branchCount: 1
|
1293
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1141
1294
|
};
|
1142
1295
|
};
|
1143
1296
|
var vercelToCachedThreadMessages2 = (messages) => {
|
1144
1297
|
return messages.map((m, idx) => {
|
1145
1298
|
const cached = ThreadMessageCache2.get(m);
|
1146
|
-
const parentId = messages[idx - 1]?.id ??
|
1299
|
+
const parentId = messages[idx - 1]?.id ?? null;
|
1147
1300
|
if (cached && cached.parentId === parentId)
|
1148
1301
|
return cached;
|
1149
1302
|
const newMessage = vercelToThreadMessage2(parentId, m);
|
@@ -1162,12 +1315,11 @@ var VercelRSCAssistantProvider = ({
|
|
1162
1315
|
}, [vercelMessages]);
|
1163
1316
|
const append = (0, import_react23.useCallback)(
|
1164
1317
|
async (message) => {
|
1165
|
-
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ??
|
1318
|
+
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null))
|
1166
1319
|
throw new Error("Unexpected: Message editing is not supported");
|
1167
1320
|
if (message.content[0]?.type !== "text") {
|
1168
1321
|
throw new Error("Only text content is currently supported");
|
1169
1322
|
}
|
1170
|
-
context.useThread.getState().scrollToBottom();
|
1171
1323
|
await vercelAppend(message);
|
1172
1324
|
},
|
1173
1325
|
[context, vercelAppend]
|
@@ -1178,7 +1330,7 @@ var VercelRSCAssistantProvider = ({
|
|
1178
1330
|
append
|
1179
1331
|
});
|
1180
1332
|
}, [context, messages, append]);
|
1181
|
-
return /* @__PURE__ */
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AssistantContext.Provider, { value: context, children });
|
1182
1334
|
};
|
1183
1335
|
// Annotate the CommonJS export names for ESM import in node:
|
1184
1336
|
0 && (module.exports = {
|