@assistant-ui/react 0.0.5 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.d.mts +93 -28
- package/dist/index.d.ts +93 -28
- package/dist/index.js +213 -76
- package/dist/index.mjs +212 -73
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
import * as react from 'react';
|
2
|
-
import { FC, PropsWithChildren } from 'react';
|
2
|
+
import { FC, PropsWithChildren, ReactNode, ComponentType } from 'react';
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
|
-
import {
|
5
|
-
import { UseChatHelpers } from 'ai/react';
|
4
|
+
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
6
5
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
6
|
|
8
7
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -84,9 +83,60 @@ 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 ThreadMessageTextPart = {
|
105
|
+
type: "text";
|
106
|
+
text: string;
|
107
|
+
};
|
108
|
+
type ThreadMessageImagePart = {
|
109
|
+
type: "image";
|
110
|
+
image: string;
|
111
|
+
};
|
112
|
+
type ThreadMessageUIPart = {
|
113
|
+
type: "ui";
|
114
|
+
display: ReactNode;
|
115
|
+
};
|
116
|
+
type ThreadMessageToolCallPart = {
|
117
|
+
type: "tool-call";
|
118
|
+
name: string;
|
119
|
+
args: object;
|
120
|
+
result?: object;
|
121
|
+
};
|
122
|
+
type ThreadUserMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart;
|
123
|
+
type ThreadAssistantMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart | ThreadMessageToolCallPart;
|
124
|
+
type ThreadUserMessage = {
|
125
|
+
id: string;
|
126
|
+
role: "user";
|
127
|
+
content: ThreadUserMessageContent[];
|
128
|
+
};
|
129
|
+
type ThreadAssistantMessage = {
|
130
|
+
id: string;
|
131
|
+
role: "assistant";
|
132
|
+
content: ThreadAssistantMessageContent[];
|
133
|
+
};
|
134
|
+
type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
|
135
|
+
type CreateThreadMessage = Omit<ThreadUserMessage, "id">;
|
136
|
+
|
87
137
|
type MessageProviderProps = {
|
88
138
|
children?: React.ReactNode;
|
89
|
-
message:
|
139
|
+
message: ThreadMessage;
|
90
140
|
};
|
91
141
|
declare const MessageProvider: FC<MessageProviderProps>;
|
92
142
|
|
@@ -108,7 +158,28 @@ type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
|
|
108
158
|
};
|
109
159
|
declare const MessageIf: FC<MessageIfProps>;
|
110
160
|
|
111
|
-
|
161
|
+
type MessageContentProps = {
|
162
|
+
components?: {
|
163
|
+
Text?: ComponentType<{
|
164
|
+
part: ThreadMessageTextPart;
|
165
|
+
}>;
|
166
|
+
Image?: ComponentType<{
|
167
|
+
part: ThreadMessageImagePart;
|
168
|
+
}>;
|
169
|
+
UI?: ComponentType<{
|
170
|
+
part: ThreadMessageUIPart;
|
171
|
+
}>;
|
172
|
+
tools?: {
|
173
|
+
by_name?: Record<string, ComponentType<{
|
174
|
+
part: ThreadMessageToolCallPart;
|
175
|
+
}>>;
|
176
|
+
Fallback?: ComponentType<{
|
177
|
+
part: ThreadMessageToolCallPart;
|
178
|
+
}>;
|
179
|
+
};
|
180
|
+
};
|
181
|
+
};
|
182
|
+
declare const MessageContent: FC<MessageContentProps>;
|
112
183
|
|
113
184
|
declare namespace index$2 {
|
114
185
|
export { MessageContent as Content, MessageIf as If, MessageProvider as Provider, MessageRoot as Root };
|
@@ -177,32 +248,26 @@ declare namespace index {
|
|
177
248
|
export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
|
178
249
|
}
|
179
250
|
|
180
|
-
type VercelAIAssistantProviderProps = {
|
251
|
+
type VercelAIAssistantProviderProps$1 = PropsWithChildren<{
|
181
252
|
chat: UseChatHelpers;
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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;
|
253
|
+
} | {
|
254
|
+
assistant: UseAssistantHelpers;
|
255
|
+
}>;
|
256
|
+
declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps$1>;
|
257
|
+
|
258
|
+
type RSCMessage = {
|
259
|
+
id: string;
|
260
|
+
role: "user" | "assistant";
|
261
|
+
display: ReactNode;
|
202
262
|
};
|
263
|
+
type VercelAIAssistantProviderProps = PropsWithChildren<{
|
264
|
+
messages: RSCMessage[];
|
265
|
+
append: (message: CreateThreadMessage) => Promise<void>;
|
266
|
+
}>;
|
267
|
+
declare const VercelRSCAssistantProvider: FC<VercelAIAssistantProviderProps>;
|
203
268
|
|
204
269
|
type MessageState = {
|
205
|
-
message:
|
270
|
+
message: ThreadMessage;
|
206
271
|
branchState: BranchState;
|
207
272
|
isLast: boolean;
|
208
273
|
isCopied: boolean;
|
@@ -227,4 +292,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
227
292
|
|
228
293
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
229
294
|
|
230
|
-
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider as
|
295
|
+
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider, VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.d.ts
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
import * as react from 'react';
|
2
|
-
import { FC, PropsWithChildren } from 'react';
|
2
|
+
import { FC, PropsWithChildren, ReactNode, ComponentType } from 'react';
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
|
-
import {
|
5
|
-
import { UseChatHelpers } from 'ai/react';
|
4
|
+
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
6
5
|
import { UseBoundStore, StoreApi } from 'zustand';
|
7
6
|
|
8
7
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -84,9 +83,60 @@ 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 ThreadMessageTextPart = {
|
105
|
+
type: "text";
|
106
|
+
text: string;
|
107
|
+
};
|
108
|
+
type ThreadMessageImagePart = {
|
109
|
+
type: "image";
|
110
|
+
image: string;
|
111
|
+
};
|
112
|
+
type ThreadMessageUIPart = {
|
113
|
+
type: "ui";
|
114
|
+
display: ReactNode;
|
115
|
+
};
|
116
|
+
type ThreadMessageToolCallPart = {
|
117
|
+
type: "tool-call";
|
118
|
+
name: string;
|
119
|
+
args: object;
|
120
|
+
result?: object;
|
121
|
+
};
|
122
|
+
type ThreadUserMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart;
|
123
|
+
type ThreadAssistantMessageContent = ThreadMessageTextPart | ThreadMessageImagePart | ThreadMessageUIPart | ThreadMessageToolCallPart;
|
124
|
+
type ThreadUserMessage = {
|
125
|
+
id: string;
|
126
|
+
role: "user";
|
127
|
+
content: ThreadUserMessageContent[];
|
128
|
+
};
|
129
|
+
type ThreadAssistantMessage = {
|
130
|
+
id: string;
|
131
|
+
role: "assistant";
|
132
|
+
content: ThreadAssistantMessageContent[];
|
133
|
+
};
|
134
|
+
type ThreadMessage = ThreadUserMessage | ThreadAssistantMessage;
|
135
|
+
type CreateThreadMessage = Omit<ThreadUserMessage, "id">;
|
136
|
+
|
87
137
|
type MessageProviderProps = {
|
88
138
|
children?: React.ReactNode;
|
89
|
-
message:
|
139
|
+
message: ThreadMessage;
|
90
140
|
};
|
91
141
|
declare const MessageProvider: FC<MessageProviderProps>;
|
92
142
|
|
@@ -108,7 +158,28 @@ type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
|
|
108
158
|
};
|
109
159
|
declare const MessageIf: FC<MessageIfProps>;
|
110
160
|
|
111
|
-
|
161
|
+
type MessageContentProps = {
|
162
|
+
components?: {
|
163
|
+
Text?: ComponentType<{
|
164
|
+
part: ThreadMessageTextPart;
|
165
|
+
}>;
|
166
|
+
Image?: ComponentType<{
|
167
|
+
part: ThreadMessageImagePart;
|
168
|
+
}>;
|
169
|
+
UI?: ComponentType<{
|
170
|
+
part: ThreadMessageUIPart;
|
171
|
+
}>;
|
172
|
+
tools?: {
|
173
|
+
by_name?: Record<string, ComponentType<{
|
174
|
+
part: ThreadMessageToolCallPart;
|
175
|
+
}>>;
|
176
|
+
Fallback?: ComponentType<{
|
177
|
+
part: ThreadMessageToolCallPart;
|
178
|
+
}>;
|
179
|
+
};
|
180
|
+
};
|
181
|
+
};
|
182
|
+
declare const MessageContent: FC<MessageContentProps>;
|
112
183
|
|
113
184
|
declare namespace index$2 {
|
114
185
|
export { MessageContent as Content, MessageIf as If, MessageProvider as Provider, MessageRoot as Root };
|
@@ -177,32 +248,26 @@ declare namespace index {
|
|
177
248
|
export { ActionBarCopy as Copy, ActionBarEdit as Edit, ActionBarReload as Reload, ActionBarRoot as Root };
|
178
249
|
}
|
179
250
|
|
180
|
-
type VercelAIAssistantProviderProps = {
|
251
|
+
type VercelAIAssistantProviderProps$1 = PropsWithChildren<{
|
181
252
|
chat: UseChatHelpers;
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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;
|
253
|
+
} | {
|
254
|
+
assistant: UseAssistantHelpers;
|
255
|
+
}>;
|
256
|
+
declare const VercelAIAssistantProvider: FC<VercelAIAssistantProviderProps$1>;
|
257
|
+
|
258
|
+
type RSCMessage = {
|
259
|
+
id: string;
|
260
|
+
role: "user" | "assistant";
|
261
|
+
display: ReactNode;
|
202
262
|
};
|
263
|
+
type VercelAIAssistantProviderProps = PropsWithChildren<{
|
264
|
+
messages: RSCMessage[];
|
265
|
+
append: (message: CreateThreadMessage) => Promise<void>;
|
266
|
+
}>;
|
267
|
+
declare const VercelRSCAssistantProvider: FC<VercelAIAssistantProviderProps>;
|
203
268
|
|
204
269
|
type MessageState = {
|
205
|
-
message:
|
270
|
+
message: ThreadMessage;
|
206
271
|
branchState: BranchState;
|
207
272
|
isLast: boolean;
|
208
273
|
isCopied: boolean;
|
@@ -227,4 +292,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
227
292
|
|
228
293
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
229
294
|
|
230
|
-
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider as
|
295
|
+
export { index as ActionBarPrimitive, index$1 as BranchPickerPrimitive, index$3 as ComposerPrimitive, index$2 as MessagePrimitive, index$4 as ThreadPrimitive, VercelAIAssistantProvider, VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.js
CHANGED
@@ -35,7 +35,8 @@ __export(src_exports, {
|
|
35
35
|
ComposerPrimitive: () => composer_exports,
|
36
36
|
MessagePrimitive: () => message_exports,
|
37
37
|
ThreadPrimitive: () => thread_exports,
|
38
|
-
|
38
|
+
VercelAIAssistantProvider: () => VercelAIAssistantProvider,
|
39
|
+
unstable_VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
|
39
40
|
unstable_useMessageContext: () => useMessageContext,
|
40
41
|
useBeginMessageEdit: () => useBeginMessageEdit,
|
41
42
|
useCopyMessage: () => useCopyMessage,
|
@@ -102,10 +103,10 @@ var ThreadEmpty = ({ children }) => {
|
|
102
103
|
};
|
103
104
|
|
104
105
|
// src/primitives/thread/ThreadViewport.tsx
|
105
|
-
var import_react4 = require("react");
|
106
|
-
var import_react_primitive2 = require("@radix-ui/react-primitive");
|
107
|
-
var import_react_compose_refs = require("@radix-ui/react-compose-refs");
|
108
106
|
var import_primitive = require("@radix-ui/primitive");
|
107
|
+
var import_react_compose_refs = require("@radix-ui/react-compose-refs");
|
108
|
+
var import_react_primitive2 = require("@radix-ui/react-primitive");
|
109
|
+
var import_react4 = require("react");
|
109
110
|
|
110
111
|
// src/utils/hooks/useOnResizeContent.tsx
|
111
112
|
var import_react3 = require("react");
|
@@ -138,10 +139,8 @@ var useOnResizeContent = (ref, callback) => {
|
|
138
139
|
mutationObserver.observe(el, { childList: true });
|
139
140
|
for (const child of el.children) {
|
140
141
|
resizeObserver.observe(child);
|
141
|
-
console.log("observing child", child);
|
142
142
|
}
|
143
143
|
return () => {
|
144
|
-
console.log("disconnecting");
|
145
144
|
resizeObserver.disconnect();
|
146
145
|
mutationObserver.disconnect();
|
147
146
|
};
|
@@ -165,7 +164,6 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
|
|
165
164
|
return;
|
166
165
|
setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight + 50);
|
167
166
|
};
|
168
|
-
console.log(isAtBottom);
|
169
167
|
return /* @__PURE__ */ React.createElement(
|
170
168
|
import_react_primitive2.Primitive.div,
|
171
169
|
{
|
@@ -177,7 +175,7 @@ var ThreadViewport = (0, import_react4.forwardRef)(({ onScroll, children, ...res
|
|
177
175
|
);
|
178
176
|
});
|
179
177
|
|
180
|
-
// src/
|
178
|
+
// src/vercel/useVercelAIBranches.tsx
|
181
179
|
var import_react5 = require("react");
|
182
180
|
var ROOT_ID = "__ROOT_ID__";
|
183
181
|
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
@@ -245,7 +243,7 @@ var sliceMessagesUntil = (messages, message) => {
|
|
245
243
|
throw new Error("Unexpected: Message not found");
|
246
244
|
return messages.slice(0, messageIdx);
|
247
245
|
};
|
248
|
-
var
|
246
|
+
var useVercelAIBranches = (chat) => {
|
249
247
|
const data = (0, import_react5.useRef)({
|
250
248
|
parentMap: /* @__PURE__ */ new Map(),
|
251
249
|
branchMap: /* @__PURE__ */ new Map(),
|
@@ -270,19 +268,27 @@ var useChatWithBranches = (chat) => {
|
|
270
268
|
},
|
271
269
|
[data, chat.messages, chat.setMessages]
|
272
270
|
);
|
271
|
+
const reloadMaybe = "reload" in chat ? chat.reload : void 0;
|
273
272
|
const reloadAt = (0, import_react5.useCallback)(
|
274
273
|
async (message) => {
|
274
|
+
if (!reloadMaybe)
|
275
|
+
throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
|
275
276
|
const newMessages = sliceMessagesUntil(chat.messages, message);
|
276
277
|
chat.setMessages(newMessages);
|
277
|
-
await
|
278
|
+
await reloadMaybe();
|
278
279
|
},
|
279
|
-
[chat.messages, chat.setMessages,
|
280
|
+
[chat.messages, chat.setMessages, reloadMaybe]
|
280
281
|
);
|
281
282
|
const editAt = (0, import_react5.useCallback)(
|
282
283
|
async (message, newMessage) => {
|
283
284
|
const newMessages = sliceMessagesUntil(chat.messages, message);
|
284
285
|
chat.setMessages(newMessages);
|
285
|
-
|
286
|
+
if (newMessage.content[0]?.type !== "text")
|
287
|
+
throw new Error("Only text content is currently supported");
|
288
|
+
await chat.append({
|
289
|
+
role: "user",
|
290
|
+
content: newMessage.content[0].text
|
291
|
+
});
|
286
292
|
},
|
287
293
|
[chat.messages, chat.setMessages, chat.append]
|
288
294
|
);
|
@@ -373,18 +379,25 @@ var useMessageContext2 = () => {
|
|
373
379
|
const useComposer = (0, import_zustand.create)((set, get) => ({
|
374
380
|
isEditing: false,
|
375
381
|
canCancel: true,
|
376
|
-
edit: () =>
|
377
|
-
|
378
|
-
|
379
|
-
|
382
|
+
edit: () => {
|
383
|
+
const message = useMessage.getState().message;
|
384
|
+
if (message.role !== "user")
|
385
|
+
throw new Error("Editing is only supported for user messages");
|
386
|
+
if (message.content[0]?.type !== "text")
|
387
|
+
throw new Error("Editing is only supported for text-only messages");
|
388
|
+
return set({
|
389
|
+
isEditing: true,
|
390
|
+
value: message.content[0].text
|
391
|
+
});
|
392
|
+
},
|
380
393
|
cancel: () => set({ isEditing: false }),
|
381
394
|
send: () => {
|
382
395
|
const message = useMessage.getState().message;
|
396
|
+
if (message.role !== "user")
|
397
|
+
throw new Error("Editing is only supported for user messages");
|
383
398
|
useBranchObserver.getState().editAt(message, {
|
384
|
-
|
385
|
-
|
386
|
-
// remove id to create a new message
|
387
|
-
content: get().value
|
399
|
+
role: "user",
|
400
|
+
content: [{ type: "text", text: get().value }]
|
388
401
|
});
|
389
402
|
set({ isEditing: false });
|
390
403
|
},
|
@@ -483,10 +496,41 @@ var MessageIf = ({ children, ...query }) => {
|
|
483
496
|
};
|
484
497
|
|
485
498
|
// src/primitives/message/MessageContent.tsx
|
486
|
-
var
|
499
|
+
var defaultComponents = {
|
500
|
+
Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
|
501
|
+
Image: () => null,
|
502
|
+
UI: ({ part }) => part.display,
|
503
|
+
tools: {
|
504
|
+
Fallback: () => null
|
505
|
+
}
|
506
|
+
};
|
507
|
+
var MessageContent = ({
|
508
|
+
components: {
|
509
|
+
Text = defaultComponents.Text,
|
510
|
+
Image = defaultComponents.Image,
|
511
|
+
UI = defaultComponents.UI,
|
512
|
+
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
513
|
+
} = {}
|
514
|
+
}) => {
|
487
515
|
const { useMessage } = useMessageContext();
|
488
516
|
const content = useMessage((s) => s.message.content);
|
489
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, content)
|
517
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
|
518
|
+
const key = i;
|
519
|
+
switch (part.type) {
|
520
|
+
case "text":
|
521
|
+
return /* @__PURE__ */ React.createElement(Text, { key, part });
|
522
|
+
case "image":
|
523
|
+
return /* @__PURE__ */ React.createElement(Image, { key, part });
|
524
|
+
case "ui":
|
525
|
+
return /* @__PURE__ */ React.createElement(UI, { key, part });
|
526
|
+
case "tool-call": {
|
527
|
+
const Tool = by_name[part.name] || Fallback;
|
528
|
+
return /* @__PURE__ */ React.createElement(Tool, { key, part });
|
529
|
+
}
|
530
|
+
default:
|
531
|
+
return null;
|
532
|
+
}
|
533
|
+
}));
|
490
534
|
};
|
491
535
|
|
492
536
|
// src/primitives/thread/ThreadMessages.tsx
|
@@ -515,7 +559,7 @@ var ThreadMessages = ({ components }) => {
|
|
515
559
|
message: {
|
516
560
|
id: UPCOMING_MESSAGE_ID,
|
517
561
|
role: "assistant",
|
518
|
-
content: "..."
|
562
|
+
content: [{ type: "text", text: "..." }]
|
519
563
|
}
|
520
564
|
},
|
521
565
|
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
@@ -810,11 +854,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
|
810
854
|
if (isEditing)
|
811
855
|
return null;
|
812
856
|
return () => {
|
813
|
-
const {
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
navigator.clipboard.writeText(content);
|
857
|
+
const { message, setIsCopied } = useMessage.getState();
|
858
|
+
if (message.content[0]?.type !== "text")
|
859
|
+
throw new Error("Copying is only supported for text-only messages");
|
860
|
+
navigator.clipboard.writeText(message.content[0].text);
|
818
861
|
setIsCopied(true);
|
819
862
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
820
863
|
};
|
@@ -832,7 +875,10 @@ var useReloadMessage = () => {
|
|
832
875
|
if (isLoading || !isAssistant)
|
833
876
|
return null;
|
834
877
|
return () => {
|
835
|
-
|
878
|
+
const message = useMessage.getState().message;
|
879
|
+
if (message.role !== "assistant")
|
880
|
+
throw new Error("Reloading is only supported on assistant messages");
|
881
|
+
useBranchObserver.getState().reloadAt(message);
|
836
882
|
};
|
837
883
|
};
|
838
884
|
|
@@ -856,36 +902,40 @@ var useBeginMessageEdit = () => {
|
|
856
902
|
var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
857
903
|
|
858
904
|
// src/vercel/VercelAIAssistantProvider.tsx
|
905
|
+
var import_react18 = require("react");
|
906
|
+
|
907
|
+
// src/vercel/useDummyAIAssistantContext.tsx
|
859
908
|
var import_react17 = require("react");
|
860
909
|
var import_zustand2 = require("zustand");
|
861
|
-
var
|
910
|
+
var useDummyAIAssistantContext = () => {
|
862
911
|
const [context] = (0, import_react17.useState)(() => {
|
863
912
|
const useThread = (0, import_zustand2.create)()(() => ({
|
864
913
|
messages: [],
|
865
|
-
setMessages: () => {
|
866
|
-
},
|
867
914
|
isLoading: false,
|
868
915
|
reload: async () => {
|
916
|
+
throw new Error("Not implemented");
|
869
917
|
},
|
870
918
|
append: async () => {
|
919
|
+
throw new Error("Not implemented");
|
871
920
|
},
|
872
921
|
stop: () => {
|
922
|
+
throw new Error("Not implemented");
|
873
923
|
}
|
874
924
|
}));
|
875
925
|
const useComposer = (0, import_zustand2.create)()(() => ({
|
876
926
|
isEditing: true,
|
877
927
|
canCancel: false,
|
878
928
|
value: "",
|
879
|
-
setValue: () => {
|
929
|
+
setValue: (value) => {
|
930
|
+
useComposer.setState({ value });
|
880
931
|
},
|
881
932
|
edit: () => {
|
882
933
|
throw new Error("Not implemented");
|
883
934
|
},
|
884
935
|
send: () => {
|
885
936
|
useThread.getState().append({
|
886
|
-
content: useComposer.getState().value,
|
887
937
|
role: "user",
|
888
|
-
|
938
|
+
content: [{ type: "text", text: useComposer.getState().value }]
|
889
939
|
});
|
890
940
|
useComposer.getState().setValue("");
|
891
941
|
},
|
@@ -896,70 +946,156 @@ var useAIAssistantContext = () => {
|
|
896
946
|
const useBranchObserver = (0, import_zustand2.create)()(() => ({
|
897
947
|
getBranchState: () => ({
|
898
948
|
branchId: 0,
|
899
|
-
branchCount:
|
949
|
+
branchCount: 1
|
900
950
|
}),
|
901
951
|
switchToBranch: () => {
|
952
|
+
throw new Error("Not implemented");
|
902
953
|
},
|
903
954
|
editAt: async () => {
|
955
|
+
throw new Error("Not implemented");
|
904
956
|
},
|
905
957
|
reloadAt: async () => {
|
958
|
+
throw new Error("Not implemented");
|
906
959
|
}
|
907
960
|
}));
|
908
961
|
return { useThread, useComposer, useBranchObserver };
|
909
962
|
});
|
910
963
|
return context;
|
911
964
|
};
|
965
|
+
|
966
|
+
// src/vercel/VercelAIAssistantProvider.tsx
|
967
|
+
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
968
|
+
var vercelToThreadMessage = (message) => {
|
969
|
+
if (message.role !== "user" && message.role !== "assistant")
|
970
|
+
throw new Error("Unsupported role");
|
971
|
+
return {
|
972
|
+
id: message.id,
|
973
|
+
role: message.role,
|
974
|
+
content: [{ type: "text", text: message.content }]
|
975
|
+
};
|
976
|
+
};
|
977
|
+
var vercelToCachedThreadMessages = (messages) => {
|
978
|
+
return messages.map((m) => {
|
979
|
+
const cached = ThreadMessageCache.get(m);
|
980
|
+
if (cached)
|
981
|
+
return cached;
|
982
|
+
const newMessage = vercelToThreadMessage(m);
|
983
|
+
ThreadMessageCache.set(m, newMessage);
|
984
|
+
return newMessage;
|
985
|
+
});
|
986
|
+
};
|
912
987
|
var VercelAIAssistantProvider = ({
|
913
|
-
|
914
|
-
|
988
|
+
children,
|
989
|
+
...rest
|
915
990
|
}) => {
|
916
|
-
const context =
|
917
|
-
|
991
|
+
const context = useDummyAIAssistantContext();
|
992
|
+
const vercel = "chat" in rest ? rest.chat : rest.assistant;
|
993
|
+
const messages = (0, import_react18.useMemo)(() => {
|
994
|
+
return vercelToCachedThreadMessages(vercel.messages);
|
995
|
+
}, [vercel.messages]);
|
996
|
+
const maybeReload = "reload" in vercel ? vercel.reload : null;
|
997
|
+
const reload = (0, import_react18.useCallback)(async () => {
|
998
|
+
if (!maybeReload)
|
999
|
+
throw new Error("Reload not supported");
|
1000
|
+
await maybeReload();
|
1001
|
+
}, [maybeReload]);
|
1002
|
+
const append = (0, import_react18.useCallback)(
|
1003
|
+
async (message) => {
|
1004
|
+
if (message.content[0]?.type !== "text") {
|
1005
|
+
throw new Error("Only text content is currently supported");
|
1006
|
+
}
|
1007
|
+
await vercel.append({
|
1008
|
+
role: message.role,
|
1009
|
+
content: message.content[0].text
|
1010
|
+
});
|
1011
|
+
},
|
1012
|
+
[vercel.append]
|
1013
|
+
);
|
1014
|
+
const stop = (0, import_react18.useCallback)(() => {
|
1015
|
+
const lastMessage = vercel.messages.at(-1);
|
1016
|
+
vercel.stop();
|
1017
|
+
if (lastMessage?.role === "user") {
|
1018
|
+
vercel.setInput(lastMessage.content);
|
1019
|
+
}
|
1020
|
+
}, [vercel.messages, vercel.stop, vercel.setInput]);
|
1021
|
+
const isLoading = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
|
1022
|
+
(0, import_react18.useMemo)(() => {
|
918
1023
|
context.useThread.setState(
|
919
1024
|
{
|
920
|
-
messages
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
reload: async () => {
|
926
|
-
await chat.reload();
|
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
|
-
}
|
1025
|
+
messages,
|
1026
|
+
isLoading,
|
1027
|
+
reload,
|
1028
|
+
append,
|
1029
|
+
stop
|
938
1030
|
},
|
939
1031
|
true
|
940
1032
|
);
|
941
|
-
}, [context,
|
942
|
-
(0,
|
1033
|
+
}, [context, messages, reload, append, stop, isLoading]);
|
1034
|
+
(0, import_react18.useMemo)(() => {
|
943
1035
|
context.useComposer.setState({
|
944
|
-
canCancel:
|
945
|
-
value:
|
946
|
-
setValue:
|
1036
|
+
canCancel: isLoading,
|
1037
|
+
value: vercel.input,
|
1038
|
+
setValue: vercel.setInput
|
947
1039
|
});
|
948
|
-
}, [context,
|
949
|
-
const branches =
|
950
|
-
(0,
|
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
|
-
);
|
1040
|
+
}, [context, isLoading, vercel.input, vercel.setInput]);
|
1041
|
+
const branches = useVercelAIBranches(vercel);
|
1042
|
+
(0, import_react18.useMemo)(() => {
|
1043
|
+
context.useBranchObserver.setState(branches, true);
|
960
1044
|
}, [context, branches]);
|
961
1045
|
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
962
1046
|
};
|
1047
|
+
|
1048
|
+
// src/vercel/VercelRSCAssistantProvider.tsx
|
1049
|
+
var import_react19 = require("react");
|
1050
|
+
var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
|
1051
|
+
var vercelToThreadMessage2 = (message) => {
|
1052
|
+
if (message.role !== "user" && message.role !== "assistant")
|
1053
|
+
throw new Error("Unsupported role");
|
1054
|
+
return {
|
1055
|
+
id: message.id,
|
1056
|
+
role: message.role,
|
1057
|
+
content: [{ type: "ui", display: message.display }]
|
1058
|
+
};
|
1059
|
+
};
|
1060
|
+
var vercelToCachedThreadMessages2 = (messages) => {
|
1061
|
+
return messages.map((m) => {
|
1062
|
+
const cached = ThreadMessageCache2.get(m);
|
1063
|
+
if (cached)
|
1064
|
+
return cached;
|
1065
|
+
const newMessage = vercelToThreadMessage2(m);
|
1066
|
+
ThreadMessageCache2.set(m, newMessage);
|
1067
|
+
return newMessage;
|
1068
|
+
});
|
1069
|
+
};
|
1070
|
+
var VercelRSCAssistantProvider = ({
|
1071
|
+
children,
|
1072
|
+
messages: vercelMessages,
|
1073
|
+
append: vercelAppend
|
1074
|
+
}) => {
|
1075
|
+
const context = useDummyAIAssistantContext();
|
1076
|
+
const messages = (0, import_react19.useMemo)(() => {
|
1077
|
+
return vercelToCachedThreadMessages2(vercelMessages);
|
1078
|
+
}, [vercelMessages]);
|
1079
|
+
const append = (0, import_react19.useCallback)(
|
1080
|
+
async (message) => {
|
1081
|
+
if (message.content[0]?.type !== "text") {
|
1082
|
+
throw new Error("Only text content is currently supported");
|
1083
|
+
}
|
1084
|
+
await vercelAppend({
|
1085
|
+
role: message.role,
|
1086
|
+
content: [{ type: "text", text: message.content[0].text }]
|
1087
|
+
});
|
1088
|
+
},
|
1089
|
+
[vercelAppend]
|
1090
|
+
);
|
1091
|
+
(0, import_react19.useMemo)(() => {
|
1092
|
+
context.useThread.setState({
|
1093
|
+
messages,
|
1094
|
+
append
|
1095
|
+
});
|
1096
|
+
}, [context, messages, append]);
|
1097
|
+
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
1098
|
+
};
|
963
1099
|
// Annotate the CommonJS export names for ESM import in node:
|
964
1100
|
0 && (module.exports = {
|
965
1101
|
ActionBarPrimitive,
|
@@ -967,7 +1103,8 @@ var VercelAIAssistantProvider = ({
|
|
967
1103
|
ComposerPrimitive,
|
968
1104
|
MessagePrimitive,
|
969
1105
|
ThreadPrimitive,
|
970
|
-
|
1106
|
+
VercelAIAssistantProvider,
|
1107
|
+
unstable_VercelRSCAssistantProvider,
|
971
1108
|
unstable_useMessageContext,
|
972
1109
|
useBeginMessageEdit,
|
973
1110
|
useCopyMessage,
|
package/dist/index.mjs
CHANGED
@@ -63,12 +63,12 @@ var ThreadEmpty = ({ children }) => {
|
|
63
63
|
};
|
64
64
|
|
65
65
|
// src/primitives/thread/ThreadViewport.tsx
|
66
|
-
import {
|
66
|
+
import { composeEventHandlers } from "@radix-ui/primitive";
|
67
|
+
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
67
68
|
import {
|
68
69
|
Primitive as Primitive2
|
69
70
|
} from "@radix-ui/react-primitive";
|
70
|
-
import {
|
71
|
-
import { composeEventHandlers } from "@radix-ui/primitive";
|
71
|
+
import { forwardRef as forwardRef2, useRef as useRef2, useState } from "react";
|
72
72
|
|
73
73
|
// src/utils/hooks/useOnResizeContent.tsx
|
74
74
|
import { useLayoutEffect, useRef } from "react";
|
@@ -101,10 +101,8 @@ var useOnResizeContent = (ref, callback) => {
|
|
101
101
|
mutationObserver.observe(el, { childList: true });
|
102
102
|
for (const child of el.children) {
|
103
103
|
resizeObserver.observe(child);
|
104
|
-
console.log("observing child", child);
|
105
104
|
}
|
106
105
|
return () => {
|
107
|
-
console.log("disconnecting");
|
108
106
|
resizeObserver.disconnect();
|
109
107
|
mutationObserver.disconnect();
|
110
108
|
};
|
@@ -128,7 +126,6 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
|
|
128
126
|
return;
|
129
127
|
setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight + 50);
|
130
128
|
};
|
131
|
-
console.log(isAtBottom);
|
132
129
|
return /* @__PURE__ */ React.createElement(
|
133
130
|
Primitive2.div,
|
134
131
|
{
|
@@ -140,7 +137,7 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
|
|
140
137
|
);
|
141
138
|
});
|
142
139
|
|
143
|
-
// src/
|
140
|
+
// src/vercel/useVercelAIBranches.tsx
|
144
141
|
import { useCallback, useMemo, useRef as useRef3 } from "react";
|
145
142
|
var ROOT_ID = "__ROOT_ID__";
|
146
143
|
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
@@ -208,7 +205,7 @@ var sliceMessagesUntil = (messages, message) => {
|
|
208
205
|
throw new Error("Unexpected: Message not found");
|
209
206
|
return messages.slice(0, messageIdx);
|
210
207
|
};
|
211
|
-
var
|
208
|
+
var useVercelAIBranches = (chat) => {
|
212
209
|
const data = useRef3({
|
213
210
|
parentMap: /* @__PURE__ */ new Map(),
|
214
211
|
branchMap: /* @__PURE__ */ new Map(),
|
@@ -233,19 +230,27 @@ var useChatWithBranches = (chat) => {
|
|
233
230
|
},
|
234
231
|
[data, chat.messages, chat.setMessages]
|
235
232
|
);
|
233
|
+
const reloadMaybe = "reload" in chat ? chat.reload : void 0;
|
236
234
|
const reloadAt = useCallback(
|
237
235
|
async (message) => {
|
236
|
+
if (!reloadMaybe)
|
237
|
+
throw new Error("Reload not supported by Vercel AI SDK's useAssistant");
|
238
238
|
const newMessages = sliceMessagesUntil(chat.messages, message);
|
239
239
|
chat.setMessages(newMessages);
|
240
|
-
await
|
240
|
+
await reloadMaybe();
|
241
241
|
},
|
242
|
-
[chat.messages, chat.setMessages,
|
242
|
+
[chat.messages, chat.setMessages, reloadMaybe]
|
243
243
|
);
|
244
244
|
const editAt = useCallback(
|
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
|
},
|
@@ -448,10 +460,41 @@ var MessageIf = ({ children, ...query }) => {
|
|
448
460
|
};
|
449
461
|
|
450
462
|
// src/primitives/message/MessageContent.tsx
|
451
|
-
var
|
463
|
+
var defaultComponents = {
|
464
|
+
Text: ({ part }) => /* @__PURE__ */ React.createElement(React.Fragment, null, part.text),
|
465
|
+
Image: () => null,
|
466
|
+
UI: ({ part }) => part.display,
|
467
|
+
tools: {
|
468
|
+
Fallback: () => null
|
469
|
+
}
|
470
|
+
};
|
471
|
+
var MessageContent = ({
|
472
|
+
components: {
|
473
|
+
Text = defaultComponents.Text,
|
474
|
+
Image = defaultComponents.Image,
|
475
|
+
UI = defaultComponents.UI,
|
476
|
+
tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
|
477
|
+
} = {}
|
478
|
+
}) => {
|
452
479
|
const { useMessage } = useMessageContext();
|
453
480
|
const content = useMessage((s) => s.message.content);
|
454
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, content)
|
481
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, content.map((part, i) => {
|
482
|
+
const key = i;
|
483
|
+
switch (part.type) {
|
484
|
+
case "text":
|
485
|
+
return /* @__PURE__ */ React.createElement(Text, { key, part });
|
486
|
+
case "image":
|
487
|
+
return /* @__PURE__ */ React.createElement(Image, { key, part });
|
488
|
+
case "ui":
|
489
|
+
return /* @__PURE__ */ React.createElement(UI, { key, part });
|
490
|
+
case "tool-call": {
|
491
|
+
const Tool = by_name[part.name] || Fallback;
|
492
|
+
return /* @__PURE__ */ React.createElement(Tool, { key, part });
|
493
|
+
}
|
494
|
+
default:
|
495
|
+
return null;
|
496
|
+
}
|
497
|
+
}));
|
455
498
|
};
|
456
499
|
|
457
500
|
// src/primitives/thread/ThreadMessages.tsx
|
@@ -480,7 +523,7 @@ var ThreadMessages = ({ components }) => {
|
|
480
523
|
message: {
|
481
524
|
id: UPCOMING_MESSAGE_ID,
|
482
525
|
role: "assistant",
|
483
|
-
content: "..."
|
526
|
+
content: [{ type: "text", text: "..." }]
|
484
527
|
}
|
485
528
|
},
|
486
529
|
/* @__PURE__ */ React.createElement(AssistantMessage, null)
|
@@ -793,11 +836,10 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
|
|
793
836
|
if (isEditing)
|
794
837
|
return null;
|
795
838
|
return () => {
|
796
|
-
const {
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
navigator.clipboard.writeText(content);
|
839
|
+
const { message, setIsCopied } = useMessage.getState();
|
840
|
+
if (message.content[0]?.type !== "text")
|
841
|
+
throw new Error("Copying is only supported for text-only messages");
|
842
|
+
navigator.clipboard.writeText(message.content[0].text);
|
801
843
|
setIsCopied(true);
|
802
844
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
803
845
|
};
|
@@ -815,7 +857,10 @@ var useReloadMessage = () => {
|
|
815
857
|
if (isLoading || !isAssistant)
|
816
858
|
return null;
|
817
859
|
return () => {
|
818
|
-
|
860
|
+
const message = useMessage.getState().message;
|
861
|
+
if (message.role !== "assistant")
|
862
|
+
throw new Error("Reloading is only supported on assistant messages");
|
863
|
+
useBranchObserver.getState().reloadAt(message);
|
819
864
|
};
|
820
865
|
};
|
821
866
|
|
@@ -839,36 +884,40 @@ var useBeginMessageEdit = () => {
|
|
839
884
|
var ActionBarEdit = createActionButton(useBeginMessageEdit);
|
840
885
|
|
841
886
|
// src/vercel/VercelAIAssistantProvider.tsx
|
842
|
-
import {
|
887
|
+
import { useCallback as useCallback2, useMemo as useMemo4 } from "react";
|
888
|
+
|
889
|
+
// src/vercel/useDummyAIAssistantContext.tsx
|
890
|
+
import { useState as useState3 } from "react";
|
843
891
|
import { create as create2 } from "zustand";
|
844
|
-
var
|
892
|
+
var useDummyAIAssistantContext = () => {
|
845
893
|
const [context] = useState3(() => {
|
846
894
|
const useThread = create2()(() => ({
|
847
895
|
messages: [],
|
848
|
-
setMessages: () => {
|
849
|
-
},
|
850
896
|
isLoading: false,
|
851
897
|
reload: async () => {
|
898
|
+
throw new Error("Not implemented");
|
852
899
|
},
|
853
900
|
append: async () => {
|
901
|
+
throw new Error("Not implemented");
|
854
902
|
},
|
855
903
|
stop: () => {
|
904
|
+
throw new Error("Not implemented");
|
856
905
|
}
|
857
906
|
}));
|
858
907
|
const useComposer = create2()(() => ({
|
859
908
|
isEditing: true,
|
860
909
|
canCancel: false,
|
861
910
|
value: "",
|
862
|
-
setValue: () => {
|
911
|
+
setValue: (value) => {
|
912
|
+
useComposer.setState({ value });
|
863
913
|
},
|
864
914
|
edit: () => {
|
865
915
|
throw new Error("Not implemented");
|
866
916
|
},
|
867
917
|
send: () => {
|
868
918
|
useThread.getState().append({
|
869
|
-
content: useComposer.getState().value,
|
870
919
|
role: "user",
|
871
|
-
|
920
|
+
content: [{ type: "text", text: useComposer.getState().value }]
|
872
921
|
});
|
873
922
|
useComposer.getState().setValue("");
|
874
923
|
},
|
@@ -879,77 +928,167 @@ var useAIAssistantContext = () => {
|
|
879
928
|
const useBranchObserver = create2()(() => ({
|
880
929
|
getBranchState: () => ({
|
881
930
|
branchId: 0,
|
882
|
-
branchCount:
|
931
|
+
branchCount: 1
|
883
932
|
}),
|
884
933
|
switchToBranch: () => {
|
934
|
+
throw new Error("Not implemented");
|
885
935
|
},
|
886
936
|
editAt: async () => {
|
937
|
+
throw new Error("Not implemented");
|
887
938
|
},
|
888
939
|
reloadAt: async () => {
|
940
|
+
throw new Error("Not implemented");
|
889
941
|
}
|
890
942
|
}));
|
891
943
|
return { useThread, useComposer, useBranchObserver };
|
892
944
|
});
|
893
945
|
return context;
|
894
946
|
};
|
947
|
+
|
948
|
+
// src/vercel/VercelAIAssistantProvider.tsx
|
949
|
+
var ThreadMessageCache = /* @__PURE__ */ new WeakMap();
|
950
|
+
var vercelToThreadMessage = (message) => {
|
951
|
+
if (message.role !== "user" && message.role !== "assistant")
|
952
|
+
throw new Error("Unsupported role");
|
953
|
+
return {
|
954
|
+
id: message.id,
|
955
|
+
role: message.role,
|
956
|
+
content: [{ type: "text", text: message.content }]
|
957
|
+
};
|
958
|
+
};
|
959
|
+
var vercelToCachedThreadMessages = (messages) => {
|
960
|
+
return messages.map((m) => {
|
961
|
+
const cached = ThreadMessageCache.get(m);
|
962
|
+
if (cached)
|
963
|
+
return cached;
|
964
|
+
const newMessage = vercelToThreadMessage(m);
|
965
|
+
ThreadMessageCache.set(m, newMessage);
|
966
|
+
return newMessage;
|
967
|
+
});
|
968
|
+
};
|
895
969
|
var VercelAIAssistantProvider = ({
|
896
|
-
|
897
|
-
|
970
|
+
children,
|
971
|
+
...rest
|
898
972
|
}) => {
|
899
|
-
const context =
|
973
|
+
const context = useDummyAIAssistantContext();
|
974
|
+
const vercel = "chat" in rest ? rest.chat : rest.assistant;
|
975
|
+
const messages = useMemo4(() => {
|
976
|
+
return vercelToCachedThreadMessages(vercel.messages);
|
977
|
+
}, [vercel.messages]);
|
978
|
+
const maybeReload = "reload" in vercel ? vercel.reload : null;
|
979
|
+
const reload = useCallback2(async () => {
|
980
|
+
if (!maybeReload)
|
981
|
+
throw new Error("Reload not supported");
|
982
|
+
await maybeReload();
|
983
|
+
}, [maybeReload]);
|
984
|
+
const append = useCallback2(
|
985
|
+
async (message) => {
|
986
|
+
if (message.content[0]?.type !== "text") {
|
987
|
+
throw new Error("Only text content is currently supported");
|
988
|
+
}
|
989
|
+
await vercel.append({
|
990
|
+
role: message.role,
|
991
|
+
content: message.content[0].text
|
992
|
+
});
|
993
|
+
},
|
994
|
+
[vercel.append]
|
995
|
+
);
|
996
|
+
const stop = useCallback2(() => {
|
997
|
+
const lastMessage = vercel.messages.at(-1);
|
998
|
+
vercel.stop();
|
999
|
+
if (lastMessage?.role === "user") {
|
1000
|
+
vercel.setInput(lastMessage.content);
|
1001
|
+
}
|
1002
|
+
}, [vercel.messages, vercel.stop, vercel.setInput]);
|
1003
|
+
const isLoading = "isLoading" in vercel ? vercel.isLoading : vercel.status === "in_progress";
|
900
1004
|
useMemo4(() => {
|
901
1005
|
context.useThread.setState(
|
902
1006
|
{
|
903
|
-
messages
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
reload: async () => {
|
909
|
-
await chat.reload();
|
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
|
-
}
|
1007
|
+
messages,
|
1008
|
+
isLoading,
|
1009
|
+
reload,
|
1010
|
+
append,
|
1011
|
+
stop
|
921
1012
|
},
|
922
1013
|
true
|
923
1014
|
);
|
924
|
-
}, [context,
|
1015
|
+
}, [context, messages, reload, append, stop, isLoading]);
|
925
1016
|
useMemo4(() => {
|
926
1017
|
context.useComposer.setState({
|
927
|
-
canCancel:
|
928
|
-
value:
|
929
|
-
setValue:
|
1018
|
+
canCancel: isLoading,
|
1019
|
+
value: vercel.input,
|
1020
|
+
setValue: vercel.setInput
|
930
1021
|
});
|
931
|
-
}, [context,
|
932
|
-
const branches =
|
1022
|
+
}, [context, isLoading, vercel.input, vercel.setInput]);
|
1023
|
+
const branches = useVercelAIBranches(vercel);
|
933
1024
|
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
|
-
);
|
1025
|
+
context.useBranchObserver.setState(branches, true);
|
943
1026
|
}, [context, branches]);
|
944
1027
|
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
945
1028
|
};
|
1029
|
+
|
1030
|
+
// src/vercel/VercelRSCAssistantProvider.tsx
|
1031
|
+
import {
|
1032
|
+
useCallback as useCallback3,
|
1033
|
+
useMemo as useMemo5
|
1034
|
+
} from "react";
|
1035
|
+
var ThreadMessageCache2 = /* @__PURE__ */ new WeakMap();
|
1036
|
+
var vercelToThreadMessage2 = (message) => {
|
1037
|
+
if (message.role !== "user" && message.role !== "assistant")
|
1038
|
+
throw new Error("Unsupported role");
|
1039
|
+
return {
|
1040
|
+
id: message.id,
|
1041
|
+
role: message.role,
|
1042
|
+
content: [{ type: "ui", display: message.display }]
|
1043
|
+
};
|
1044
|
+
};
|
1045
|
+
var vercelToCachedThreadMessages2 = (messages) => {
|
1046
|
+
return messages.map((m) => {
|
1047
|
+
const cached = ThreadMessageCache2.get(m);
|
1048
|
+
if (cached)
|
1049
|
+
return cached;
|
1050
|
+
const newMessage = vercelToThreadMessage2(m);
|
1051
|
+
ThreadMessageCache2.set(m, newMessage);
|
1052
|
+
return newMessage;
|
1053
|
+
});
|
1054
|
+
};
|
1055
|
+
var VercelRSCAssistantProvider = ({
|
1056
|
+
children,
|
1057
|
+
messages: vercelMessages,
|
1058
|
+
append: vercelAppend
|
1059
|
+
}) => {
|
1060
|
+
const context = useDummyAIAssistantContext();
|
1061
|
+
const messages = useMemo5(() => {
|
1062
|
+
return vercelToCachedThreadMessages2(vercelMessages);
|
1063
|
+
}, [vercelMessages]);
|
1064
|
+
const append = useCallback3(
|
1065
|
+
async (message) => {
|
1066
|
+
if (message.content[0]?.type !== "text") {
|
1067
|
+
throw new Error("Only text content is currently supported");
|
1068
|
+
}
|
1069
|
+
await vercelAppend({
|
1070
|
+
role: message.role,
|
1071
|
+
content: [{ type: "text", text: message.content[0].text }]
|
1072
|
+
});
|
1073
|
+
},
|
1074
|
+
[vercelAppend]
|
1075
|
+
);
|
1076
|
+
useMemo5(() => {
|
1077
|
+
context.useThread.setState({
|
1078
|
+
messages,
|
1079
|
+
append
|
1080
|
+
});
|
1081
|
+
}, [context, messages, append]);
|
1082
|
+
return /* @__PURE__ */ React.createElement(AssistantContext.Provider, { value: context }, children);
|
1083
|
+
};
|
946
1084
|
export {
|
947
1085
|
actionBar_exports as ActionBarPrimitive,
|
948
1086
|
branchPicker_exports as BranchPickerPrimitive,
|
949
1087
|
composer_exports as ComposerPrimitive,
|
950
1088
|
message_exports as MessagePrimitive,
|
951
1089
|
thread_exports as ThreadPrimitive,
|
952
|
-
VercelAIAssistantProvider
|
1090
|
+
VercelAIAssistantProvider,
|
1091
|
+
VercelRSCAssistantProvider as unstable_VercelRSCAssistantProvider,
|
953
1092
|
useMessageContext as unstable_useMessageContext,
|
954
1093
|
useBeginMessageEdit,
|
955
1094
|
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.7",
|
4
4
|
"license": "MIT",
|
5
5
|
"exports": {
|
6
6
|
".": {
|
@@ -28,7 +28,7 @@
|
|
28
28
|
"@radix-ui/react-compose-refs": "^1.0.1",
|
29
29
|
"@radix-ui/react-primitive": "^1.0.3",
|
30
30
|
"@radix-ui/react-slot": "^1.0.2",
|
31
|
-
"ai": "^3.1.
|
31
|
+
"ai": "^3.1.12",
|
32
32
|
"react-textarea-autosize": "^8.5.3",
|
33
33
|
"zustand": "^4.5.2"
|
34
34
|
},
|