Sign inSign up

rickicode/axonrouter-web

By rickicode

•Updated about 20 hours ago

Enterprise-grade AI routing gateway — 40+ LLM providers, PostgreSQL 17, OpenAI-compatible API

Image
0

2.1K

rickicode/axonrouter-web repository overview

⁠AxonRouter

docker pull rickicode/axonrouter:latest

Every release is published with an immutable sha-<short> tag, a semver tag on tagged releases, and latest tracking the release branch. ghcr.io/rmz17x/axonrouter carries the identical image as a mirror.


⁠AxonRouter — Enterprise-Grade AI Routing Gateway

Connect all your AI coding agents to 40+ LLM providers with pure PostgreSQL 17 concurrency, dedicated Hono API gateway, and zero file-lock bottlenecks.

Docker Hub License PostgreSQL Docker

⚔ AxonRouter vs 9Router⁠ • šŸš€ Quick Start (Docker)⁠ • šŸ’” Features⁠ • šŸ› ļø Supported Tools⁠ • 🌐 Providers⁠ • šŸ“– Setup⁠


⁠⚔ AxonRouter vs 9Router

AxonRouter is an enterprise-grade, high-concurrency fork of decolua/9router (9Router)⁠. While 9Router targets local single-user developer setups using embedded SQLite (data.sqlite), AxonRouter is purpose-built for heavy multi-agent concurrency, containerized environments, and production deployments.

Fork Lineage: decolua/9router (local SQLite) → rickicode/9router-X → AxonRouter (Pure PostgreSQL 17 SSOT + Dedicated Hono Gateway cluster).

Architectural Component9Router OriginalAxonRouter (Enterprise Edition)
Database EngineSQLite file-based (better-sqlite3 / sql.js) — locks on parallel writesPure PostgreSQL 17 — connection pooling via postgres.js, ACID transactions, zero file locks
API Gateway LayerIntegrated inside Next.js server event loopDedicated Hono API Gateway (gateway/server.js) — multi-worker Node cluster on port 3778
Cache & CooldownsIn-memory Map (unindexed, wipes on reload)In-Memory Speed Layer (memoryStore.js) — TTL keys, owner-token mutexes, zero hot-path DB tax
Usage LoggingMonolithic unpartitioned tablesNative Monthly Range Partitioning (usage_history, request_details) with auto-rolling tables
Failover & RecoveryBasic sequential fallbackCombo Fusion, Difficulty Scoring & Circuit Breaker — negative-availability memoization
Client Error IsolationClient 4xx errors can lock provider accountsStrict 4xx Error Isolation — client errors (400, 404, 413, 499) never freeze upstream accounts
Deployment ModelLocal Single-User CLI / WebDocker Compose Production Stack (Web Dashboard 3777 + Hono Gateway 3778 + PostgreSQL 17)

ā šŸš€ Standalone API Gateway — Built for Speed

