Database Schema & Operations Guide (Español)
¿Por qué SQLite?
Sección titulada «¿Por qué SQLite?»OmniRoute eligió SQLite en lugar de PostgreSQL/MySQL por varios motivos:
| Factor | SQLite | PostgreSQL |
|---|---|---|
| Despliegue | Integrado — no requiere un servidor separado | Requiere configurar un servidor |
| Cifrado | Capa de aplicación (AES-256-GCM) | TDE integrado |
| Rendimiento | Más rápido para cargas pequeñas/medianas | Mejor para un gran volumen de escrituras simultáneas |
| Concurrencia | El modo WAL permite lecturas simultáneas | MVCC completo |
| Copia de seguridad | Copia de un único archivo | pg_dump o instantánea del sistema de archivos |
| Caso de uso | Instalación por usuario, integrado | SaaS multiinquilino |
Para despliegues de un solo usuario y una sola instancia (el caso de uso principal de OmniRoute), SQLite es más sencillo y rápido.
Registro WAL
Sección titulada «Registro WAL»core.ts abre la base de datos en modo WAL (registro de escritura anticipada):
db.pragma("journal_mode = WAL");db.pragma("busy_timeout = 2000");db.pragma("synchronous = NORMAL");db.pragma(`cache_size = -${DEFAULT_DATABASE_SETTINGS.optimization.cacheSize}`);WAL permite lecturas simultáneas durante las escrituras, algo importante para el panel, que realiza consultas mientras se registran las solicitudes.
El tamaño predeterminado de la caché es de 65,536 KiB (64 MiB). SQLite interpreta un valor negativo de
cache_size como un límite superior aproximado en KiB y asigna páginas según sea necesario.
Configuración > Sistema y almacenamiento > Tamaño de caché acepta valores enteros de 1 a
1,000,000 KiB; al guardar la configuración, esta se aplica a la conexión activa de la base de datos,
y OmniRoute restaura el valor almacenado durante el inicio.
Ubicación de la base de datos
Sección titulada «Ubicación de la base de datos»El archivo SQLite se almacena en:
| SO | Ruta |
|---|---|
| Linux | ~/.omniroute/storage.sqlite |
| macOS | ~/.omniroute/storage.sqlite |
| Windows | %USERPROFILE%\.omniroute\storage.sqlite |
| Docker | /app/data/storage.sqlite (configurable mediante DATA_DIR) |
Archivos complementarios:
storage.sqlite-wal— registro de escritura anticipadastorage.sqlite-shm— archivo de memoria compartidacall_logs/— artefactos de las cargas útiles de las solicitudes (si están habilitados)
Sobrescribir la ubicación:
DATA_DIR=/custom/path omnirouteArquitectura de módulos de dominio
Sección titulada «Arquitectura de módulos de dominio»La base de datos de OmniRoute tiene 110 módulos TypeScript de nivel superior en src/lib/db/. Cada módulo de dominio:
- Gestiona una o más tablas específicas
- Exporta funciones CRUD tipadas
- Nunca accede a las tablas de otro módulo
- Usa
getDbInstance()decore.tspara acceder a la base de datos
Los 110 módulos de base de datos de nivel superior
Sección titulada «Los 110 módulos de base de datos de nivel superior»OmniRoute tiene 110 archivos TypeScript de nivel superior en src/lib/db/. A continuación se muestra una selección de los módulos principales; consulta el listado del directorio para ver la lista completa:
| Módulo | Tablas | Responsabilidad |
|---|---|---|
providers.ts |
provider_connections |
Registro y credenciales de proveedores mediante OAuth/claves de API |
models.ts |
key_value (datos de modelos) |
Definiciones, capacidades y precios de los modelos |
combos.ts |
combos |
Configuraciones y orden de enrutamiento de combos |
apiKeys.ts |
api_keys |
Ciclo de vida, ámbitos y seguimiento de cuotas de las claves de API |
settings.ts |
key_value, api_keys, combos |
Configuración del sistema y almacén KV compartido |
backup.ts |
— | Operaciones de exportación/importación de copias de seguridad |
proxies.ts |
proxy_registry, proxy_assignments, provider_connections |
Configuraciones de proxy y reglas de enrutamiento |
prompts.ts |
prompt_templates |
Plantillas de prompts reutilizables y control de versiones |
webhooks.ts |
webhooks |
Suscripciones y registros de webhooks basados en eventos |
detailedLogs.ts |
request_detail_logs |
Registro de auditoría por solicitud (opcional, de gran volumen) |
domainState.ts |
domain_* (5 tablas) |
Presupuestos de dominio, disyuntores, bloqueos, cadenas de respaldo e historial de costes |
registeredKeys.ts |
registered_keys, account_key_limits, provider_key_limits |
Claves de API incluidas en la lista blanca para MCP/A2A |
quotaSnapshots.ts |
quota_snapshots |
Uso histórico de cuotas |
modelComboMappings.ts |
model_combo_mappings |
Asignación de modelos a combos predeterminados |
cliToolState.ts |
cli_tool_state |
Estado persistente específico de la CLI |
encryption.ts |
— | Utilidades para cifrar/descifrar campos |
readCache.ts |
— | Caché en memoria para operaciones con gran volumen de lecturas |
secrets.ts |
key_value (entradas cifradas) |
Almacenamiento cifrado de secretos |
stateReset.ts |
— | Borrado/restablecimiento del estado de la base de datos para pruebas |
contextHandoffs.ts |
context_handoffs |
Contexto de sesión para la transferencia entre agentes |
usage*.ts |
usage_history, call_logs, proxy_logs |
Seguimiento del uso |
compression*.ts |
compression_settings, compression_combos |
Configuración de compresión |
Límites entre módulos
Sección titulada «Límites entre módulos»Una regla arquitectónica fundamental: los módulos no acceden directamente a las tablas de otros módulos. Para trabajar con los datos de otro módulo, importa la función de ese módulo.
// ❌ INCORRECTO: SQL directo desde otro módulodb.prepare("SELECT * FROM provider_connections").all();
// ✅ CORRECTO: usa la función del módulo de proveedoresimport { listProviders } from "@/lib/db/providers";const providers = await listProviders();Esta regla se aplica mediante la revisión de código: no existe una comprobación estática, pero las infracciones se señalan.
Esquema base (17 tablas)
Sección titulada «Esquema base (17 tablas)»core.ts define las 17 tablas base en SCHEMA_SQL. Estas se crean mediante la migración 001_initial_schema.sql y conforman el esquema principal.
Tablas principales (creadas en la migración inicial)
Sección titulada «Tablas principales (creadas en la migración inicial)»| Tabla | Propósito | Columnas clave |
|---|---|---|
provider_connections |
Credenciales del proveedor (cifradas) | id, provider, auth_type, api_key, is_active |
provider_nodes |
Información de enrutamiento de nodos | id, type, name, base_url, created_at |
key_value |
Almacén KV de propósito general | namespace, key, value |
combos |
Definiciones de combinaciones de enrutamiento | id, name, data, sort_order |
api_keys |
Claves de API para la puerta de enlace | id, name, key, machine_id, allowed_models |
db_meta |
Metadatos de la base de datos | key, value |
usage_history |
Registros de uso de solicitudes | id, provider, model, tokens_input, tokens_output, timestamp |
call_logs |
Cargas útiles y respuestas de las solicitudes | id, timestamp, status, model, provider, latency_ms |
proxy_logs |
Registros de solicitudes del proxy | id, timestamp, proxy_type, status, provider |
domain_fallback_chains |
Cadenas de modelos a proveedores | model, chain |
domain_budgets |
Presupuestos de gasto por dominio | api_key_id, daily_limit_usd, warning_threshold, reset_interval |
domain_budget_reset_logs |
Historial de restablecimientos de presupuesto | id, api_key_id, reset_interval, previous_spend, reset_at |
domain_cost_history |
Seguimiento de costes por dominio | id, api_key_id, cost, timestamp |
domain_lockout_state |
Estado del límite de solicitudes por dominio | identifier, attempts, locked_until |
domain_circuit_breakers |
Estado del disyuntor por dominio | name, state, failure_count, last_failure_time |
semantic_cache |
Caché de respuestas del LLM | id, signature, model, prompt_hash, response |
quota_snapshots |
Instantáneas históricas de cuotas | id, provider, connection_id, window_key, remaining_percentage |
Tablas adicionales (añadidas mediante migraciones posteriores)
Sección titulada «Tablas adicionales (añadidas mediante migraciones posteriores)»Las migraciones posteriores añaden tablas como:
cli_tool_state(migración 011) — estado de la herramienta CLI- Tablas
mcp_*— auditoría del servidor MCP - Tablas
a2a_*— estado de tareas A2A - Tablas
usage_*— seguimiento del uso - Tablas
plugin_*— sistema de complementos skill_executions— historial de ejecución de habilidades- Tablas
memory_*— sistema de memoria - Tablas
compression_*— sistema de compresión - Tablas
webhook_*— registro de entrega de webhooks - Tablas
acp_*— Protocolo de Cliente de Agente - Tablas
oneproxy_*— mercado de 1proxy proxy_assignments— vinculaciones de ámbito del proxydetailed_call_artifacts— metadatos de artefactos del registro de llamadasquota_alert_history— auditoría de alertas de cuotacommand_code_auth_sessions— sesiones OAuth de Command Code
La lista completa de más de 30 tablas se encuentra en src/lib/db/migrations/.
Migraciones
Sección titulada «Migraciones»OmniRoute utiliza migraciones versionadas e idempotentes en src/lib/db/migrations/. Cada migración es un único archivo SQL denominado NNN_description.sql.
Nomenclatura de las migraciones
Sección titulada «Nomenclatura de las migraciones»001_initial_schema.sql002_mcp_a2a_tables.sql003_provider_node_custom_paths.sql...021_combo_call_log_targets.sqlCómo se ejecutan las migraciones
Sección titulada «Cómo se ejecutan las migraciones»Al iniciarse, migrationRunner.ts:
- Crea la tabla
_omniroute_migrationssi no existe - Consulta las migraciones ya aplicadas
- Aplica las migraciones nuevas en orden, cada una dentro de una transacción
- Registra cada migración aplicada con una marca de tiempo
// src/lib/db/migrationRunner.ts (simplificado)export async function runMigrations(db: SqliteDatabase, migrationsDir: string) { const applied = getAppliedMigrations(db); const available = readMigrationFiles(migrationsDir);
for (const migration of available) { if (applied.includes(migration.id)) continue; db.transaction(() => { db.exec(migration.sql); recordAppliedMigration(db, migration.id); })(); }}Idempotencia
Sección titulada «Idempotencia»Las migraciones deben ser idempotentes: ejecutarlas dos veces no debe producir ningún cambio:
-- 004_proxy_registry.sqlCREATE TABLE IF NOT EXISTS proxy_registry ( id TEXT PRIMARY KEY, host TEXT NOT NULL, port INTEGER NOT NULL, ...);Utilice ampliamente las cláusulas IF NOT EXISTS, IF EXISTS y OR IGNORE / OR REPLACE.
Añadir una nueva migración
Sección titulada «Añadir una nueva migración»- Identifique el siguiente número:
ls src/lib/db/migrations/ | tail -1 - Cree el archivo:
NNN_my_change.sql - Utilice DDL seguro:
CREATE TABLE IF NOT EXISTS,ALTER TABLE ... ADD COLUMN - Complete los datos con cuidado: utilice
UPDATE ... WHERE ...para gestionar las filas existentes - Pruébela en una copia: nunca ejecute migraciones sin probar en producción
Ejemplo:
-- 022_add_combo_priority.sqlALTER TABLE combos ADD COLUMN priority INTEGER DEFAULT 100;UPDATE combos SET priority = 100 WHERE priority IS NULL;CREATE INDEX IF NOT EXISTS idx_combos_priority ON combos(priority);Los cambios incompatibles con versiones anteriores (p. ej., eliminar columnas) son complicados. OmniRoute NO admite la reversión a una versión anterior; una vez aplicada una migración, el cambio del esquema es permanente. Planifique en consecuencia.
Cifrado en reposo
Sección titulada «Cifrado en reposo»Los campos sensibles (claves de API, tokens de OAuth y cadenas de conexión) se cifran en reposo mediante AES-256-GCM.
Cómo funciona
Sección titulada «Cómo funciona»// src/lib/db/encryption.ts (simplificado)const key = deriveKeyFromPassphrase(passphrase, salt);const iv = randomBytes(12);const cipher = createCipheriv("aes-256-gcm", key, iv);const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);const authTag = cipher.getAuthTag();return { encrypted, iv, authTag };Dónde se utiliza
Sección titulada «Dónde se utiliza»provider_connections.api_key: cifrado en el nivel de la aplicaciónprovider_connections.access_token,refresh_token,id_token: cifrados en el nivel de la aplicación- Entradas de
key_valueconnamespace = "secrets": cifradas en el nivel de la aplicación proxy_registry.auth: cifrado en el nivel de la aplicación (si está presente)
Clave de cifrado
Sección titulada «Clave de cifrado»La clave de cifrado se deriva de una frase de contraseña (configurada mediante la variable de entorno STORAGE_ENCRYPTION_KEY) y una sal (almacenada en la base de datos). Ambas son necesarias para descifrar los datos.
# Genere una frase de contraseña seguraopenssl rand -hex 32
# Configúrela en .envSTORAGE_ENCRYPTION_KEY=<your-key>Importante: perder la clave de cifrado implica perder el acceso a todos los datos cifrados. Realice una copia de seguridad de la clave por separado de la base de datos.
Qué NO está cifrado
Sección titulada «Qué NO está cifrado»Por motivos de rendimiento, los siguientes elementos se almacenan en texto sin formato:
- Nombres para mostrar de los proveedores
- Definiciones de modelos (ya son públicas)
- Reglas de enrutamiento
- Registros de uso (sin PII)
Consideraciones sobre el cifrado (v3.8.16+)
Sección titulada «Consideraciones sobre el cifrado (v3.8.16+)»OmniRoute utiliza migrateLegacyEncryptedString() para gestionar de forma transparente dos esquemas de cifrado:
- Heredado (anterior a v3.5.0): «cifrado» basado en XOR (no es criptografía real)
- Actual: AES-256-GCM con un IV y una etiqueta de autenticación adecuados
La función auxiliar de migración detecta el formato heredado y vuelve a cifrar los datos con el nuevo esquema durante la primera lectura. Esto significa que puede actualizar una base de datos antigua sin perder las credenciales.
Caché de lectura
Sección titulada «Caché de lectura»Para los datos que se leen con frecuencia (modelos, proveedores y ajustes), readCache.ts proporciona una caché en memoria:
// Almacenado en caché al iniciar; se invalida al escribirconst providers = await getCachedProviders(); // Rápido, en memoriaconst fresh = await listProviders(); // Lento, consulta la BD| Entidad almacenada en caché | Clave de caché | TTL |
|---|---|---|
models |
models:v1 |
Hasta la escritura |
provider_connections |
providers:v1 |
Hasta la escritura |
settings |
settings:v1 |
Hasta la escritura |
combos |
combos:v1 |
Hasta la escritura |
La caché se invalida con cada escritura en la tabla correspondiente.
Copia de seguridad y recuperación
Sección titulada «Copia de seguridad y recuperación»Copia de seguridad manual
Sección titulada «Copia de seguridad manual»# Utilice la CLI para crear una copia de seguridad localomniroute backup create --name pre-migration
# O mediante la APIcurl -X PUT http://localhost:20128/api/db-backups \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "pre-migration"}'El archivo de copia de seguridad incluye:
- Todas las tablas de la BD (serializadas en JSON)
- Artefactos del registro de llamadas (codificados en base64, opcionales)
- Ajustes y secretos (cifrados)
- Configuración de complementos
Restauración
Sección titulada «Restauración»# Mediante la CLIomniroute restore pre-migration
# Mediante la APIcurl -X POST http://localhost:20128/api/db-backups/restore \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "pre-migration"}'Advertencia: La restauración sobrescribe toda la BD. Detenga primero todos los clientes.
Copias de seguridad automatizadas
Sección titulada «Copias de seguridad automatizadas»# Habilite las copias de seguridad diarias automatizadas mediante la CLIomniroute backup auto enable --cron "0 2 * * *" --retention 7La programación se ejecuta en el servidor mediante una tarea en segundo plano que se activa cada 30 segundos (de forma predeterminada) y evalúa la expresión cron según la hora local del servidor.
| Variable | Valor predeterminado | Descripción |
|---|---|---|
OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS |
30000 |
Intervalo de activación en ms (mín. 5000). Debe ser inferior a 60 s para coincidir de forma fiable con el minuto cron. |
Copia de seguridad en caliente de SQLite
Sección titulada «Copia de seguridad en caliente de SQLite»Para realizar una copia de seguridad sin tiempo de inactividad de una BD activa:
sqlite3 ~/.omniroute/storage.sqlite ".backup /backups/omniroute-hot.db"Esto utiliza la API de copia de seguridad en línea de SQLite; es seguro ejecutarlo mientras OmniRoute está en funcionamiento.
Ajuste del rendimiento
Sección titulada «Ajuste del rendimiento»Modo WAL
Sección titulada «Modo WAL»WAL está habilitado de forma predeterminada. Para cargas de trabajo con muchas escrituras, considere:
PRAGMA wal_autocheckpoint = 1000; -- Punto de control cada 1000 páginasPRAGMA journal_size_limit = 67108864; -- Límite de WAL de 64 MBÍndices
Sección titulada «Índices»Índices clave para el rendimiento (creados automáticamente mediante migraciones):
idx_models_provider— búsquedas de modelos por proveedoridx_combo_targets_combo_id— expansión de destinos combinadosidx_usage_history_api_key_timestamp— análisis de usoidx_quota_snapshots_api_key_window— seguimiento de cuotasidx_call_logs_timestamp— consultas de registros de llamadas
Para añadir un índice nuevo, cree una migración:
-- 023_add_my_index.sqlCREATE INDEX IF NOT EXISTS idx_my_table_my_column ON my_table(my_column);E/S asignada en memoria
Sección titulada «E/S asignada en memoria»Para bases de datos muy grandes (>10 GB), la asignación de memoria se puede ajustar mediante una pragma de SQLite:
-- Configurar mediante una pragma de SQLite (ajustar en core.ts o en tiempo de ejecución)PRAGMA mmap_size = 268435456; -- 256 MBCompactación
Sección titulada «Compactación»Las instancias de OmniRoute que se ejecutan durante largos periodos se benefician de ejecutar VACUUM ocasionalmente:
sqlite3 ~/.omniroute/storage.sqlite "VACUUM;"Ejecútelo mensualmente durante periodos de poco tráfico. (El modo WAL reduce la necesidad, pero no la elimina).
Comprobación de estado
Sección titulada «Comprobación de estado»src/lib/db/healthCheck.ts proporciona diagnósticos del estado de la base de datos:
Ambos verbos requieren autenticación (de lo contrario, se devuelve 401). GET solo realiza el diagnóstico; POST ejecuta la
misma comprobación con autoRepair habilitado.
GET /api/db/health # diagnosticarPOST /api/db/health # diagnosticar + repararLa respuesta es el DbHealthCheckResult generado por runDbHealthCheck()
(src/lib/db/healthCheck.ts):
{ "isHealthy": false, "issues": [ { "type": "broken_reference", "table": "domain_budgets", "description": "Los presupuestos de dominio hacían referencia a claves de API que ya no existen.", "count": 2 } ], "repairedCount": 0, "backupCreated": false, "autoRepair": false, "checkedAt": "2026-08-18T09:00:00.000Z", "driver": { "name": "better-sqlite3", "degraded": false }}| Campo | Significado |
|---|---|
isHealthy |
true cuando issues está vacío. driver nunca influye en este valor. |
issues[].type |
Uno de integrity_check_failed, broken_reference, stale_snapshot, invalid_state. |
repairedCount |
Filas reparadas durante esta ejecución; siempre es 0 cuando autoRepair es falso. |
backupCreated |
Indica si se creó una copia de seguridad antes de realizar la reparación. |
checkedAt |
Marca de tiempo ISO compartida por la ejecución y por cualquier nota de reparación que esta escriba. |
driver.name |
Controlador de SQLite que atiende la base de datos comprobada. |
driver.degraded |
true cuando las escrituras no están respaldadas de forma duradera por el archivo de la base de datos: el mecanismo alternativo WASM sql.js (persistencia del archivo completo) o una base de datos en memoria. |
La herramienta MCP omniroute_db_health_check devuelve la misma carga útil.
Ejecute PRAGMA integrity_check para detectar daños:
sqlite3 ~/.omniroute/storage.sqlite "PRAGMA integrity_check;"# Debería mostrar: okSi devuelve cualquier valor distinto de ok, deje de usar la base de datos inmediatamente y restáurela desde una copia de seguridad.
Recuperación ante desastres
Sección titulada «Recuperación ante desastres»Escenario 1: archivo WAL perdido
Sección titulada «Escenario 1: archivo WAL perdido»Falta el archivo -wal, pero -shm y la base de datos principal están intactos:
# Se recupera automáticamente al abrirse de nuevoomnirouteSi SQLite no puede recuperarse automáticamente:
sqlite3 ~/.omniroute/storage.sqlite ".recover" > recovered.sqlsqlite3 recovered.db < recovered.sqlmv recovered.db ~/.omniroute/storage.sqliteEscenario 2: archivo principal de la base de datos dañado
Sección titulada «Escenario 2: archivo principal de la base de datos dañado»Restaure desde una copia de seguridad:
omniroute sync pull --merge # o bien: omniroute backup restore <backup-id>Escenario 3: clave de cifrado perdida
Sección titulada «Escenario 3: clave de cifrado perdida»No es posible recuperar los datos sin la clave. Los campos cifrados no se pueden leer. Vuelva a añadir manualmente todos los proveedores con credenciales nuevas.
Mitigación: Haga siempre una copia de seguridad de la clave de cifrado por separado, preferiblemente en un gestor de contraseñas o KMS.
Escenario 4: disco lleno
Sección titulada «Escenario 4: disco lleno»SQLite devolverá errores SQLITE_FULL. Libere espacio en disco y, a continuación:
# Cree un punto de control del WAL para liberar espaciosqlite3 ~/.omniroute/storage.sqlite "PRAGMA wal_checkpoint(TRUNCATE);"Operaciones comunes
Sección titulada «Operaciones comunes»Inspeccionar una tabla
Sección titulada «Inspeccionar una tabla»sqlite3 ~/.omniroute/storage.sqlite "SELECT * FROM api_keys LIMIT 5;"Contar las filas de todas las tablas
Sección titulada «Contar las filas de todas las tablas»sqlite3 ~/.omniroute/storage.sqlite <<EOFSELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';EOFRestablecer (borrar) todos los datos
Sección titulada «Restablecer (borrar) todos los datos»# Detenga primero OmniRouteomniroute stop
# Elimine el archivo de la base de datosrm ~/.omniroute/storage.sqlite*
# Reinicie (se volverá a crear una base de datos vacía)omniroutePara un restablecimiento selectivo (conservar los proveedores y borrar el uso):
DELETE FROM usage_history WHERE timestamp < datetime('now', '-30 day');DELETE FROM call_logs WHERE timestamp < datetime('now', '-30 day');DELETE FROM proxy_logs WHERE timestamp < datetime('now', '-30 day');Exportar una sola tabla
Sección titulada «Exportar una sola tabla»sqlite3 ~/.omniroute/storage.sqlite <<EOF.mode csv.output api_keys.csvSELECT * FROM api_keys;EOFSolución de problemas
Sección titulada «Solución de problemas»“La base de datos está bloqueada”
Sección titulada «“La base de datos está bloqueada”»Otro proceso mantiene un bloqueo de escritura. Puede:
- Esperar a que finalice el otro proceso (compruebe
lsof | grep storage.sqlite) - Finalizar el otro proceso
- Si el problema persiste, reiniciar OmniRoute
“Error en la restricción de clave externa”
Sección titulada «“Error en la restricción de clave externa”»Un módulo de dominio está infringiendo la integridad referencial. Compruebe:
- Filas huérfanas en tablas dependientes
- Eliminaciones en cascada que no se propagaron
- Alguna migración reciente que haya modificado una clave externa
Ejecute PRAGMA foreign_key_check; para encontrar las infracciones.
“Memoria insuficiente”
Sección titulada «“Memoria insuficiente”»La E/S de SQLite asignada en memoria está superando el límite del sistema operativo. Redúzcala mediante un pragma de SQLite:
PRAGMA mmap_size = 134217728; -- 128MB en lugar de 256MBO desactívela:
PRAGMA mmap_size = 0;“La migración falló a mitad del proceso”
Sección titulada «“La migración falló a mitad del proceso”»La migración se ejecutó dentro de una transacción, por lo que debería haberse revertido. Si no fue así:
- Detenga OmniRoute (para evitar nuevos intentos)
- Compruebe el estado de la base de datos con
sqlite3 - Corrija manualmente la migración parcial
- Vuelva a ejecutar OmniRoute (se reintentará la migración)
Para evitarlo, pruebe siempre las migraciones primero en una copia.
Véase también
Sección titulada «Véase también»- USAGE_QUOTA_GUIDE.md — tablas de uso
- MONITORING_GUIDE.md — supervisión del estado
- RELEASE_CHECKLIST.md — flujo de publicación
- Código fuente:
src/lib/db/(más de 80 archivos, unas 25 000 líneas de código)
HagiCode
HagiCode es un espacio de trabajo de programación con agentes, flujos estructurados, ejecución multiagente y vistas de Hero Dungeon.
Convierte ideas en software útil con un flujo de trabajo con agentes más inteligente, rápido y ameno.

- SmartLos flujos estructurados convierten la intención en un itinerario ejecutable desde la idea hasta la entrega.
- EfficientLos flujos multiagente permiten avanzar en paralelo con la investigación, implementación y revisión.
- FunHero Dungeon hace que las largas sesiones de programación sean visuales y colaborativas.