Skip to content

Repository files navigation

Quilonix AI Gateway

Intelligent routing layer for Quilonix Studio — an AI-native coding platform where multiple AI providers connect through a single gateway.

What It Is

Quilonix AI Gateway is a lightweight, modular TypeScript service that sits between Quilonix Studio's frontend and multiple AI coding providers. It provides:

  • Unified API — one endpoint for all providers
  • Smart routing — automatically picks the best provider per request
  • Streaming — consistent SSE interface regardless of upstream format
  • Resilience — circuit breakers, retries, and automatic fallback
  • Security — encrypted credential storage, no telemetry sent externally

Architecture

┌─────────────────────────────────────────────────┐
│              Quilonix Studio (Frontend)          │
└───────────────────────┬─────────────────────────┘
                        │  HTTP / SSE
                        ▼
┌─────────────────────────────────────────────────┐
│           Quilonix AI Gateway                    │
│                                                  │
│  ┌─────────┐  ┌────────┐  ┌──────────────────┐ │
│  │   API   │→ │ Router │→ │  Request Pipeline │ │
│  └─────────┘  └────────┘  └──────────────────┘ │
│       │            │               │            │
│  ┌─────────┐  ┌────────┐  ┌──────────────────┐ │
│  │Sessions │  │Circuit │  │   Stream Manager  │ │
│  │         │  │Breaker │  │                   │ │
│  └─────────┘  └────────┘  └──────────────────┘ │
│                                                  │
│  ┌────────────── Connector Registry ───────────┐│
│  │ OpenAI │ Ollama │ OpenRouter │ ... more ... ││
│  └─────────────────────────────────────────────┘│
└─────────────────────────────────────────────────┘

Quick Start

# Install dependencies
npm install

# Development (with hot reload)
npm run dev

# Build for production
npm run build

# Run production build
npm start

# Run tests
npm test

The gateway starts at http://127.0.0.1:4190 by default.

API Endpoints

Method Path Description
POST /chat Chat completion (non-streaming)
POST /stream Chat completion (SSE streaming)
DELETE /stream/:id Cancel an active stream
GET /models List available models
GET /providers List providers and status
POST /providers/connect Connect a provider
POST /providers/disconnect Disconnect a provider
GET /tools List available tools
POST /tools/execute Execute a tool
POST /sessions Get/create a workspace session
GET /sessions/:id/conversations List conversations
POST /sessions/:id/conversations Create a conversation
GET /health Gateway health check

Configuration

Environment variables (all optional):

Variable Default Description
QUILONIX_PORT 4190 Server port
QUILONIX_HOST 127.0.0.1 Bind address
QUILONIX_LOG_LEVEL info Log level
QUILONIX_ENCRYPTION_KEY 32+ char key for credential encryption
QUILONIX_ROUTING_STRATEGY fallback-chain Default routing strategy
QUILONIX_PREFERRED_PROVIDER Preferred provider ID
QUILONIX_HEALTH_CHECK_INTERVAL 30000 Health check interval (ms)
QUILONIX_WORKSPACE_ROOT cwd Sandbox root for filesystem/terminal tools

Per-provider base URLs and OAuth client IDs are also configurable — see .env.example.

Project Structure

src/
├── main.ts                          # Entry point
└── packages/
    ├── api/                         # HTTP routes (Hono)
    │   ├── app.ts                   # App factory
    │   └── routes/                  # Route handlers
    ├── auth/                        # Authentication & credentials
    │   ├── auth-manager.ts          # Auth orchestration
    │   ├── credential-store.ts      # Encrypted credential storage
    │   └── strategies/              # Pluggable auth strategies
    │       ├── api-key.strategy.ts
    │       ├── oauth.strategy.ts
    │       ├── device-auth.strategy.ts
    │       └── session-token.strategy.ts
    ├── config/                      # Configuration & validation
    │   ├── gateway-config.ts        # Config manager
    │   └── schema.ts               # Zod schemas
    ├── connectors/                  # Provider abstraction
    │   ├── connector.interface.ts   # The Connector contract
    │   ├── base-connector.ts        # Shared connector logic
    │   ├── connector-registry.ts    # Connector lookup & lifecycle
    │   ├── openai-compatible.connector.ts  # Reusable base for OpenAI-protocol providers
    │   └── providers/
    │       ├── provider-catalog.ts       # Declarative registry of OpenAI-compatible providers
    │       ├── connector-factory.ts      # Builds & registers all connectors
    │       ├── ollama.connector.ts       # Native protocol: local Ollama
    │       ├── anthropic.connector.ts    # Native protocol: Claude Messages API
    │       └── gemini.connector.ts       # Native protocol: Gemini generateContent
    ├── gateway/                     # Core orchestrator
    │   ├── gateway.ts               # Top-level Gateway class
    │   └── request-pipeline.ts      # Request lifecycle
    ├── logging/                     # Structured logging (pino)
    ├── router/                      # Smart routing engine
    │   ├── router.ts                # Routing strategies
    │   ├── circuit-breaker.ts       # Failure isolation
    │   └── latency-tracker.ts       # Latency-based routing
    ├── sessions/                    # Workspace & conversation state
    ├── shared/                      # Types, errors, event bus
    ├── streaming/                   # Unified streaming
    │   ├── stream-manager.ts        # Stream lifecycle
    │   └── stream-buffer.ts         # Async iterable buffer
    ├── telemetry/                   # Local-only metrics
    └── tools/                       # Unified tool execution layer
        ├── tool-registry.ts         # Registration + provider-agnostic execution
        └── builtin/                 # Sandboxed built-in tools
            ├── filesystem.tools.ts  # read/write/list (workspace-sandboxed)
            └── terminal.tools.ts    # run_command + git status/diff/log

