Skip to content

Commit f3c6297

Browse files
authored
Merge pull request #107 from will-lp1/ai-sdk-v5
feat: better error and document ID handling
2 parents b3a7cfd + 61cbec4 commit f3c6297

File tree

4 files changed

+32
-21
lines changed

4 files changed

+32
-21
lines changed

apps/saru/app/api/chat/route.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export async function POST(request: Request) {
189189
trailingMessageId,
190190
}: ChatRequestBody = await request.json();
191191

192-
const activeDocumentId: ActiveDocumentId = requestData?.activeDocumentId ?? null;
192+
const activeDocumentId: ActiveDocumentId = requestData?.activeDocumentId ?? undefined;
193193
const mentionedDocumentIds = requestData?.mentionedDocumentIds ?? undefined;
194194
const customInstructions = aiOptions?.customInstructions ?? null;
195195
const suggestionLength = aiOptions?.suggestionLength ?? 'medium';
@@ -249,7 +249,12 @@ export async function POST(request: Request) {
249249
}
250250

251251
if (trailingMessageId) {
252-
await deleteMessagesAfterMessageId({ chatId, messageId: trailingMessageId });
252+
const anchorMessage = await getMessageById({ id: trailingMessageId });
253+
if (anchorMessage && anchorMessage.chatId === chatId) {
254+
await deleteMessagesAfterMessageId({ chatId, messageId: trailingMessageId });
255+
} else {
256+
console.warn(`Invalid trailingMessageId ${trailingMessageId} for chat ${chatId}`);
257+
}
253258
}
254259

255260
const toolSession = session;
@@ -258,7 +263,7 @@ export async function POST(request: Request) {
258263
}
259264

260265

261-
let validatedActiveDocumentId: string | null = null;
266+
let validatedActiveDocumentId: string | undefined = undefined;
262267
let activeDoc: Document | null = null;
263268
if (activeDocumentId && uuidRegex.test(activeDocumentId)) {
264269
try {
@@ -278,8 +283,7 @@ export async function POST(request: Request) {
278283
const activeDocumentContent = activeDoc?.content ?? '';
279284
const isActiveDocumentEmpty = activeDocumentContent.trim().length === 0;
280285

281-
if (!validatedActiveDocumentId) {
282-
// No active document - only allow streaming document for new content generation
286+
if (validatedActiveDocumentId === undefined) {
283287
availableTools.streamingDocument = streamingDocument({ session: toolSession });
284288
activeToolsList.push('streamingDocument');
285289
} else {
@@ -305,7 +309,7 @@ export async function POST(request: Request) {
305309

306310
const dynamicSystemPrompt = await createEnhancedSystemPrompt({
307311
selectedChatModel,
308-
activeDocumentId,
312+
activeDocumentId: validatedActiveDocumentId,
309313
mentionedDocumentIds,
310314
customInstructions,
311315
writingStyleSummary,
@@ -320,7 +324,7 @@ export async function POST(request: Request) {
320324
toolsWithStream.streamingDocument = streamingDocument({
321325
session: toolSession,
322326
dataStream,
323-
documentId: validatedActiveDocumentId ?? undefined,
327+
documentId: validatedActiveDocumentId,
324328
});
325329
}
326330

@@ -341,7 +345,7 @@ export async function POST(request: Request) {
341345
onFinish: async ({ messages: allMessages }) => {
342346
if (userId) {
343347
try {
344-
const assistant = allMessages.find((m) => m.role === 'assistant') ?? allMessages[allMessages.length - 1];
348+
const assistant = allMessages.findLast((m) => m.role === 'assistant') ?? allMessages[allMessages.length - 1];
345349
if (assistant) {
346350
const dbMessage = convertUIMessageToDBFormat(assistant, chatId);
347351
await saveMessages({ messages: [dbMessage] });

apps/saru/components/chat/chat.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,23 +138,29 @@ export function Chat({
138138
});
139139
window.dispatchEvent(finishEvent);
140140
}
141-
} catch {}
141+
} catch (error) {
142+
console.error('Error processing chat data payload:', error);
143+
}
142144
},
143145
onError: (err) => {
144146
console.error('Chat Error:', err);
145147
},
146148
});
147149

148150
useEffect(() => {
149-
let timer: NodeJS.Timeout;
151+
let timerId: number | undefined;
152+
150153
if (status === 'submitted' || status === 'streaming') {
151-
timer = setTimeout(() => scrollToBottom(), 50);
152-
}
153-
else if (messages.length > 0) {
154-
timer = setTimeout(() => scrollToBottom(), 100);
154+
timerId = window.setTimeout(() => scrollToBottom(), 50);
155+
} else if (messages.length > 0) {
156+
timerId = window.setTimeout(() => scrollToBottom(), 100);
155157
}
156158

157-
return () => timer && clearTimeout(timer);
159+
return () => {
160+
if (timerId !== undefined) {
161+
window.clearTimeout(timerId);
162+
}
163+
};
158164
}, [status, messages.length, scrollToBottom]);
159165

160166

@@ -272,7 +278,7 @@ export function Chat({
272278
const activeDocumentId =
273279
document.documentId && document.documentId !== 'init'
274280
? document.documentId
275-
: null;
281+
: undefined;
276282

277283
const incoming = body ?? {};
278284
const incomingData =
@@ -340,7 +346,7 @@ export function Chat({
340346
activeDocumentId:
341347
document.documentId && document.documentId !== 'init'
342348
? document.documentId
343-
: null,
349+
: undefined,
344350
};
345351

346352
if (confirmedMentions.length > 0) {

apps/saru/lib/utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export function convertUIMessageToDBFormat(
9090
id: message.id || generateUUID(),
9191
chatId,
9292
role: message.role,
93-
content: { parts },
93+
content: { parts },
9494
createdAt: new Date().toISOString(),
9595
};
9696
}
@@ -106,8 +106,9 @@ export function getDocumentTimestampByIndex(
106106
documents: Document[],
107107
index: number,
108108
) {
109-
if (!documents) { return new Date(); }
110-
if (index > documents.length) { return new Date(); }
109+
if (!documents || index < 0 || index >= documents.length) {
110+
return new Date();
111+
}
111112

112113
return documents[index].createdAt;
113114
}

apps/saru/types/chat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { updateDocument } from "@/lib/ai/tools/update-document";
44
import type { streamingDocument } from "@/lib/ai/tools/document-streaming";
55
import type { webSearch } from "@/lib/ai/tools/web-search";
66

7-
export type ActiveDocumentId = string | null;
7+
export type ActiveDocumentId = string | undefined;
88

99
export interface ChatContextPayload {
1010
activeDocumentId?: ActiveDocumentId;

0 commit comments

Comments
 (0)