Files
Alpha/src/services/session-analyzer.ts
T
ricardo 066047f3d1 dual storage: sesiones en BD + markdown como output
- db.ts: v3 con tablas sessions, session_summaries, project_state
- transcriptions-db.ts: CRUD para sesiones, summaries, project state
- project-doc.ts: generateMasterDoc() desde BD (no desde datos en memoria)
- session-analyzer.ts: +sessionDate en prompt y extraction
- TranscriptionsView: flujo parse -> guardar BD -> IA -> project_state -> MD
- docs/arquitectura_transcripciones.md: documentacion oficial del patron
2026-05-28 13:38:19 -05:00

105 lines
3.7 KiB
TypeScript

import { callAI } from '@/services/ai'
export interface SessionExtraction {
sessionDate: string // YYYY-MM-DD
sessionTitle: string
summary: string
objectives: { text: string; isNew: boolean }[]
pendingTasks: { description: string; origin: string; priority: string }[]
commitments: { description: string; responsible: string; dueDate: string; status: string }[]
decisions: string[]
completedTasks: string[]
keyPoints: string[]
}
const SESSION_SYSTEM_PROMPT = `Eres un asistente de gestión de proyectos. Analizás transcripciones de reuniones y extraés información estructurada.
Reglas:
1. Identificá la fecha de la sesión (si no está explícita, usá la fecha actual)
2. Identificá el título de la sesión basado en el contenido
3. Extraé un resumen ejecutivo de 2-3 oraciones
4. Listá objetivos mencionados, marcando cuáles son NUEVOS vs existentes
5. Extraé tareas pendientes con su origen y prioridad (Alta/Media/Baja)
6. Identificá compromisos con responsable, fecha límite y estado
7. Listá decisiones tomadas durante la sesión
8. Detectá tareas completadas (si hay evidencia)
9. Incluí puntos clave, bloqueos o descubrimientos
10. No inventes información que no esté en la transcripción
11. Respondé SOLO con JSON válido
Formato de respuesta JSON:
{
"sessionDate": "YYYY-MM-DD",
"sessionTitle": "Título descriptivo de la sesión",
"summary": "Resumen ejecutivo de 2-3 oraciones",
"objectives": [
{ "text": "Descripción del objetivo", "isNew": true }
],
"pendingTasks": [
{ "description": "Descripción de la tarea", "origin": "Sesión o contexto", "priority": "Alta|Media|Baja" }
],
"commitments": [
{ "description": "Compromiso", "responsible": "Nombre", "dueDate": "YYYY-MM-DD", "status": "Pendiente|Cumplido|Vencido" }
],
"decisions": ["Decisión 1", "Decisión 2"],
"completedTasks": ["Tarea completada 1"],
"keyPoints": ["Punto clave 1"]
}`
export async function analyzeSession(
transcription: string,
projectName: string,
signal?: AbortSignal
): Promise<SessionExtraction> {
const userContent = `Proyecto: ${projectName}\n\nTranscripción:\n${transcription}`
console.log(`[Alpha] Session analyze — project: ${projectName}, text: ${transcription.length} chars`)
const content = await callAI(
[
{ role: 'system', content: SESSION_SYSTEM_PROMPT },
{ role: 'user', content: userContent },
],
0.3,
4096,
signal,
)
try {
const jsonStr = extractJSON(content)
const result: SessionExtraction = JSON.parse(jsonStr)
console.log(`[Alpha] Session analysis complete — ${result.pendingTasks.length} tasks, ${result.decisions.length} decisions`)
return result
} catch (e) {
console.error('[Alpha] Failed to parse session analysis. Raw response:', content)
throw new Error('No se pudo parsear el análisis de la sesión')
}
}
/**
* Extrae el primer objeto JSON válido del texto.
* Maneja markdown code blocks, texto antes/después, etc.
*/
function extractJSON(text: string): string {
// 1. Intentar parse directo
try { JSON.parse(text); return text } catch {}
// 2. Extraer entre ```json y ```
const jsonBlock = text.match(/```(?:json)?\s*([\s\S]*?)```/)
if (jsonBlock) {
const candidate = jsonBlock[1].trim()
try { JSON.parse(candidate); return candidate } catch {}
}
// 3. Extraer entre { y } (first { to last })
const firstBrace = text.indexOf('{')
const lastBrace = text.lastIndexOf('}')
if (firstBrace !== -1 && lastBrace > firstBrace) {
const candidate = text.slice(firstBrace, lastBrace + 1)
try { JSON.parse(candidate); return candidate } catch {}
}
// 4. Fallback: devolver el texto original (lanzará error en el caller)
return text
}