@assistant-ui/react 0.0.16 → 0.0.17
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 +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",
|