How the OmniRoute Version Manager Handles Live Updates and Rollback
OmniRoute's Version Manager enables safe, zero-downtime live upgrades and controlled rollbacks for auxiliary tools through database-persisted state, process orchestration, and version pinning.
The OmniRoute Version Manager is a core subsystem designed to manage the lifecycle of external tools like 9router and cliproxy. According to the diegosouzapw/OmniRoute source code, it combines a SQLite-backed state store with runtime process management to support live version updates without server restarts and instant rollback via pinned versions.
Core Architecture
The Version Manager operates through five integrated layers:
| Component | Key File | Responsibility |
|---|---|---|
| Database layer | src/lib/db/versionManager.ts |
Schema and CRUD operations for the version_manager_tools table |
| Process manager | src/lib/versionManager/processManager.ts |
Runtime orchestration: start, stop, pin, unpin |
| Service façade | src/lib/versionManager/index.ts |
Public API exports for route handlers |
| Bootstrap controller | src/lib/services/bootstrap.ts |
Reads persisted state on startup to launch correct versions |
| Tool installers | src/lib/services/installers/*.ts |
Binary download and version resolution logic |
The version_manager_tools table persists one row per tool with these critical fields:
installedVersion— the currently active binary versionpinnedVersion— optional override forcing a specific versionstatus—running,stopped, ornot_installedlastStartedAt/lastSyncAt— timestamps for health tracking
Live Updates: Zero-Downtime Version Swaps
OmniRoute applies updates through a database-driven state machine. The server does not require restart to activate new versions.
Step 1: API Request and Validation
Clients trigger updates via the Version Manager endpoint. The request body is validated by Zod in src/app/api/version-manager/request.ts:
// Example payload for live update
{
tool: "cliproxy",
installedVersion: "2.1.0",
status: "running"
}
Step 2: Persist State Change
The updateVersionManagerTool function in src/lib/db/versionManager.ts writes the new version and status to the database row. This function is exported alongside upsertVersionManagerTool, getVersionManagerTool, and deleteVersionManagerTool from the same file.
Step 3: Process Manager Reaction
The process manager (processManager.ts) monitors the database state. When installedVersion changes, it:
- Gracefully terminates the running tool process
- Spawns the binary matching the new version
- Records the PID and updates
lastStartedAt
Step 4: Health Confirmation
A background sync task (src/lib/services/modelSync.ts) periodically calls updateVersionManagerTool with fresh lastSyncAt timestamps, confirming the tool remains healthy.
// Direct database update for live version change
import { updateVersionManagerTool } from '@/lib/db/versionManager'
await updateVersionManagerTool('cliproxy', {
installedVersion: '2.0.0',
status: 'running',
lastStartedAt: new Date().toISOString()
})
Rollback Mechanism: Version Pinning
Rollback is controlled through the pinnedVersion field, which overrides any newer installedVersion on restart or health-check failure.
Pinning a Version
The pinToolVersion function in processManager.ts sets pinnedVersion in the database:
// Force cliproxy to run version 1.4.2 regardless of installedVersion
await updateVersionManagerTool('cliproxy', {
pinnedVersion: '1.4.2',
status: 'running'
})
Resolver Logic in Bootstrap
When src/lib/services/bootstrap.ts initializes a tool, it checks pinnedVersion first:
- If
pinnedVersionexists → force that version - If
pinnedVersionisnull→ useinstalledVersion - If neither exists → trigger installer to fetch latest
Unpinning to Resume Auto-Upgrade
Clearing the pin restores normal upgrade behavior:
// Remove version lock
await updateVersionManagerTool('cliproxy', {
pinnedVersion: null
})
Automatic Fallback on Failure
Tool installers in src/lib/services/installers/cliproxy.ts and similar files implement defensive logic: if a health check fails or the binary crashes, the installer consults pinnedVersion (if set) or falls back to the last known good installedVersion recorded in the database.
API Examples
Live Update via cURL
# Upgrade cliproxy to v2.0.0 immediately
curl -X PATCH https://omniroute.example.com/api/v1/version-manager \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"tool":"cliproxy","installedVersion":"2.0.0","status":"running"}'
Rollback via cURL
# Pin to older version for instant rollback
curl -X PATCH https://omniroute.example.com/api/v1/version-manager \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"tool":"cliproxy","pinnedVersion":"1.4.2"}'
Key Source Files
| File Path | Purpose |
|---|---|
src/lib/db/versionManager.ts |
Database schema and CRUD: upsertVersionManagerTool, updateVersionManagerTool, getVersionManagerStatus |
src/lib/versionManager/processManager.ts |
Runtime orchestration with setToolStatus, pinToolVersion, unpinToolVersion |
src/lib/versionManager/index.ts |
Public façade exporting all Version Manager functions |
src/lib/services/bootstrap.ts |
Startup routine reading tool state from database |
src/app/api/version-manager/request.ts |
Zod validation schemas for API requests |
src/lib/services/installers/cliproxy.ts |
Example installer respecting pinnedVersion and installedVersion |
src/lib/services/modelSync.ts |
Background health check and timestamp updates |
Summary
- Database-driven state — The
version_manager_toolstable insrc/lib/db/versionManager.tsis the single source of truth for tool versions and status - Zero-downtime updates — Changing
installedVersiontriggers process manager restart without server reload - Controlled rollback — The
pinnedVersionfield forces specific versions, with resolution logic insrc/lib/services/bootstrap.ts - Health monitoring — Background sync tasks confirm tool viability via
lastSyncAttimestamps - API-first design — All operations exposed through validated REST endpoints under
/api/v1/version-manager/
Frequently Asked Questions
What database table stores the Version Manager state?
The version_manager_tools table, defined in the migration files and accessed through src/lib/db/versionManager.ts, stores one row per tool with fields for installedVersion, pinnedVersion, status, and timing metadata.
How does OmniRoute switch versions without restarting the server?
The process manager (src/lib/versionManager/processManager.ts) monitors database changes to installedVersion. When updated, it terminates the current process and spawns the new binary immediately—no server restart required.
What happens if a tool fails health checks?
The bootstrap controller and installer scripts check pinnedVersion first, then fall back to the last successful installedVersion. This automatic recovery logic is implemented in src/lib/services/installers/*.ts files.
Can I pin multiple tools to different versions simultaneously?
Yes. Each tool has its own row in version_manager_tools with an independent pinnedVersion field. Pinning one tool does not affect others.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →