Skip to main content

Base de datos

PostgreSQL con la extensión pgvector. ORM y migraciones con Drizzle. Los schemas viven junto a cada módulo (src/**/*.schema.ts) y se re-exportan desde el barrel src/database/db.schema.ts.

Tablas

memory_embeddings — correcciones (flywheel)

Lecciones validadas por supervisores; se recuperan por RAG en llamadas futuras.

ColumnaTipoNotas
idTEXT PKSHA-256 del complaint (lowercase, trim) → idempotente
embeddingvector(1536)HNSW cosine
customer_complaintTEXTQueja original
wrong_answer_botTEXTRespuesta incorrecta del bot
human_correctionTEXTCorrección del supervisor
supervisor_idTEXTQuién corrigió
categoryTEXTfeedback_wrong | feedback_approved | general
call_idTEXTLlamada de origen
created_atTIMESTAMPTZ

knowledge_base — manuales técnicos

Chunks de los manuales de equipos. Ver RAG → Ingesta.

ColumnaTipoNotas
idTEXT PKSHA-256 de source::section::rowKey → idempotente
sourceTEXTRuta del .md dentro de documentation/manuals/
categoryTEXTCarpeta de primer nivel (ej. concentradores electricos, cap)
titleTEXTH1 del manual
sectionTEXTH2 de la sección
contentTEXTTexto del chunk
embeddingvector(1536)HNSW cosine
created_atTIMESTAMPTZ

call_sessions — sesiones persistidas

Se escribe al terminar la llamada. Fuente del historial y del teléfono en los logs.

ColumnaTipoNotas
idTEXT PKcall_id de Retell o FreeSWITCH
caller_idTEXTNúmero o nombre del llamante
agent_idTEXTAgente que atendió
transcriptJSONB{ speaker, text }[]
suggestionsJSONBSugerencias generadas
sourceTEXTretell | audio_fork
started_at / ended_atTIMESTAMPTZ

feedback — acciones del supervisor

Una fila por marca sobre una sugerencia. Alimenta /feedback/stats y el flywheel.

ColumnaTipoNotas
idBIGSERIAL PK
call_id / agent_id / suggestion_idTEXTsuggestion_id = {call_id}_{turn}
actionTEXTused | correct | wrong | flagged_wrong | discarded | edited
suggestion_text / edited_textTEXTOriginal / corrección
flag_mode / flag_reasonTEXTOpcionales
created_atTIMESTAMPTZ

event_log — logging estructurado + auditoría

Store append-only de todos los eventos operativos y de usuario. Ver Observabilidad.

Migraciones (Drizzle)

Regla de oro: nunca editar a mano los .sql ni drizzle/meta/_journal.json. Siempre generar con db:generate, que fija el when con el timestamp actual.

# 1. Modificar el schema en src/**/*.schema.ts
# 2. Generar la migración (crea el .sql y actualiza _journal.json)
pnpm db:generate
# 3. Revisar el SQL en drizzle/XXXX_nombre.sql
# 4. Aplicar en local
pnpm db:migrate
# 5. Commitear drizzle/ junto con el cambio de schema
ComandoQué hace
pnpm db:generateGenera SQL de migración desde cambios del schema (no toca la DB)
pnpm db:migrateAplica migraciones pendientes en la DB local (lee .env)
pnpm db:migrate:prodIgual pero contra producción (lee .env.prod)
pnpm db:pushPush directo del schema sin migración (solo dev)
pnpm db:studioDrizzle Studio (explorador visual)
Enums: ALTER TYPE ... ADD VALUE

Agregar un valor a un enum de Postgres (ej. un nuevo tipo de evento) va en su propia migración y no puede usarse en la misma transacción en que se crea. Drizzle lo separa con breakpoints; si db:migrate se queja de "unsafe use of new value", dividir el ADD VALUE en una migración aparte de las columnas que lo usen.

Timestamps de migraciones

Drizzle solo corre migraciones cuyo when sea mayor al último created_at en __drizzle_migrations. Si una migración se saltea en prod, verificar su when en _journal.json contra SELECT MAX(created_at) FROM __drizzle_migrations.

En producción (DigitalOcean) las migraciones corren como job pre-deploy automáticamente; ver Operaciones → Despliegue.