/** 上下文检查点(A3.8):平台保存「发给模型的上下文」的摘要与来源,权威在平台(实施设计 1.5) */ import type { Database } from './db.js'; export interface ContextCheckpoint { sessionId: string; summary: string; summarySourceIds: string[]; includedMessageIds: string[]; lastMessageId: string | null; pinned: string[]; estimatedChars: number; updatedAt: number; } interface CheckpointRow { session_id: string; summary: string; summary_source_ids: string; included_message_ids: string; last_message_id: string | null; pinned: string; estimated_chars: number; updated_at: number; } const parseIds = (raw: string): string[] => { try { const parsed = JSON.parse(raw) as unknown; return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : []; } catch { return []; } }; export class ContextRepository { constructor(private readonly db: Database) {} save(checkpoint: Omit): void { this.db .prepare( `insert into context_checkpoints (session_id, summary, summary_source_ids, included_message_ids, last_message_id, pinned, estimated_chars, updated_at) values (?, ?, ?, ?, ?, ?, ?, ?) on conflict(session_id) do update set summary = excluded.summary, summary_source_ids = excluded.summary_source_ids, included_message_ids = excluded.included_message_ids, last_message_id = excluded.last_message_id, pinned = excluded.pinned, estimated_chars = excluded.estimated_chars, updated_at = excluded.updated_at`, ) .run( checkpoint.sessionId, checkpoint.summary, JSON.stringify(checkpoint.summarySourceIds), JSON.stringify(checkpoint.includedMessageIds), checkpoint.lastMessageId, JSON.stringify(checkpoint.pinned), checkpoint.estimatedChars, Date.now(), ); } get(sessionId: string): ContextCheckpoint | undefined { const row = this.db.prepare('select * from context_checkpoints where session_id = ?').get(sessionId) as unknown as CheckpointRow | undefined; if (!row) return undefined; return { sessionId: row.session_id, summary: row.summary, summarySourceIds: parseIds(row.summary_source_ids), includedMessageIds: parseIds(row.included_message_ids), lastMessageId: row.last_message_id, pinned: parseIds(row.pinned), estimatedChars: row.estimated_chars, updatedAt: row.updated_at, }; } }