Files
penx/apps/web/lib/chat.utils.ts
2025-04-30 20:27:49 +08:00

76 lines
1.8 KiB
TypeScript

import type { CoreAssistantMessage, CoreToolMessage, UIMessage } from 'ai'
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { IDocument } from '@penx/model-type'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
interface ApplicationError extends Error {
info: string
status: number
}
export const fetcher = async (url: string) => {
const res = await fetch(url)
if (!res.ok) {
const error = new Error(
'An error occurred while fetching the data.',
) as ApplicationError
error.info = await res.json()
error.status = res.status
throw error
}
return res.json()
}
export function getLocalStorage(key: string) {
if (typeof window !== 'undefined') {
return JSON.parse(localStorage.getItem(key) || '[]')
}
return []
}
export function generateUUID(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}
type ResponseMessageWithoutId = CoreToolMessage | CoreAssistantMessage
type ResponseMessage = ResponseMessageWithoutId & { id: string }
export function getMostRecentUserMessage(messages: Array<UIMessage>) {
const userMessages = messages.filter((message) => message.role === 'user')
return userMessages.at(-1)
}
export function getDocumentTimestampByIndex(
documents: Array<IDocument>,
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
}