Connectors

Supported Providers (Initial Version)

Provider Auth Strategy Notes
OpenAI Codex API Key OpenAI chat completions API
OpenRouter API Key Unified access to many upstream models
GitHub Copilot Device Auth OAuth device flow (RFC 8628)
Cursor Session Token Captured from Cursor login
Kiro OAuth (paste token) Free Claude-family with monthly credits
Antigravity OAuth browser sign-in Real Google sign-in, zero setup
Windsurf OAuth (paste token) Windsurf/Codeium account token
Continue API Key Routes to configured OpenAI-compatible host
Cline API Key Configurable OpenAI-compatible endpoint
OpenClaw API Key OpenAI-compatible endpoint
Qoder Session Token Free tier (Kimi/DeepSeek family)
Ollama None Local models, no auth (native protocol)
Anthropic (Claude) API Key Native Messages API (/v1/messages)
Google Gemini API Key Native generateContent API

Architecture: Two Connector Types

Most coding providers speak the OpenAI-compatible protocol and differ only in base URL, auth strategy, and model list. These are declared as one-line entries in the provider catalog (providers/provider-catalog.ts) and share a single OpenAICompatibleConnector implementation.

Providers with a native (non-OpenAI) protocol get a dedicated connector class:

  • Ollama — local /api/chat protocol
  • Anthropic (Claude) — native Messages API (/v1/messages, x-api-key, content blocks, named SSE events)
  • Google Gemini — native generateContent API (contents/parts, ?key= auth)

These are registered via NATIVE_CONNECTORS in the connector factory.

Authentication is fully isolated into pluggable strategies:

  • ApiKeyStrategy — static bearer token
  • OAuthStrategy — access token + refresh token rotation
  • DeviceAuthStrategy — OAuth device flow for headless/CLI clients
  • SessionTokenStrategy — session token or cookie from web login

Browser sign-in (zero-setup OAuth)

For OAuth providers, Quilonix mirrors how the official CLIs authenticate: it reuses each tool's real, first-party OAuth client and runs a temporary loopback server on that client's fixed callback port to catch the redirect. No OAuth app registration is required.

Flow (OAuthFlowManager + oauth-provider-config.ts):

  1. Dashboard → POST /auth/oauth/start → gateway starts a loopback server on the provider's port (e.g. Antigravity → localhost:51121/oauth-callback) and returns the provider's authorization URL.
  2. The browser opens it; the user logs in at the real provider (e.g. Google).
  3. The provider redirects to the loopback server, which exchanges the code (PKCE or client-secret per provider) and connects the provider.
  4. Dashboard polls GET /auth/oauth/status until connected.

Verified real configs live in oauth-provider-config.ts: Antigravity (Google client, no PKCE, port 51121) and OpenAI Codex (PKCE, port 1455). Providers without a verified client fall back to token paste, so a broken invalid_client browser flow is never shown.

Adding a New Provider

OpenAI-compatible provider (the common case) — add ONE catalog entry:

// src/packages/connectors/providers/provider-catalog.ts
{
  id: 'my-provider',
  displayName: 'My Provider',
  kind: 'openai-compatible',
  notes: 'API key auth against an OpenAI-compatible endpoint.',
  buildSpec: () => ({
    id: 'my-provider',
    displayName: 'My Provider',
    baseUrl: 'https://api.myprovider.com/v1',
    authStrategy: new ApiKeyStrategy(),
    defaultContextWindow: 128000,
  }),
}

That's it — no request code, no streaming code, no new class. It's built and registered automatically by the connector factory.

Provider with a non-OpenAI protocol — extend BaseConnector:

export class MyConnector extends BaseConnector {
  readonly id = 'my-provider';
  readonly displayName = 'My Provider';
  readonly supportedAuthMethods = ['api-key'];

  protected async onInitialize() { /* setup */ }
  protected async onAuthenticate(creds) { /* validate */ }
  protected async onRefreshSession() { return true; }
  protected async onHealthCheck() { return 'healthy'; }
  protected async onDisconnect() { /* cleanup */ }

  async listModels() { /* ... */ }
  async sendChat(options) { /* ... */ }
  async *streamChat(options) { /* ... */ }
}

Then add it to buildAllConnectors() in connector-factory.ts.

Routing Strategies

Strategy Description
preferred Always use the configured preferred provider
lowest-latency Pick the provider with the lowest observed latency
round-robin Distribute evenly across providers
quality-first Pick by known code-generation quality
fallback-chain Use configured priority order
user-preference Respect user's provider preference

Routing rules can be added programmatically to match on task category, model pattern, or provider availability.

Security

  • Credentials encrypted at rest with AES-256-GCM when QUILONIX_ENCRYPTION_KEY is set
  • No external telemetry — all metrics stay local
  • CORS restricted to configured origins
  • Structured error responses (no stack traces leaked to clients)

Tech Stack

  • Runtime: Node.js ≥ 20
  • Language: TypeScript (strict mode)
  • Framework: Hono (lightweight, web-standards based)
  • Validation: Zod
  • Logging: pino (structured JSON)
  • Testing: Vitest

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages