diff --git a/apps/cli/src/http/routes/web/summaries.ts b/apps/cli/src/http/routes/web/summaries.ts index 4abb1c2a..f006c42b 100644 --- a/apps/cli/src/http/routes/web/summaries.ts +++ b/apps/cli/src/http/routes/web/summaries.ts @@ -52,4 +52,12 @@ export function registerSummaryRoutes( } return result }) + + server.post<{ + Params: { id: string } + Body: { chatSessionIds: number[] } + }>('/_web/sessions/:id/summaries/check-can-generate', async (request) => { + const { chatSessionIds } = request.body + return summaryService.checkCanGenerate(adapter, request.params.id, chatSessionIds) + }) } diff --git a/packages/node-runtime/src/services/summary-service.ts b/packages/node-runtime/src/services/summary-service.ts index 5f29731e..bb10f7d0 100644 --- a/packages/node-runtime/src/services/summary-service.ts +++ b/packages/node-runtime/src/services/summary-service.ts @@ -12,7 +12,13 @@ import { getSessionMessages, } from '@openchatlab/core' import type { DatabaseAdapter } from '@openchatlab/core' -import { generateSessionSummary, type SummaryDeps, completeSimple, type PiTextContent } from '../ai' +import { + generateSessionSummary, + checkSessionsCanGenerateSummary, + type SummaryDeps, + completeSimple, + type PiTextContent, +} from '../ai' import type { SessionRuntimeAdapter } from './adapters' export interface LlmConfig { @@ -99,3 +105,25 @@ export async function generateAllSummaries( return { success, failed, total: chatSessions.length } } + +export function checkCanGenerate( + adapter: SessionRuntimeAdapter, + sessionId: string, + chatSessionIds: number[] +): Record { + const db = adapter.ensureReadonly(sessionId) + const deps: Pick = { + loadMessages(chatSessionId, limit = 500) { + const data = getSessionMessages(db, chatSessionId, limit) + if (!data) return null + return data.messages.map((m) => ({ senderName: m.senderName, content: m.content })) + }, + t: (key: string) => key, + } + const resultMap = checkSessionsCanGenerateSummary(deps, chatSessionIds) + const result: Record = {} + for (const [id, info] of resultMap) { + result[id] = info + } + return result +} diff --git a/src/services/session-index/fetch.ts b/src/services/session-index/fetch.ts index 2791dce4..17232e8c 100644 --- a/src/services/session-index/fetch.ts +++ b/src/services/session-index/fetch.ts @@ -96,18 +96,63 @@ export class FetchSessionIndexAdapter implements SessionIndexAdapter { ) } - async generateSummary(): Promise { - return { success: false, error: 'Not available in web mode' } + async generateSummary( + dbSessionId: string, + chatSessionId: number, + locale?: string, + forceRegenerate?: boolean + ): Promise { + try { + const resp = await fetch(`/_web/sessions/${dbSessionId}/summaries/generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ chatSessionId, locale, forceRegenerate }), + }) + const result = await resp.json() + if (!resp.ok) { + return { success: false, error: result.error || `HTTP ${resp.status}` } + } + return result + } catch (error) { + return { success: false, error: error instanceof Error ? error.message : String(error) } + } } - async generateSummaries(): Promise { - return { success: 0, failed: 0, skipped: 0 } + async generateSummaries( + dbSessionId: string, + _chatSessionIds: number[], + locale?: string + ): Promise { + try { + const resp = await fetch(`/_web/sessions/${dbSessionId}/summaries/generate-all`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ locale }), + }) + const result = await resp.json() + if (!resp.ok) { + return { success: 0, failed: 0, skipped: 0 } + } + return { success: result.success ?? 0, failed: result.failed ?? 0, skipped: result.skipped ?? 0 } + } catch { + return { success: 0, failed: 0, skipped: 0 } + } } async checkCanGenerateSummary( - _dbSessionId: string, - _chatSessionIds: number[] + dbSessionId: string, + chatSessionIds: number[] ): Promise> { - return {} + try { + const resp = await fetch(`/_web/sessions/${dbSessionId}/summaries/check-can-generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ chatSessionIds }), + }) + if (!resp.ok) return {} + return await resp.json() + } catch { + return {} + } } }