import { getBackendBaseURL } from '@/core/config'; import { apiFetch } from '@/core/api'; import type { ProgressEvent, CompletedIntervention } from '../types/ai-writing'; export interface AIWritingSessionSummary { id: string; user_id: string | null; title: string; user_intent: string | null; status: string; draft_title: string | null; draft_markdown: string | null; completed_interventions: CompletedInterventionRecord[] | null; review_result: Record | null; transcript: AIWritingTranscript | null; created_at: string; updated_at: string; } export interface CompletedInterventionRecord { pausePoint: string; action: string; timestamp: string; } /** 完整对话时间线快照:与实时对话用同一份数据结构,历史回显时直接喂给 AIWritingTimeline。 */ export interface AIWritingTranscript { progressEvents: ProgressEvent[]; completedInterventions: CompletedIntervention[]; } const BASE = () => `${getBackendBaseURL()}/api/ai-writing/sessions`; // ── admin 调试用 —— 阶段 7 删冗余时一并移除 ─────────────────────────────────── export interface AIWritingCleanupResult { deleted_db: number; deleted_checkpoints: number; skipped_active: number; elapsed_seconds: number; params: { retention_days: number; only_finished: boolean; batch_size: number }; } /** 仅 admin 可用:触发一次性会话清理(保留 ai-writing-优化.md 迁移期临时调试入口)。 */ export async function adminCleanupAIWritingSessions(body: { retention_days?: number; only_finished?: boolean; batch_size?: number; } = {}): Promise { const resp = await apiFetch(`${getBackendBaseURL()}/api/ai-writing/admin/cleanup`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!resp.ok) { const text = await resp.text().catch(() => ''); throw new Error(`清理失败 ${resp.status}: ${text || resp.statusText}`); } return resp.json(); } export async function listAIWritingSessions(): Promise { const resp = await apiFetch(BASE()); if (!resp.ok) throw new Error(`获取历史记录失败: ${resp.status}`); return resp.json(); } export async function getAIWritingSession(id: string): Promise { const resp = await apiFetch(`${BASE()}/${id}`); if (!resp.ok) throw new Error(`获取会话失败: ${resp.status}`); return resp.json(); } export async function renameAIWritingSession(id: string, title: string): Promise { const resp = await apiFetch(`${BASE()}/${id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title }), }); if (!resp.ok) throw new Error(`重命名失败: ${resp.status}`); return resp.json(); } export async function deleteAIWritingSession(id: string): Promise { const resp = await apiFetch(`${BASE()}/${id}`, { method: 'DELETE' }); if (!resp.ok) throw new Error(`删除失败: ${resp.status}`); } /** * 保存会话的完整对话时间线,供历史回显出与实时对话一致的富时间线。 * * 该功能属于「锦上添花」:保存失败不应影响写作主流程,因此本函数永不抛错, * 内部捕获所有异常(网络错误 / 接口 500 等),仅打印告警并返回是否成功。 */ export async function saveAIWritingTranscript( id: string, transcript: AIWritingTranscript, ): Promise { try { const resp = await apiFetch(`${BASE()}/${id}/transcript`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ transcript }), }); if (!resp.ok) { console.warn(`[ai-writing] 保存对话时间线失败: HTTP ${resp.status}(已忽略,不影响写作流程)`); return false; } return true; } catch (err) { console.warn('[ai-writing] 保存对话时间线异常(已忽略,不影响写作流程):', err); return false; } }