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
This commit is contained in:
+39
-1
@@ -13,14 +13,52 @@ export interface ProjectDocRecord {
|
||||
markdown: string
|
||||
}
|
||||
|
||||
export interface SessionRecord {
|
||||
id?: number
|
||||
projectId: number
|
||||
date: string
|
||||
title: string
|
||||
fileName: string
|
||||
fileType: string
|
||||
fileSize: number
|
||||
rawText: string
|
||||
processedAt: string
|
||||
}
|
||||
|
||||
export interface SessionSummaryRecord {
|
||||
sessionId: number
|
||||
summary: string
|
||||
objectives: string // JSON array
|
||||
tasks: string // JSON array
|
||||
commitments: string // JSON array
|
||||
decisions: string // JSON array
|
||||
keyPoints: string // JSON array
|
||||
modelUsed: string
|
||||
}
|
||||
|
||||
export interface ProjectStateRecord {
|
||||
projectId: number
|
||||
summary: string
|
||||
objectives: string // JSON array (unificado)
|
||||
tasks: string // JSON array (consolidado)
|
||||
commitments: string // JSON array (consolidado)
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
const db = new Dexie('alpha-core') as Dexie & {
|
||||
settings: Dexie.Table<SettingEntry, string>
|
||||
project_docs: Dexie.Table<ProjectDocRecord, number>
|
||||
sessions: Dexie.Table<SessionRecord, number>
|
||||
session_summaries: Dexie.Table<SessionSummaryRecord, number>
|
||||
project_state: Dexie.Table<ProjectStateRecord, number>
|
||||
}
|
||||
|
||||
db.version(2).stores({
|
||||
db.version(3).stores({
|
||||
settings: '&key',
|
||||
project_docs: '&projectId, projectName, updatedAt',
|
||||
sessions: '++id, projectId, date',
|
||||
session_summaries: '&sessionId',
|
||||
project_state: '&projectId',
|
||||
})
|
||||
|
||||
export default db
|
||||
|
||||
+65
-86
@@ -1,66 +1,56 @@
|
||||
import db from '@/services/db'
|
||||
import type { SessionExtraction } from '@/services/session-analyzer'
|
||||
import { getSessionsByProject, getSessionSummary, getProjectState, type SessionRecord, type ProjectStateRecord } from '@/services/transcriptions-db'
|
||||
|
||||
export interface ProjectDoc {
|
||||
projectId: number
|
||||
projectName: string
|
||||
updatedAt: string
|
||||
sessionCount: number
|
||||
markdown: string
|
||||
/**
|
||||
* Genera el markdown del proyecto completamente desde la BD.
|
||||
* No recibe datos de sesión directos — los obtiene de las tablas.
|
||||
*/
|
||||
export async function generateMasterDoc(projectId: number, projectName: string): Promise<string> {
|
||||
const state = await getProjectState(projectId)
|
||||
const sessions = await getSessionsByProject(projectId)
|
||||
|
||||
const block1 = buildBlock1(state, projectName, sessions.length)
|
||||
const block2 = await buildBlock2(sessions)
|
||||
|
||||
return `${block1}\n\n${block2}\n`
|
||||
}
|
||||
|
||||
export async function getProjectDoc(projectId: number): Promise<ProjectDoc | null> {
|
||||
const doc = await db.table('project_docs').get(projectId)
|
||||
return (doc as ProjectDoc) || null
|
||||
}
|
||||
|
||||
export async function generateProjectDoc(
|
||||
projectId: number,
|
||||
function buildBlock1(
|
||||
state: ProjectStateRecord | undefined,
|
||||
projectName: string,
|
||||
extraction: SessionExtraction,
|
||||
transcriptionText: string,
|
||||
fileName: string,
|
||||
previousDoc?: ProjectDoc | null,
|
||||
): Promise<ProjectDoc> {
|
||||
sessionCount: number,
|
||||
): string {
|
||||
const now = new Date().toISOString().slice(0, 16).replace('T', ' ')
|
||||
const sessionCount = (previousDoc?.sessionCount || 0) + 1
|
||||
|
||||
// ─── Block 1: Summary (replaced) ───────────────────────
|
||||
const objectives = safeParse<string[]>(state?.objectives, [])
|
||||
const tasks = safeParse<{ description: string; origin: string; priority: string; status?: string }[]>(state?.tasks, [])
|
||||
const commitments = safeParse<{ description: string; responsible: string; dueDate: string; status: string }[]>(state?.commitments, [])
|
||||
const summary = state?.summary || 'Sin resumen disponible'
|
||||
|
||||
const objectivesMd = extraction.objectives.map(o =>
|
||||
o.isNew ? `- [ ] ${o.text} 🆕` : `- [ ] ${o.text}`
|
||||
).join('\n')
|
||||
|
||||
const tasksMd = extraction.pendingTasks.map((t, i) =>
|
||||
`| ${i + 1} | [ ] ${t.description} | ${t.origin} | ${now.slice(0, 10)} | ${t.priority} |`
|
||||
).join('\n')
|
||||
|
||||
const commitmentsMd = extraction.commitments.map(c =>
|
||||
const objectivesMd = objectives.map(o => `- [ ] ${o}`).join('\n')
|
||||
const tasksMd = tasks.map((t, i) => `| ${i + 1} | [${t.status === 'completada' ? 'x' : ' '}] ${t.description} | ${t.origin} | ${t.priority} |`).join('\n')
|
||||
const commitmentsMd = commitments.map(c =>
|
||||
`| ${c.description} | ${c.responsible} | ${c.dueDate} | ${c.status === 'Cumplido' ? '✅' : '⏳'} | — |`
|
||||
).join('\n')
|
||||
|
||||
const completedMd = extraction.completedTasks.map(t => `- [x] ${t}`).join('\n')
|
||||
|
||||
const milestonesMd = extraction.commitments
|
||||
const milestonesMd = commitments
|
||||
.filter(c => c.dueDate && c.status !== 'Cumplido')
|
||||
.map(c => `- **${c.dueDate}**: ${c.description}`)
|
||||
.map(c => `- **${c.dueDate}**: ${c.description} (_${c.responsible}_)`)
|
||||
.join('\n')
|
||||
|
||||
const block1 = `# 📋 ${projectName} — Resumen Ejecutivo
|
||||
return `# 📋 ${projectName} — Resumen Ejecutivo
|
||||
|
||||
> ⚠️ Última actualización: ${now}
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Resumen Ejecutivo
|
||||
${extraction.summary}
|
||||
${summary}
|
||||
|
||||
## 🎯 Objetivos
|
||||
${objectivesMd || '_Sin objetivos registrados_'}
|
||||
|
||||
## 📝 Tareas Pendientes
|
||||
| # | Tarea | Origen | Fecha creación | Prioridad |
|
||||
|---|-------|--------|----------------|-----------|
|
||||
| # | Tarea | Origen | Prioridad |
|
||||
|---|-------|--------|-----------|
|
||||
${tasksMd || '_Sin tareas pendientes_'}
|
||||
|
||||
## ✅ Compromisos
|
||||
@@ -68,76 +58,65 @@ ${tasksMd || '_Sin tareas pendientes_'}
|
||||
|------------|-------------|--------------|--------|-------|
|
||||
${commitmentsMd || '_Sin compromisos_'}
|
||||
|
||||
## ✅ Tareas Completadas
|
||||
${completedMd || '_Sin tareas completadas en esta sesión_'}
|
||||
|
||||
## 📅 Próximos Hitos
|
||||
${milestonesMd || '_Sin hitos próximos_'}
|
||||
|
||||
## 📊 Métricas de Seguimiento
|
||||
- Sesiones registradas: ${sessionCount}
|
||||
- Tareas pendientes: ${extraction.pendingTasks.length}
|
||||
- Compromisos cumplidos: ${extraction.commitments.filter(c => c.status === 'Cumplido').length}/${extraction.commitments.length}
|
||||
- Decisiones tomadas: ${extraction.decisions.length}
|
||||
- Tareas pendientes: ${tasks.filter(t => t.status !== 'completada').length}
|
||||
- Compromisos cumplidos: ${commitments.filter(c => c.status === 'Cumplido').length}/${commitments.length}`
|
||||
}
|
||||
|
||||
---
|
||||
async function buildBlock2(sessions: SessionRecord[]): Promise<string> {
|
||||
if (sessions.length === 0) return '## 📜 Registro de Sesiones\n\n_Sin sesiones registradas_'
|
||||
|
||||
### Bloque 2: Registro de Sesiones
|
||||
const parts: string[] = ['---\n\n## 📜 Registro Completo de Sesiones']
|
||||
|
||||
---
|
||||
for (const session of sessions) {
|
||||
const summary = await getSessionSummary(session.id!)
|
||||
const objectives = safeParse<{ text: string; isNew: boolean }[]>(summary?.objectives, [])
|
||||
const tasks = safeParse<{ description: string; origin: string; priority: string }[]>(summary?.tasks, [])
|
||||
const commitments = safeParse<{ description: string; responsible: string; dueDate: string; status: string }[]>(summary?.commitments, [])
|
||||
const decisions = safeParse<string[]>(summary?.decisions, [])
|
||||
const keyPoints = safeParse<string[]>(summary?.keyPoints, [])
|
||||
|
||||
## 📜 Registro Completo de Sesiones
|
||||
`
|
||||
const entry = `---
|
||||
|
||||
// ─── Block 2: Session entry (appended) ─────────────────
|
||||
## 📍 Sesión: ${session.date} — ${session.title}
|
||||
|
||||
const decisionsMd = extraction.decisions.map(d => `- ${d}`).join('\n')
|
||||
const keyPointsMd = extraction.keyPoints.map(k => `- ${k}`).join('\n')
|
||||
|
||||
const sessionEntry = `---
|
||||
|
||||
## 📍 Sesión ${sessionCount}: ${extraction.sessionTitle}
|
||||
|
||||
**Archivo fuente:** \`${fileName}\`
|
||||
**Fecha:** ${now}
|
||||
**Archivo fuente:** \`${session.fileName}\`
|
||||
|
||||
### Resumen de la sesión
|
||||
${extraction.summary}
|
||||
${summary?.summary || '_Sin resumen disponible_'}
|
||||
|
||||
### Objetivos de esta sesión
|
||||
${objectives.map(o => `- ${o.isNew ? '🆕 ' : ''}${o.text}`).join('\n') || '_Ninguno_'}
|
||||
|
||||
### Tareas identificadas en esta sesión
|
||||
${extraction.pendingTasks.map(t => `- [ ] ${t.description} (_${t.priority}_)`).join('\n') || '_Ninguna_'}
|
||||
${tasks.map(t => `- [ ] ${t.description} (_${t.priority}_)`).join('\n') || '_Ninguna_'}
|
||||
|
||||
### Compromisos de esta sesión
|
||||
${commitments.map(c => `- ${c.description} → ${c.responsible} (${c.dueDate}) [${c.status}]`).join('\n') || '_Ninguno_'}
|
||||
|
||||
### Decisiones tomadas
|
||||
${decisionsMd || '_Ninguna_'}
|
||||
${decisions.map(d => `- ${d}`).join('\n') || '_Ninguna_'}
|
||||
|
||||
### Puntos clave
|
||||
${keyPointsMd || '_Ninguno_'}
|
||||
${keyPoints.map(k => `- ${k}`).join('\n') || '_Ninguno_'}
|
||||
|
||||
### Transcripción completa
|
||||
|
||||
\`\`\`
|
||||
${transcriptionText}
|
||||
\`\`\`
|
||||
`
|
||||
${session.rawText}
|
||||
\`\`\``
|
||||
|
||||
// ─── Assemble document ─────────────────────────────────
|
||||
|
||||
const previousSessions = previousDoc
|
||||
? previousDoc.markdown.split('---\n\n## 📜 Registro Completo de Sesiones')[1] || ''
|
||||
: ''
|
||||
|
||||
const markdown = `${block1}${previousSessions}\n${sessionEntry}\n`
|
||||
|
||||
const doc: ProjectDoc = {
|
||||
projectId,
|
||||
projectName,
|
||||
updatedAt: now,
|
||||
sessionCount,
|
||||
markdown,
|
||||
parts.push(entry)
|
||||
}
|
||||
|
||||
// Save to Dexie
|
||||
await db.table('project_docs').put(doc)
|
||||
|
||||
return doc
|
||||
return parts.join('\n')
|
||||
}
|
||||
|
||||
function safeParse<T>(json: string | undefined | null, fallback: T): T {
|
||||
if (!json) return fallback
|
||||
try { return JSON.parse(json) as T } catch { return fallback }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { callAI } from '@/services/ai'
|
||||
|
||||
export interface SessionExtraction {
|
||||
sessionDate: string // YYYY-MM-DD
|
||||
sessionTitle: string
|
||||
summary: string
|
||||
objectives: { text: string; isNew: boolean }[]
|
||||
@@ -14,19 +15,21 @@ export interface SessionExtraction {
|
||||
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á el título de la sesión basado en el contenido y fecha
|
||||
2. Extraé un resumen ejecutivo de 2-3 oraciones
|
||||
3. Listá objetivos mencionados, marcando cuáles son NUEVOS vs existentes
|
||||
4. Extraé tareas pendientes con su origen y prioridad (Alta/Media/Baja)
|
||||
5. Identificá compromisos con responsable, fecha límite y estado
|
||||
6. Listá decisiones tomadas durante la sesión
|
||||
7. Detectá tareas completadas (si hay evidencia)
|
||||
8. Incluí puntos clave, bloqueos o descubrimientos
|
||||
9. No inventes información que no esté en la transcripción
|
||||
10. Respondé SOLO con JSON válido
|
||||
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": [
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import db, { type SessionRecord, type SessionSummaryRecord, type ProjectStateRecord } from '@/services/db'
|
||||
export type { SessionRecord, SessionSummaryRecord, ProjectStateRecord }
|
||||
|
||||
// ─── Sessions ─────────────────────────────────────────────
|
||||
|
||||
export async function saveSession(s: Omit<SessionRecord, 'id'>): Promise<number> {
|
||||
return db.sessions.add(s)
|
||||
}
|
||||
|
||||
export async function getSessionsByProject(projectId: number): Promise<SessionRecord[]> {
|
||||
return db.sessions.where('projectId').equals(projectId).reverse().sortBy('date')
|
||||
}
|
||||
|
||||
export async function getSession(id: number): Promise<SessionRecord | undefined> {
|
||||
return db.sessions.get(id)
|
||||
}
|
||||
|
||||
// ─── Session Summaries ────────────────────────────────────
|
||||
|
||||
export async function saveSessionSummary(s: SessionSummaryRecord) {
|
||||
await db.session_summaries.put(s)
|
||||
}
|
||||
|
||||
export async function getSessionSummary(sessionId: number): Promise<SessionSummaryRecord | undefined> {
|
||||
return db.session_summaries.get(sessionId)
|
||||
}
|
||||
|
||||
export async function getSummariesByProject(projectId: number): Promise<SessionSummaryRecord[]> {
|
||||
const sessions = await getSessionsByProject(projectId)
|
||||
const ids = sessions.map(s => s.id!).filter(Boolean)
|
||||
const summaries: SessionSummaryRecord[] = []
|
||||
for (const id of ids) {
|
||||
const s = await getSessionSummary(id)
|
||||
if (s) summaries.push(s)
|
||||
}
|
||||
return summaries
|
||||
}
|
||||
|
||||
// ─── Project State ────────────────────────────────────────
|
||||
|
||||
export async function saveProjectState(s: ProjectStateRecord) {
|
||||
await db.project_state.put(s)
|
||||
}
|
||||
|
||||
export async function getProjectState(projectId: number): Promise<ProjectStateRecord | undefined> {
|
||||
return db.project_state.get(projectId)
|
||||
}
|
||||
|
||||
// ─── Helpers ──────────────────────────────────────────────
|
||||
|
||||
export async function deleteProjectData(projectId: number) {
|
||||
const sessions = await getSessionsByProject(projectId)
|
||||
const ids = sessions.map(s => s.id!).filter(Boolean)
|
||||
await db.sessions.where('projectId').equals(projectId).delete()
|
||||
await db.session_summaries.bulkDelete(ids)
|
||||
await db.project_state.delete(projectId)
|
||||
}
|
||||
|
||||
export async function getSessionCount(projectId: number): Promise<number> {
|
||||
return db.sessions.where('projectId').equals(projectId).count()
|
||||
}
|
||||
@@ -12,8 +12,9 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { analyzeSession, type SessionExtraction } from '@/services/session-analyzer'
|
||||
import { generateProjectDoc, getProjectDoc } from '@/services/project-doc'
|
||||
import { generateMasterDoc } from '@/services/project-doc'
|
||||
import { parseFile } from '@/services/parse-transcription'
|
||||
import { saveSession, saveSessionSummary, saveProjectState, getSessionCount } from '@/services/transcriptions-db'
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -93,12 +94,12 @@ const selectedProject = computed(() =>
|
||||
watch(selectedProjectId, async (id) => {
|
||||
if (!id) return
|
||||
clearAll()
|
||||
const doc = await getProjectDoc(id)
|
||||
if (doc) {
|
||||
docMarkdown.value = doc.markdown
|
||||
docSessionCount.value = doc.sessionCount
|
||||
docUpdatedAt.value = doc.updatedAt
|
||||
parseSessionOffsets(doc.markdown)
|
||||
const count = await getSessionCount(id)
|
||||
docSessionCount.value = count
|
||||
if (count > 0) {
|
||||
const md = await generateMasterDoc(id, selectedProject.value?.name || '')
|
||||
docMarkdown.value = md
|
||||
parseSessionOffsets(md)
|
||||
}
|
||||
}, { immediate: false })
|
||||
|
||||
@@ -273,7 +274,48 @@ async function analyzeAsSession() {
|
||||
parsedText.value,
|
||||
selectedProject.value?.name || '',
|
||||
)
|
||||
|
||||
// 1. Guardar transcripción en BD
|
||||
const now = new Date().toISOString()
|
||||
const sessionId = await saveSession({
|
||||
projectId: selectedProjectId.value,
|
||||
date: result.sessionDate || now.slice(0, 10),
|
||||
title: result.sessionTitle,
|
||||
fileName: parsedFileName.value,
|
||||
fileType: parsedFileName.value.split('.').pop() || 'txt',
|
||||
fileSize: parsedText.value.length,
|
||||
rawText: parsedText.value,
|
||||
processedAt: now,
|
||||
})
|
||||
|
||||
// 2. Guardar resumen de IA en BD
|
||||
await saveSessionSummary({
|
||||
sessionId,
|
||||
summary: result.summary,
|
||||
objectives: JSON.stringify(result.objectives),
|
||||
tasks: JSON.stringify(result.pendingTasks),
|
||||
commitments: JSON.stringify(result.commitments),
|
||||
decisions: JSON.stringify(result.decisions),
|
||||
keyPoints: JSON.stringify(result.keyPoints),
|
||||
modelUsed: settingsStore.modelId,
|
||||
})
|
||||
|
||||
// 3. Consolidar y actualizar project_state
|
||||
await consolidateProjectState(selectedProjectId.value)
|
||||
|
||||
// 4. Regenerar documento MD
|
||||
const md = await generateMasterDoc(selectedProjectId.value, selectedProject.value?.name || '')
|
||||
docMarkdown.value = md
|
||||
docSessionCount.value = await getSessionCount(selectedProjectId.value)
|
||||
docUpdatedAt.value = now.slice(0, 16).replace('T', ' ')
|
||||
parseSessionOffsets(md)
|
||||
docGenerated.value = true
|
||||
|
||||
// 5. Mostrar resultado en UI
|
||||
sessionResult.value = result
|
||||
parsedText.value = ''
|
||||
parsedFileName.value = ''
|
||||
|
||||
} catch (e: any) {
|
||||
sessionError.value = e.message
|
||||
} finally {
|
||||
@@ -281,29 +323,71 @@ async function analyzeAsSession() {
|
||||
}
|
||||
}
|
||||
|
||||
async function consolidateProjectState(projectId: number) {
|
||||
// Reconstruye project_state desde todas las summaries del proyecto
|
||||
const { getSummariesByProject, getProjectState } = await import('@/services/transcriptions-db')
|
||||
const summaries = await getSummariesByProject(projectId)
|
||||
const prev = await getProjectState(projectId)
|
||||
|
||||
const allObjectives: string[] = []
|
||||
const allTasks: { description: string; origin: string; priority: string; status?: string }[] = []
|
||||
const allCommitments: { description: string; responsible: string; dueDate: string; status: string }[] = []
|
||||
let consolidatedSummary = ''
|
||||
|
||||
for (const s of summaries) {
|
||||
const objs = safeParseJSON<{ text: string; isNew: boolean }[]>(s.objectives, [])
|
||||
objs.forEach(o => { if (!allObjectives.includes(o.text)) allObjectives.push(o.text) })
|
||||
|
||||
const tasks = safeParseJSON<{ description: string; origin: string; priority: string }[]>(s.tasks, [])
|
||||
tasks.forEach(t => {
|
||||
const exists = allTasks.find(ex => ex.description === t.description)
|
||||
if (!exists) allTasks.push({ ...t, status: 'pendiente' })
|
||||
})
|
||||
|
||||
const cmts = safeParseJSON<{ description: string; responsible: string; dueDate: string; status: string }[]>(s.commitments, [])
|
||||
cmts.forEach(c => {
|
||||
const exists = allCommitments.find(ex => ex.description === c.description)
|
||||
if (!exists) allCommitments.push(c)
|
||||
})
|
||||
|
||||
if (!consolidatedSummary) consolidatedSummary = s.summary
|
||||
}
|
||||
|
||||
// Preservar estados de tareas existentes (por si se marcaron como completadas)
|
||||
if (prev) {
|
||||
const prevTasks = safeParseJSON<{ description: string; status?: string }[]>(prev.tasks, [])
|
||||
for (const pt of prevTasks) {
|
||||
const match = allTasks.find(t => t.description === pt.description)
|
||||
if (match && pt.status === 'completada') match.status = 'completada'
|
||||
}
|
||||
}
|
||||
|
||||
await saveProjectState({
|
||||
projectId,
|
||||
summary: consolidatedSummary,
|
||||
objectives: JSON.stringify(allObjectives),
|
||||
tasks: JSON.stringify(allTasks),
|
||||
commitments: JSON.stringify(allCommitments),
|
||||
updatedAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
function safeParseJSON<T>(json: string | undefined | null, fallback: T): T {
|
||||
if (!json) return fallback
|
||||
try { return JSON.parse(json) as T } catch { return fallback }
|
||||
}
|
||||
|
||||
async function generateDoc() {
|
||||
if (!sessionResult.value || !selectedProjectId.value || !parsedText.value) return
|
||||
if (!selectedProjectId.value) return
|
||||
docGenerating.value = true
|
||||
|
||||
const prevDoc = await getProjectDoc(selectedProjectId.value)
|
||||
|
||||
try {
|
||||
const doc = await generateProjectDoc(
|
||||
selectedProjectId.value,
|
||||
selectedProject.value?.name || '',
|
||||
sessionResult.value,
|
||||
parsedText.value,
|
||||
parsedFileName.value,
|
||||
prevDoc,
|
||||
)
|
||||
docMarkdown.value = doc.markdown
|
||||
docSessionCount.value = doc.sessionCount
|
||||
docUpdatedAt.value = doc.updatedAt
|
||||
parseSessionOffsets(doc.markdown)
|
||||
const md = await generateMasterDoc(selectedProjectId.value, selectedProject.value?.name || '')
|
||||
docMarkdown.value = md
|
||||
docSessionCount.value = await getSessionCount(selectedProjectId.value)
|
||||
docUpdatedAt.value = new Date().toISOString().slice(0, 16).replace('T', ' ')
|
||||
parseSessionOffsets(md)
|
||||
docGenerated.value = true
|
||||
parsedText.value = ''
|
||||
parsedFileName.value = ''
|
||||
sessionResult.value = null
|
||||
} catch (e: any) {
|
||||
sessionError.value = e.message
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user