@assistant-ui/react 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.d.mts +45 -24
- package/dist/index.d.ts +45 -24
- package/dist/index.js +91 -57
- package/dist/index.mjs +91 -57
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import * as react from 'react';
|
2
2
|
import { FC, PropsWithChildren } from 'react';
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
|
-
import { Message } from 'ai';
|
5
4
|
import { UseChatHelpers } from 'ai/react';
|
6
5
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
6
|
|
@@ -84,9 +83,49 @@ declare namespace index$3 {
|
|
84
83
|
export { ComposerCancel as Cancel, ComposerIf as If, ComposerInput as Input, ComposerRoot as Root, ComposerSend as Send };
|
85
84
|
}
|
86
85
|
|
86
|
+
type BranchState = {
|
87
|
+
branchId: number;
|
88
|
+
branchCount: number;
|
89
|
+
};
|
90
|
+
|
91
|
+
type ComposerState = {
|
92
|
+
isEditing: boolean;
|
93
|
+
canCancel: boolean;
|
94
|
+
edit: () => void;
|
95
|
+
send: () => void;
|
96
|
+
cancel: () => void;
|
97
|
+
value: string;
|
98
|
+
setValue: (value: string) => void;
|
99
|
+
};
|
100
|
+
type ComposerStore = {
|
101
|
+
useComposer: UseBoundStore<StoreApi<ComposerState>>;
|
102
|
+
};
|
103
|
+
|
104
|
+
type TextContent = {
|
105
|
+
type: "text";
|
106
|
+
text: string;
|
107
|
+
};
|
108
|
+
type ImageContent = {
|
109
|
+
type: "image";
|
110
|
+
image: string;
|
111
|
+
};
|
112
|
+
type ThreadUserMessageContent = TextContent | ImageContent;
|
113
|
+
type ThreadAssistantMessageContent = TextContent | ImageContent;
|
114
|
+
type ThreadUserMessage = {
|
115
|
+
id: string;
|
116
|
+
role: "user";
|
117
|
+
content: ThreadUserMessageContent[];
|
118
|
+
};
|
119
|
+
type ThreadAssistantMessage = {
|
120
|
+
id: string;
|
121
|
+
role: "assistant";
|
122
|
+
content: ThreadAssistantMessageContent[];
|
123
|
+
};
|
124
|
+
type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
|
125
|
+
|
87
126
|
type MessageProviderProps = {
|
88
127
|
children?: React.ReactNode;
|
89
|
-
message:
|
128
|
+
message: ThreadMessage;
|
90
129
|
};
|
91
130
|
declare const MessageProvider: FC<MessageProviderProps>;
|
92
131
|
|
@@ -177,32 +216,14 @@ declare namespace index {
|
|
177
216
|
export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
|
178
217
|
}
|
179
218
|
|
180
|
-
type
|
219
|
+
type VercelAIChatAssistantProviderProps = {
|
181
220
|
chat: UseChatHelpers;
|
182
221
|
children: React.ReactNode;
|
183
222
|
};
|
184
|
-
declare const
|
185
|
-
|
186
|
-
type ComposerState = {
|
187
|
-
isEditing: boolean;
|
188
|
-
canCancel: boolean;
|
189
|
-
edit: () => void;
|
190
|
-
send: () => void;
|
191
|
-
cancel: () => void;
|
192
|
-
value: string;
|
193
|
-
setValue: (value: string) => void;
|
194
|
-
};
|
195
|
-
type ComposerStore = {
|
196
|
-
useComposer: UseBoundStore<StoreApi<ComposerState>>;
|
197
|
-
};
|
198
|
-
|
199
|
-
type BranchState = {
|
200
|
-
branchId: number;
|
201
|
-
branchCount: number;
|
202
|
-
};
|
223
|
+
declare const VercelAIChatAssistantProvider: FC<VercelAIChatAssistantProviderProps>;
|
203
224
|
|
204
225
|
type MessageState = {
|
205
|
-
message:
|
226
|
+
message: ThreadMessage;
|
206
227
|
branchState: BranchState;
|
207
228
|
isLast: boolean;
|
208
229
|
isCopied: boolean;
|
@@ -227,4 +248,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
227
248
|
|
228
249
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
229
250
|
|
230
|
-
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive,
|
251
|
+
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIChatAssistantProvider as VercelAIAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.d.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import * as react from 'react';
|
2
2
|
import { FC, PropsWithChildren } from 'react';
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
|
-
import { Message } from 'ai';
|
5
4
|
import { UseChatHelpers } from 'ai/react';
|
6
5
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
6
|
|
@@ -84,9 +83,49 @@ declare namespace index$3 {
|
|
84
83
|
export { ComposerCancel as Cancel, ComposerIf as If, ComposerInput as Input, ComposerRoot as Root, ComposerSend as Send };
|
85
84
|
}
|
86
85
|
|
86
|
+
type BranchState = {
|
87
|
+
branchId: number;
|
88
|
+
branchCount: number;
|
89
|
+
};
|
90
|
+
|
91
|
+
type ComposerState = {
|
92
|
+
isEditing: boolean;
|
93
|
+
canCancel: boolean;
|
94
|
+
edit: () => void;
|
95
|
+
send: () => void;
|
96
|
+
cancel: () => void;
|
97
|
+
value: string;
|
98
|
+
setValue: (value: string) => void;
|
99
|
+
};
|
100
|
+
type ComposerStore = {
|
101
|
+
useComposer: UseBoundStore<StoreApi<ComposerState>>;
|
102
|
+
};
|
103
|
+
|
104
|
+
type TextContent = {
|
105
|
+
type: "text";
|
106
|
+
text: string;
|
107
|
+
};
|
108
|
+
type ImageContent = {
|
109
|
+
type: "image";
|
110
|
+
image: string;
|
111
|
+
};
|
112
|
+
type ThreadUserMessageContent = TextContent | ImageContent;
|
113
|
+
type ThreadAssistantMessageContent = TextContent | ImageContent;
|
114
|
+
type ThreadUserMessage = {
|
115
|
+
id: string;
|
116
|
+
role: "user";
|
117
|
+
content: ThreadUserMessageContent[];
|
118
|
+
};
|
119
|
+
type ThreadAssistantMessage = {
|
120
|
+
id: string;
|
121
|
+
role: "assistant";
|
122
|
+
content: ThreadAssistantMessageContent[];
|
123
|
+
};
|
124
|
+
type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
|
125
|
+
|
87
126
|
type MessageProviderProps = {
|
88
127
|
children?: React.ReactNode;
|
89
|
-
message:
|
128
|
+
message: ThreadMessage;
|
90
129
|
};
|
91
130
|
declare const MessageProvider: FC<MessageProviderProps>;
|
92
131
|
|
@@ -177,32 +216,14 @@ declare namespace index {
|
|
177
216
|
export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
|
178
217
|
}
|
179
218
|
|
180
|
-
type
|
219
|
+
type VercelAIChatAssistantProviderProps = {
|
181
220
|
chat: UseChatHelpers;
|
182
221
|
children: React.ReactNode;
|
183
222
|
};
|
184
|
-
declare const
|
185
|
-
|
186
|
-
type ComposerState = {
|
187
|
-
isEditing: boolean;
|
188
|
-
canCancel: boolean;
|
189
|
-
edit: () => void;
|
190
|
-
send: () => void;
|
191
|
-
cancel: () => void;
|
192
|
-
value: string;
|
193
|
-
setValue: (value: string) => void;
|
194
|
-
};
|
195
|
-
type ComposerStore = {
|
196
|
-
useComposer: UseBoundStore<StoreApi<ComposerState>>;
|
197
|
-
};
|
198
|
-
|
199
|
-
type BranchState = {
|
200
|
-
branchId: number;
|
201
|
-
branchCount: number;
|
202
|
-
};
|
223
|
+
declare const VercelAIChatAssistantProvider: FC<VercelAIChatAssistantProviderProps>;
|
203
224
|
|
204
225
|
type MessageState = {
|
205
|
-
message:
|
226
|
+
message: ThreadMessage;
|
206
227
|
branchState: BranchState;
|
207
228
|
isLast: boolean;
|
208
229
|
isCopied: boolean;
|
@@ -227,4 +248,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
227
248
|
|
228
249
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
229
250
|
|
230
|
-
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive,
|
251
|
+
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIChatAssistantProvider as VercelAIAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.js
CHANGED
@@ -35,7 +35,7 @@ __export(src_exports, {
|
|
35
35
|
ComposerPrimitive: () => composer_exports,
|
36
36
|
MessagePrimitive: () => message_exports,
|
37
37
|
ThreadPrimitive: () => thread_exports,
|
38
|
-
|
38
|
+
VercelAIAssistantProvider: () => VercelAIChatAssistantProvider,
|
39
39
|
unstable_useMessageContext: () => useMessageContext,
|
40
40
|
useBeginMessageEdit: () => useBeginMessageEdit,
|
41
41
|
useCopyMessage: () => useCopyMessage,
|
@@ -177,7 +177,7 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
|
|
177
177
|
);
|
178
178
|
});
|
179
179
|
|
180
|
-
// src/
|
180
|
+
// src/vercel/useVercelAIBranches.tsx
|
181
181
|
var import_react5 = require("react");
|
182
182
|
var ROOT_ID = "__ROOT_ID__";
|
183
183
|
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
@@ -245,7 +245,7 @@ var sliceMessagesUntil = (messages, message) => {
|
|
245
245
|
throw new Error("Unexpected: Message not found");
|
246
246
|
return messages.slice(0, messageIdx);
|
247
247
|
};
|
248
|
-
var
|
248
|
+
var useVercelAIBranches = (chat) => {
|
249
249
|
const data = (0, import_react5.useRef)({
|
250
250
|
parentMap: /* @__PURE__ */ new Map(),
|
251
251
|
branchMap: /* @__PURE__ */ new Map(),
|
@@ -282,7 +282,12 @@ var useChatWithBranches = (chat) => {
|
|
282
282
|
async (message, newMessage) => {
|
283
283
|
const newMessages = sliceMessagesUntil(chat.messages, message);
|
284
284
|
chat.setMessages(newMessages);
|
285
|
-
|
285
|
+
if (newMessage.content[0]?.type !== "text")
|
286
|
+
throw new Error("Only text content is currently supported");
|
287
|
+
await chat.append({
|
288
|
+
role: "user",
|
289
|
+
content: newMessage.content[0].text
|
290
|
+
});
|
286
291
|
},
|
287
292
|
[chat.messages, chat.setMessages, chat.append]
|
288
293
|
);
|
@@ -373,18 +378,25 @@ var useMessageContext2 = () => {
|
|
373
378
|
const useComposer = (0, import_zustand.create)((set, get) => ({
|
374
379
|
isEditing: false,
|
375
380
|
canCancel: true,
|
376
|
-
edit: () =>
|
377
|
-
|
378
|
-
|
379
|
-
|
381
|
+
edit: () => {
|
382
|
+
const message = useMessage.getState().message;
|
383
|
+
if (message.role !== "user")
|
384
|
+
throw new Error("Editing is only supported for user messages");
|
385
|
+
if (message.content[0]?.type !== "text")
|
386
|
+
throw new Error("Editing is only supported for text-only messages");
|
387
|
+
return set({
|
388
|
+
isEditing: true,
|
389
|
+
value: message.content[0].text
|
390
|
+
});
|
391
|
+
},
|
380
392
|
cancel: () => set({ isEditing: false }),
|
381
393
|
send: () => {
|
382
394
|
const message = useMessage.getState().message;
|
395
|
+
if (message.role !== "user")
|
396
|
+
throw new Error("Editing is only supported for user messages");
|
383
397
|
useBranchObserver.getState().editAt(message, {
|
384
|
-
|
385
|
-
|
386
|
-
// remove id to create a new message
|
387
|
-
content: get().value
|
398
|
+
role: "user",
|
399
|
+
content: [{ type: "text", text: get().value }]
|
388
400
|
});
|
389
401
|
set({ isEditing: false });
|
390
402
|
},
|
@@ -486,7 +498,9 @@ var MessageIf = ({ children, ...query }) => {
|
|
486
498
|
var MessageContent = () => {
|
487
499
|
const { useMessage } = useMessageContext();
|
488
500
|
const content = useMessage((s) => s.message.content);
|
489
|
-
|
501
|
+
if (content[0]?.type !== "text")
|
502
|
+
throw new Error("Unsupported message content type");
|
503
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, content[0].text);
|
490
504
|
};
|
491
505
|
|
492
506
|
// src/primitives/thread/ThreadMessages.tsx
|
@@ -515,7 +529,7 @@ var ThreadMessages = ({ components }) => {
|
|
515
529
|
message: {
|
516
530
|
id: UPCOMING_MESSAGE_ID,
|
517
531
|
role: "assistant",
|
518
|
-
content: "..."
|
532
|
+
content: [{ type: "text", text: "..." }]
|
519
533
|
}
|
520
534
|
},
|
521
535
|
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
@@ -810,11 +824,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
|
810
824
|
if (isEditing)
|
811
825
|
return null;
|
812
826
|
return () => {
|
813
|
-
const {
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
navigator.clipboard.writeText(content);
|
827
|
+
const { message, setIsCopied } = useMessage.getState();
|
828
|
+
if (message.content[0]?.type !== "text")
|
829
|
+
throw new Error("Copying is only supported for text-only messages");
|
830
|
+
navigator.clipboard.writeText(message.content[0].text);
|
818
831
|
setIsCopied(true);
|
819
832
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
820
833
|
};
|
@@ -832,7 +845,10 @@ var useReloadMessage = () => {
|
|
832
845
|
if (isLoading || !isAssistant)
|
833
846
|
return null;
|
834
847
|
return () => {
|
835
|
-
|
848
|
+
const message = useMessage.getState().message;
|
849
|
+
if (message.role !== "assistant")
|
850
|
+
throw new Error("Reloading is only supported on assistant messages");
|
851
|
+
useBranchObserver.getState().reloadAt(message);
|
836
852
|
};
|
837
853
|
};
|
838
854
|
|
@@ -862,8 +878,6 @@ var useAIAssistantContext = () => {
|
|
862
878
|
const [context] = (0, import_react17.useState)(() => {
|
863
879
|
const useThread = (0, import_zustand2.create)()(() => ({
|
864
880
|
messages: [],
|
865
|
-
setMessages: () => {
|
866
|
-
},
|
867
881
|
isLoading: false,
|
868
882
|
reload: async () => {
|
869
883
|
},
|
@@ -883,9 +897,8 @@ var useAIAssistantContext = () => {
|
|
883
897
|
},
|
884
898
|
send: () => {
|
885
899
|
useThread.getState().append({
|
886
|
-
content: useComposer.getState().value,
|
887
900
|
role: "user",
|
888
|
-
|
901
|
+
content: [{ type: "text", text: useComposer.getState().value }]
|
889
902
|
});
|
890
903
|
useComposer.getState().setValue("");
|
891
904
|
},
|
@@ -909,36 +922,65 @@ var useAIAssistantContext = () => {
|
|
909
922
|
});
|
910
923
|
return context;
|
911
924
|
};
|
912
|
-
var
|
913
|
-
|
914
|
-
|
915
|
-
|
925
|
+
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
926
|
+
var vercelToThreadMessage = (message) => {
|
927
|
+
if (message.role !== "user" && message.role !== "assistant")
|
928
|
+
throw new Error("Unsupported role");
|
929
|
+
return {
|
930
|
+
id: message.id,
|
931
|
+
role: message.role,
|
932
|
+
content: [{ type: "text", text: message.content }]
|
933
|
+
};
|
934
|
+
};
|
935
|
+
var vercelToCachedThreadMessages = (messages) => {
|
936
|
+
return messages.map((m) => {
|
937
|
+
const cached = ThreadMessageCache.get(m);
|
938
|
+
if (cached)
|
939
|
+
return cached;
|
940
|
+
const newMessage = vercelToThreadMessage(m);
|
941
|
+
ThreadMessageCache.set(m, newMessage);
|
942
|
+
return newMessage;
|
943
|
+
});
|
944
|
+
};
|
945
|
+
var VercelAIChatAssistantProvider = ({ chat, children }) => {
|
916
946
|
const context = useAIAssistantContext();
|
947
|
+
const messages = (0, import_react17.useMemo)(() => {
|
948
|
+
return vercelToCachedThreadMessages(chat.messages);
|
949
|
+
}, [chat.messages]);
|
950
|
+
const reload = (0, import_react17.useCallback)(async () => {
|
951
|
+
await chat.reload();
|
952
|
+
}, [chat.reload]);
|
953
|
+
const append = (0, import_react17.useCallback)(
|
954
|
+
async (message) => {
|
955
|
+
if (message.content[0]?.type !== "text") {
|
956
|
+
throw new Error("Only text content is currently supported");
|
957
|
+
}
|
958
|
+
await chat.append({
|
959
|
+
role: message.role,
|
960
|
+
content: message.content[0].text
|
961
|
+
});
|
962
|
+
},
|
963
|
+
[chat.append]
|
964
|
+
);
|
965
|
+
const stop = (0, import_react17.useCallback)(() => {
|
966
|
+
const lastMessage = chat.messages.at(-1);
|
967
|
+
chat.stop();
|
968
|
+
if (lastMessage?.role === "user") {
|
969
|
+
chat.setInput(lastMessage.content);
|
970
|
+
}
|
971
|
+
}, [chat.messages, chat.stop, chat.setInput]);
|
917
972
|
(0, import_react17.useMemo)(() => {
|
918
973
|
context.useThread.setState(
|
919
974
|
{
|
920
|
-
messages
|
921
|
-
setMessages: (value) => {
|
922
|
-
chat.setMessages(value);
|
923
|
-
},
|
975
|
+
messages,
|
924
976
|
isLoading: chat.isLoading,
|
925
|
-
reload
|
926
|
-
|
927
|
-
|
928
|
-
append: async (message) => {
|
929
|
-
await chat.append(message);
|
930
|
-
},
|
931
|
-
stop: () => {
|
932
|
-
const lastMessage = chat.messages.at(-1);
|
933
|
-
chat.stop();
|
934
|
-
if (lastMessage?.role === "user") {
|
935
|
-
chat.setInput(lastMessage.content);
|
936
|
-
}
|
937
|
-
}
|
977
|
+
reload,
|
978
|
+
append,
|
979
|
+
stop
|
938
980
|
},
|
939
981
|
true
|
940
982
|
);
|
941
|
-
}, [context, chat]);
|
983
|
+
}, [context, messages, reload, append, stop, chat.isLoading]);
|
942
984
|
(0, import_react17.useMemo)(() => {
|
943
985
|
context.useComposer.setState({
|
944
986
|
canCancel: chat.isLoading,
|
@@ -946,17 +988,9 @@ var VercelAIAssistantProvider = ({
|
|
946
988
|
setValue: chat.setInput
|
947
989
|
});
|
948
990
|
}, [context, chat.isLoading, chat.input, chat.setInput]);
|
949
|
-
const branches =
|
991
|
+
const branches = useVercelAIBranches(chat);
|
950
992
|
(0, import_react17.useMemo)(() => {
|
951
|
-
context.useBranchObserver.setState(
|
952
|
-
{
|
953
|
-
getBranchState: (message) => branches.getBranchState(message),
|
954
|
-
switchToBranch: (message, branchId) => branches.switchToBranch(message, branchId),
|
955
|
-
editAt: async (message, newMessage) => branches.editAt(message, newMessage),
|
956
|
-
reloadAt: async (message) => branches.reloadAt(message)
|
957
|
-
},
|
958
|
-
true
|
959
|
-
);
|
993
|
+
context.useBranchObserver.setState(branches, true);
|
960
994
|
}, [context, branches]);
|
961
995
|
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
962
996
|
};
|
@@ -967,7 +1001,7 @@ var VercelAIAssistantProvider = ({
|
|
967
1001
|
ComposerPrimitive,
|
968
1002
|
MessagePrimitive,
|
969
1003
|
ThreadPrimitive,
|
970
|
-
|
1004
|
+
VercelAIAssistantProvider,
|
971
1005
|
unstable_useMessageContext,
|
972
1006
|
useBeginMessageEdit,
|
973
1007
|
useCopyMessage,
|
package/dist/index.mjs
CHANGED
@@ -140,7 +140,7 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
|
|
140
140
|
);
|
141
141
|
});
|
142
142
|
|
143
|
-
// src/
|
143
|
+
// src/vercel/useVercelAIBranches.tsx
|
144
144
|
import { useCallback, useMemo, useRef as useRef3 } from "react";
|
145
145
|
var ROOT_ID = "__ROOT_ID__";
|
146
146
|
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
@@ -208,7 +208,7 @@ var sliceMessagesUntil = (messages, message) => {
|
|
208
208
|
throw new Error("Unexpected: Message not found");
|
209
209
|
return messages.slice(0, messageIdx);
|
210
210
|
};
|
211
|
-
var
|
211
|
+
var useVercelAIBranches = (chat) => {
|
212
212
|
const data = useRef3({
|
213
213
|
parentMap: /* @__PURE__ */ new Map(),
|
214
214
|
branchMap: /* @__PURE__ */ new Map(),
|
@@ -245,7 +245,12 @@ var useChatWithBranches = (chat) => {
|
|
245
245
|
async (message, newMessage) => {
|
246
246
|
const newMessages = sliceMessagesUntil(chat.messages, message);
|
247
247
|
chat.setMessages(newMessages);
|
248
|
-
|
248
|
+
if (newMessage.content[0]?.type !== "text")
|
249
|
+
throw new Error("Only text content is currently supported");
|
250
|
+
await chat.append({
|
251
|
+
role: "user",
|
252
|
+
content: newMessage.content[0].text
|
253
|
+
});
|
249
254
|
},
|
250
255
|
[chat.messages, chat.setMessages, chat.append]
|
251
256
|
);
|
@@ -336,18 +341,25 @@ var useMessageContext2 = () => {
|
|
336
341
|
const useComposer = create((set, get) => ({
|
337
342
|
isEditing: false,
|
338
343
|
canCancel: true,
|
339
|
-
edit: () =>
|
340
|
-
|
341
|
-
|
342
|
-
|
344
|
+
edit: () => {
|
345
|
+
const message = useMessage.getState().message;
|
346
|
+
if (message.role !== "user")
|
347
|
+
throw new Error("Editing is only supported for user messages");
|
348
|
+
if (message.content[0]?.type !== "text")
|
349
|
+
throw new Error("Editing is only supported for text-only messages");
|
350
|
+
return set({
|
351
|
+
isEditing: true,
|
352
|
+
value: message.content[0].text
|
353
|
+
});
|
354
|
+
},
|
343
355
|
cancel: () => set({ isEditing: false }),
|
344
356
|
send: () => {
|
345
357
|
const message = useMessage.getState().message;
|
358
|
+
if (message.role !== "user")
|
359
|
+
throw new Error("Editing is only supported for user messages");
|
346
360
|
useBranchObserver.getState().editAt(message, {
|
347
|
-
|
348
|
-
|
349
|
-
// remove id to create a new message
|
350
|
-
content: get().value
|
361
|
+
role: "user",
|
362
|
+
content: [{ type: "text", text: get().value }]
|
351
363
|
});
|
352
364
|
set({ isEditing: false });
|
353
365
|
},
|
@@ -451,7 +463,9 @@ var MessageIf = ({ children, ...query }) => {
|
|
451
463
|
var MessageContent = () => {
|
452
464
|
const { useMessage } = useMessageContext();
|
453
465
|
const content = useMessage((s) => s.message.content);
|
454
|
-
|
466
|
+
if (content[0]?.type !== "text")
|
467
|
+
throw new Error("Unsupported message content type");
|
468
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, content[0].text);
|
455
469
|
};
|
456
470
|
|
457
471
|
// src/primitives/thread/ThreadMessages.tsx
|
@@ -480,7 +494,7 @@ var ThreadMessages = ({ components }) => {
|
|
480
494
|
message: {
|
481
495
|
id: UPCOMING_MESSAGE_ID,
|
482
496
|
role: "assistant",
|
483
|
-
content: "..."
|
497
|
+
content: [{ type: "text", text: "..." }]
|
484
498
|
}
|
485
499
|
},
|
486
500
|
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
@@ -793,11 +807,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
|
793
807
|
if (isEditing)
|
794
808
|
return null;
|
795
809
|
return () => {
|
796
|
-
const {
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
navigator.clipboard.writeText(content);
|
810
|
+
const { message, setIsCopied } = useMessage.getState();
|
811
|
+
if (message.content[0]?.type !== "text")
|
812
|
+
throw new Error("Copying is only supported for text-only messages");
|
813
|
+
navigator.clipboard.writeText(message.content[0].text);
|
801
814
|
setIsCopied(true);
|
802
815
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
803
816
|
};
|
@@ -815,7 +828,10 @@ var useReloadMessage = () => {
|
|
815
828
|
if (isLoading || !isAssistant)
|
816
829
|
return null;
|
817
830
|
return () => {
|
818
|
-
|
831
|
+
const message = useMessage.getState().message;
|
832
|
+
if (message.role !== "assistant")
|
833
|
+
throw new Error("Reloading is only supported on assistant messages");
|
834
|
+
useBranchObserver.getState().reloadAt(message);
|
819
835
|
};
|
820
836
|
};
|
821
837
|
|
@@ -839,14 +855,12 @@ var useBeginMessageEdit = () => {
|
|
839
855
|
var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
840
856
|
|
841
857
|
// src/vercel/VercelAIAssistantProvider.tsx
|
842
|
-
import { useMemo as useMemo4, useState as useState3 } from "react";
|
858
|
+
import { useCallback as useCallback2, useMemo as useMemo4, useState as useState3 } from "react";
|
843
859
|
import { create as create2 } from "zustand";
|
844
860
|
var useAIAssistantContext = () => {
|
845
861
|
const [context] = useState3(() => {
|
846
862
|
const useThread = create2()(() => ({
|
847
863
|
messages: [],
|
848
|
-
setMessages: () => {
|
849
|
-
},
|
850
864
|
isLoading: false,
|
851
865
|
reload: async () => {
|
852
866
|
},
|
@@ -866,9 +880,8 @@ var useAIAssistantContext = () => {
|
|
866
880
|
},
|
867
881
|
send: () => {
|
868
882
|
useThread.getState().append({
|
869
|
-
content: useComposer.getState().value,
|
870
883
|
role: "user",
|
871
|
-
|
884
|
+
content: [{ type: "text", text: useComposer.getState().value }]
|
872
885
|
});
|
873
886
|
useComposer.getState().setValue("");
|
874
887
|
},
|
@@ -892,36 +905,65 @@ var useAIAssistantContext = () => {
|
|
892
905
|
});
|
893
906
|
return context;
|
894
907
|
};
|
895
|
-
var
|
896
|
-
|
897
|
-
|
898
|
-
|
908
|
+
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
909
|
+
var vercelToThreadMessage = (message) => {
|
910
|
+
if (message.role !== "user" && message.role !== "assistant")
|
911
|
+
throw new Error("Unsupported role");
|
912
|
+
return {
|
913
|
+
id: message.id,
|
914
|
+
role: message.role,
|
915
|
+
content: [{ type: "text", text: message.content }]
|
916
|
+
};
|
917
|
+
};
|
918
|
+
var vercelToCachedThreadMessages = (messages) => {
|
919
|
+
return messages.map((m) => {
|
920
|
+
const cached = ThreadMessageCache.get(m);
|
921
|
+
if (cached)
|
922
|
+
return cached;
|
923
|
+
const newMessage = vercelToThreadMessage(m);
|
924
|
+
ThreadMessageCache.set(m, newMessage);
|
925
|
+
return newMessage;
|
926
|
+
});
|
927
|
+
};
|
928
|
+
var VercelAIChatAssistantProvider = ({ chat, children }) => {
|
899
929
|
const context = useAIAssistantContext();
|
930
|
+
const messages = useMemo4(() => {
|
931
|
+
return vercelToCachedThreadMessages(chat.messages);
|
932
|
+
}, [chat.messages]);
|
933
|
+
const reload = useCallback2(async () => {
|
934
|
+
await chat.reload();
|
935
|
+
}, [chat.reload]);
|
936
|
+
const append = useCallback2(
|
937
|
+
async (message) => {
|
938
|
+
if (message.content[0]?.type !== "text") {
|
939
|
+
throw new Error("Only text content is currently supported");
|
940
|
+
}
|
941
|
+
await chat.append({
|
942
|
+
role: message.role,
|
943
|
+
content: message.content[0].text
|
944
|
+
});
|
945
|
+
},
|
946
|
+
[chat.append]
|
947
|
+
);
|
948
|
+
const stop = useCallback2(() => {
|
949
|
+
const lastMessage = chat.messages.at(-1);
|
950
|
+
chat.stop();
|
951
|
+
if (lastMessage?.role === "user") {
|
952
|
+
chat.setInput(lastMessage.content);
|
953
|
+
}
|
954
|
+
}, [chat.messages, chat.stop, chat.setInput]);
|
900
955
|
useMemo4(() => {
|
901
956
|
context.useThread.setState(
|
902
957
|
{
|
903
|
-
messages
|
904
|
-
setMessages: (value) => {
|
905
|
-
chat.setMessages(value);
|
906
|
-
},
|
958
|
+
messages,
|
907
959
|
isLoading: chat.isLoading,
|
908
|
-
reload
|
909
|
-
|
910
|
-
|
911
|
-
append: async (message) => {
|
912
|
-
await chat.append(message);
|
913
|
-
},
|
914
|
-
stop: () => {
|
915
|
-
const lastMessage = chat.messages.at(-1);
|
916
|
-
chat.stop();
|
917
|
-
if (lastMessage?.role === "user") {
|
918
|
-
chat.setInput(lastMessage.content);
|
919
|
-
}
|
920
|
-
}
|
960
|
+
reload,
|
961
|
+
append,
|
962
|
+
stop
|
921
963
|
},
|
922
964
|
true
|
923
965
|
);
|
924
|
-
}, [context, chat]);
|
966
|
+
}, [context, messages, reload, append, stop, chat.isLoading]);
|
925
967
|
useMemo4(() => {
|
926
968
|
context.useComposer.setState({
|
927
969
|
canCancel: chat.isLoading,
|
@@ -929,17 +971,9 @@ var VercelAIAssistantProvider = ({
|
|
929
971
|
setValue: chat.setInput
|
930
972
|
});
|
931
973
|
}, [context, chat.isLoading, chat.input, chat.setInput]);
|
932
|
-
const branches =
|
974
|
+
const branches = useVercelAIBranches(chat);
|
933
975
|
useMemo4(() => {
|
934
|
-
context.useBranchObserver.setState(
|
935
|
-
{
|
936
|
-
getBranchState: (message) => branches.getBranchState(message),
|
937
|
-
switchToBranch: (message, branchId) => branches.switchToBranch(message, branchId),
|
938
|
-
editAt: async (message, newMessage) => branches.editAt(message, newMessage),
|
939
|
-
reloadAt: async (message) => branches.reloadAt(message)
|
940
|
-
},
|
941
|
-
true
|
942
|
-
);
|
976
|
+
context.useBranchObserver.setState(branches, true);
|
943
977
|
}, [context, branches]);
|
944
978
|
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
945
979
|
};
|
@@ -949,7 +983,7 @@ export {
|
|
949
983
|
composer_exports as ComposerPrimitive,
|
950
984
|
message_exports as MessagePrimitive,
|
951
985
|
thread_exports as ThreadPrimitive,
|
952
|
-
|
986
|
+
VercelAIChatAssistantProvider as VercelAIAssistantProvider,
|
953
987
|
useMessageContext as unstable_useMessageContext,
|
954
988
|
useBeginMessageEdit,
|
955
989
|
useCopyMessage,
|