Database Schema & Operations Guide (Русский)
Почему SQLite?
Заголовок раздела «Почему SQLite?»OmniRoute выбрал SQLite вместо PostgreSQL/MySQL по нескольким причинам:
| Фактор | SQLite | PostgreSQL |
|---|---|---|
| Развертывание | Встраиваемая БД — отдельный сервер не нужен | Требуется настройка сервера |
| Шифрование | На уровне приложения (AES-256-GCM) | Встроенное TDE |
| Производительность | Быстрее для малых/средних нагрузок | Лучше для огромного числа параллельных операций записи |
| Параллелизм | Режим WAL допускает параллельное чтение | Полноценный MVCC |
| Резервное копирование | Копирование одного файла | pg_dump или снимок файловой системы |
| Вариант использования | Установка для одного пользователя, встраиваемая БД | Многопользовательский SaaS |
Для развертываний с одним пользователем и одним экземпляром (основной вариант использования OmniRoute) SQLite проще и быстрее.
Журналирование WAL
Заголовок раздела «Журналирование WAL»core.ts открывает базу данных в режиме WAL (Write-Ahead Logging — журналирование с упреждающей записью):
db.pragma("journal_mode = WAL");db.pragma("busy_timeout = 2000");db.pragma("synchronous = NORMAL");db.pragma(`cache_size = -${DEFAULT_DATABASE_SETTINGS.optimization.cacheSize}`);WAL допускает параллельное чтение во время записи — это важно для панели мониторинга, которая выполняет запросы одновременно с регистрацией запросов.
Размер кэша по умолчанию составляет 65 536 КиБ (64 МиБ). SQLite интерпретирует отрицательное значение
cache_size как приблизительную верхнюю границу в КиБ и выделяет страницы по мере необходимости.
В разделе Настройки > Система и хранилище > Размер кэша можно указывать целые значения от 1 до
1 000 000 КиБ; при сохранении настройка применяется к активному подключению к базе данных,
а при запуске OmniRoute восстанавливает сохраненное значение.
Расположение базы данных
Заголовок раздела «Расположение базы данных»Файл SQLite хранится по следующему пути:
| ОС | Путь |
|---|---|
| Linux | ~/.omniroute/storage.sqlite |
| macOS | ~/.omniroute/storage.sqlite |
| Windows | %USERPROFILE%\.omniroute\storage.sqlite |
| Docker | /app/data/storage.sqlite (настраивается через DATA_DIR) |
Сопутствующие файлы:
storage.sqlite-wal— журнал упреждающей записиstorage.sqlite-shm— файл общей памятиcall_logs/— артефакты полезной нагрузки запросов (если включено)
Изменение расположения:
DATA_DIR=/custom/path omnirouteАрхитектура доменных модулей
Заголовок раздела «Архитектура доменных модулей»База данных OmniRoute содержит 110 модулей TypeScript верхнего уровня в src/lib/db/. Каждый доменный модуль:
- Управляет одной или несколькими определёнными таблицами
- Экспортирует типизированные CRUD-функции
- Никогда не обращается к таблицам другого модуля
- Использует
getDbInstance()изcore.tsдля доступа к БД
110 модулей БД верхнего уровня
Заголовок раздела «110 модулей БД верхнего уровня»OmniRoute содержит 110 файлов TypeScript верхнего уровня в src/lib/db/. Ниже приведены некоторые из основных модулей; полный список см. в содержимом каталога:
| Модуль | Таблицы | Назначение |
|---|---|---|
providers.ts |
provider_connections |
Регистрация провайдеров по OAuth/API-ключу и учётные данные |
models.ts |
key_value (данные моделей) |
Определения моделей, возможности, цены |
combos.ts |
combos |
Конфигурации комбинированной маршрутизации и порядок |
apiKeys.ts |
api_keys |
Жизненный цикл API-ключей, области доступа, отслеживание квот |
settings.ts |
key_value, api_keys, combos |
Системная конфигурация и общее KV-хранилище |
backup.ts |
— | Операции экспорта/импорта резервных копий |
proxies.ts |
proxy_registry, proxy_assignments, provider_connections |
Конфигурации прокси и правила маршрутизации |
prompts.ts |
prompt_templates |
Многократно используемые шаблоны промптов и управление версиями |
webhooks.ts |
webhooks |
Подписки на вебхуки, управляемые событиями, и журналы |
detailedLogs.ts |
request_detail_logs |
Журналирование аудита для каждого запроса (необязательно, большой объём) |
domainState.ts |
domain_* (5 таблиц) |
Бюджеты доменов, автоматические выключатели, блокировки, цепочки резервирования, история затрат |
registeredKeys.ts |
registered_keys, account_key_limits, provider_key_limits |
Разрешённые API-ключи для MCP/A2A |
quotaSnapshots.ts |
quota_snapshots |
История использования квот |
modelComboMappings.ts |
model_combo_mappings |
Сопоставление моделей с комбинациями по умолчанию |
cliToolState.ts |
cli_tool_state |
Сохраняемое состояние, специфичное для CLI |
encryption.ts |
— | Вспомогательные средства для шифрования/расшифровки полей |
readCache.ts |
— | Кеш в памяти для операций с интенсивным чтением |
secrets.ts |
key_value (зашифрованные записи) |
Зашифрованное хранилище секретов |
stateReset.ts |
— | Очистка/сброс состояния БД для тестирования |
contextHandoffs.ts |
context_handoffs |
Контекст сеанса для передачи управления между агентами |
usage*.ts |
usage_history, call_logs, proxy_logs |
Отслеживание использования |
compression*.ts |
compression_settings, compression_combos |
Конфигурация сжатия |
Границы модулей
Заголовок раздела «Границы модулей»Основное архитектурное правило: модули не обращаются напрямую к таблицам друг друга. Для работы с данными другого модуля импортируйте функцию из этого модуля.
// ❌ НЕПРАВИЛЬНО: прямой SQL-запрос к таблице другого модуляdb.prepare("SELECT * FROM provider_connections").all();
// ✅ ПРАВИЛЬНО: используйте функцию модуля providersimport { listProviders } from "@/lib/db/providers";const providers = await listProviders();Соблюдение этого правила контролируется при проверке кода — статическая проверка отсутствует, но нарушения отмечаются.
Базовая схема (17 таблиц)
Заголовок раздела «Базовая схема (17 таблиц)»core.ts определяет 17 базовых таблиц в SCHEMA_SQL. Они создаются миграцией 001_initial_schema.sql и формируют основную схему.
Основные таблицы (создаются при начальной миграции)
Заголовок раздела «Основные таблицы (создаются при начальной миграции)»| Таблица | Назначение | Ключевые столбцы |
|---|---|---|
provider_connections |
Учётные данные провайдеров (зашифрованы) | id, provider, auth_type, api_key, is_active |
provider_nodes |
Информация о маршрутизации узлов провайдера | id, type, name, base_url, created_at |
key_value |
Универсальное KV-хранилище | namespace, key, value |
combos |
Определения комбинаций маршрутизации | id, name, data, sort_order |
api_keys |
API-ключи для шлюза | id, name, key, machine_id, allowed_models |
db_meta |
Метаданные базы данных | key, value |
usage_history |
Записи об использовании запросов | id, provider, model, tokens_input, tokens_output, timestamp |
call_logs |
Данные запросов и ответы | id, timestamp, status, model, provider, latency_ms |
proxy_logs |
Журналы прокси-запросов | id, timestamp, proxy_type, status, provider |
domain_fallback_chains |
Цепочки провайдеров для моделей | model, chain |
domain_budgets |
Бюджеты расходов для отдельных доменов | api_key_id, daily_limit_usd, warning_threshold, reset_interval |
domain_budget_reset_logs |
История сбросов бюджета | id, api_key_id, reset_interval, previous_spend, reset_at |
domain_cost_history |
Отслеживание затрат по доменам | id, api_key_id, cost, timestamp |
domain_lockout_state |
Состояние ограничения частоты запросов домена | identifier, attempts, locked_until |
domain_circuit_breakers |
Состояние предохранителя для каждого домена | name, state, failure_count, last_failure_time |
semantic_cache |
Кэш ответов LLM | id, signature, model, prompt_hash, response |
quota_snapshots |
Исторические снимки квот | id, provider, connection_id, window_key, remaining_percentage |
Дополнительные таблицы (добавлены последующими миграциями)
Заголовок раздела «Дополнительные таблицы (добавлены последующими миграциями)»Последующие миграции добавляют такие таблицы, как:
cli_tool_state(миграция 011) — состояние инструмента CLI- Таблицы
mcp_*— аудит сервера MCP - Таблицы
a2a_*— состояние задач A2A - Таблицы
usage_*— отслеживание использования - Таблицы
plugin_*— система плагинов skill_executions— история выполнения навыков- Таблицы
memory_*— система памяти - Таблицы
compression_*— система сжатия - Таблицы
webhook_*— журнал доставки вебхуков - Таблицы
acp_*— Agent Client Protocol - Таблицы
oneproxy_*— маркетплейс 1proxy proxy_assignments— привязки областей действия проксиdetailed_call_artifacts— метаданные артефактов журнала вызововquota_alert_history— аудит оповещений о квотахcommand_code_auth_sessions— сеансы OAuth Command Code
Полный список из более чем 30 таблиц находится в src/lib/db/migrations/.
Миграции
Заголовок раздела «Миграции»OmniRoute использует версионированные идемпотентные миграции в src/lib/db/migrations/. Каждая миграция представляет собой отдельный SQL-файл с именем NNN_description.sql.
Именование миграций
Заголовок раздела «Именование миграций»001_initial_schema.sql002_mcp_a2a_tables.sql003_provider_node_custom_paths.sql...021_combo_call_log_targets.sqlКак выполняются миграции
Заголовок раздела «Как выполняются миграции»При запуске migrationRunner.ts:
- Создаёт таблицу
_omniroute_migrations, если она не существует - Запрашивает список уже применённых миграций
- Последовательно применяет все новые миграции, каждую в отдельной транзакции
- Записывает каждую применённую миграцию с временной меткой
// src/lib/db/migrationRunner.ts (упрощённо)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); })(); }}Идемпотентность
Заголовок раздела «Идемпотентность»Миграции должны быть идемпотентными — их повторный запуск не должен приводить к каким-либо изменениям:
-- 004_proxy_registry.sqlCREATE TABLE IF NOT EXISTS proxy_registry ( id TEXT PRIMARY KEY, host TEXT NOT NULL, port INTEGER NOT NULL, ...);Активно используйте конструкции IF NOT EXISTS, IF EXISTS, а также OR IGNORE / OR REPLACE.
Добавление новой миграции
Заголовок раздела «Добавление новой миграции»- Определите следующий номер:
ls src/lib/db/migrations/ | tail -1 - Создайте файл:
NNN_my_change.sql - Используйте безопасный DDL:
CREATE TABLE IF NOT EXISTS,ALTER TABLE ... ADD COLUMN - Осторожно заполните данные: используйте
UPDATE ... WHERE ...для обработки существующих строк - Протестируйте на копии: никогда не запускайте непроверенные миграции в рабочей среде
Пример:
-- 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);Изменения без обратной совместимости (например, удаление столбцов) требуют особой осторожности. OmniRoute НЕ поддерживает откат к предыдущей версии — после применения миграции изменение схемы становится постоянным. Учитывайте это при планировании.
Шифрование хранимых данных
Заголовок раздела «Шифрование хранимых данных»Конфиденциальные поля (ключи API, токены OAuth, строки подключения) шифруются при хранении с использованием AES-256-GCM.
Как это работает
Заголовок раздела «Как это работает»// src/lib/db/encryption.ts (упрощённо)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 };Где это используется
Заголовок раздела «Где это используется»provider_connections.api_key— шифруется на уровне приложенияprovider_connections.access_token,refresh_token,id_token— шифруются на уровне приложения- Записи
key_valueсnamespace = "secrets"— шифруются на уровне приложения proxy_registry.auth— шифруется на уровне приложения (если присутствует)
Ключ шифрования
Заголовок раздела «Ключ шифрования»Ключ шифрования формируется на основе секретной фразы (задаётся через переменную окружения STORAGE_ENCRYPTION_KEY) и соли (хранится в БД). Для расшифровки данных необходимы оба значения.
# Сгенерировать безопасную секретную фразуopenssl rand -hex 32
# Задать в .envSTORAGE_ENCRYPTION_KEY=<ваш-ключ>Критически важно: потеря ключа шифрования означает потерю доступа ко всем зашифрованным данным. Храните резервную копию ключа отдельно от базы данных.
Что НЕ шифруется
Заголовок раздела «Что НЕ шифруется»По соображениям производительности следующие данные хранятся в открытом виде:
- Отображаемые имена провайдеров
- Определения моделей (они и так общедоступны)
- Правила маршрутизации
- Записи об использовании (без персональных данных)
Особенности шифрования (v3.8.16+)
Заголовок раздела «Особенности шифрования (v3.8.16+)»OmniRoute использует migrateLegacyEncryptedString() для прозрачной поддержки двух схем шифрования:
- Устаревшая (до v3.5.0): «шифрование» на основе XOR (не является настоящей криптографией)
- Текущая: AES-256-GCM с корректным IV и тегом аутентификации
Вспомогательная функция миграции обнаруживает устаревший формат и при первом чтении повторно шифрует данные с использованием новой схемы. Это означает, что старую базу данных можно обновить без потери учётных данных.
Кэш чтения
Заголовок раздела «Кэш чтения»Для часто считываемых данных (моделей, провайдеров, настроек) readCache.ts предоставляет кэш в памяти:
// Кэшируется при запуске, сбрасывается при записиconst providers = await getCachedProviders(); // Быстро, из памятиconst fresh = await listProviders(); // Медленно, обращается к БД| Кэшируемая сущность | Ключ кэша | TTL |
|---|---|---|
models |
models:v1 |
До записи |
provider_connections |
providers:v1 |
До записи |
settings |
settings:v1 |
До записи |
combos |
combos:v1 |
До записи |
Кэш сбрасывается при каждой записи в соответствующую таблицу.
Резервное копирование и восстановление
Заголовок раздела «Резервное копирование и восстановление»Резервное копирование вручную
Заголовок раздела «Резервное копирование вручную»# Используйте CLI для создания локальной резервной копииomniroute backup create --name pre-migration
# Или через APIcurl -X PUT http://localhost:20128/api/db-backups \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "pre-migration"}'Файл резервной копии содержит:
- Все таблицы БД (сериализованные в JSON)
- Артефакты журнала вызовов (закодированные в base64, необязательно)
- Настройки и секреты (в зашифрованном виде)
- Конфигурацию плагинов
Восстановление
Заголовок раздела «Восстановление»# Через CLIomniroute restore pre-migration
# Через APIcurl -X POST http://localhost:20128/api/db-backups/restore \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "pre-migration"}'Предупреждение: восстановление перезаписывает всю БД. Сначала остановите все клиенты.
Автоматическое резервное копирование
Заголовок раздела «Автоматическое резервное копирование»# Включите автоматическое ежедневное резервное копирование через CLIomniroute backup auto enable --cron "0 2 * * *" --retention 7Расписание выполняется на стороне сервера фоновой задачей, которая запускается каждые 30 секунд (по умолчанию) и сопоставляет cron-выражение с локальным временем сервера.
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS |
30000 |
Интервал запуска в мс (мин. 5000). Должен быть короче 60 с, чтобы надёжно попадать в минуту, соответствующую cron-выражению. |
Горячее резервное копирование SQLite
Заголовок раздела «Горячее резервное копирование SQLite»Для резервного копирования работающей БД без простоя:
sqlite3 ~/.omniroute/storage.sqlite ".backup /backups/omniroute-hot.db"При этом используется API оперативного резервного копирования SQLite — команду можно безопасно выполнять во время работы OmniRoute.
Настройка производительности
Заголовок раздела «Настройка производительности»Режим WAL
Заголовок раздела «Режим WAL»WAL включён по умолчанию. Для рабочих нагрузок с большим количеством операций записи рекомендуется:
PRAGMA wal_autocheckpoint = 1000; -- Контрольная точка каждые 1000 страницPRAGMA journal_size_limit = 67108864; -- Ограничение WAL в 64 МБИндексы
Заголовок раздела «Индексы»Ключевые индексы для повышения производительности (автоматически создаются миграциями):
idx_models_provider— поиск моделей по поставщикуidx_combo_targets_combo_id— развёртывание целей комбинацииidx_usage_history_api_key_timestamp— аналитика использованияidx_quota_snapshots_api_key_window— отслеживание квотidx_call_logs_timestamp— запросы к журналу вызовов
Чтобы добавить новый индекс, создайте миграцию:
-- 023_add_my_index.sqlCREATE INDEX IF NOT EXISTS idx_my_table_my_column ON my_table(my_column);Ввод-вывод с отображением в память
Заголовок раздела «Ввод-вывод с отображением в память»Для очень больших баз данных (>10 ГБ) размер отображаемой памяти можно настроить с помощью pragma SQLite:
-- Задаётся через pragma SQLite (настройте в core.ts или во время выполнения)PRAGMA mmap_size = 268435456; -- 256 МБУплотнение
Заголовок раздела «Уплотнение»Для длительно работающих экземпляров OmniRoute полезно время от времени выполнять VACUUM:
sqlite3 ~/.omniroute/storage.sqlite "VACUUM;"Запускайте ежемесячно в периоды низкой нагрузки. (Режим WAL снижает необходимость в этом, но не устраняет её полностью.)
Проверка работоспособности
Заголовок раздела «Проверка работоспособности»src/lib/db/healthCheck.ts предоставляет диагностику работоспособности на уровне БД:
Оба метода требуют аутентификации (в противном случае возвращается 401). GET выполняет только диагностику; POST выполняет
ту же проверку с включённым параметром autoRepair.
GET /api/db/health # диагностикаPOST /api/db/health # диагностика + восстановлениеОтветом является DbHealthCheckResult, сформированный функцией runDbHealthCheck()
(src/lib/db/healthCheck.ts):
{ "isHealthy": false, "issues": [ { "type": "broken_reference", "table": "domain_budgets", "description": "Бюджеты доменов ссылались на API-ключи, которых больше не существует.", "count": 2 } ], "repairedCount": 0, "backupCreated": false, "autoRepair": false, "checkedAt": "2026-08-18T09:00:00.000Z", "driver": { "name": "better-sqlite3", "degraded": false }}| Поле | Значение |
|---|---|
isHealthy |
Имеет значение true, если issues пуст. driver никогда не влияет на это значение. |
issues[].type |
Одно из значений: integrity_check_failed, broken_reference, stale_snapshot, invalid_state. |
repairedCount |
Количество строк, восстановленных во время этого запуска; всегда равно 0, если autoRepair имеет значение false. |
backupCreated |
Указывает, была ли создана резервная копия перед восстановлением. |
checkedAt |
Временная метка ISO, общая для запуска и любой созданной им записи о восстановлении. |
driver.name |
Драйвер SQLite, обслуживающий проверяемую базу данных. |
driver.degraded |
Имеет значение true, если записи не сохраняются надёжно в файле базы данных — резервный WASM-драйвер sql.js (с сохранением всего файла целиком) или база данных в памяти. |
Те же данные возвращаются инструментом MCP omniroute_db_health_check.
Выполните PRAGMA integrity_check, чтобы обнаружить повреждения:
sqlite3 ~/.omniroute/storage.sqlite "PRAGMA integrity_check;"# Должно быть выведено: okЕсли команда возвращает что-либо, кроме ok, немедленно прекратите использовать базу данных и восстановите её из резервной копии.
Аварийное восстановление
Заголовок раздела «Аварийное восстановление»Сценарий 1: потерян файл WAL
Заголовок раздела «Сценарий 1: потерян файл WAL»Файл -wal отсутствует, но -shm и основной файл БД не повреждены:
# Автоматическое восстановление при следующем открытииomnirouteЕсли SQLite не может выполнить автоматическое восстановление:
sqlite3 ~/.omniroute/storage.sqlite ".recover" > recovered.sqlsqlite3 recovered.db < recovered.sqlmv recovered.db ~/.omniroute/storage.sqliteСценарий 2: повреждён основной файл БД
Заголовок раздела «Сценарий 2: повреждён основной файл БД»Восстановите его из резервной копии:
omniroute sync pull --merge # или: omniroute backup restore <backup-id>Сценарий 3: потерян ключ шифрования
Заголовок раздела «Сценарий 3: потерян ключ шифрования»Без ключа восстановление невозможно. Зашифрованные поля невозможно прочитать. Повторно добавьте всех провайдеров вручную с новыми учётными данными.
Мера предосторожности: всегда создавайте отдельную резервную копию ключа шифрования, желательно в менеджере паролей или KMS.
Сценарий 4: диск заполнен
Заголовок раздела «Сценарий 4: диск заполнен»SQLite будет возвращать ошибки SQLITE_FULL. Освободите место на диске, затем выполните:
# Выполнить контрольную точку WAL, чтобы освободить местоsqlite3 ~/.omniroute/storage.sqlite "PRAGMA wal_checkpoint(TRUNCATE);"Распространённые операции
Заголовок раздела «Распространённые операции»Просмотр таблицы
Заголовок раздела «Просмотр таблицы»sqlite3 ~/.omniroute/storage.sqlite "SELECT * FROM api_keys LIMIT 5;"Подсчёт строк во всех таблицах
Заголовок раздела «Подсчёт строк во всех таблицах»sqlite3 ~/.omniroute/storage.sqlite <<EOFSELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';EOFСброс (удаление) всех данных
Заголовок раздела «Сброс (удаление) всех данных»# Сначала остановите OmniRouteomniroute stop
# Удалите файл БДrm ~/.omniroute/storage.sqlite*
# Перезапустите приложение (будет повторно создана пустая БД)omnirouteДля выборочного сброса (сохранить провайдеров, удалить данные об использовании):
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');Экспорт отдельной таблицы
Заголовок раздела «Экспорт отдельной таблицы»sqlite3 ~/.omniroute/storage.sqlite <<EOF.mode csv.output api_keys.csvSELECT * FROM api_keys;EOFУстранение неполадок
Заголовок раздела «Устранение неполадок»«База данных заблокирована»
Заголовок раздела ««База данных заблокирована»»Другой процесс удерживает блокировку записи. Выполните одно из следующих действий:
- Дождитесь завершения другого процесса (проверьте с помощью
lsof | grep storage.sqlite) - Завершите другой процесс
- Если проблема сохраняется, перезапустите OmniRoute
«Нарушено ограничение внешнего ключа»
Заголовок раздела ««Нарушено ограничение внешнего ключа»»Модуль домена нарушает ссылочную целостность. Проверьте:
- Потерянные строки в зависимых таблицах
- Каскадные удаления, которые не были распространены
- Недавнюю миграцию, изменившую внешний ключ
Выполните PRAGMA foreign_key_check;, чтобы найти нарушения.
«Недостаточно памяти»
Заголовок раздела ««Недостаточно памяти»»Ввод-вывод SQLite с отображением в память превышает ограничение ОС. Уменьшите объём с помощью директивы pragma SQLite:
PRAGMA mmap_size = 134217728; -- 128 МБ вместо 256 МБИли отключите его:
PRAGMA mmap_size = 0;«Сбой миграции в процессе выполнения»
Заголовок раздела ««Сбой миграции в процессе выполнения»»Миграция выполнялась в транзакции, поэтому изменения должны были откатиться. Если этого не произошло:
- Остановите OmniRoute (чтобы предотвратить дальнейшие попытки)
- Проверьте состояние БД с помощью
sqlite3 - Исправьте вручную частично выполненную миграцию
- Снова запустите OmniRoute (будет выполнена повторная попытка миграции)
Чтобы предотвратить такую ситуацию, всегда сначала тестируйте миграции на копии.
См. также
Заголовок раздела «См. также»- USAGE_QUOTA_GUIDE.md — таблицы использования
- MONITORING_GUIDE.md — мониторинг состояния
- RELEASE_CHECKLIST.md — процесс выпуска
- Исходный код:
src/lib/db/(более 80 файлов, около 25 тыс. строк кода)
HagiCode
HagiCode — агентная среда разработки со структурированными процессами, параллельным выполнением несколькими агентами и интерфейсами Hero Dungeon.
Превращайте идеи в полезное ПО с более умным, быстрым и увлекательным агентным рабочим процессом.

- SmartСтруктурированные процессы превращают намерение в исполнимый путь от идеи до готового изменения.
- EfficientМультиагентные процессы параллельно продвигают исследование, реализацию и проверку.
- FunHero Dungeon делает длительную совместную разработку наглядной и увлекательной.