@assistant-ui/react 0.0.17 → 0.0.18
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 +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.js +294 -36
- package/dist/index.mjs +291 -36
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
@@ -3,7 +3,7 @@ import { FC, ReactNode, PropsWithChildren, ComponentType } from 'react';
|
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
4
|
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
6
|
-
import { Message } from 'ai';
|
6
|
+
import { LanguageModel, Message } from 'ai';
|
7
7
|
import { UseBoundStore, StoreApi } from 'zustand';
|
8
8
|
|
9
9
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -133,7 +133,7 @@ type ToolCallContentPart = {
|
|
133
133
|
result?: object;
|
134
134
|
};
|
135
135
|
type UserContentPart = TextContentPart | ImageContentPart | UIContentPart;
|
136
|
-
type AssistantContentPart = TextContentPart |
|
136
|
+
type AssistantContentPart = TextContentPart | UIContentPart | ToolCallContentPart;
|
137
137
|
type AppendContentPart = TextContentPart | ImageContentPart;
|
138
138
|
type BaseMessage = {
|
139
139
|
id: string;
|
@@ -312,6 +312,70 @@ type RSCMessageConverter<T> = {
|
|
312
312
|
type VercelRSCAssistantProviderProps<T = VercelRSCMessage> = VercelRSCAssistantProviderBaseProps<T> & (T extends VercelRSCMessage ? object : RSCMessageConverter<T>);
|
313
313
|
declare const VercelRSCAssistantProvider: <T extends WeakKey = VercelRSCMessage>({ children, convertMessage, messages: vercelMessages, append: appendCallback, edit, reload, }: VercelRSCAssistantProviderProps<T>) => react_jsx_runtime.JSX.Element;
|
314
314
|
|
315
|
+
type MessageUpdateCallback = (parentId: string | null, message: ThreadMessage) => void;
|
316
|
+
type StatusUpdateCallback = (isRunning: boolean) => void;
|
317
|
+
type Unsubscribe = () => void;
|
318
|
+
type ThreadRuntime = {
|
319
|
+
append(message: AppendMessage): Promise<{
|
320
|
+
parentId: string;
|
321
|
+
id: string;
|
322
|
+
}>;
|
323
|
+
startRun(parentId: string | null): Promise<{
|
324
|
+
id: string;
|
325
|
+
}>;
|
326
|
+
cancelRun(): void;
|
327
|
+
subscribeToMessageUpdates(callback: MessageUpdateCallback): Unsubscribe;
|
328
|
+
subscribeToStatusUpdates(callback: StatusUpdateCallback): Unsubscribe;
|
329
|
+
};
|
330
|
+
|
331
|
+
type AssistantProviderProps = {
|
332
|
+
runtime: ThreadRuntime;
|
333
|
+
};
|
334
|
+
declare const AssistantProvider: FC<PropsWithChildren<AssistantProviderProps>>;
|
335
|
+
|
336
|
+
type ChatModelRunResult = {
|
337
|
+
content: AssistantContentPart[];
|
338
|
+
};
|
339
|
+
type ChatModelRunOptions = {
|
340
|
+
messages: ThreadMessage[];
|
341
|
+
abortSignal: AbortSignal;
|
342
|
+
onUpdate: (result: ChatModelRunResult) => void;
|
343
|
+
};
|
344
|
+
type ChatModelAdapter = {
|
345
|
+
run: (options: ChatModelRunOptions) => Promise<ChatModelRunResult>;
|
346
|
+
};
|
347
|
+
|
348
|
+
declare class LocalRuntime implements ThreadRuntime {
|
349
|
+
adapter: ChatModelAdapter;
|
350
|
+
private _messageUpdateCallbacks;
|
351
|
+
private _statusUpdateCallbacks;
|
352
|
+
private abortController;
|
353
|
+
private repository;
|
354
|
+
constructor(adapter: ChatModelAdapter);
|
355
|
+
append(message: AppendMessage): Promise<{
|
356
|
+
parentId: string;
|
357
|
+
id: string;
|
358
|
+
}>;
|
359
|
+
startRun(parentId: string | null): Promise<{
|
360
|
+
id: string;
|
361
|
+
}>;
|
362
|
+
private addOrUpdateMessage;
|
363
|
+
private run;
|
364
|
+
cancelRun(): void;
|
365
|
+
subscribeToMessageUpdates(callback: MessageUpdateCallback): Unsubscribe;
|
366
|
+
subscribeToStatusUpdates(callback: StatusUpdateCallback): Unsubscribe;
|
367
|
+
}
|
368
|
+
|
369
|
+
declare const useLocalRuntime: (adapter: ChatModelAdapter) => LocalRuntime;
|
370
|
+
|
371
|
+
declare class VercelModelAdapter implements ChatModelAdapter {
|
372
|
+
private readonly model;
|
373
|
+
constructor(model: LanguageModel);
|
374
|
+
run({ messages, abortSignal, onUpdate }: ChatModelRunOptions): Promise<{
|
375
|
+
content: AssistantContentPart[];
|
376
|
+
}>;
|
377
|
+
}
|
378
|
+
|
315
379
|
declare const getVercelMessage: (message: ThreadMessage) => Message | undefined;
|
316
380
|
declare const getVercelRSCMessage: <T>(message: ThreadMessage) => T | undefined;
|
317
381
|
|
@@ -346,4 +410,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
346
410
|
|
347
411
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
348
412
|
|
349
|
-
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
413
|
+
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, AssistantProvider as unstable_AssistantProvider, type ChatModelAdapter as unstable_ChatModelAdapter, type ChatModelRunOptions as unstable_ChatModelRunOptions, VercelModelAdapter as unstable_VercelModelAdapter, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useLocalRuntime as unstable_useLocalRuntime, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.d.ts
CHANGED
@@ -3,7 +3,7 @@ import { FC, ReactNode, PropsWithChildren, ComponentType } from 'react';
|
|
3
3
|
import { TextareaAutosizeProps } from 'react-textarea-autosize';
|
4
4
|
import { UseChatHelpers, UseAssistantHelpers } from 'ai/react';
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
6
|
-
import { Message } from 'ai';
|
6
|
+
import { LanguageModel, Message } from 'ai';
|
7
7
|
import { UseBoundStore, StoreApi } from 'zustand';
|
8
8
|
|
9
9
|
declare const ThreadRoot: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
@@ -133,7 +133,7 @@ type ToolCallContentPart = {
|
|
133
133
|
result?: object;
|
134
134
|
};
|
135
135
|
type UserContentPart = TextContentPart | ImageContentPart | UIContentPart;
|
136
|
-
type AssistantContentPart = TextContentPart |
|
136
|
+
type AssistantContentPart = TextContentPart | UIContentPart | ToolCallContentPart;
|
137
137
|
type AppendContentPart = TextContentPart | ImageContentPart;
|
138
138
|
type BaseMessage = {
|
139
139
|
id: string;
|
@@ -312,6 +312,70 @@ type RSCMessageConverter<T> = {
|
|
312
312
|
type VercelRSCAssistantProviderProps<T = VercelRSCMessage> = VercelRSCAssistantProviderBaseProps<T> & (T extends VercelRSCMessage ? object : RSCMessageConverter<T>);
|
313
313
|
declare const VercelRSCAssistantProvider: <T extends WeakKey = VercelRSCMessage>({ children, convertMessage, messages: vercelMessages, append: appendCallback, edit, reload, }: VercelRSCAssistantProviderProps<T>) => react_jsx_runtime.JSX.Element;
|
314
314
|
|
315
|
+
type MessageUpdateCallback = (parentId: string | null, message: ThreadMessage) => void;
|
316
|
+
type StatusUpdateCallback = (isRunning: boolean) => void;
|
317
|
+
type Unsubscribe = () => void;
|
318
|
+
type ThreadRuntime = {
|
319
|
+
append(message: AppendMessage): Promise<{
|
320
|
+
parentId: string;
|
321
|
+
id: string;
|
322
|
+
}>;
|
323
|
+
startRun(parentId: string | null): Promise<{
|
324
|
+
id: string;
|
325
|
+
}>;
|
326
|
+
cancelRun(): void;
|
327
|
+
subscribeToMessageUpdates(callback: MessageUpdateCallback): Unsubscribe;
|
328
|
+
subscribeToStatusUpdates(callback: StatusUpdateCallback): Unsubscribe;
|
329
|
+
};
|
330
|
+
|
331
|
+
type AssistantProviderProps = {
|
332
|
+
runtime: ThreadRuntime;
|
333
|
+
};
|
334
|
+
declare const AssistantProvider: FC<PropsWithChildren<AssistantProviderProps>>;
|
335
|
+
|
336
|
+
type ChatModelRunResult = {
|
337
|
+
content: AssistantContentPart[];
|
338
|
+
};
|
339
|
+
type ChatModelRunOptions = {
|
340
|
+
messages: ThreadMessage[];
|
341
|
+
abortSignal: AbortSignal;
|
342
|
+
onUpdate: (result: ChatModelRunResult) => void;
|
343
|
+
};
|
344
|
+
type ChatModelAdapter = {
|
345
|
+
run: (options: ChatModelRunOptions) => Promise<ChatModelRunResult>;
|
346
|
+
};
|
347
|
+
|
348
|
+
declare class LocalRuntime implements ThreadRuntime {
|
349
|
+
adapter: ChatModelAdapter;
|
350
|
+
private _messageUpdateCallbacks;
|
351
|
+
private _statusUpdateCallbacks;
|
352
|
+
private abortController;
|
353
|
+
private repository;
|
354
|
+
constructor(adapter: ChatModelAdapter);
|
355
|
+
append(message: AppendMessage): Promise<{
|
356
|
+
parentId: string;
|
357
|
+
id: string;
|
358
|
+
}>;
|
359
|
+
startRun(parentId: string | null): Promise<{
|
360
|
+
id: string;
|
361
|
+
}>;
|
362
|
+
private addOrUpdateMessage;
|
363
|
+
private run;
|
364
|
+
cancelRun(): void;
|
365
|
+
subscribeToMessageUpdates(callback: MessageUpdateCallback): Unsubscribe;
|
366
|
+
subscribeToStatusUpdates(callback: StatusUpdateCallback): Unsubscribe;
|
367
|
+
}
|
368
|
+
|
369
|
+
declare const useLocalRuntime: (adapter: ChatModelAdapter) => LocalRuntime;
|
370
|
+
|
371
|
+
declare class VercelModelAdapter implements ChatModelAdapter {
|
372
|
+
private readonly model;
|
373
|
+
constructor(model: LanguageModel);
|
374
|
+
run({ messages, abortSignal, onUpdate }: ChatModelRunOptions): Promise<{
|
375
|
+
content: AssistantContentPart[];
|
376
|
+
}>;
|
377
|
+
}
|
378
|
+
|
315
379
|
declare const getVercelMessage: (message: ThreadMessage) => Message | undefined;
|
316
380
|
declare const getVercelRSCMessage: <T>(message: ThreadMessage) => T | undefined;
|
317
381
|
|
@@ -346,4 +410,4 @@ declare const useGoToNextBranch: () => (() => void) | null;
|
|
346
410
|
|
347
411
|
declare const useGoToPreviousBranch: () => (() => void) | null;
|
348
412
|
|
349
|
-
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
413
|
+
export { index$1 as ActionBarPrimitive, type AppendContentPart, type AppendMessage, index$2 as BranchPickerPrimitive, index$4 as ComposerPrimitive, index as ContentPartPrimitive, type ImageContentPart, index$3 as MessagePrimitive, type VercelRSCMessage as RSCMessage, type TextContentPart, index$5 as ThreadPrimitive, VercelAIAssistantProvider, type VercelAIAssistantProviderProps, VercelRSCAssistantProvider, type VercelRSCAssistantProviderProps, AssistantProvider as unstable_AssistantProvider, type ChatModelAdapter as unstable_ChatModelAdapter, type ChatModelRunOptions as unstable_ChatModelRunOptions, VercelModelAdapter as unstable_VercelModelAdapter, getVercelMessage as unstable_getVercelMessage, getVercelRSCMessage as unstable_getVercelRSCMessage, useLocalRuntime as unstable_useLocalRuntime, useMessageContext as unstable_useMessageContext, useBeginMessageEdit, useCopyMessage, useGoToNextBranch, useGoToPreviousBranch, useReloadMessage };
|
package/dist/index.js
CHANGED
@@ -38,8 +38,11 @@ __export(src_exports, {
|
|
38
38
|
ThreadPrimitive: () => thread_exports,
|
39
39
|
VercelAIAssistantProvider: () => VercelAIAssistantProvider,
|
40
40
|
VercelRSCAssistantProvider: () => VercelRSCAssistantProvider,
|
41
|
+
unstable_AssistantProvider: () => AssistantProvider,
|
42
|
+
unstable_VercelModelAdapter: () => VercelModelAdapter,
|
41
43
|
unstable_getVercelMessage: () => getVercelMessage,
|
42
44
|
unstable_getVercelRSCMessage: () => getVercelRSCMessage,
|
45
|
+
unstable_useLocalRuntime: () => useLocalRuntime,
|
43
46
|
unstable_useMessageContext: () => useMessageContext,
|
44
47
|
useBeginMessageEdit: () => useBeginMessageEdit,
|
45
48
|
useCopyMessage: () => useCopyMessage,
|
@@ -1090,7 +1093,7 @@ var useDummyAIAssistantContext = () => {
|
|
1090
1093
|
var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
|
1091
1094
|
var import_react25 = require("react");
|
1092
1095
|
|
1093
|
-
// src/adapters/
|
1096
|
+
// src/adapters/idUtils.tsx
|
1094
1097
|
var import_non_secure = require("nanoid/non-secure");
|
1095
1098
|
var generateId = (0, import_non_secure.customAlphabet)(
|
1096
1099
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
@@ -1098,6 +1101,8 @@ var generateId = (0, import_non_secure.customAlphabet)(
|
|
1098
1101
|
);
|
1099
1102
|
var optimisticPrefix = "__optimistic__";
|
1100
1103
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1104
|
+
|
1105
|
+
// src/adapters/MessageRepository.tsx
|
1101
1106
|
var findHead = (message) => {
|
1102
1107
|
if (message.next) return findHead(message.next);
|
1103
1108
|
return message;
|
@@ -1109,15 +1114,6 @@ var MessageRepository = class {
|
|
1109
1114
|
root = {
|
1110
1115
|
children: []
|
1111
1116
|
};
|
1112
|
-
getFallbackChild(p) {
|
1113
|
-
const childId = p.children.at(-1);
|
1114
|
-
const child = childId ? this.messages.get(childId) : null;
|
1115
|
-
if (child === void 0)
|
1116
|
-
throw new Error(
|
1117
|
-
"MessageRepository(getFallbackChild): Child message not found. This is likely an internal bug in assistant-ui."
|
1118
|
-
);
|
1119
|
-
return child;
|
1120
|
-
}
|
1121
1117
|
performOp(newParent, child, operation) {
|
1122
1118
|
const parentOrRoot = child.prev ?? this.root;
|
1123
1119
|
const newParentOrRoot = newParent ?? this.root;
|
@@ -1127,7 +1123,14 @@ var MessageRepository = class {
|
|
1127
1123
|
(m) => m !== child.current.id
|
1128
1124
|
);
|
1129
1125
|
if (child.prev?.next === child) {
|
1130
|
-
child.prev.
|
1126
|
+
const fallbackId = child.prev.children.at(-1);
|
1127
|
+
const fallback = fallbackId ? this.messages.get(fallbackId) : null;
|
1128
|
+
if (fallback === void 0) {
|
1129
|
+
throw new Error(
|
1130
|
+
"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
|
1131
|
+
);
|
1132
|
+
}
|
1133
|
+
child.prev.next = fallback;
|
1131
1134
|
}
|
1132
1135
|
}
|
1133
1136
|
if (operation !== "cut") {
|
@@ -1186,14 +1189,14 @@ var MessageRepository = class {
|
|
1186
1189
|
});
|
1187
1190
|
return optimisticId;
|
1188
1191
|
}
|
1189
|
-
deleteMessage(messageId,
|
1192
|
+
deleteMessage(messageId, replacementId) {
|
1190
1193
|
const message = this.messages.get(messageId);
|
1191
|
-
const
|
1194
|
+
const replacement = replacementId ? this.messages.get(replacementId) : null;
|
1192
1195
|
if (!message)
|
1193
1196
|
throw new Error(
|
1194
1197
|
"MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
|
1195
1198
|
);
|
1196
|
-
if (
|
1199
|
+
if (replacement === void 0)
|
1197
1200
|
throw new Error(
|
1198
1201
|
"MessageRepository(deleteMessage): New message not found. This is likely an internal bug in assistant-ui."
|
1199
1202
|
);
|
@@ -1203,11 +1206,11 @@ var MessageRepository = class {
|
|
1203
1206
|
throw new Error(
|
1204
1207
|
"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
|
1205
1208
|
);
|
1206
|
-
this.performOp(
|
1209
|
+
this.performOp(replacement, childMessage, "relink");
|
1207
1210
|
}
|
1208
1211
|
this.messages.delete(messageId);
|
1209
1212
|
if (this.head === message) {
|
1210
|
-
this.head =
|
1213
|
+
this.head = replacement;
|
1211
1214
|
}
|
1212
1215
|
this.performOp(null, message, "cut");
|
1213
1216
|
}
|
@@ -1250,17 +1253,13 @@ var MessageRepository = class {
|
|
1250
1253
|
}
|
1251
1254
|
};
|
1252
1255
|
|
1253
|
-
// src/adapters/ThreadMessageConverter.
|
1256
|
+
// src/adapters/ThreadMessageConverter.ts
|
1254
1257
|
var ThreadMessageConverter = class {
|
1255
|
-
constructor(converter) {
|
1256
|
-
this.converter = converter;
|
1257
|
-
}
|
1258
1258
|
cache = /* @__PURE__ */ new WeakMap();
|
1259
|
-
convertMessages(messages) {
|
1259
|
+
convertMessages(converter, messages) {
|
1260
1260
|
return messages.map((m) => {
|
1261
1261
|
const cached = this.cache.get(m);
|
1262
|
-
|
1263
|
-
const newMessage = this.converter(m);
|
1262
|
+
const newMessage = converter(m, cached);
|
1264
1263
|
this.cache.set(m, newMessage);
|
1265
1264
|
return newMessage;
|
1266
1265
|
});
|
@@ -1333,16 +1332,17 @@ var getIsRunning = (vercel) => {
|
|
1333
1332
|
var useVercelAIThreadState = (vercel) => {
|
1334
1333
|
const [data] = (0, import_react25.useState)(() => new MessageRepository());
|
1335
1334
|
const isRunning = getIsRunning(vercel);
|
1336
|
-
const
|
1337
|
-
return vercelToThreadMessage(
|
1338
|
-
message,
|
1339
|
-
vercel.messages.at(-1) === message && isRunning ? "in_progress" : "done"
|
1340
|
-
);
|
1341
|
-
});
|
1342
|
-
const converter = new ThreadMessageConverter(convertCallback);
|
1335
|
+
const converter = (0, import_react25.useMemo)(() => new ThreadMessageConverter(), []);
|
1343
1336
|
const assistantOptimisticIdRef = (0, import_react25.useRef)(null);
|
1344
1337
|
const messages = (0, import_react25.useMemo)(() => {
|
1345
|
-
const
|
1338
|
+
const lastMessageId = vercel.messages.at(-1)?.id;
|
1339
|
+
const convertCallback = (message, cache) => {
|
1340
|
+
const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
|
1341
|
+
if (cache && (cache.role === "user" || cache.status === status))
|
1342
|
+
return cache;
|
1343
|
+
return vercelToThreadMessage(message, status);
|
1344
|
+
};
|
1345
|
+
const vm = converter.convertMessages(convertCallback, vercel.messages);
|
1346
1346
|
for (let i = 0; i < vm.length; i++) {
|
1347
1347
|
const message = vm[i];
|
1348
1348
|
const parent = vm[i - 1];
|
@@ -1490,15 +1490,17 @@ var VercelRSCAssistantProvider = ({
|
|
1490
1490
|
setIsRunning(true);
|
1491
1491
|
return callback.finally(() => setIsRunning(false));
|
1492
1492
|
}, []);
|
1493
|
-
const converter = (0, import_react27.useMemo)(() => {
|
1493
|
+
const [converter, convertCallback] = (0, import_react27.useMemo)(() => {
|
1494
1494
|
const rscConverter = convertMessage ?? ((m) => m);
|
1495
|
-
|
1495
|
+
const convertCallback2 = (m, cache) => {
|
1496
|
+
if (cache) return cache;
|
1496
1497
|
return vercelToThreadMessage2(rscConverter, m);
|
1497
|
-
}
|
1498
|
+
};
|
1499
|
+
return [new ThreadMessageConverter(), convertCallback2];
|
1498
1500
|
}, [convertMessage]);
|
1499
1501
|
const messages = (0, import_react27.useMemo)(() => {
|
1500
|
-
return converter.convertMessages(vercelMessages);
|
1501
|
-
}, [converter, vercelMessages]);
|
1502
|
+
return converter.convertMessages(convertCallback, vercelMessages);
|
1503
|
+
}, [converter, convertCallback, vercelMessages]);
|
1502
1504
|
const append = (0, import_react27.useCallback)(
|
1503
1505
|
async (message) => {
|
1504
1506
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
@@ -1539,6 +1541,259 @@ var VercelRSCAssistantProvider = ({
|
|
1539
1541
|
}, [context, messages, isRunning, append, startRun]);
|
1540
1542
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AssistantContext.Provider, { value: context, children });
|
1541
1543
|
};
|
1544
|
+
|
1545
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1546
|
+
var import_react28 = require("react");
|
1547
|
+
var import_zustand6 = require("zustand");
|
1548
|
+
|
1549
|
+
// src/adapters/core/utils/AssistantMessageRepository.tsx
|
1550
|
+
var AssistantMessageRepository = class {
|
1551
|
+
constructor(flushCallback) {
|
1552
|
+
this.flushCallback = flushCallback;
|
1553
|
+
}
|
1554
|
+
repository = new MessageRepository();
|
1555
|
+
getBranches(messageId) {
|
1556
|
+
return this.repository.getBranches(messageId);
|
1557
|
+
}
|
1558
|
+
withModifications(callback) {
|
1559
|
+
const res = callback(this.repository);
|
1560
|
+
this.flushCallback(this.repository.getMessages());
|
1561
|
+
return res;
|
1562
|
+
}
|
1563
|
+
};
|
1564
|
+
|
1565
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1566
|
+
var makeThreadStore = (runtimeRef) => {
|
1567
|
+
const repository = new AssistantMessageRepository((messages) => {
|
1568
|
+
useThread.setState({ messages });
|
1569
|
+
});
|
1570
|
+
const useThread = (0, import_zustand6.create)(() => ({
|
1571
|
+
messages: [],
|
1572
|
+
isRunning: false,
|
1573
|
+
getBranches: (messageId) => repository.getBranches(messageId),
|
1574
|
+
switchToBranch: (branchId) => {
|
1575
|
+
repository.withModifications((repository2) => {
|
1576
|
+
repository2.switchToBranch(branchId);
|
1577
|
+
});
|
1578
|
+
},
|
1579
|
+
startRun: async (parentId) => {
|
1580
|
+
const optimisticId = repository.withModifications((repository2) => {
|
1581
|
+
const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
|
1582
|
+
role: "assistant",
|
1583
|
+
content: [{ type: "text", text: "" }]
|
1584
|
+
});
|
1585
|
+
repository2.resetHead(optimisticId2);
|
1586
|
+
return optimisticId2;
|
1587
|
+
});
|
1588
|
+
const { id } = await runtimeRef.current.startRun(parentId);
|
1589
|
+
repository.withModifications((repository2) => {
|
1590
|
+
repository2.deleteMessage(optimisticId, id);
|
1591
|
+
});
|
1592
|
+
},
|
1593
|
+
append: async (message) => {
|
1594
|
+
const [parentOptimisticId, optimisticId] = repository.withModifications(
|
1595
|
+
(repository2) => {
|
1596
|
+
const parentOptimisticId2 = repository2.appendOptimisticMessage(
|
1597
|
+
message.parentId,
|
1598
|
+
{
|
1599
|
+
role: "user",
|
1600
|
+
content: message.content
|
1601
|
+
}
|
1602
|
+
);
|
1603
|
+
const optimisticId2 = repository2.appendOptimisticMessage(
|
1604
|
+
parentOptimisticId2,
|
1605
|
+
{
|
1606
|
+
role: "assistant",
|
1607
|
+
content: [{ type: "text", text: "" }]
|
1608
|
+
}
|
1609
|
+
);
|
1610
|
+
repository2.resetHead(optimisticId2);
|
1611
|
+
return [parentOptimisticId2, optimisticId2];
|
1612
|
+
}
|
1613
|
+
);
|
1614
|
+
const { parentId, id } = await runtimeRef.current.append(message);
|
1615
|
+
repository.withModifications((repository2) => {
|
1616
|
+
repository2.deleteMessage(parentOptimisticId, parentId);
|
1617
|
+
repository2.deleteMessage(optimisticId, id);
|
1618
|
+
});
|
1619
|
+
},
|
1620
|
+
cancelRun: () => runtimeRef.current.cancelRun()
|
1621
|
+
}));
|
1622
|
+
const onNewMessage = (parentId, message) => {
|
1623
|
+
repository.withModifications((repository2) => {
|
1624
|
+
repository2.addOrUpdateMessage(parentId, message);
|
1625
|
+
});
|
1626
|
+
};
|
1627
|
+
const onRunningChange = (isRunning) => {
|
1628
|
+
useThread.setState({ isRunning });
|
1629
|
+
};
|
1630
|
+
return {
|
1631
|
+
useThread,
|
1632
|
+
onNewMessage,
|
1633
|
+
onRunningChange
|
1634
|
+
};
|
1635
|
+
};
|
1636
|
+
var useAssistantContext2 = (runtime) => {
|
1637
|
+
const runtimeRef = (0, import_react28.useRef)(runtime);
|
1638
|
+
runtimeRef.current = runtime;
|
1639
|
+
const [{ context, onNewMessage, onRunningChange }] = (0, import_react28.useState)(() => {
|
1640
|
+
const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
|
1641
|
+
const useViewport = makeViewportStore();
|
1642
|
+
const useComposer = makeThreadComposerStore(useThread);
|
1643
|
+
return {
|
1644
|
+
context: { useViewport, useThread, useComposer },
|
1645
|
+
onNewMessage: onNewMessage2,
|
1646
|
+
onRunningChange: onRunningChange2
|
1647
|
+
};
|
1648
|
+
});
|
1649
|
+
(0, import_react28.useEffect)(() => {
|
1650
|
+
return runtime.subscribeToMessageUpdates(onNewMessage);
|
1651
|
+
}, [runtime, onNewMessage]);
|
1652
|
+
(0, import_react28.useEffect)(() => {
|
1653
|
+
return runtime.subscribeToStatusUpdates(onRunningChange);
|
1654
|
+
}, [runtime, onRunningChange]);
|
1655
|
+
return context;
|
1656
|
+
};
|
1657
|
+
|
1658
|
+
// src/adapters/core/AssistantProvider.tsx
|
1659
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
1660
|
+
var AssistantProvider = ({ children, runtime }) => {
|
1661
|
+
const context = useAssistantContext2(runtime);
|
1662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantContext.Provider, { value: context, children });
|
1663
|
+
};
|
1664
|
+
|
1665
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1666
|
+
var import_react29 = require("react");
|
1667
|
+
|
1668
|
+
// src/adapters/core/local/LocalRuntime.tsx
|
1669
|
+
var LocalRuntime = class {
|
1670
|
+
constructor(adapter) {
|
1671
|
+
this.adapter = adapter;
|
1672
|
+
}
|
1673
|
+
_messageUpdateCallbacks = /* @__PURE__ */ new Set();
|
1674
|
+
_statusUpdateCallbacks = /* @__PURE__ */ new Set();
|
1675
|
+
abortController = null;
|
1676
|
+
repository = new MessageRepository();
|
1677
|
+
async append(message) {
|
1678
|
+
const userMessageId = generateId();
|
1679
|
+
const userMessage = {
|
1680
|
+
id: userMessageId,
|
1681
|
+
role: "user",
|
1682
|
+
content: message.content,
|
1683
|
+
createdAt: /* @__PURE__ */ new Date()
|
1684
|
+
};
|
1685
|
+
this.addOrUpdateMessage(message.parentId, userMessage);
|
1686
|
+
const { id } = await this.startRun(userMessageId);
|
1687
|
+
return { parentId: userMessageId, id };
|
1688
|
+
}
|
1689
|
+
async startRun(parentId) {
|
1690
|
+
const id = generateId();
|
1691
|
+
this.repository.resetHead(parentId);
|
1692
|
+
const messages = this.repository.getMessages();
|
1693
|
+
const message = {
|
1694
|
+
id,
|
1695
|
+
role: "assistant",
|
1696
|
+
status: "in_progress",
|
1697
|
+
content: [{ type: "text", text: "" }],
|
1698
|
+
createdAt: /* @__PURE__ */ new Date()
|
1699
|
+
};
|
1700
|
+
this.addOrUpdateMessage(parentId, message);
|
1701
|
+
void this.run(parentId, messages, message);
|
1702
|
+
return { id };
|
1703
|
+
}
|
1704
|
+
addOrUpdateMessage(parentId, message) {
|
1705
|
+
const clone = { ...message };
|
1706
|
+
this.repository.addOrUpdateMessage(parentId, clone);
|
1707
|
+
for (const callback of this._messageUpdateCallbacks)
|
1708
|
+
callback(parentId, clone);
|
1709
|
+
}
|
1710
|
+
async run(parentId, messages, message) {
|
1711
|
+
this.cancelRun();
|
1712
|
+
for (const callback of this._statusUpdateCallbacks) callback(true);
|
1713
|
+
this.abortController = new AbortController();
|
1714
|
+
try {
|
1715
|
+
await this.adapter.run({
|
1716
|
+
messages,
|
1717
|
+
abortSignal: this.abortController.signal,
|
1718
|
+
onUpdate: ({ content }) => {
|
1719
|
+
message.content = content;
|
1720
|
+
this.addOrUpdateMessage(parentId, message);
|
1721
|
+
}
|
1722
|
+
});
|
1723
|
+
message.status = "done";
|
1724
|
+
this.addOrUpdateMessage(parentId, message);
|
1725
|
+
} catch (e) {
|
1726
|
+
message.status = "error";
|
1727
|
+
this.addOrUpdateMessage(parentId, message);
|
1728
|
+
console.error(e);
|
1729
|
+
} finally {
|
1730
|
+
this.cancelRun();
|
1731
|
+
}
|
1732
|
+
}
|
1733
|
+
cancelRun() {
|
1734
|
+
if (!this.abortController) return;
|
1735
|
+
this.abortController.abort();
|
1736
|
+
this.abortController = null;
|
1737
|
+
for (const callback of this._statusUpdateCallbacks) callback(false);
|
1738
|
+
}
|
1739
|
+
subscribeToMessageUpdates(callback) {
|
1740
|
+
this._messageUpdateCallbacks.add(callback);
|
1741
|
+
return () => this._messageUpdateCallbacks.delete(callback);
|
1742
|
+
}
|
1743
|
+
subscribeToStatusUpdates(callback) {
|
1744
|
+
this._statusUpdateCallbacks.add(callback);
|
1745
|
+
return () => this._statusUpdateCallbacks.delete(callback);
|
1746
|
+
}
|
1747
|
+
};
|
1748
|
+
|
1749
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1750
|
+
var useLocalRuntime = (adapter) => {
|
1751
|
+
const [runtime] = (0, import_react29.useState)(() => new LocalRuntime(adapter));
|
1752
|
+
runtime.adapter = adapter;
|
1753
|
+
return runtime;
|
1754
|
+
};
|
1755
|
+
|
1756
|
+
// src/adapters/core/local/vercel/VercelModelAdapter.tsx
|
1757
|
+
var import_ai = require("ai");
|
1758
|
+
var VercelModelAdapter = class {
|
1759
|
+
constructor(model) {
|
1760
|
+
this.model = model;
|
1761
|
+
}
|
1762
|
+
async run({ messages, abortSignal, onUpdate }) {
|
1763
|
+
const { fullStream } = await (0, import_ai.streamText)({
|
1764
|
+
model: this.model,
|
1765
|
+
abortSignal,
|
1766
|
+
messages: messages.map((m) => ({
|
1767
|
+
role: m.role,
|
1768
|
+
content: m.content.filter((c) => c.type !== "ui")
|
1769
|
+
}))
|
1770
|
+
});
|
1771
|
+
const content = [];
|
1772
|
+
for await (const aiPart of fullStream) {
|
1773
|
+
switch (aiPart.type) {
|
1774
|
+
case "text-delta": {
|
1775
|
+
let part = content.at(-1);
|
1776
|
+
if (!part || part.type !== "text") {
|
1777
|
+
part = { type: "text", text: "" };
|
1778
|
+
content.push(part);
|
1779
|
+
}
|
1780
|
+
part.text += aiPart.textDelta;
|
1781
|
+
break;
|
1782
|
+
}
|
1783
|
+
case "tool-call": {
|
1784
|
+
content.push({
|
1785
|
+
type: "tool-call",
|
1786
|
+
name: aiPart.toolName,
|
1787
|
+
args: aiPart.args
|
1788
|
+
});
|
1789
|
+
break;
|
1790
|
+
}
|
1791
|
+
}
|
1792
|
+
onUpdate({ content });
|
1793
|
+
}
|
1794
|
+
return { content };
|
1795
|
+
}
|
1796
|
+
};
|
1542
1797
|
// Annotate the CommonJS export names for ESM import in node:
|
1543
1798
|
0 && (module.exports = {
|
1544
1799
|
ActionBarPrimitive,
|
@@ -1549,8 +1804,11 @@ var VercelRSCAssistantProvider = ({
|
|
1549
1804
|
ThreadPrimitive,
|
1550
1805
|
VercelAIAssistantProvider,
|
1551
1806
|
VercelRSCAssistantProvider,
|
1807
|
+
unstable_AssistantProvider,
|
1808
|
+
unstable_VercelModelAdapter,
|
1552
1809
|
unstable_getVercelMessage,
|
1553
1810
|
unstable_getVercelRSCMessage,
|
1811
|
+
unstable_useLocalRuntime,
|
1554
1812
|
unstable_useMessageContext,
|
1555
1813
|
useBeginMessageEdit,
|
1556
1814
|
useCopyMessage,
|
package/dist/index.mjs
CHANGED
@@ -1076,7 +1076,7 @@ var useDummyAIAssistantContext = () => {
|
|
1076
1076
|
import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
|
1077
1077
|
import { useCallback as useCallback2, useMemo as useMemo5, useRef as useRef4, useState as useState4 } from "react";
|
1078
1078
|
|
1079
|
-
// src/adapters/
|
1079
|
+
// src/adapters/idUtils.tsx
|
1080
1080
|
import { customAlphabet } from "nanoid/non-secure";
|
1081
1081
|
var generateId = customAlphabet(
|
1082
1082
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
@@ -1084,6 +1084,8 @@ var generateId = customAlphabet(
|
|
1084
1084
|
);
|
1085
1085
|
var optimisticPrefix = "__optimistic__";
|
1086
1086
|
var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
1087
|
+
|
1088
|
+
// src/adapters/MessageRepository.tsx
|
1087
1089
|
var findHead = (message) => {
|
1088
1090
|
if (message.next) return findHead(message.next);
|
1089
1091
|
return message;
|
@@ -1095,15 +1097,6 @@ var MessageRepository = class {
|
|
1095
1097
|
root = {
|
1096
1098
|
children: []
|
1097
1099
|
};
|
1098
|
-
getFallbackChild(p) {
|
1099
|
-
const childId = p.children.at(-1);
|
1100
|
-
const child = childId ? this.messages.get(childId) : null;
|
1101
|
-
if (child === void 0)
|
1102
|
-
throw new Error(
|
1103
|
-
"MessageRepository(getFallbackChild): Child message not found. This is likely an internal bug in assistant-ui."
|
1104
|
-
);
|
1105
|
-
return child;
|
1106
|
-
}
|
1107
1100
|
performOp(newParent, child, operation) {
|
1108
1101
|
const parentOrRoot = child.prev ?? this.root;
|
1109
1102
|
const newParentOrRoot = newParent ?? this.root;
|
@@ -1113,7 +1106,14 @@ var MessageRepository = class {
|
|
1113
1106
|
(m) => m !== child.current.id
|
1114
1107
|
);
|
1115
1108
|
if (child.prev?.next === child) {
|
1116
|
-
child.prev.
|
1109
|
+
const fallbackId = child.prev.children.at(-1);
|
1110
|
+
const fallback = fallbackId ? this.messages.get(fallbackId) : null;
|
1111
|
+
if (fallback === void 0) {
|
1112
|
+
throw new Error(
|
1113
|
+
"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui."
|
1114
|
+
);
|
1115
|
+
}
|
1116
|
+
child.prev.next = fallback;
|
1117
1117
|
}
|
1118
1118
|
}
|
1119
1119
|
if (operation !== "cut") {
|
@@ -1172,14 +1172,14 @@ var MessageRepository = class {
|
|
1172
1172
|
});
|
1173
1173
|
return optimisticId;
|
1174
1174
|
}
|
1175
|
-
deleteMessage(messageId,
|
1175
|
+
deleteMessage(messageId, replacementId) {
|
1176
1176
|
const message = this.messages.get(messageId);
|
1177
|
-
const
|
1177
|
+
const replacement = replacementId ? this.messages.get(replacementId) : null;
|
1178
1178
|
if (!message)
|
1179
1179
|
throw new Error(
|
1180
1180
|
"MessageRepository(deleteMessage): Optimistic message not found. This is likely an internal bug in assistant-ui."
|
1181
1181
|
);
|
1182
|
-
if (
|
1182
|
+
if (replacement === void 0)
|
1183
1183
|
throw new Error(
|
1184
1184
|
"MessageRepository(deleteMessage): New message not found. This is likely an internal bug in assistant-ui."
|
1185
1185
|
);
|
@@ -1189,11 +1189,11 @@ var MessageRepository = class {
|
|
1189
1189
|
throw new Error(
|
1190
1190
|
"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui."
|
1191
1191
|
);
|
1192
|
-
this.performOp(
|
1192
|
+
this.performOp(replacement, childMessage, "relink");
|
1193
1193
|
}
|
1194
1194
|
this.messages.delete(messageId);
|
1195
1195
|
if (this.head === message) {
|
1196
|
-
this.head =
|
1196
|
+
this.head = replacement;
|
1197
1197
|
}
|
1198
1198
|
this.performOp(null, message, "cut");
|
1199
1199
|
}
|
@@ -1236,17 +1236,13 @@ var MessageRepository = class {
|
|
1236
1236
|
}
|
1237
1237
|
};
|
1238
1238
|
|
1239
|
-
// src/adapters/ThreadMessageConverter.
|
1239
|
+
// src/adapters/ThreadMessageConverter.ts
|
1240
1240
|
var ThreadMessageConverter = class {
|
1241
|
-
constructor(converter) {
|
1242
|
-
this.converter = converter;
|
1243
|
-
}
|
1244
1241
|
cache = /* @__PURE__ */ new WeakMap();
|
1245
|
-
convertMessages(messages) {
|
1242
|
+
convertMessages(converter, messages) {
|
1246
1243
|
return messages.map((m) => {
|
1247
1244
|
const cached = this.cache.get(m);
|
1248
|
-
|
1249
|
-
const newMessage = this.converter(m);
|
1245
|
+
const newMessage = converter(m, cached);
|
1250
1246
|
this.cache.set(m, newMessage);
|
1251
1247
|
return newMessage;
|
1252
1248
|
});
|
@@ -1319,16 +1315,17 @@ var getIsRunning = (vercel) => {
|
|
1319
1315
|
var useVercelAIThreadState = (vercel) => {
|
1320
1316
|
const [data] = useState4(() => new MessageRepository());
|
1321
1317
|
const isRunning = getIsRunning(vercel);
|
1322
|
-
const
|
1323
|
-
return vercelToThreadMessage(
|
1324
|
-
message,
|
1325
|
-
vercel.messages.at(-1) === message && isRunning ? "in_progress" : "done"
|
1326
|
-
);
|
1327
|
-
});
|
1328
|
-
const converter = new ThreadMessageConverter(convertCallback);
|
1318
|
+
const converter = useMemo5(() => new ThreadMessageConverter(), []);
|
1329
1319
|
const assistantOptimisticIdRef = useRef4(null);
|
1330
1320
|
const messages = useMemo5(() => {
|
1331
|
-
const
|
1321
|
+
const lastMessageId = vercel.messages.at(-1)?.id;
|
1322
|
+
const convertCallback = (message, cache) => {
|
1323
|
+
const status = lastMessageId === message.id && isRunning ? "in_progress" : "done";
|
1324
|
+
if (cache && (cache.role === "user" || cache.status === status))
|
1325
|
+
return cache;
|
1326
|
+
return vercelToThreadMessage(message, status);
|
1327
|
+
};
|
1328
|
+
const vm = converter.convertMessages(convertCallback, vercel.messages);
|
1332
1329
|
for (let i = 0; i < vm.length; i++) {
|
1333
1330
|
const message = vm[i];
|
1334
1331
|
const parent = vm[i - 1];
|
@@ -1480,15 +1477,17 @@ var VercelRSCAssistantProvider = ({
|
|
1480
1477
|
setIsRunning(true);
|
1481
1478
|
return callback.finally(() => setIsRunning(false));
|
1482
1479
|
}, []);
|
1483
|
-
const converter = useMemo7(() => {
|
1480
|
+
const [converter, convertCallback] = useMemo7(() => {
|
1484
1481
|
const rscConverter = convertMessage ?? ((m) => m);
|
1485
|
-
|
1482
|
+
const convertCallback2 = (m, cache) => {
|
1483
|
+
if (cache) return cache;
|
1486
1484
|
return vercelToThreadMessage2(rscConverter, m);
|
1487
|
-
}
|
1485
|
+
};
|
1486
|
+
return [new ThreadMessageConverter(), convertCallback2];
|
1488
1487
|
}, [convertMessage]);
|
1489
1488
|
const messages = useMemo7(() => {
|
1490
|
-
return converter.convertMessages(vercelMessages);
|
1491
|
-
}, [converter, vercelMessages]);
|
1489
|
+
return converter.convertMessages(convertCallback, vercelMessages);
|
1490
|
+
}, [converter, convertCallback, vercelMessages]);
|
1492
1491
|
const append = useCallback3(
|
1493
1492
|
async (message) => {
|
1494
1493
|
if (message.parentId !== (context.useThread.getState().messages.at(-1)?.id ?? null)) {
|
@@ -1529,6 +1528,259 @@ var VercelRSCAssistantProvider = ({
|
|
1529
1528
|
}, [context, messages, isRunning, append, startRun]);
|
1530
1529
|
return /* @__PURE__ */ jsx22(AssistantContext.Provider, { value: context, children });
|
1531
1530
|
};
|
1531
|
+
|
1532
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1533
|
+
import { useEffect as useEffect4, useRef as useRef5, useState as useState6 } from "react";
|
1534
|
+
import { create as create6 } from "zustand";
|
1535
|
+
|
1536
|
+
// src/adapters/core/utils/AssistantMessageRepository.tsx
|
1537
|
+
var AssistantMessageRepository = class {
|
1538
|
+
constructor(flushCallback) {
|
1539
|
+
this.flushCallback = flushCallback;
|
1540
|
+
}
|
1541
|
+
repository = new MessageRepository();
|
1542
|
+
getBranches(messageId) {
|
1543
|
+
return this.repository.getBranches(messageId);
|
1544
|
+
}
|
1545
|
+
withModifications(callback) {
|
1546
|
+
const res = callback(this.repository);
|
1547
|
+
this.flushCallback(this.repository.getMessages());
|
1548
|
+
return res;
|
1549
|
+
}
|
1550
|
+
};
|
1551
|
+
|
1552
|
+
// src/adapters/core/utils/useAssistantContext.tsx
|
1553
|
+
var makeThreadStore = (runtimeRef) => {
|
1554
|
+
const repository = new AssistantMessageRepository((messages) => {
|
1555
|
+
useThread.setState({ messages });
|
1556
|
+
});
|
1557
|
+
const useThread = create6(() => ({
|
1558
|
+
messages: [],
|
1559
|
+
isRunning: false,
|
1560
|
+
getBranches: (messageId) => repository.getBranches(messageId),
|
1561
|
+
switchToBranch: (branchId) => {
|
1562
|
+
repository.withModifications((repository2) => {
|
1563
|
+
repository2.switchToBranch(branchId);
|
1564
|
+
});
|
1565
|
+
},
|
1566
|
+
startRun: async (parentId) => {
|
1567
|
+
const optimisticId = repository.withModifications((repository2) => {
|
1568
|
+
const optimisticId2 = repository2.appendOptimisticMessage(parentId, {
|
1569
|
+
role: "assistant",
|
1570
|
+
content: [{ type: "text", text: "" }]
|
1571
|
+
});
|
1572
|
+
repository2.resetHead(optimisticId2);
|
1573
|
+
return optimisticId2;
|
1574
|
+
});
|
1575
|
+
const { id } = await runtimeRef.current.startRun(parentId);
|
1576
|
+
repository.withModifications((repository2) => {
|
1577
|
+
repository2.deleteMessage(optimisticId, id);
|
1578
|
+
});
|
1579
|
+
},
|
1580
|
+
append: async (message) => {
|
1581
|
+
const [parentOptimisticId, optimisticId] = repository.withModifications(
|
1582
|
+
(repository2) => {
|
1583
|
+
const parentOptimisticId2 = repository2.appendOptimisticMessage(
|
1584
|
+
message.parentId,
|
1585
|
+
{
|
1586
|
+
role: "user",
|
1587
|
+
content: message.content
|
1588
|
+
}
|
1589
|
+
);
|
1590
|
+
const optimisticId2 = repository2.appendOptimisticMessage(
|
1591
|
+
parentOptimisticId2,
|
1592
|
+
{
|
1593
|
+
role: "assistant",
|
1594
|
+
content: [{ type: "text", text: "" }]
|
1595
|
+
}
|
1596
|
+
);
|
1597
|
+
repository2.resetHead(optimisticId2);
|
1598
|
+
return [parentOptimisticId2, optimisticId2];
|
1599
|
+
}
|
1600
|
+
);
|
1601
|
+
const { parentId, id } = await runtimeRef.current.append(message);
|
1602
|
+
repository.withModifications((repository2) => {
|
1603
|
+
repository2.deleteMessage(parentOptimisticId, parentId);
|
1604
|
+
repository2.deleteMessage(optimisticId, id);
|
1605
|
+
});
|
1606
|
+
},
|
1607
|
+
cancelRun: () => runtimeRef.current.cancelRun()
|
1608
|
+
}));
|
1609
|
+
const onNewMessage = (parentId, message) => {
|
1610
|
+
repository.withModifications((repository2) => {
|
1611
|
+
repository2.addOrUpdateMessage(parentId, message);
|
1612
|
+
});
|
1613
|
+
};
|
1614
|
+
const onRunningChange = (isRunning) => {
|
1615
|
+
useThread.setState({ isRunning });
|
1616
|
+
};
|
1617
|
+
return {
|
1618
|
+
useThread,
|
1619
|
+
onNewMessage,
|
1620
|
+
onRunningChange
|
1621
|
+
};
|
1622
|
+
};
|
1623
|
+
var useAssistantContext2 = (runtime) => {
|
1624
|
+
const runtimeRef = useRef5(runtime);
|
1625
|
+
runtimeRef.current = runtime;
|
1626
|
+
const [{ context, onNewMessage, onRunningChange }] = useState6(() => {
|
1627
|
+
const { useThread, onNewMessage: onNewMessage2, onRunningChange: onRunningChange2 } = makeThreadStore(runtimeRef);
|
1628
|
+
const useViewport = makeViewportStore();
|
1629
|
+
const useComposer = makeThreadComposerStore(useThread);
|
1630
|
+
return {
|
1631
|
+
context: { useViewport, useThread, useComposer },
|
1632
|
+
onNewMessage: onNewMessage2,
|
1633
|
+
onRunningChange: onRunningChange2
|
1634
|
+
};
|
1635
|
+
});
|
1636
|
+
useEffect4(() => {
|
1637
|
+
return runtime.subscribeToMessageUpdates(onNewMessage);
|
1638
|
+
}, [runtime, onNewMessage]);
|
1639
|
+
useEffect4(() => {
|
1640
|
+
return runtime.subscribeToStatusUpdates(onRunningChange);
|
1641
|
+
}, [runtime, onRunningChange]);
|
1642
|
+
return context;
|
1643
|
+
};
|
1644
|
+
|
1645
|
+
// src/adapters/core/AssistantProvider.tsx
|
1646
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
1647
|
+
var AssistantProvider = ({ children, runtime }) => {
|
1648
|
+
const context = useAssistantContext2(runtime);
|
1649
|
+
return /* @__PURE__ */ jsx23(AssistantContext.Provider, { value: context, children });
|
1650
|
+
};
|
1651
|
+
|
1652
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1653
|
+
import { useState as useState7 } from "react";
|
1654
|
+
|
1655
|
+
// src/adapters/core/local/LocalRuntime.tsx
|
1656
|
+
var LocalRuntime = class {
|
1657
|
+
constructor(adapter) {
|
1658
|
+
this.adapter = adapter;
|
1659
|
+
}
|
1660
|
+
_messageUpdateCallbacks = /* @__PURE__ */ new Set();
|
1661
|
+
_statusUpdateCallbacks = /* @__PURE__ */ new Set();
|
1662
|
+
abortController = null;
|
1663
|
+
repository = new MessageRepository();
|
1664
|
+
async append(message) {
|
1665
|
+
const userMessageId = generateId();
|
1666
|
+
const userMessage = {
|
1667
|
+
id: userMessageId,
|
1668
|
+
role: "user",
|
1669
|
+
content: message.content,
|
1670
|
+
createdAt: /* @__PURE__ */ new Date()
|
1671
|
+
};
|
1672
|
+
this.addOrUpdateMessage(message.parentId, userMessage);
|
1673
|
+
const { id } = await this.startRun(userMessageId);
|
1674
|
+
return { parentId: userMessageId, id };
|
1675
|
+
}
|
1676
|
+
async startRun(parentId) {
|
1677
|
+
const id = generateId();
|
1678
|
+
this.repository.resetHead(parentId);
|
1679
|
+
const messages = this.repository.getMessages();
|
1680
|
+
const message = {
|
1681
|
+
id,
|
1682
|
+
role: "assistant",
|
1683
|
+
status: "in_progress",
|
1684
|
+
content: [{ type: "text", text: "" }],
|
1685
|
+
createdAt: /* @__PURE__ */ new Date()
|
1686
|
+
};
|
1687
|
+
this.addOrUpdateMessage(parentId, message);
|
1688
|
+
void this.run(parentId, messages, message);
|
1689
|
+
return { id };
|
1690
|
+
}
|
1691
|
+
addOrUpdateMessage(parentId, message) {
|
1692
|
+
const clone = { ...message };
|
1693
|
+
this.repository.addOrUpdateMessage(parentId, clone);
|
1694
|
+
for (const callback of this._messageUpdateCallbacks)
|
1695
|
+
callback(parentId, clone);
|
1696
|
+
}
|
1697
|
+
async run(parentId, messages, message) {
|
1698
|
+
this.cancelRun();
|
1699
|
+
for (const callback of this._statusUpdateCallbacks) callback(true);
|
1700
|
+
this.abortController = new AbortController();
|
1701
|
+
try {
|
1702
|
+
await this.adapter.run({
|
1703
|
+
messages,
|
1704
|
+
abortSignal: this.abortController.signal,
|
1705
|
+
onUpdate: ({ content }) => {
|
1706
|
+
message.content = content;
|
1707
|
+
this.addOrUpdateMessage(parentId, message);
|
1708
|
+
}
|
1709
|
+
});
|
1710
|
+
message.status = "done";
|
1711
|
+
this.addOrUpdateMessage(parentId, message);
|
1712
|
+
} catch (e) {
|
1713
|
+
message.status = "error";
|
1714
|
+
this.addOrUpdateMessage(parentId, message);
|
1715
|
+
console.error(e);
|
1716
|
+
} finally {
|
1717
|
+
this.cancelRun();
|
1718
|
+
}
|
1719
|
+
}
|
1720
|
+
cancelRun() {
|
1721
|
+
if (!this.abortController) return;
|
1722
|
+
this.abortController.abort();
|
1723
|
+
this.abortController = null;
|
1724
|
+
for (const callback of this._statusUpdateCallbacks) callback(false);
|
1725
|
+
}
|
1726
|
+
subscribeToMessageUpdates(callback) {
|
1727
|
+
this._messageUpdateCallbacks.add(callback);
|
1728
|
+
return () => this._messageUpdateCallbacks.delete(callback);
|
1729
|
+
}
|
1730
|
+
subscribeToStatusUpdates(callback) {
|
1731
|
+
this._statusUpdateCallbacks.add(callback);
|
1732
|
+
return () => this._statusUpdateCallbacks.delete(callback);
|
1733
|
+
}
|
1734
|
+
};
|
1735
|
+
|
1736
|
+
// src/adapters/core/local/useLocalRuntime.tsx
|
1737
|
+
var useLocalRuntime = (adapter) => {
|
1738
|
+
const [runtime] = useState7(() => new LocalRuntime(adapter));
|
1739
|
+
runtime.adapter = adapter;
|
1740
|
+
return runtime;
|
1741
|
+
};
|
1742
|
+
|
1743
|
+
// src/adapters/core/local/vercel/VercelModelAdapter.tsx
|
1744
|
+
import { streamText } from "ai";
|
1745
|
+
var VercelModelAdapter = class {
|
1746
|
+
constructor(model) {
|
1747
|
+
this.model = model;
|
1748
|
+
}
|
1749
|
+
async run({ messages, abortSignal, onUpdate }) {
|
1750
|
+
const { fullStream } = await streamText({
|
1751
|
+
model: this.model,
|
1752
|
+
abortSignal,
|
1753
|
+
messages: messages.map((m) => ({
|
1754
|
+
role: m.role,
|
1755
|
+
content: m.content.filter((c) => c.type !== "ui")
|
1756
|
+
}))
|
1757
|
+
});
|
1758
|
+
const content = [];
|
1759
|
+
for await (const aiPart of fullStream) {
|
1760
|
+
switch (aiPart.type) {
|
1761
|
+
case "text-delta": {
|
1762
|
+
let part = content.at(-1);
|
1763
|
+
if (!part || part.type !== "text") {
|
1764
|
+
part = { type: "text", text: "" };
|
1765
|
+
content.push(part);
|
1766
|
+
}
|
1767
|
+
part.text += aiPart.textDelta;
|
1768
|
+
break;
|
1769
|
+
}
|
1770
|
+
case "tool-call": {
|
1771
|
+
content.push({
|
1772
|
+
type: "tool-call",
|
1773
|
+
name: aiPart.toolName,
|
1774
|
+
args: aiPart.args
|
1775
|
+
});
|
1776
|
+
break;
|
1777
|
+
}
|
1778
|
+
}
|
1779
|
+
onUpdate({ content });
|
1780
|
+
}
|
1781
|
+
return { content };
|
1782
|
+
}
|
1783
|
+
};
|
1532
1784
|
export {
|
1533
1785
|
actionBar_exports as ActionBarPrimitive,
|
1534
1786
|
branchPicker_exports as BranchPickerPrimitive,
|
@@ -1538,8 +1790,11 @@ export {
|
|
1538
1790
|
thread_exports as ThreadPrimitive,
|
1539
1791
|
VercelAIAssistantProvider,
|
1540
1792
|
VercelRSCAssistantProvider,
|
1793
|
+
AssistantProvider as unstable_AssistantProvider,
|
1794
|
+
VercelModelAdapter as unstable_VercelModelAdapter,
|
1541
1795
|
getVercelMessage as unstable_getVercelMessage,
|
1542
1796
|
getVercelRSCMessage as unstable_getVercelRSCMessage,
|
1797
|
+
useLocalRuntime as unstable_useLocalRuntime,
|
1543
1798
|
useMessageContext as unstable_useMessageContext,
|
1544
1799
|
useBeginMessageEdit,
|
1545
1800
|
useCopyMessage,
|