@assistant-ui/react 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.d.mts +13 -8
- package/dist/index.d.ts +13 -8
- package/dist/index.js +121 -99
- package/dist/index.mjs +132 -112
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
@@ -3,6 +3,7 @@ import { FC, ReactNode, PropsWithChildren, ComponentType } from 'react';
|
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
4
|
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
6
|
+
import { Message } from 'ai';
|
6
7
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
8
|
|
8
9
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -145,6 +146,7 @@ type UserMessage = BaseMessage & {
|
|
145
146
|
type AssistantMessage = BaseMessage & {
|
146
147
|
role: "assistant";
|
147
148
|
content: AssistantContentPart[];
|
149
|
+
status: "in_progress" | "done" | "error";
|
148
150
|
};
|
149
151
|
type AppendMessage = {
|
150
152
|
parentId: string | null;
|
@@ -199,14 +201,14 @@ type MessageContentProps = {
|
|
199
201
|
};
|
200
202
|
declare const MessageContent: FC<MessageContentProps>;
|
201
203
|
|
202
|
-
declare const
|
204
|
+
declare const MessageInProgress: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
203
205
|
ref?: ((instance: HTMLDivElement | null) => void) | react.RefObject<HTMLDivElement> | null | undefined;
|
204
206
|
} & {
|
205
207
|
asChild?: boolean;
|
206
208
|
}, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & react.RefAttributes<HTMLDivElement>>;
|
207
209
|
|
208
210
|
declare namespace index$3 {
|
209
|
-
export { MessageContent as Content, MessageIf as If,
|
211
|
+
export { MessageContent as Content, MessageIf as If, MessageInProgress as InProgress, MessageProvider as Provider, MessageRoot as Root };
|
210
212
|
}
|
211
213
|
|
212
214
|
declare const BranchPickerNext: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
@@ -274,14 +276,14 @@ declare namespace index$1 {
|
|
274
276
|
|
275
277
|
type ContentPartProviderProps = PropsWithChildren<{
|
276
278
|
part: ThreadMessage["content"][number];
|
277
|
-
|
279
|
+
status: "in_progress" | "done" | "error";
|
278
280
|
}>;
|
279
281
|
declare const ContentPartProvider: FC<ContentPartProviderProps>;
|
280
282
|
|
281
|
-
declare const
|
283
|
+
declare const ContentPartInProgressIndicator: FC;
|
282
284
|
|
283
285
|
declare namespace index {
|
284
|
-
export {
|
286
|
+
export { ContentPartInProgressIndicator as InProgressIndicator, ContentPartProvider as Provider };
|
285
287
|
}
|
286
288
|
|
287
289
|
type VercelAIAssistantProviderProps = PropsWithChildren<{
|
@@ -310,13 +312,16 @@ type RSCMessageConverter<T> = {
|
|
310
312
|
type VercelRSCAssistantProviderProps<T = VercelRSCMessage> = VercelRSCAssistantProviderBaseProps<T> & (T extends VercelRSCMessage ? object : RSCMessageConverter<T>);
|
311
313
|
declare const VercelRSCAssistantProvider: <T extends WeakKey = VercelRSCMessage>({ children, convertMessage, messages: vercelMessages, append: appendCallback, edit, reload, }: VercelRSCAssistantProviderProps<T>) => react_jsx_runtime.JSX.Element;
|
312
314
|
|
315
|
+
declare const getVercelMessage: (message: ThreadMessage) => Message | undefined;
|
316
|
+
declare const getVercelRSCMessage: <T>(message: ThreadMessage) => T | undefined;
|
317
|
+
|
313
318
|
type MessageState = {
|
314
319
|
message: ThreadMessage;
|
315
320
|
parentId: string | null;
|
316
321
|
branches: string[];
|
317
322
|
isLast: boolean;
|
318
|
-
|
319
|
-
|
323
|
+
inProgressIndicator: ReactNode | null;
|
324
|
+
setInProgressIndicator: (value: ReactNode | null) => void;
|
320
325
|
isCopied: boolean;
|
321
326
|
setIsCopied: (value: boolean) => void;
|
322
327
|
isHovering: boolean;
|
@@ -341,4 +346,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
341
346
|
|
342
347
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
343
348
|
|
344
|
-
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
349
|
+
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.d.ts
CHANGED
@@ -3,6 +3,7 @@ import { FC, ReactNode, PropsWithChildren, ComponentType } from 'react';
|
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
4
|
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
6
|
+
import { Message } from 'ai';
|
6
7
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
8
|
|
8
9
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -145,6 +146,7 @@ type UserMessage = BaseMessage & {
|
|
145
146
|
type AssistantMessage = BaseMessage & {
|
146
147
|
role: "assistant";
|
147
148
|
content: AssistantContentPart[];
|
149
|
+
status: "in_progress" | "done" | "error";
|
148
150
|
};
|
149
151
|
type AppendMessage = {
|
150
152
|
parentId: string | null;
|
@@ -199,14 +201,14 @@ type MessageContentProps = {
|
|
199
201
|
};
|
200
202
|
declare const MessageContent: FC<MessageContentProps>;
|
201
203
|
|
202
|
-
declare const
|
204
|
+
declare const MessageInProgress: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
203
205
|
ref?: ((instance: HTMLDivElement | null) => void) | react.RefObject<HTMLDivElement> | null | undefined;
|
204
206
|
} & {
|
205
207
|
asChild?: boolean;
|
206
208
|
}, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & react.RefAttributes<HTMLDivElement>>;
|
207
209
|
|
208
210
|
declare namespace index$3 {
|
209
|
-
export { MessageContent as Content, MessageIf as If,
|
211
|
+
export { MessageContent as Content, MessageIf as If, MessageInProgress as InProgress, MessageProvider as Provider, MessageRoot as Root };
|
210
212
|
}
|
211
213
|
|
212
214
|
declare const BranchPickerNext: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
@@ -274,14 +276,14 @@ declare namespace index$1 {
|
|
274
276
|
|
275
277
|
type ContentPartProviderProps = PropsWithChildren<{
|
276
278
|
part: ThreadMessage["content"][number];
|
277
|
-
|
279
|
+
status: "in_progress" | "done" | "error";
|
278
280
|
}>;
|
279
281
|
declare const ContentPartProvider: FC<ContentPartProviderProps>;
|
280
282
|
|
281
|
-
declare const
|
283
|
+
declare const ContentPartInProgressIndicator: FC;
|
282
284
|
|
283
285
|
declare namespace index {
|
284
|
-
export {
|
286
|
+
export { ContentPartInProgressIndicator as InProgressIndicator, ContentPartProvider as Provider };
|
285
287
|
}
|
286
288
|
|
287
289
|
type VercelAIAssistantProviderProps = PropsWithChildren<{
|
@@ -310,13 +312,16 @@ type RSCMessageConverter<T> = {
|
|
310
312
|
type VercelRSCAssistantProviderProps<T = VercelRSCMessage> = VercelRSCAssistantProviderBaseProps<T> & (T extends VercelRSCMessage ? object : RSCMessageConverter<T>);
|
311
313
|
declare const VercelRSCAssistantProvider: <T extends WeakKey = VercelRSCMessage>({ children, convertMessage, messages: vercelMessages, append: appendCallback, edit, reload, }: VercelRSCAssistantProviderProps<T>) => react_jsx_runtime.JSX.Element;
|
312
314
|
|
315
|
+
declare const getVercelMessage: (message: ThreadMessage) => Message | undefined;
|
316
|
+
declare const getVercelRSCMessage: <T>(message: ThreadMessage) => T | undefined;
|
317
|
+
|
313
318
|
type MessageState = {
|
314
319
|
message: ThreadMessage;
|
315
320
|
parentId: string | null;
|
316
321
|
branches: string[];
|
317
322
|
isLast: boolean;
|
318
|
-
|
319
|
-
|
323
|
+
inProgressIndicator: ReactNode | null;
|
324
|
+
setInProgressIndicator: (value: ReactNode | null) => void;
|
320
325
|
isCopied: boolean;
|
321
326
|
setIsCopied: (value: boolean) => void;
|
322
327
|
isHovering: boolean;
|
@@ -341,4 +346,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
341
346
|
|
342
347
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
343
348
|
|
344
|
-
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
349
|
+
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.js
CHANGED
@@ -38,6 +38,8 @@ __export(src_exports, {
|
|
38
38
|
ThreadPrimitive: () => thread_exports,
|
39
39
|
VercelAIAssistantProvider: () => VercelAIAssistantProvider,
|
40
40
|
VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
|
41
|
+
unstable_getVercelMessage: () => getVercelMessage,
|
42
|
+
unstable_getVercelRSCMessage: () => getVercelRSCMessage,
|
41
43
|
unstable_useMessageContext: () => useMessageContext,
|
42
44
|
useBeginMessageEdit: () => useBeginMessageEdit,
|
43
45
|
useCopyMessage: () => useCopyMessage,
|
@@ -110,15 +112,15 @@ var import_react_primitive2 = require("@radix-ui/react-primitive");
|
|
110
112
|
var import_react5 = require("react");
|
111
113
|
|
112
114
|
// src/utils/hooks/useOnResizeContent.tsx
|
115
|
+
var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
|
113
116
|
var import_react3 = require("react");
|
114
117
|
var useOnResizeContent = (ref, callback) => {
|
115
|
-
const callbackRef = (0,
|
116
|
-
callbackRef.current = callback;
|
118
|
+
const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
|
117
119
|
(0, import_react3.useEffect)(() => {
|
118
120
|
const el = ref.current;
|
119
121
|
if (!el) return;
|
120
122
|
const resizeObserver = new ResizeObserver(() => {
|
121
|
-
callbackRef
|
123
|
+
callbackRef();
|
122
124
|
});
|
123
125
|
const mutationObserver = new MutationObserver((mutations) => {
|
124
126
|
for (const mutation of mutations) {
|
@@ -133,7 +135,7 @@ var useOnResizeContent = (ref, callback) => {
|
|
133
135
|
}
|
134
136
|
}
|
135
137
|
}
|
136
|
-
callbackRef
|
138
|
+
callbackRef();
|
137
139
|
});
|
138
140
|
resizeObserver.observe(el);
|
139
141
|
mutationObserver.observe(el, { childList: true });
|
@@ -144,20 +146,20 @@ var useOnResizeContent = (ref, callback) => {
|
|
144
146
|
resizeObserver.disconnect();
|
145
147
|
mutationObserver.disconnect();
|
146
148
|
};
|
147
|
-
}, [ref.current]);
|
149
|
+
}, [ref.current, callbackRef]);
|
148
150
|
};
|
149
151
|
|
150
152
|
// src/utils/hooks/useOnScrollToBottom.tsx
|
153
|
+
var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
|
151
154
|
var import_react4 = require("react");
|
152
155
|
var useOnScrollToBottom = (callback) => {
|
153
|
-
const callbackRef = (0,
|
154
|
-
callbackRef.current = callback;
|
156
|
+
const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
|
155
157
|
const { useViewport } = useAssistantContext();
|
156
158
|
(0, import_react4.useEffect)(() => {
|
157
159
|
return useViewport.getState().onScrollToBottom(() => {
|
158
|
-
callbackRef
|
160
|
+
callbackRef();
|
159
161
|
});
|
160
|
-
}, [useViewport]);
|
162
|
+
}, [useViewport, callbackRef]);
|
161
163
|
};
|
162
164
|
|
163
165
|
// src/primitives/thread/ThreadViewport.tsx
|
@@ -253,7 +255,7 @@ var message_exports = {};
|
|
253
255
|
__export(message_exports, {
|
254
256
|
Content: () => MessageContent,
|
255
257
|
If: () => MessageIf,
|
256
|
-
|
258
|
+
InProgress: () => MessageInProgress,
|
257
259
|
Provider: () => MessageProvider,
|
258
260
|
Root: () => MessageRoot
|
259
261
|
});
|
@@ -333,11 +335,11 @@ var useMessageContext2 = () => {
|
|
333
335
|
parentId: null,
|
334
336
|
branches: [],
|
335
337
|
isLast: false,
|
336
|
-
|
338
|
+
inProgressIndicator: null,
|
337
339
|
isCopied: false,
|
338
340
|
isHovering: false,
|
339
|
-
|
340
|
-
set({
|
341
|
+
setInProgressIndicator: (value) => {
|
342
|
+
set({ inProgressIndicator: value });
|
341
343
|
},
|
342
344
|
setIsCopied: (value) => {
|
343
345
|
set({ isCopied: value });
|
@@ -478,15 +480,15 @@ var useContentPartContext = () => {
|
|
478
480
|
return context;
|
479
481
|
};
|
480
482
|
|
481
|
-
// src/primitives/contentPart/
|
482
|
-
var
|
483
|
+
// src/primitives/contentPart/ContentPartInProgressIndicator.tsx
|
484
|
+
var ContentPartInProgressIndicator = () => {
|
483
485
|
const { useMessage } = useMessageContext();
|
484
486
|
const { useContentPart } = useContentPartContext();
|
485
|
-
const
|
487
|
+
const indicator = useCombinedStore(
|
486
488
|
[useMessage, useContentPart],
|
487
|
-
(m, c) => c.
|
489
|
+
(m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
|
488
490
|
);
|
489
|
-
return
|
491
|
+
return indicator;
|
490
492
|
};
|
491
493
|
|
492
494
|
// src/primitives/contentPart/ContentPartProvider.tsx
|
@@ -497,7 +499,7 @@ var useContentPartContext2 = () => {
|
|
497
499
|
const [context] = (0, import_react13.useState)(() => {
|
498
500
|
const useContentPart = (0, import_zustand3.create)(() => ({
|
499
501
|
part: null,
|
500
|
-
|
502
|
+
status: "done"
|
501
503
|
}));
|
502
504
|
return { useContentPart };
|
503
505
|
});
|
@@ -505,7 +507,7 @@ var useContentPartContext2 = () => {
|
|
505
507
|
};
|
506
508
|
var ContentPartProvider = ({
|
507
509
|
part,
|
508
|
-
|
510
|
+
status,
|
509
511
|
children
|
510
512
|
}) => {
|
511
513
|
const context = useContentPartContext2();
|
@@ -513,11 +515,11 @@ var ContentPartProvider = ({
|
|
513
515
|
context.useContentPart.setState(
|
514
516
|
{
|
515
517
|
part,
|
516
|
-
|
518
|
+
status
|
517
519
|
},
|
518
520
|
true
|
519
521
|
);
|
520
|
-
}, [context, part,
|
522
|
+
}, [context, part, status]);
|
521
523
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ContentPartContext.Provider, { value: context, children });
|
522
524
|
};
|
523
525
|
|
@@ -526,7 +528,7 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
526
528
|
var defaultComponents = {
|
527
529
|
Text: ({ part }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
528
530
|
part.text,
|
529
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
531
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContentPartInProgressIndicator, {})
|
530
532
|
] }),
|
531
533
|
Image: () => null,
|
532
534
|
UI: ({ part }) => part.display,
|
@@ -542,13 +544,10 @@ var MessageContent = ({
|
|
542
544
|
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
543
545
|
} = {}
|
544
546
|
}) => {
|
545
|
-
const { useThread } = useAssistantContext();
|
546
547
|
const { useMessage } = useMessageContext();
|
547
|
-
const
|
548
|
-
const
|
549
|
-
|
550
|
-
(t, s) => s.isLast && t.isRunning
|
551
|
-
);
|
548
|
+
const message = useMessage((s) => s.message);
|
549
|
+
const content = message.content;
|
550
|
+
const status = message.role === "assistant" ? message.status : "done";
|
552
551
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: content.map((part, i) => {
|
553
552
|
const key = i;
|
554
553
|
const type = part.type;
|
@@ -575,7 +574,7 @@ var MessageContent = ({
|
|
575
574
|
ContentPartProvider,
|
576
575
|
{
|
577
576
|
part,
|
578
|
-
|
577
|
+
status: i === content.length - 1 ? status : "done",
|
579
578
|
children: component
|
580
579
|
},
|
581
580
|
key
|
@@ -583,14 +582,14 @@ var MessageContent = ({
|
|
583
582
|
}) });
|
584
583
|
};
|
585
584
|
|
586
|
-
// src/primitives/message/
|
585
|
+
// src/primitives/message/MessageInProgress.tsx
|
587
586
|
var import_react_primitive4 = require("@radix-ui/react-primitive");
|
588
587
|
var import_react14 = require("react");
|
589
588
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
590
|
-
var
|
589
|
+
var MessageInProgress = (0, import_react14.forwardRef)((props, ref) => {
|
591
590
|
const { useMessage } = useMessageContext();
|
592
591
|
(0, import_react14.useMemo)(() => {
|
593
|
-
useMessage.getState().
|
592
|
+
useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_primitive4.Primitive.div, { ...props, ref }));
|
594
593
|
}, [useMessage, props, ref]);
|
595
594
|
return null;
|
596
595
|
});
|
@@ -892,7 +891,6 @@ var useGoToPreviousBranch = () => {
|
|
892
891
|
const { message, branches } = useMessage.getState();
|
893
892
|
useThread.getState().switchToBranch(
|
894
893
|
branches[branches.indexOf(message.id) - 1]
|
895
|
-
// TODO probably there's a more elegant way to do this
|
896
894
|
);
|
897
895
|
};
|
898
896
|
};
|
@@ -1025,7 +1023,7 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
|
1025
1023
|
// src/primitives/contentPart/index.ts
|
1026
1024
|
var contentPart_exports = {};
|
1027
1025
|
__export(contentPart_exports, {
|
1028
|
-
|
1026
|
+
InProgressIndicator: () => ContentPartInProgressIndicator,
|
1029
1027
|
Provider: () => ContentPartProvider
|
1030
1028
|
});
|
1031
1029
|
|
@@ -1089,6 +1087,7 @@ var useDummyAIAssistantContext = () => {
|
|
1089
1087
|
};
|
1090
1088
|
|
1091
1089
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1090
|
+
var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
|
1092
1091
|
var import_react25 = require("react");
|
1093
1092
|
|
1094
1093
|
// src/adapters/MessageRepository.tsx
|
@@ -1099,7 +1098,6 @@ var generateId = (0, import_non_secure.customAlphabet)(
|
|
1099
1098
|
);
|
1100
1099
|
var optimisticPrefix = "__optimistic__";
|
1101
1100
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1102
|
-
var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
1103
1101
|
var findHead = (message) => {
|
1104
1102
|
if (message.next) return findHead(message.next);
|
1105
1103
|
return message;
|
@@ -1183,7 +1181,8 @@ var MessageRepository = class {
|
|
1183
1181
|
this.addOrUpdateMessage(parentId, {
|
1184
1182
|
...message,
|
1185
1183
|
id: optimisticId,
|
1186
|
-
createdAt: /* @__PURE__ */ new Date()
|
1184
|
+
createdAt: /* @__PURE__ */ new Date(),
|
1185
|
+
...message.role === "assistant" ? { status: "in_progress" } : void 0
|
1187
1186
|
});
|
1188
1187
|
return optimisticId;
|
1189
1188
|
}
|
@@ -1253,8 +1252,8 @@ var MessageRepository = class {
|
|
1253
1252
|
|
1254
1253
|
// src/adapters/ThreadMessageConverter.tsx
|
1255
1254
|
var ThreadMessageConverter = class {
|
1256
|
-
constructor(
|
1257
|
-
this.converter =
|
1255
|
+
constructor(converter) {
|
1256
|
+
this.converter = converter;
|
1258
1257
|
}
|
1259
1258
|
cache = /* @__PURE__ */ new WeakMap();
|
1260
1259
|
convertMessages(messages) {
|
@@ -1268,33 +1267,55 @@ var ThreadMessageConverter = class {
|
|
1268
1267
|
}
|
1269
1268
|
};
|
1270
1269
|
|
1270
|
+
// src/adapters/vercel/VercelThreadMessage.tsx
|
1271
|
+
var symbolInnerMessage = Symbol("innerMessage");
|
1272
|
+
var symbolInnerRSCMessage = Symbol("innerRSCMessage");
|
1273
|
+
var getVercelMessage = (message) => {
|
1274
|
+
return message[symbolInnerMessage];
|
1275
|
+
};
|
1276
|
+
var getVercelRSCMessage = (message) => {
|
1277
|
+
return message[symbolInnerRSCMessage];
|
1278
|
+
};
|
1279
|
+
|
1271
1280
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1272
|
-
var vercelToThreadMessage = (message) => {
|
1273
|
-
|
1274
|
-
throw new Error(
|
1275
|
-
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1276
|
-
);
|
1277
|
-
return {
|
1281
|
+
var vercelToThreadMessage = (message, status) => {
|
1282
|
+
const common = {
|
1278
1283
|
id: message.id,
|
1279
|
-
role: message.role,
|
1280
|
-
content: [
|
1281
|
-
...message.content ? [{ type: "text", text: message.content }] : [],
|
1282
|
-
...message.toolInvocations?.map((t) => ({
|
1283
|
-
type: "tool-call",
|
1284
|
-
name: t.toolName,
|
1285
|
-
args: t.args,
|
1286
|
-
result: "result" in t ? t.result : void 0
|
1287
|
-
})) ?? []
|
1288
|
-
],
|
1289
|
-
// ignore type mismatch for now
|
1290
1284
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1291
|
-
|
1285
|
+
[symbolInnerMessage]: message
|
1292
1286
|
};
|
1287
|
+
switch (message.role) {
|
1288
|
+
case "user":
|
1289
|
+
return {
|
1290
|
+
...common,
|
1291
|
+
role: "user",
|
1292
|
+
content: [{ type: "text", text: message.content }]
|
1293
|
+
};
|
1294
|
+
case "assistant":
|
1295
|
+
return {
|
1296
|
+
...common,
|
1297
|
+
role: "assistant",
|
1298
|
+
content: [
|
1299
|
+
...message.content ? [{ type: "text", text: message.content }] : [],
|
1300
|
+
...message.toolInvocations?.map(
|
1301
|
+
(t) => ({
|
1302
|
+
type: "tool-call",
|
1303
|
+
name: t.toolName,
|
1304
|
+
args: t.args,
|
1305
|
+
result: "result" in t ? t.result : void 0
|
1306
|
+
})
|
1307
|
+
) ?? []
|
1308
|
+
],
|
1309
|
+
status
|
1310
|
+
};
|
1311
|
+
default:
|
1312
|
+
throw new Error(
|
1313
|
+
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1314
|
+
);
|
1315
|
+
}
|
1293
1316
|
};
|
1294
|
-
var converter = new ThreadMessageConverter(vercelToThreadMessage);
|
1295
1317
|
var sliceMessagesUntil = (messages, messageId) => {
|
1296
1318
|
if (messageId == null) return [];
|
1297
|
-
if (isOptimisticId(messageId)) return messages;
|
1298
1319
|
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1299
1320
|
if (messageIdx === -1)
|
1300
1321
|
throw new Error(
|
@@ -1311,9 +1332,14 @@ var getIsRunning = (vercel) => {
|
|
1311
1332
|
};
|
1312
1333
|
var useVercelAIThreadState = (vercel) => {
|
1313
1334
|
const [data] = (0, import_react25.useState)(() => new MessageRepository());
|
1314
|
-
const
|
1315
|
-
|
1316
|
-
|
1335
|
+
const isRunning = getIsRunning(vercel);
|
1336
|
+
const convertCallback = (0, import_react_use_callback_ref3.useCallbackRef)((message) => {
|
1337
|
+
return vercelToThreadMessage(
|
1338
|
+
message,
|
1339
|
+
vercel.messages.at(-1) === message && isRunning ? "in_progress" : "done"
|
1340
|
+
);
|
1341
|
+
});
|
1342
|
+
const converter = new ThreadMessageConverter(convertCallback);
|
1317
1343
|
const assistantOptimisticIdRef = (0, import_react25.useRef)(null);
|
1318
1344
|
const messages = (0, import_react25.useMemo)(() => {
|
1319
1345
|
const vm = converter.convertMessages(vercel.messages);
|
@@ -1337,55 +1363,46 @@ var useVercelAIThreadState = (vercel) => {
|
|
1337
1363
|
}
|
1338
1364
|
data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
|
1339
1365
|
return data.getMessages();
|
1340
|
-
}, [data, isRunning, vercel.messages]);
|
1366
|
+
}, [converter, data, isRunning, vercel.messages]);
|
1341
1367
|
const getBranches2 = (0, import_react25.useCallback)(
|
1342
1368
|
(messageId) => {
|
1343
1369
|
return data.getBranches(messageId);
|
1344
1370
|
},
|
1345
1371
|
[data]
|
1346
1372
|
);
|
1347
|
-
const switchToBranch2 = (0,
|
1348
|
-
(messageId)
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
);
|
1356
|
-
const startRun = (0, import_react25.useCallback)(async (parentId) => {
|
1357
|
-
const reloadMaybe = "reload" in vercelRef.current ? vercelRef.current.reload : void 0;
|
1373
|
+
const switchToBranch2 = (0, import_react_use_callback_ref3.useCallbackRef)((messageId) => {
|
1374
|
+
data.switchToBranch(messageId);
|
1375
|
+
vercel.setMessages(
|
1376
|
+
data.getMessages().map(getVercelMessage).filter((m) => m != null)
|
1377
|
+
);
|
1378
|
+
});
|
1379
|
+
const startRun = (0, import_react_use_callback_ref3.useCallbackRef)(async (parentId) => {
|
1380
|
+
const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
|
1358
1381
|
if (!reloadMaybe)
|
1359
1382
|
throw new Error(
|
1360
1383
|
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1361
1384
|
);
|
1362
|
-
const newMessages = sliceMessagesUntil(
|
1363
|
-
|
1364
|
-
parentId
|
1365
|
-
);
|
1366
|
-
vercelRef.current.setMessages(newMessages);
|
1385
|
+
const newMessages = sliceMessagesUntil(vercel.messages, parentId);
|
1386
|
+
vercel.setMessages(newMessages);
|
1367
1387
|
await reloadMaybe();
|
1368
|
-
}
|
1369
|
-
const append = (0,
|
1388
|
+
});
|
1389
|
+
const append = (0, import_react_use_callback_ref3.useCallbackRef)(async (message) => {
|
1370
1390
|
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1371
1391
|
throw new Error("Only text content is supported by Vercel AI SDK.");
|
1372
|
-
const newMessages = sliceMessagesUntil(
|
1373
|
-
|
1374
|
-
|
1375
|
-
);
|
1376
|
-
vercelRef.current.setMessages(newMessages);
|
1377
|
-
await vercelRef.current.append({
|
1392
|
+
const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
|
1393
|
+
vercel.setMessages(newMessages);
|
1394
|
+
await vercel.append({
|
1378
1395
|
role: "user",
|
1379
1396
|
content: message.content[0].text
|
1380
1397
|
});
|
1381
|
-
}
|
1382
|
-
const cancelRun2 = (0,
|
1383
|
-
const lastMessage =
|
1384
|
-
|
1398
|
+
});
|
1399
|
+
const cancelRun2 = (0, import_react_use_callback_ref3.useCallbackRef)(() => {
|
1400
|
+
const lastMessage = vercel.messages.at(-1);
|
1401
|
+
vercel.stop();
|
1385
1402
|
if (lastMessage?.role === "user") {
|
1386
|
-
|
1403
|
+
vercel.setInput(lastMessage.content);
|
1387
1404
|
}
|
1388
|
-
}
|
1405
|
+
});
|
1389
1406
|
return (0, import_react25.useMemo)(
|
1390
1407
|
() => ({
|
1391
1408
|
isRunning,
|
@@ -1432,12 +1449,15 @@ var VercelAIAssistantProvider = ({
|
|
1432
1449
|
// src/adapters/vercel/VercelRSCAssistantProvider.tsx
|
1433
1450
|
var import_react27 = require("react");
|
1434
1451
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
1435
|
-
var vercelToThreadMessage2 = (
|
1452
|
+
var vercelToThreadMessage2 = (converter, rawMessage) => {
|
1453
|
+
const message = converter(rawMessage);
|
1436
1454
|
return {
|
1437
1455
|
id: message.id,
|
1438
1456
|
role: message.role,
|
1439
1457
|
content: [{ type: "ui", display: message.display }],
|
1440
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1458
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1459
|
+
...{ status: "done" },
|
1460
|
+
[symbolInnerRSCMessage]: rawMessage
|
1441
1461
|
};
|
1442
1462
|
};
|
1443
1463
|
var EMPTY_BRANCHES = [];
|
@@ -1470,15 +1490,15 @@ var VercelRSCAssistantProvider = ({
|
|
1470
1490
|
setIsRunning(true);
|
1471
1491
|
return callback.finally(() => setIsRunning(false));
|
1472
1492
|
}, []);
|
1473
|
-
const
|
1493
|
+
const converter = (0, import_react27.useMemo)(() => {
|
1474
1494
|
const rscConverter = convertMessage ?? ((m) => m);
|
1475
1495
|
return new ThreadMessageConverter((m) => {
|
1476
|
-
return vercelToThreadMessage2(rscConverter
|
1496
|
+
return vercelToThreadMessage2(rscConverter, m);
|
1477
1497
|
});
|
1478
1498
|
}, [convertMessage]);
|
1479
1499
|
const messages = (0, import_react27.useMemo)(() => {
|
1480
|
-
return
|
1481
|
-
}, [
|
1500
|
+
return converter.convertMessages(vercelMessages);
|
1501
|
+
}, [converter, vercelMessages]);
|
1482
1502
|
const append = (0, import_react27.useCallback)(
|
1483
1503
|
async (message) => {
|
1484
1504
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
@@ -1529,6 +1549,8 @@ var VercelRSCAssistantProvider = ({
|
|
1529
1549
|
ThreadPrimitive,
|
1530
1550
|
VercelAIAssistantProvider,
|
1531
1551
|
VercelRSCAssistantProvider,
|
1552
|
+
unstable_getVercelMessage,
|
1553
|
+
unstable_getVercelRSCMessage,
|
1532
1554
|
unstable_useMessageContext,
|
1533
1555
|
useBeginMessageEdit,
|
1534
1556
|
useCopyMessage,
|
package/dist/index.mjs
CHANGED
@@ -68,18 +68,18 @@ import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
68
68
|
import {
|
69
69
|
Primitive as Primitive2
|
70
70
|
} from "@radix-ui/react-primitive";
|
71
|
-
import { forwardRef as forwardRef2, useRef
|
71
|
+
import { forwardRef as forwardRef2, useRef } from "react";
|
72
72
|
|
73
73
|
// src/utils/hooks/useOnResizeContent.tsx
|
74
|
-
import {
|
74
|
+
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
75
|
+
import { useEffect } from "react";
|
75
76
|
var useOnResizeContent = (ref, callback) => {
|
76
|
-
const callbackRef =
|
77
|
-
callbackRef.current = callback;
|
77
|
+
const callbackRef = useCallbackRef(callback);
|
78
78
|
useEffect(() => {
|
79
79
|
const el = ref.current;
|
80
80
|
if (!el) return;
|
81
81
|
const resizeObserver = new ResizeObserver(() => {
|
82
|
-
callbackRef
|
82
|
+
callbackRef();
|
83
83
|
});
|
84
84
|
const mutationObserver = new MutationObserver((mutations) => {
|
85
85
|
for (const mutation of mutations) {
|
@@ -94,7 +94,7 @@ var useOnResizeContent = (ref, callback) => {
|
|
94
94
|
}
|
95
95
|
}
|
96
96
|
}
|
97
|
-
callbackRef
|
97
|
+
callbackRef();
|
98
98
|
});
|
99
99
|
resizeObserver.observe(el);
|
100
100
|
mutationObserver.observe(el, { childList: true });
|
@@ -105,31 +105,31 @@ var useOnResizeContent = (ref, callback) => {
|
|
105
105
|
resizeObserver.disconnect();
|
106
106
|
mutationObserver.disconnect();
|
107
107
|
};
|
108
|
-
}, [ref.current]);
|
108
|
+
}, [ref.current, callbackRef]);
|
109
109
|
};
|
110
110
|
|
111
111
|
// src/utils/hooks/useOnScrollToBottom.tsx
|
112
|
-
import {
|
112
|
+
import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
|
113
|
+
import { useEffect as useEffect2 } from "react";
|
113
114
|
var useOnScrollToBottom = (callback) => {
|
114
|
-
const callbackRef =
|
115
|
-
callbackRef.current = callback;
|
115
|
+
const callbackRef = useCallbackRef2(callback);
|
116
116
|
const { useViewport } = useAssistantContext();
|
117
117
|
useEffect2(() => {
|
118
118
|
return useViewport.getState().onScrollToBottom(() => {
|
119
|
-
callbackRef
|
119
|
+
callbackRef();
|
120
120
|
});
|
121
|
-
}, [useViewport]);
|
121
|
+
}, [useViewport, callbackRef]);
|
122
122
|
};
|
123
123
|
|
124
124
|
// src/primitives/thread/ThreadViewport.tsx
|
125
125
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
126
126
|
var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
|
127
|
-
const messagesEndRef =
|
128
|
-
const divRef =
|
127
|
+
const messagesEndRef = useRef(null);
|
128
|
+
const divRef = useRef(null);
|
129
129
|
const ref = useComposedRefs(forwardedRef, divRef);
|
130
130
|
const { useViewport } = useAssistantContext();
|
131
|
-
const firstRenderRef =
|
132
|
-
const lastScrollTop =
|
131
|
+
const firstRenderRef = useRef(true);
|
132
|
+
const lastScrollTop = useRef(0);
|
133
133
|
const scrollToBottom = () => {
|
134
134
|
const div = messagesEndRef.current;
|
135
135
|
if (!div || !autoScroll) return;
|
@@ -214,7 +214,7 @@ var message_exports = {};
|
|
214
214
|
__export(message_exports, {
|
215
215
|
Content: () => MessageContent,
|
216
216
|
If: () => MessageIf,
|
217
|
-
|
217
|
+
InProgress: () => MessageInProgress,
|
218
218
|
Provider: () => MessageProvider,
|
219
219
|
Root: () => MessageRoot
|
220
220
|
});
|
@@ -296,11 +296,11 @@ var useMessageContext2 = () => {
|
|
296
296
|
parentId: null,
|
297
297
|
branches: [],
|
298
298
|
isLast: false,
|
299
|
-
|
299
|
+
inProgressIndicator: null,
|
300
300
|
isCopied: false,
|
301
301
|
isHovering: false,
|
302
|
-
|
303
|
-
set({
|
302
|
+
setInProgressIndicator: (value) => {
|
303
|
+
set({ inProgressIndicator: value });
|
304
304
|
},
|
305
305
|
setIsCopied: (value) => {
|
306
306
|
set({ isCopied: value });
|
@@ -443,15 +443,15 @@ var useContentPartContext = () => {
|
|
443
443
|
return context;
|
444
444
|
};
|
445
445
|
|
446
|
-
// src/primitives/contentPart/
|
447
|
-
var
|
446
|
+
// src/primitives/contentPart/ContentPartInProgressIndicator.tsx
|
447
|
+
var ContentPartInProgressIndicator = () => {
|
448
448
|
const { useMessage } = useMessageContext();
|
449
449
|
const { useContentPart } = useContentPartContext();
|
450
|
-
const
|
450
|
+
const indicator = useCombinedStore(
|
451
451
|
[useMessage, useContentPart],
|
452
|
-
(m, c) => c.
|
452
|
+
(m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
|
453
453
|
);
|
454
|
-
return
|
454
|
+
return indicator;
|
455
455
|
};
|
456
456
|
|
457
457
|
// src/primitives/contentPart/ContentPartProvider.tsx
|
@@ -462,7 +462,7 @@ var useContentPartContext2 = () => {
|
|
462
462
|
const [context] = useState2(() => {
|
463
463
|
const useContentPart = create3(() => ({
|
464
464
|
part: null,
|
465
|
-
|
465
|
+
status: "done"
|
466
466
|
}));
|
467
467
|
return { useContentPart };
|
468
468
|
});
|
@@ -470,7 +470,7 @@ var useContentPartContext2 = () => {
|
|
470
470
|
};
|
471
471
|
var ContentPartProvider = ({
|
472
472
|
part,
|
473
|
-
|
473
|
+
status,
|
474
474
|
children
|
475
475
|
}) => {
|
476
476
|
const context = useContentPartContext2();
|
@@ -478,11 +478,11 @@ var ContentPartProvider = ({
|
|
478
478
|
context.useContentPart.setState(
|
479
479
|
{
|
480
480
|
part,
|
481
|
-
|
481
|
+
status
|
482
482
|
},
|
483
483
|
true
|
484
484
|
);
|
485
|
-
}, [context, part,
|
485
|
+
}, [context, part, status]);
|
486
486
|
return /* @__PURE__ */ jsx6(ContentPartContext.Provider, { value: context, children });
|
487
487
|
};
|
488
488
|
|
@@ -491,7 +491,7 @@ import { Fragment, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
491
491
|
var defaultComponents = {
|
492
492
|
Text: ({ part }) => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
493
493
|
part.text,
|
494
|
-
/* @__PURE__ */ jsx7(
|
494
|
+
/* @__PURE__ */ jsx7(ContentPartInProgressIndicator, {})
|
495
495
|
] }),
|
496
496
|
Image: () => null,
|
497
497
|
UI: ({ part }) => part.display,
|
@@ -507,13 +507,10 @@ var MessageContent = ({
|
|
507
507
|
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
508
508
|
} = {}
|
509
509
|
}) => {
|
510
|
-
const { useThread } = useAssistantContext();
|
511
510
|
const { useMessage } = useMessageContext();
|
512
|
-
const
|
513
|
-
const
|
514
|
-
|
515
|
-
(t, s) => s.isLast && t.isRunning
|
516
|
-
);
|
511
|
+
const message = useMessage((s) => s.message);
|
512
|
+
const content = message.content;
|
513
|
+
const status = message.role === "assistant" ? message.status : "done";
|
517
514
|
return /* @__PURE__ */ jsx7(Fragment, { children: content.map((part, i) => {
|
518
515
|
const key = i;
|
519
516
|
const type = part.type;
|
@@ -540,7 +537,7 @@ var MessageContent = ({
|
|
540
537
|
ContentPartProvider,
|
541
538
|
{
|
542
539
|
part,
|
543
|
-
|
540
|
+
status: i === content.length - 1 ? status : "done",
|
544
541
|
children: component
|
545
542
|
},
|
546
543
|
key
|
@@ -548,16 +545,16 @@ var MessageContent = ({
|
|
548
545
|
}) });
|
549
546
|
};
|
550
547
|
|
551
|
-
// src/primitives/message/
|
548
|
+
// src/primitives/message/MessageInProgress.tsx
|
552
549
|
import {
|
553
550
|
Primitive as Primitive4
|
554
551
|
} from "@radix-ui/react-primitive";
|
555
552
|
import { forwardRef as forwardRef4, useMemo as useMemo4 } from "react";
|
556
553
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
557
|
-
var
|
554
|
+
var MessageInProgress = forwardRef4((props, ref) => {
|
558
555
|
const { useMessage } = useMessageContext();
|
559
556
|
useMemo4(() => {
|
560
|
-
useMessage.getState().
|
557
|
+
useMessage.getState().setInProgressIndicator(/* @__PURE__ */ jsx8(Primitive4.div, { ...props, ref }));
|
561
558
|
}, [useMessage, props, ref]);
|
562
559
|
return null;
|
563
560
|
});
|
@@ -666,13 +663,13 @@ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-ref
|
|
666
663
|
import {
|
667
664
|
Primitive as Primitive7
|
668
665
|
} from "@radix-ui/react-primitive";
|
669
|
-
import { forwardRef as forwardRef7, useRef as
|
666
|
+
import { forwardRef as forwardRef7, useRef as useRef2 } from "react";
|
670
667
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
671
668
|
var ComposerRoot = forwardRef7(
|
672
669
|
({ onSubmit, ...rest }, forwardedRef) => {
|
673
670
|
const { useViewport } = useAssistantContext();
|
674
671
|
const { useComposer } = useComposerContext();
|
675
|
-
const formRef =
|
672
|
+
const formRef = useRef2(null);
|
676
673
|
const ref = useComposedRefs2(forwardedRef, formRef);
|
677
674
|
const handleSubmit = (e) => {
|
678
675
|
const composerState = useComposer.getState();
|
@@ -700,7 +697,7 @@ import {
|
|
700
697
|
forwardRef as forwardRef8,
|
701
698
|
useCallback,
|
702
699
|
useEffect as useEffect3,
|
703
|
-
useRef as
|
700
|
+
useRef as useRef3
|
704
701
|
} from "react";
|
705
702
|
import TextareaAutosize from "react-textarea-autosize";
|
706
703
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
@@ -729,7 +726,7 @@ var ComposerInput = forwardRef8(
|
|
729
726
|
}
|
730
727
|
}
|
731
728
|
};
|
732
|
-
const textareaRef =
|
729
|
+
const textareaRef = useRef3(null);
|
733
730
|
const ref = useComposedRefs3(forwardedRef, textareaRef);
|
734
731
|
const autoFocusEnabled = autoFocus && !disabled;
|
735
732
|
const focus = useCallback(() => {
|
@@ -876,7 +873,6 @@ var useGoToPreviousBranch = () => {
|
|
876
873
|
const { message, branches } = useMessage.getState();
|
877
874
|
useThread.getState().switchToBranch(
|
878
875
|
branches[branches.indexOf(message.id) - 1]
|
879
|
-
// TODO probably there's a more elegant way to do this
|
880
876
|
);
|
881
877
|
};
|
882
878
|
};
|
@@ -1013,7 +1009,7 @@ var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
|
1013
1009
|
// src/primitives/contentPart/index.ts
|
1014
1010
|
var contentPart_exports = {};
|
1015
1011
|
__export(contentPart_exports, {
|
1016
|
-
|
1012
|
+
InProgressIndicator: () => ContentPartInProgressIndicator,
|
1017
1013
|
Provider: () => ContentPartProvider
|
1018
1014
|
});
|
1019
1015
|
|
@@ -1077,7 +1073,8 @@ var useDummyAIAssistantContext = () => {
|
|
1077
1073
|
};
|
1078
1074
|
|
1079
1075
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1080
|
-
import {
|
1076
|
+
import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
|
1077
|
+
import { useCallback as useCallback2, useMemo as useMemo5, useRef as useRef4, useState as useState4 } from "react";
|
1081
1078
|
|
1082
1079
|
// src/adapters/MessageRepository.tsx
|
1083
1080
|
import { customAlphabet } from "nanoid/non-secure";
|
@@ -1087,7 +1084,6 @@ var generateId = customAlphabet(
|
|
1087
1084
|
);
|
1088
1085
|
var optimisticPrefix = "__optimistic__";
|
1089
1086
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1090
|
-
var isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
1091
1087
|
var findHead = (message) => {
|
1092
1088
|
if (message.next) return findHead(message.next);
|
1093
1089
|
return message;
|
@@ -1171,7 +1167,8 @@ var MessageRepository = class {
|
|
1171
1167
|
this.addOrUpdateMessage(parentId, {
|
1172
1168
|
...message,
|
1173
1169
|
id: optimisticId,
|
1174
|
-
createdAt: /* @__PURE__ */ new Date()
|
1170
|
+
createdAt: /* @__PURE__ */ new Date(),
|
1171
|
+
...message.role === "assistant" ? { status: "in_progress" } : void 0
|
1175
1172
|
});
|
1176
1173
|
return optimisticId;
|
1177
1174
|
}
|
@@ -1241,8 +1238,8 @@ var MessageRepository = class {
|
|
1241
1238
|
|
1242
1239
|
// src/adapters/ThreadMessageConverter.tsx
|
1243
1240
|
var ThreadMessageConverter = class {
|
1244
|
-
constructor(
|
1245
|
-
this.converter =
|
1241
|
+
constructor(converter) {
|
1242
|
+
this.converter = converter;
|
1246
1243
|
}
|
1247
1244
|
cache = /* @__PURE__ */ new WeakMap();
|
1248
1245
|
convertMessages(messages) {
|
@@ -1256,33 +1253,55 @@ var ThreadMessageConverter = class {
|
|
1256
1253
|
}
|
1257
1254
|
};
|
1258
1255
|
|
1256
|
+
// src/adapters/vercel/VercelThreadMessage.tsx
|
1257
|
+
var symbolInnerMessage = Symbol("innerMessage");
|
1258
|
+
var symbolInnerRSCMessage = Symbol("innerRSCMessage");
|
1259
|
+
var getVercelMessage = (message) => {
|
1260
|
+
return message[symbolInnerMessage];
|
1261
|
+
};
|
1262
|
+
var getVercelRSCMessage = (message) => {
|
1263
|
+
return message[symbolInnerRSCMessage];
|
1264
|
+
};
|
1265
|
+
|
1259
1266
|
// src/adapters/vercel/useVercelAIThreadState.tsx
|
1260
|
-
var vercelToThreadMessage = (message) => {
|
1261
|
-
|
1262
|
-
throw new Error(
|
1263
|
-
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1264
|
-
);
|
1265
|
-
return {
|
1267
|
+
var vercelToThreadMessage = (message, status) => {
|
1268
|
+
const common = {
|
1266
1269
|
id: message.id,
|
1267
|
-
role: message.role,
|
1268
|
-
content: [
|
1269
|
-
...message.content ? [{ type: "text", text: message.content }] : [],
|
1270
|
-
...message.toolInvocations?.map((t) => ({
|
1271
|
-
type: "tool-call",
|
1272
|
-
name: t.toolName,
|
1273
|
-
args: t.args,
|
1274
|
-
result: "result" in t ? t.result : void 0
|
1275
|
-
})) ?? []
|
1276
|
-
],
|
1277
|
-
// ignore type mismatch for now
|
1278
1270
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1279
|
-
|
1271
|
+
[symbolInnerMessage]: message
|
1280
1272
|
};
|
1273
|
+
switch (message.role) {
|
1274
|
+
case "user":
|
1275
|
+
return {
|
1276
|
+
...common,
|
1277
|
+
role: "user",
|
1278
|
+
content: [{ type: "text", text: message.content }]
|
1279
|
+
};
|
1280
|
+
case "assistant":
|
1281
|
+
return {
|
1282
|
+
...common,
|
1283
|
+
role: "assistant",
|
1284
|
+
content: [
|
1285
|
+
...message.content ? [{ type: "text", text: message.content }] : [],
|
1286
|
+
...message.toolInvocations?.map(
|
1287
|
+
(t) => ({
|
1288
|
+
type: "tool-call",
|
1289
|
+
name: t.toolName,
|
1290
|
+
args: t.args,
|
1291
|
+
result: "result" in t ? t.result : void 0
|
1292
|
+
})
|
1293
|
+
) ?? []
|
1294
|
+
],
|
1295
|
+
status
|
1296
|
+
};
|
1297
|
+
default:
|
1298
|
+
throw new Error(
|
1299
|
+
`You have a message with an unsupported role. The role ${message.role} is not supported.`
|
1300
|
+
);
|
1301
|
+
}
|
1281
1302
|
};
|
1282
|
-
var converter = new ThreadMessageConverter(vercelToThreadMessage);
|
1283
1303
|
var sliceMessagesUntil = (messages, messageId) => {
|
1284
1304
|
if (messageId == null) return [];
|
1285
|
-
if (isOptimisticId(messageId)) return messages;
|
1286
1305
|
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
1287
1306
|
if (messageIdx === -1)
|
1288
1307
|
throw new Error(
|
@@ -1299,10 +1318,15 @@ var getIsRunning = (vercel) => {
|
|
1299
1318
|
};
|
1300
1319
|
var useVercelAIThreadState = (vercel) => {
|
1301
1320
|
const [data] = useState4(() => new MessageRepository());
|
1302
|
-
const
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1321
|
+
const isRunning = getIsRunning(vercel);
|
1322
|
+
const convertCallback = useCallbackRef3((message) => {
|
1323
|
+
return vercelToThreadMessage(
|
1324
|
+
message,
|
1325
|
+
vercel.messages.at(-1) === message && isRunning ? "in_progress" : "done"
|
1326
|
+
);
|
1327
|
+
});
|
1328
|
+
const converter = new ThreadMessageConverter(convertCallback);
|
1329
|
+
const assistantOptimisticIdRef = useRef4(null);
|
1306
1330
|
const messages = useMemo5(() => {
|
1307
1331
|
const vm = converter.convertMessages(vercel.messages);
|
1308
1332
|
for (let i = 0; i < vm.length; i++) {
|
@@ -1325,55 +1349,46 @@ var useVercelAIThreadState = (vercel) => {
|
|
1325
1349
|
}
|
1326
1350
|
data.resetHead(assistantOptimisticIdRef.current ?? vm.at(-1)?.id ?? null);
|
1327
1351
|
return data.getMessages();
|
1328
|
-
}, [data, isRunning, vercel.messages]);
|
1352
|
+
}, [converter, data, isRunning, vercel.messages]);
|
1329
1353
|
const getBranches2 = useCallback2(
|
1330
1354
|
(messageId) => {
|
1331
1355
|
return data.getBranches(messageId);
|
1332
1356
|
},
|
1333
1357
|
[data]
|
1334
1358
|
);
|
1335
|
-
const switchToBranch2 =
|
1336
|
-
(messageId)
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
);
|
1344
|
-
const startRun = useCallback2(async (parentId) => {
|
1345
|
-
const reloadMaybe = "reload" in vercelRef.current ? vercelRef.current.reload : void 0;
|
1359
|
+
const switchToBranch2 = useCallbackRef3((messageId) => {
|
1360
|
+
data.switchToBranch(messageId);
|
1361
|
+
vercel.setMessages(
|
1362
|
+
data.getMessages().map(getVercelMessage).filter((m) => m != null)
|
1363
|
+
);
|
1364
|
+
});
|
1365
|
+
const startRun = useCallbackRef3(async (parentId) => {
|
1366
|
+
const reloadMaybe = "reload" in vercel ? vercel.reload : void 0;
|
1346
1367
|
if (!reloadMaybe)
|
1347
1368
|
throw new Error(
|
1348
1369
|
"Reload is not supported by Vercel AI SDK's useAssistant."
|
1349
1370
|
);
|
1350
|
-
const newMessages = sliceMessagesUntil(
|
1351
|
-
|
1352
|
-
parentId
|
1353
|
-
);
|
1354
|
-
vercelRef.current.setMessages(newMessages);
|
1371
|
+
const newMessages = sliceMessagesUntil(vercel.messages, parentId);
|
1372
|
+
vercel.setMessages(newMessages);
|
1355
1373
|
await reloadMaybe();
|
1356
|
-
}
|
1357
|
-
const append =
|
1374
|
+
});
|
1375
|
+
const append = useCallbackRef3(async (message) => {
|
1358
1376
|
if (message.content.length !== 1 || message.content[0]?.type !== "text")
|
1359
1377
|
throw new Error("Only text content is supported by Vercel AI SDK.");
|
1360
|
-
const newMessages = sliceMessagesUntil(
|
1361
|
-
|
1362
|
-
|
1363
|
-
);
|
1364
|
-
vercelRef.current.setMessages(newMessages);
|
1365
|
-
await vercelRef.current.append({
|
1378
|
+
const newMessages = sliceMessagesUntil(vercel.messages, message.parentId);
|
1379
|
+
vercel.setMessages(newMessages);
|
1380
|
+
await vercel.append({
|
1366
1381
|
role: "user",
|
1367
1382
|
content: message.content[0].text
|
1368
1383
|
});
|
1369
|
-
}
|
1370
|
-
const cancelRun2 =
|
1371
|
-
const lastMessage =
|
1372
|
-
|
1384
|
+
});
|
1385
|
+
const cancelRun2 = useCallbackRef3(() => {
|
1386
|
+
const lastMessage = vercel.messages.at(-1);
|
1387
|
+
vercel.stop();
|
1373
1388
|
if (lastMessage?.role === "user") {
|
1374
|
-
|
1389
|
+
vercel.setInput(lastMessage.content);
|
1375
1390
|
}
|
1376
|
-
}
|
1391
|
+
});
|
1377
1392
|
return useMemo5(
|
1378
1393
|
() => ({
|
1379
1394
|
isRunning,
|
@@ -1424,12 +1439,15 @@ import {
|
|
1424
1439
|
useState as useState5
|
1425
1440
|
} from "react";
|
1426
1441
|
import { jsx as jsx22 } from "react/jsx-runtime";
|
1427
|
-
var vercelToThreadMessage2 = (
|
1442
|
+
var vercelToThreadMessage2 = (converter, rawMessage) => {
|
1443
|
+
const message = converter(rawMessage);
|
1428
1444
|
return {
|
1429
1445
|
id: message.id,
|
1430
1446
|
role: message.role,
|
1431
1447
|
content: [{ type: "ui", display: message.display }],
|
1432
|
-
createdAt: message.createdAt ?? /* @__PURE__ */ new Date()
|
1448
|
+
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
1449
|
+
...{ status: "done" },
|
1450
|
+
[symbolInnerRSCMessage]: rawMessage
|
1433
1451
|
};
|
1434
1452
|
};
|
1435
1453
|
var EMPTY_BRANCHES = [];
|
@@ -1462,15 +1480,15 @@ var VercelRSCAssistantProvider = ({
|
|
1462
1480
|
setIsRunning(true);
|
1463
1481
|
return callback.finally(() => setIsRunning(false));
|
1464
1482
|
}, []);
|
1465
|
-
const
|
1483
|
+
const converter = useMemo7(() => {
|
1466
1484
|
const rscConverter = convertMessage ?? ((m) => m);
|
1467
1485
|
return new ThreadMessageConverter((m) => {
|
1468
|
-
return vercelToThreadMessage2(rscConverter
|
1486
|
+
return vercelToThreadMessage2(rscConverter, m);
|
1469
1487
|
});
|
1470
1488
|
}, [convertMessage]);
|
1471
1489
|
const messages = useMemo7(() => {
|
1472
|
-
return
|
1473
|
-
}, [
|
1490
|
+
return converter.convertMessages(vercelMessages);
|
1491
|
+
}, [converter, vercelMessages]);
|
1474
1492
|
const append = useCallback3(
|
1475
1493
|
async (message) => {
|
1476
1494
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
@@ -1520,6 +1538,8 @@ export {
|
|
1520
1538
|
thread_exports as ThreadPrimitive,
|
1521
1539
|
VercelAIAssistantProvider,
|
1522
1540
|
VercelRSCAssistantProvider,
|
1541
|
+
getVercelMessage as unstable_getVercelMessage,
|
1542
|
+
getVercelRSCMessage as unstable_getVercelRSCMessage,
|
1523
1543
|
useMessageContext as unstable_useMessageContext,
|
1524
1544
|
useBeginMessageEdit,
|
1525
1545
|
useCopyMessage,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@assistant-ui/react",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.17",
|
4
4
|
"license": "MIT",
|
5
5
|
"exports": {
|
6
6
|
".": {
|
@@ -31,6 +31,7 @@
|
|
31
31
|
"@radix-ui/react-compose-refs": "^1.0.1",
|
32
32
|
"@radix-ui/react-primitive": "^1.0.3",
|
33
33
|
"@radix-ui/react-slot": "^1.0.2",
|
34
|
+
"@radix-ui/react-use-callback-ref": "^1.0.1",
|
34
35
|
"ai": "^3.1.23",
|
35
36
|
"nanoid": "^5.0.7",
|
36
37
|
"react-textarea-autosize": "^8.5.3",
|