chatbot-template/lib/utils.ts

117 lines
3 KiB
TypeScript
Raw Normal View History

import type {
CoreAssistantMessage,
CoreToolMessage,
UIMessage,
UIMessagePart,
} from 'ai';
2024-11-15 12:18:17 -05:00
import { type ClassValue, clsx } from 'clsx';
2024-10-30 16:01:24 +05:30
import { twMerge } from 'tailwind-merge';
import type { DBMessage, Document } from '@/lib/db/schema';
2025-05-13 19:01:28 -07:00
import { ChatSDKError, type ErrorCode } from './errors';
import type { ChatMessage, ChatTools, CustomUIDataTypes } from './types';
import { formatISO } from 'date-fns';
2023-05-19 12:33:56 -04:00
export function cn(...inputs: ClassValue[]) {
2024-10-11 18:00:22 +05:30
return twMerge(clsx(inputs));
2023-05-19 12:33:56 -04:00
}
2024-10-11 18:00:22 +05:30
export const fetcher = async (url: string) => {
2025-05-13 19:01:28 -07:00
const response = await fetch(url);
if (!response.ok) {
const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause);
}
return response.json();
};
export async function fetchWithErrorHandlers(
input: RequestInfo | URL,
init?: RequestInit,
) {
try {
const response = await fetch(input, init);
2024-03-14 20:00:52 +03:00
2025-05-13 19:01:28 -07:00
if (!response.ok) {
const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause);
}
2024-03-19 04:37:30 +03:00
2025-05-13 19:01:28 -07:00
return response;
} catch (error: unknown) {
if (typeof navigator !== 'undefined' && !navigator.onLine) {
throw new ChatSDKError('offline:chat');
}
2024-03-19 04:37:30 +03:00
2024-10-11 18:00:22 +05:30
throw error;
2024-03-19 04:37:30 +03:00
}
2025-05-13 19:01:28 -07:00
}
2024-08-24 23:23:37 -05:00
2024-10-11 18:00:22 +05:30
export function getLocalStorage(key: string) {
2024-10-30 16:01:24 +05:30
if (typeof window !== 'undefined') {
return JSON.parse(localStorage.getItem(key) || '[]');
2024-10-11 18:00:22 +05:30
}
return [];
2024-08-24 23:23:37 -05:00
}
2024-10-11 18:00:22 +05:30
export function generateUUID(): string {
2024-11-15 12:18:17 -05:00
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
2024-10-11 18:00:22 +05:30
const r = (Math.random() * 16) | 0;
2024-10-30 16:01:24 +05:30
const v = c === 'x' ? r : (r & 0x3) | 0x8;
2024-10-11 18:00:22 +05:30
return v.toString(16);
});
2024-08-24 23:23:37 -05:00
}
type ResponseMessageWithoutId = CoreToolMessage | CoreAssistantMessage;
type ResponseMessage = ResponseMessageWithoutId & { id: string };
export function getMostRecentUserMessage(messages: Array<UIMessage>) {
2024-11-05 17:15:51 +03:00
const userMessages = messages.filter((message) => message.role === 'user');
return userMessages.at(-1);
}
export function getDocumentTimestampByIndex(
documents: Array<Document>,
2024-11-15 13:00:15 -05:00
index: number,
) {
if (!documents) return new Date();
if (index > documents.length) return new Date();
return documents[index].createdAt;
}
export function getTrailingMessageId({
messages,
}: {
messages: Array<ResponseMessage>;
}): string | null {
const trailingMessage = messages.at(-1);
if (!trailingMessage) return null;
return trailingMessage.id;
}
2025-05-02 16:45:26 -07:00
export function sanitizeText(text: string) {
return text.replace('<has_function_call>', '');
}
export function convertToUIMessages(messages: DBMessage[]): ChatMessage[] {
return messages.map((message) => ({
id: message.id,
role: message.role as 'user' | 'assistant' | 'system',
parts: message.parts as UIMessagePart<CustomUIDataTypes, ChatTools>[],
metadata: {
createdAt: formatISO(message.createdAt),
},
}));
}
export function getTextFromMessage(message: ChatMessage): string {
return message.parts
.filter((part) => part.type === 'text')
.map((part) => part.text)
.join('');
}