fix: 修复构建失败并补齐聊天存储模块
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
@@ -232,13 +232,6 @@ export async function GET(request: NextRequest) {
|
|||||||
? [{ isHot: 'desc' }, { hotScore: 'desc' }, { engagement: 'desc' }, { publishedAt: 'desc' }, { id: 'desc' }]
|
? [{ isHot: 'desc' }, { hotScore: 'desc' }, { engagement: 'desc' }, { publishedAt: 'desc' }, { id: 'desc' }]
|
||||||
: [{ publishedAt: 'desc' }, { id: 'desc' }]
|
: [{ publishedAt: 'desc' }, { id: 'desc' }]
|
||||||
|
|
||||||
const cursorArgs = parsed.cursor
|
|
||||||
? {
|
|
||||||
cursor: { id: parsed.cursor },
|
|
||||||
skip: 1 as const,
|
|
||||||
}
|
|
||||||
: {}
|
|
||||||
|
|
||||||
let rows: Array<{
|
let rows: Array<{
|
||||||
id: string
|
id: string
|
||||||
source: string
|
source: string
|
||||||
@@ -262,7 +255,8 @@ export async function GET(request: NextRequest) {
|
|||||||
where,
|
where,
|
||||||
orderBy,
|
orderBy,
|
||||||
take: parsed.limit + 1,
|
take: parsed.limit + 1,
|
||||||
...cursorArgs,
|
cursor: parsed.cursor ? { id: parsed.cursor } : undefined,
|
||||||
|
skip: parsed.cursor ? 1 : undefined,
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
source: true,
|
source: true,
|
||||||
@@ -293,7 +287,8 @@ export async function GET(request: NextRequest) {
|
|||||||
where,
|
where,
|
||||||
orderBy: fallbackOrderBy,
|
orderBy: fallbackOrderBy,
|
||||||
take: parsed.limit + 1,
|
take: parsed.limit + 1,
|
||||||
...cursorArgs,
|
cursor: parsed.cursor ? { id: parsed.cursor } : undefined,
|
||||||
|
skip: parsed.cursor ? 1 : undefined,
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
source: true,
|
source: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user