@assistant-ui/react 0.0.5 → 0.0.6
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 +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,
|