fix: 修复构建失败并补齐聊天存储模块

This commit is contained in:
2026-02-24 19:12:59 +08:00
parent ff6f12be21
commit 84b0209b03
2 changed files with 133 additions and 9 deletions
+129
View File
@@ -0,0 +1,129 @@
type ChatLocale = 'zh' | 'en'
type ChatRole = 'USER' | 'ASSISTANT' | 'SYSTEM'
type ChatStatus = 'ACTIVE'
interface ChatMessage {
id: string
sessionId: string
role: ChatRole
contentText: string
mode: string | null
createdAt: string
}
interface ChatSession {
id: string
clientId: string
locale: ChatLocale
title: string
status: ChatStatus
createdAt: string
updatedAt: string
lastMessageAt: string
}
interface ChatStoreState {
sessions: Map<string, ChatSession>
messages: Map<string, ChatMessage[]>
}
declare global {
// eslint-disable-next-line no-var
var __agentParkChatStore: ChatStoreState | undefined
}
function getStore(): ChatStoreState {
if (!globalThis.__agentParkChatStore) {
globalThis.__agentParkChatStore = {
sessions: new Map<string, ChatSession>(),
messages: new Map<string, ChatMessage[]>(),
}
}
return globalThis.__agentParkChatStore
}
function nowIso(): string {
return new Date().toISOString()
}
export async function createChatSession(input: {
clientId: string
locale: ChatLocale
title?: string
}): Promise<ChatSession> {
const store = getStore()
const now = nowIso()
const session: ChatSession = {
id: crypto.randomUUID(),
clientId: input.clientId,
locale: input.locale,
title: input.title?.trim() || 'New Chat',
status: 'ACTIVE',
createdAt: now,
updatedAt: now,
lastMessageAt: now,
}
store.sessions.set(session.id, session)
store.messages.set(session.id, [])
return session
}
export async function listChatSessions(input: {
clientId: string
locale?: ChatLocale
limit: number
cursor?: string
}): Promise<Array<ChatSession & { messages: ChatMessage[] }>> {
const store = getStore()
const ordered = Array.from(store.sessions.values())
.filter((session) =>
input.locale
? session.clientId === input.clientId && session.locale === input.locale
: session.clientId === input.clientId
)
.sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt))
const cursorIndex = input.cursor ? ordered.findIndex((session) => session.id === input.cursor) : -1
const page = cursorIndex >= 0 ? ordered.slice(cursorIndex + 1, cursorIndex + 1 + input.limit) : ordered.slice(0, input.limit)
return page.map((session) => {
const messageList = store.messages.get(session.id) || []
const latest = messageList.length > 0 ? [messageList[messageList.length - 1] as ChatMessage] : []
return {
...session,
messages: latest,
}
})
}
export async function assertSessionOwnership(input: {
sessionId: string
clientId: string
}): Promise<void> {
const store = getStore()
const session = store.sessions.get(input.sessionId)
if (!session) {
throw new Error('CHAT_SESSION_NOT_FOUND')
}
if (session.clientId !== input.clientId) {
throw new Error('CHAT_SESSION_FORBIDDEN')
}
}
export async function listChatMessages(input: {
sessionId: string
limit: number
}): Promise<ChatMessage[]> {
const store = getStore()
const messages = store.messages.get(input.sessionId) || []
const normalizedLimit = Math.max(1, input.limit)
return messages.slice(-normalizedLimit)
}
+4 -9
View File
@@ -232,13 +232,6 @@ export async function GET(request: NextRequest) {
? [{ isHot: 'desc' }, { hotScore: 'desc' }, { engagement: 'desc' }, { publishedAt: 'desc' }, { id: 'desc' }]
: [{ publishedAt: 'desc' }, { id: 'desc' }]
const cursorArgs = parsed.cursor
? {
cursor: { id: parsed.cursor },
skip: 1 as const,
}
: {}
let rows: Array<{
id: string
source: string
@@ -262,7 +255,8 @@ export async function GET(request: NextRequest) {
where,
orderBy,
take: parsed.limit + 1,
...cursorArgs,
cursor: parsed.cursor ? { id: parsed.cursor } : undefined,
skip: parsed.cursor ? 1 : undefined,
select: {
id: true,
source: true,
@@ -293,7 +287,8 @@ export async function GET(request: NextRequest) {
where,
orderBy: fallbackOrderBy,
take: parsed.limit + 1,
...cursorArgs,
cursor: parsed.cursor ? { id: parsed.cursor } : undefined,
skip: parsed.cursor ? 1 : undefined,
select: {
id: true,
source: true,