The public LLM API (/v1/*) runs in a dedicated Hono gateway process (axonrouter-api, port 3778), fully separated from the dashboard (axonrouter-web, port 3777). Heavy streaming traffic from dozens of concurrent coding agents never contends with the dashboard's event loop.

  • Fast path routing: /v1/chat/completions, /v1/messages, /v1/models, /v1/embeddings, audio/video endpoints.
  • Cluster mode: Spawns worker processes (GATEWAY_WORKERS=4) across CPU cores.
  • Path alias resolution: Integrated @/... module alias resolver (gateway/alias-resolver.mjs, registered at boot) with no bundler/webpack pass.

ā šŸ’” Key Features

  • āœ… Dedicated High-Throughput Hono Gateway — Independent cluster on port 3778 for low-latency streaming
  • āœ… Pure PostgreSQL 17 Backend — Handles high-concurrency multi-agent requests with zero SQLite lock contention
  • āœ… Monthly Range Partitioning — Automatic rolling partition tables for request details and token usage history
  • āœ… In-Memory Speed Layer — Process-local TTL caching for provider cooldowns, model locks, and dead circuits
  • āœ… Universal Protocol Translation — Bidirectional wire translation between OpenAI, Anthropic Claude, Google Gemini, Antigravity, and Kiro
  • āœ… Model Combos & Smart Failover — Automatic failover across subscription, cheap, and free provider accounts
  • āœ… Real-Time Observability — Live console streaming via circular buffer and token consumption analytics
  • āœ… Production Container Ready — Docker Compose stack with automatic image publishing to GHCR

ā šŸ”„ Request Pipeline

Incoming Request (Claude Code, Cursor, Codex, OpenClaw, Cline...)
               │
               ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Port 3778: Dedicated Hono API Gateway (Cluster Mode)       │
│  or Port 3777: Standalone Hono server (Vite SPA build)      │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
               │
               ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  src/sse/services/auth.js                                   │
│  • Provider / combo credential resolution via mutex locks   │
│  • Negative-availability pre-check (fast-fail on exhaustion)│
│  • LKG (Last-Known-Good) route memory                       │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
               │
               ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  open-sse/handlers/chatCore.js                              │
│  • Format detection (OpenAI / Claude / Gemini / Kiro)       │
│  • Bidirectional wire format normalization & translation    │
│  • Upstream dispatch, retry backoff & stream forwarding     │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
        │                             │
        ā–¼                             ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”          ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  PostgreSQL 17   │          │ In-Memory Speed  │
│ (Partitioned DB) │          │ Layer (TTL Maps) │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜          ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

AxonRouter ships as a containerized stack: Docker is required (the installer will offer to install it for you if missing). Running without Docker is supported only for manual local development — see Local Node.js Development⁠.

The production stack orchestrates:

  • axonrouter-api (Dedicated High-Throughput Hono API Gateway): http://localhost:3778
  • axonrouter-web (Dashboard & Management Gateway): http://localhost:3777
  • valkey (official valkey/valkey:8-alpine image — realtime speed layer, no persistence)
  • postgres (PostgreSQL 17 ACID database with healthcheck, optional): internal port 5432 (private to Docker network)

Everything lives in one compose file (docker-compose.yml). Three switches pick the topology:

WhatCommand
Split stack (default)docker compose up -d
Built-in PostgreSQL 17COMPOSE_PROFILES=builtin-db docker compose up -d
Combined — API + web in ONE containerdocker compose --profile combined up -d axonrouter

The combined container runs both servers under one supervisor (docker/entrypoint-combined.mjs): a dead web server fails the container so Docker restarts it, a crashed gateway is restarted within a budget, and SIGTERM reaches both.

All published GHCR images are multi-arch (linux/amd64 + linux/arm64) — the same compose stack works on x86 servers and ARM boxes (Raspberry Pi, Graviton, Ampere).

ā šŸ”„ Auto deploy to GHCR

Every push to main / release (and every v* tag) rebuilds the images and pushes them to GitHub Container Registry:

ImageWhat it runsPorts
rickicode/axonrouter-web:latestWeb Dashboard + Control Plane3777
rickicode/axonrouter-api:latestStandalone Hono API Gateway3778
rickicode/axonrouter:latestCombined — both in one container3777, 3778

Two pipelines publish the same three images, so the registry is correct no matter which remote you push to: GitLab CI (.gitlab-ci.yml, the source of truth) and GitHub Actions (.github/workflows/docker-publish.yml, the mirror). See DOCKER.md⁠ for the required CI variables and the tag policy.

The installer does everything interactively without needing to clone the git repository:

  1. Detects Docker — if missing, prompts Install Docker now? (yes/no) and installs it automatically via get.docker.com.
  2. Downloads docker-compose.yml and .env.example directly from GitHub into ~/AxonRouter. Zero git clone required.
  3. Prompts for Gateway Worker Mode: Choose between Cluster Mode (multi-worker Hono for heavy AI traffic) or Standalone Mode (single process for 1 CPU / low-RAM VPS).
  4. Generates all cryptographic secrets into .env (JWT_SECRET, API_KEY_SECRET, ENCRYPTION_KEY, POSTGRES_PASSWORD, INITIAL_PASSWORD) — press Enter to accept auto-generated values.
  5. Asks Start AxonRouter now? (yes/no) and launches the stack with docker compose up -d using pre-built multi-arch GHCR images.
curl -sSL https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/install.sh | sh
⁠Where does it install? (docker-compose.yml location)

The default install path is ~/AxonRouter (your home directory) — wherever you run the command. Pass an explicit path as the first argument to override it:

EnvironmentCommandResulting compose file
Default (any OS user)run the installer~/AxonRouter/docker-compose.yml
Custom locationcurl … | sh -s -- /your/path/your/path/docker-compose.yml

Default example (installs to ~/AxonRouter):

curl -sSL https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/install.sh | sh
⁠Windows

Native PowerShell installer (recommended — installs Docker Desktop via winget if missing, generates secrets, starts the stack):

irm https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/install.ps1 | iex
  • Default location: C:\Users\<you>\AxonRouter\docker-compose.yml
  • Custom location: & ([scriptblock]::Create((irm https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/install.ps1))) -Path D:\AxonRouter
  • Alternative (WSL2): run the Linux one-liner inside WSL → \\wsl$\<distro>\home\<user>\AxonRouter\docker-compose.yml
ā šŸ”‘ Port & Endpoint Reference
PortServiceDeskripsi & Contoh URL
3777Web Dashboard & Control Planehttp://localhost:3777 (manajemen router, provider API keys, proxy pool, metrics)
3778High-Throughput Hono API Gateway (/v1)Endpoint cepat multi-worker untuk AI agent (Cursor, Claude Code, Cline):
• http://localhost:3778/v1/chat/completions (OpenAI format)
• http://localhost:3778/v1/messages (Anthropic format)
• http://localhost:3778/v1/models (Daftar model aktif)

Base URL Klien: Untuk menghubungkan Cursor, Claude Code, Cline, atau SDK OpenAI, arahkan Base URL ke: http://localhost:3778/v1

ā šŸ”„ Reset Password Dashboard

Jika Anda lupa password dashboard, Anda bisa meresetnya kapan saja dengan perintah satu baris:

  • Linux / macOS:
    # Reset ke default (12345677):
    curl -sSL https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/reset-password.sh | sh
    
    # Atau reset ke password baru pilihan Anda:
    curl -sSL https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/reset-password.sh | sh -s -- "password_baru_anda"
    
  • Windows (PowerShell):
    irm https://raw.githubusercontent.com/rickicode/AxonRouter/main/scripts/reset-password.ps1 | iex
    
⁠Start or manage the stack later

All compose commands run from the install directory:

cd ~/AxonRouter          # default install location
docker compose up -d      # start
docker compose ps         # status
docker compose logs -f    # logs
docker compose down       # stop
⁠Option 2: Manual Setup

1. Install Docker (skip if the installer already offered and you accepted):

curl -sSL https://get.docker.com | sh

2. One-command install (recommended):

sh install.sh

The installer ships inside the image: it pulls rickicode/axonrouter:latest, extracts docker-compose.yml + .env.example, generates secrets, and starts the stack. No git clone needed.

Configure .env with your secure secrets (e.g. via openssl rand -hex 32):

  • JWT_SECRET — Session cookie signing key
  • INITIAL_PASSWORD — Initial dashboard admin password
  • API_KEY_SECRET — HMAC secret for gateway tokens
  • POSTGRES_PASSWORD — PostgreSQL database password
  • DATABASE_URL — PostgreSQL connection string

3. Launch Container Stack:

# Run production stack using GHCR images:
docker compose up -d

# Or build locally from source (same compose file):
docker compose build && docker compose up -d

# Or run API + web in ONE container:
docker compose --profile combined up -d axonrouter
⁠Access Services
  • AxonRouter Web Dashboard: http://localhost:3777/dashboard
  • Hono API Gateway Endpoint: http://localhost:3778/v1

⁠🧱 Dual-Process Architecture — Why Ports 3777 and 3778

AxonRouter intentionally separates the web dashboard and the public LLM API into two independent processes:

AspectDashboard (Port 3777)API Gateway (Port 3778)
ProcessHono server serving the Vite SPA (dist/)Standalone Hono multi-worker cluster
Entryserver.js → src/server/webServer.mjsgateway/server.js
PurposeManagement UI, settings, live observabilityHigh-throughput /v1/* inference routing
ConcurrencySingle Node event loopNode cluster across CPU cores (GATEWAY_WORKERS)
Failure isolationDashboard restart never drops live agent streamsGateway crash never kills the dashboard

Advantages of this split:

  • Zero event-loop contention: Dozens of concurrent coding agents streaming SSE never block dashboard renders or admin actions.
  • Independent scaling & restarts: Scale gateway workers or re-deploy the dashboard without dropping active inference traffic.
  • Secure blast radius: Public API keys and streaming load are isolated from session/cookie-based admin UI.
  • Stateless gateway: The gateway reads credentials from PostgreSQL, so any worker can serve any request.

Local Docker networks and agentic workspaces can reach the gateway via container DNS: http://axonrouter-api:3778/v1, or from WSL/VM hosts via http://host.docker.internal:3778/v1.

⁠🌐 Supported Providers (40+)

AxonRouter supports direct credential rotation and wire translation across 40+ providers:

  • Flagship Commercial: OpenAI, Anthropic, Google Gemini / Vertex AI, Azure OpenAI, xAI (Grok), Mistral, Cohere, DeepSeek
  • Inference Platforms: OpenRouter, Groq, Cerebras, Together AI, Fireworks, SiliconFlow, Sambanova, Chutes, Hyperbolic, Nebius
  • Coding Assistants & Subscriptions: Antigravity, Kiro AI, Codex, Qoder, CodeBuddy (CN/Intl), WorkBuddy, Trae, Windsurf, Devin CLI, Zed
  • Chinese Cloud Providers: GLM (Zhipu), Minimax, Kimi (Moonshot), Baidu Qianfan, Alibaba Bailian / Tongyi, Tencent Hunyuan, BytePlus
  • Local & Self-Hosted: Ollama, Local Device, Self-hosted STT/TTS/Embedding engines

ā šŸ“– Setup Guide & Local Development

docker compose up -d
⁠Local Node.js Development

Mode manual — hanya untuk pengembangan lokal. Produksi berjalan dengan Docker saja. Membutuhkan Node.js 22+ dan PostgreSQL 17 yang sudah berjalan:

# 1. Install dependencies
npm install

# 2. Configure environment
cp .env.example .env
# Set DATABASE_URL=postgres://axonrouter:password123@localhost:5432/axonrouter

# 3. Start development servers
npm run server            # Web + API server on port 3777 (run `npm run build` first)
npm run dev               # Vite dev UI on port 5173, proxying /api and /v1 to :3777
node gateway/server.js    # Standalone Hono Gateway on port 3778

ā šŸ“„ License

AxonRouter is open-source software licensed under the MIT License⁠.


⁠Changelog

⁠v0.1.24 (2026-10-25)

⁠Fixes

  • Credentials export is actually served in production (src/app/api/credentials/export/route.js). The TypeScript route (added in 7de8177) was invisible to src/server/routeLoader.mjs, which only loads route.js files, so GET /api/credentials/export fell through to the SPA fallback 404 even though the file shipped in the image. This adds the production-served route.js twin. Its auth verifies the live dashboard JWT session (verifyDashboardAuthToken) instead of the .ts version's PASETO check — the paseto package is not installed and the login issues JWT HS256 cookies, so the PASETO check could never validate a real session. The audit-log line is skipped (audit/settings modules are .ts-only); remote callers always need a valid dashboard cookie.

⁠v0.1.23 (2026-10-25)

⁠Fixes

  • A dead proxy subscription no longer retries every minute forever (open-sse/services/proxyAutoFetcher.js). last_fetched_at is only bumped on a successful fetch, so a group whose fetch_url answers 503 (the BrightData DC link, dead at the source while its sibling ispxx1 still answers 200) stayed permanently "due": 1440 failed fetches a day, each an HTTP call plus a DB round-trip and a fresh log line — 50% of all log output, and the source of every EHOSTUNREACH/CONNECT_TIMEOUT on the Postgres host. Failures now back off 1m → 2m → 4m … capped at the group's own interval (never below 30m) and log once per distinct error message, with an explicit recovery line when the fetch works again. The group keeps its existing pools while the feed is down; health sweeps still test them.
  • The background token refresher no longer chases providers that cannot refresh (open-sse/services/tokenRefresh.js, tokenRefresh/providers.js, src/sse/services/backgroundTokenRefresh.js). qoder accepts only a long-lived personal access token and exposes no token endpoint, so every 60s tick selected its connection and re-fired refreshAccessToken, which could only answer No refresh URL configured — 192 warnings in 6 hours for one connection. Selection now requires isRefreshableProvider() (a dedicated handler, or a resolvable refresh URL). The provider's own warning stays for the on-request path, where it is genuinely actionable.
  • request_details retention constant aligned (src/lib/db/repos/requestDetailsRepo.js). The repo's fallback cap said 200 while DEFAULT_SETTINGS.observabilityMaxRecords said 1000, so the effective row window depended on whether a settings row existed — and a prune that was working correctly looked broken (1001 rows instead of 200). Both are 1000 now, documented as a row window (roughly the last 3–4 hours at current traffic), not a time window; long-range analytics belong to usage_history.
  • Difficulty decisions report the classifier hop that actually answered (open-sse/services/combo.js, open-sse/services/jevUpstream.js). A chain answered by a judge hop was logged as tier=<x> (jev), hiding which classifier ran, and a judge-only chain logged 0 of 2 upstream(s) usable on every request even while classifying correctly.

⁠Tests

  • background-token-refresh gains a regression case for a personal-access-token provider being skipped (qoder vs grok-cli); bg-refresh-disable-dead mock updated for the new selector gate. 47 tests green across the five affected files.

Tag summary

Content type

Image

Digest

sha256:802fc8b87…

Size

116.7 MB

Last updated

about 20 hours ago

docker pull rickicode/axonrouter-web