Sign inSign up

rickicode/axonrouter-api

By rickicode

•Updated about 16 hours ago

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

Image
0

1.5K

rickicode/axonrouter-api 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.19 (2026-10-24)

⁠Features

  • Free.ai is now a first-class provider (open-sse/providers/registry/freeai.js). api.free.ai is registered as an official provider (id: freeai, aliases: ["free"]) with a built-in transport (https://api.free.ai/v1/chat/completions, validate https://api.free.ai/v1/models) and the 7 verified free chat models as a seed — qwen7b, qwen3-8b, qwen-coder, qwen3-coder, deepseek-r1, deepseek-r1-7b, mistral (passthroughModels accepts the rest). Connections are now added by API key only, no hand-entered custom baseUrl. The live /v1/models catalogue uses a non-standard {models:[...]} shape, so there is no modelsFetcher. aliases: ["free"] preserves the legacy free/<model> prefix so existing combos keep routing.
  • Migrated existing Free.ai connections to the official provider. The openai-compatible-chat-freeai custom-URL connections were repointed to provider = freeai (custom baseUrl/nodeName removed); the legacy free/ prefix and any freeai/ references resolve to the same connections.

⁠v0.1.18 (2026-10-24)

⁠Fixes

  • Client retry crash on upstream 30-min Retry-After fixed (open-sse/utils/error.js, open-sse/config/errorConfig.js). AxonRouter relayed an upstream retryAfter hint verbatim into its own Retry-After header. A broker 402 like broker GNK reserve exhausted carrying retryAfter: 1800 (30 min) reached clients whose own retry cap is lower (OpenAI Node SDK default maxDelayMs = 90s), which then threw Provider requested 1800000ms wait, exceeds retry.maxDelayMs (90000ms) instead of backing off. unavailableResponse now clamps the relayed Retry-After to MAX_RELAY_RETRY_AFTER_S = 90, so the hint stays within typical client retry caps and never crashes the caller — the upstream's real reset is still tracked internally for AxonRouter's own cooldowns.
  • reserve exhausted classified as capacity, not a payment fault (open-sse/config/errorConfig.js). A broker-side reserve outage (broker GNK reserve exhausted, etc.) is now matched by a text rule (reserve exhausted) → modelWide 15-min cooldown, shouldFallback: true, lockAll: false. Previously it fell through to the bare status: 402 billing rule; now accounts are never locked (every account on the provider shares the same broker reserve, so locking is wrong) and the model is parked provider-wide so the fleet stops re-hitting the dead broker.
  • Shared-broker 402 no longer marks each account terminally exhausted (src/sse/handlers/chat.js, src/domain/accountExhaustionProviders.js). The chat handler treated ANY 402 as account-wide credit death via markAccountExhaustedFromCredits, and the credit-quota regex matched the word "exhaust" — so a broker GNK reserve exhausted 402 marked every gonka account exhausted in lockstep (they share one broker reserve), making "many accounts" useless until each was manually reset. A new isSharedReserveExhaustion guard skips the terminal mark; the 402 now rides a transient model/broker cooldown bounded by the broker's own retryAfter hint instead.

Tag summary

Content type

Image

Digest

sha256:daeb4c28b…

Size

109.4 MB

Last updated

about 16 hours ago

docker pull rickicode/axonrouter-api