/** * Chat Mode Resolution Logic * * Determines which chat mode (collector, extraction_review, vision, mvp, marketing, general) * should be active based on project state stored in Postgres. */ import { query } from '@/lib/db-postgres'; import type { ChatMode } from '@/lib/ai/chat-modes'; /** * Resolve the appropriate chat mode for a project using Postgres (fs_projects). */ export async function resolveChatMode(projectId: string): Promise { try { const rows = await query<{ data: any }>( `SELECT data FROM fs_projects WHERE id = $1 LIMIT 1`, [projectId] ); if (rows.length === 0) { console.warn(`[Chat Mode Resolver] Project ${projectId} not found`); return 'collector_mode'; } const projectData = rows[0].data ?? {}; const phaseData = (projectData.phaseData ?? {}) as Record; const currentPhase: string = projectData.currentPhase ?? 'collector'; // Explicit phase overrides if (currentPhase === 'extraction_review' || currentPhase === 'analyzed') return 'extraction_review_mode'; if (currentPhase === 'vision') return 'vision_mode'; if (currentPhase === 'mvp') return 'mvp_mode'; if (currentPhase === 'marketing') return 'marketing_mode'; // Derive from phase artifacts if (!phaseData.canonicalProductModel) return 'collector_mode'; if (!phaseData.mvpPlan) return 'vision_mode'; if (!phaseData.marketingPlan) return 'mvp_mode'; if (phaseData.marketingPlan) return 'marketing_mode'; return 'general_chat_mode'; } catch (error) { console.error('[Chat Mode Resolver] Failed to resolve mode:', error); return 'collector_mode'; } } /** * Summarise knowledge items for context building. * Uses Postgres fs_knowledge_items if available, otherwise returns empty. */ export async function summarizeKnowledgeItems(projectId: string): Promise<{ totalCount: number; bySourceType: Record; recentTitles: string[]; }> { try { const rows = await query<{ data: any }>( `SELECT data FROM fs_knowledge_items WHERE project_id = $1 ORDER BY created_at DESC LIMIT 20`, [projectId] ); const bySourceType: Record = {}; const recentTitles: string[] = []; for (const row of rows) { const d = row.data ?? {}; const sourceType = d.sourceType ?? 'unknown'; bySourceType[sourceType] = (bySourceType[sourceType] ?? 0) + 1; if (d.title && recentTitles.length < 5) recentTitles.push(d.title); } return { totalCount: rows.length, bySourceType, recentTitles }; } catch { // Table may not exist for older deployments — return empty return { totalCount: 0, bySourceType: {}, recentTitles: [] }; } } /** * Summarise extractions for context building. * Returns empty defaults — extractions not yet migrated to Postgres. */ export async function summarizeExtractions(projectId: string): Promise<{ totalCount: number; avgConfidence: number; avgCompletion: number; }> { return { totalCount: 0, avgConfidence: 0, avgCompletion: 0 }; }