Skip to content

Releases: TEA-ching/continue

typo keyPoollive !

typo keyPoollive ! Pre-release
Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 24 May 06:16
bbac58f

KeytoolLive with dashboard

Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 23 May 15:48
b11d73d

v1.3.39c-vscode

v1.3.39c-vscode Pre-release
Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 23 May 13:01
4ce2350

v1.3.39b-vscode

v1.3.39b-vscode Pre-release
Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 23 May 10:13
5e670f8

v1.3.39a-vscode

v1.3.39a-vscode Pre-release
Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 07 May 22:04
1af24a8

v1.3.39-vscode

v1.3.39-vscode Pre-release
Pre-release

Choose a tag to compare

@aeltorio aeltorio released this 06 May 15:50
51bea83

KeypoolLive — Shared Encrypted API Key Vault

This fork adds KeypoolLive, a system that loads AI provider API keys from an encrypted vault file hosted at a public URL. Keys are shared across a team, rotated round-robin, and never stored in plain text in version control.

How it works

  1. An AES-256-CBC encrypted vault (ai.json.enc, produced with openssl enc -aes-256-cbc -pbkdf2) is hosted at a URL you control.
  2. Continue fetches and decrypts the vault at startup using a secret you provide.
  3. All models in the vault are injected into the Continue model selector automatically — no manual config.yaml entries per model needed.
  4. Optionally, all requests are routed through a Cloudflare AI Gateway for unified logging, rate limiting, and caching.

Configuration

Add a keypoollive block to ~/.continue/config.yaml:

keypoollive:
  vaultUrl: https://your-host/ai.json.enc # URL of the encrypted vault
  secret: <decryption-secret> # AES decryption passphrase
  useGateway: true # Route via Cloudflare AI Gateway
  gatewaySecret: cfut_xxxxxxxxxxxxxxxxxxxx # cf-aig-authorization token
  gatewayId: <your-cloudflare-gateway-id> # Cloudflare account/gateway ID

All fields can be overridden with environment variables (env takes precedence over YAML):

YAML field Environment variable
vaultUrl KEYPOOL_LIVE_VAULT_URL
secret KEYPOOL_LIVE_SECRET
useGateway KEYPOOL_LIVE_USE_GATEWAY (true/false)
gatewaySecret KEYPOOL_LIVE_GATEWAY_SECRET
gatewayId KEYPOOL_LIVE_GATEWAY_ID

Sample ai.json vault format

{
  "version": 1,
  "providers": {
    "anthropic": {
      "protocol": "anthropic",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "anthropic",
      "endpoint": "https://api.anthropic.com/v1",
      "keys": [
        {
          "key": "sk-ant-api03-EXAMPLE_KEY_1234567890",
          "owner": "john.doe@example.com",
          "type": "free"
        },
        {
          "key": "sk-ant-api03-EXAMPLE_KEY_0987654321",
          "owner": "jane.smith@example.com",
          "type": "paid"
        }
      ],
      "models": [
        {
          "id": "claude-haiku-4-5-20251001",
          "usage": "chat",
          "contextWindow": 200000,
          "maxOutputTokens": 64000,
          "tpmLimit": null,
          "priority": 200,
          "tags": ["fast", "cheap", "code"]
        },
        {
          "id": "claude-sonnet-4-6",
          "usage": "chat",
          "contextWindow": 1000000,
          "maxOutputTokens": 64000,
          "tpmLimit": null,
          "priority": 210,
          "tags": ["code", "large", "reasoning"]
        },
        {
          "id": "claude-opus-4-6",
          "usage": "chat",
          "contextWindow": 1000000,
          "maxOutputTokens": 128000,
          "tpmLimit": null,
          "priority": 220,
          "tags": ["powerful", "large", "reasoning"]
        }
      ]
    },
    "gemini": {
      "protocol": "gemini",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "google-ai-studio",
      "endpoint": "https://generativelanguage.googleapis.com/v1beta",
      "keys": [
        {
          "key": "AIzaSyEXAMPLE_KEY_1234567890",
          "owner": "demo.user@example.com|projects/1234567890",
          "type": "free"
        },
        {
          "key": "AIzaSyEXAMPLE_KEY_0987654321",
          "owner": "test.user@example.com|projects/0987654321",
          "type": "free"
        }
      ],
      "models": [
        {
          "id": "gemini-embedding-2-preview",
          "contextWindow": 8192,
          "maxOutputTokens": 0,
          "tpmLimit": null,
          "priority": 1,
          "usage": "embedding",
          "defaultDimensions": 256,
          "tags": ["embedding"]
        },
        {
          "id": "gemini-3-flash-preview",
          "contextWindow": 1048576,
          "maxOutputTokens": 65536,
          "tpmLimit": null,
          "priority": 104,
          "usage": "chat",
          "tags": ["flash", "powerful", "large"]
        }
      ]
    },
    "groq": {
      "protocol": "openai",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "groq",
      "endpoint": "https://api.groq.com/openai/v1",
      "keys": [
        {
          "key": "gsk_EXAMPLE_KEY_1234567890",
          "owner": "github|demo_user",
          "type": "free"
        },
        {
          "key": "gsk_EXAMPLE_KEY_0987654321",
          "owner": "demo.user@example.com",
          "type": "free"
        }
      ],
      "models": [
        {
          "id": "llama-3.3-70b-versatile",
          "usage": "chat",
          "contextWindow": 131072,
          "maxOutputTokens": 32768,
          "tpmLimit": 12000,
          "priority": 1,
          "tags": ["fast", "code", "large"]
        },
        {
          "id": "llama-3.1-8b-instant",
          "usage": "chat",
          "contextWindow": 131072,
          "maxOutputTokens": 8192,
          "tpmLimit": 6000,
          "priority": 20,
          "tags": ["fast", "cheap"]
        }
      ]
    },
    "mistral": {
      "protocol": "openai",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "mistral",
      "endpoint": "https://api.mistral.ai/v1",
      "keys": [
        {
          "key": "EXAMPLE_KEY_1234567890",
          "owner": "demo.user@example.com|+1234567890",
          "type": "free"
        },
        {
          "key": "EXAMPLE_KEY_0987654321",
          "owner": "test.user@example.com|+0987654321",
          "type": "free"
        }
      ],
      "models": [
        {
          "id": "codestral-latest",
          "usage": "chat",
          "contextWindow": 256000,
          "maxOutputTokens": 256000,
          "tpmLimit": 500000,
          "priority": 60,
          "tags": ["codestral", "small", "code"]
        },
        {
          "id": "mistral-medium-latest",
          "usage": "chat",
          "contextWindow": 128000,
          "maxOutputTokens": 128000,
          "tpmLimit": 500000,
          "priority": 50,
          "tags": ["mistral", "medium", "fast"]
        }
      ]
    },
    "openrouter": {
      "protocol": "openai",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "openrouter",
      "endpoint": "https://openrouter.ai/api/v1",
      "keys": [
        {
          "key": "sk-or-v1-EXAMPLE_KEY_1234567890",
          "owner": "demo.user@example.com",
          "type": "free"
        },
        {
          "key": "sk-or-v1-EXAMPLE_KEY_0987654321",
          "owner": "test.user@example.com",
          "type": "free"
        }
      ],
      "models": [
        {
          "id": "qwen/qwen3.5-flash-02-23",
          "usage": "chat",
          "contextWindow": 131072,
          "maxOutputTokens": 65536,
          "tpmLimit": null,
          "priority": 150,
          "tags": ["openrouter", "qwen", "chat"]
        },
        {
          "id": "qwen/qwen3-coder:free",
          "usage": "chat",
          "contextWindow": 262000,
          "maxOutputTokens": 262000,
          "tpmLimit": null,
          "priority": 80,
          "tags": ["openrouter", "qwen", "chat"]
        }
      ]
    },
    "sambanova": {
      "protocol": "openai",
      "gatewayEndpoint": "https://gateway.ai.cloudflare.com/v1/cloudflare_account_id/default/compat",
      "gatewayModelPrefix": "custom-sambanova",
      "endpoint": "https://api.sambanova.com/v1",
      "keys": [
        {
          "key": "EXAMPLE_KEY_1234567890",
          "owner": "demo.user@example.com",
          "type": "free"
        },
        {
          "key": "EXAMPLE_KEY_0987654321",
          "owner": "test.user@example.com",
          "type": "free"
        }
      ],
      "models": [
        {
          "id": "DeepSeek-V3.1",
          "usage": "chat",
          "contextWindow": 131072,
          "maxOutputTokens": 65536,
          "tpmLimit": null,
          "priority": 100,
          "tags": ["sambanova", "chat"]
        },
        {
          "id": "Meta-Llama-3.3-70B-Instruct",
          "usage": "chat",
          "contextWindow": 131072,
          "maxOutputTokens": 65536,
          "tpmLimit": null,
          "priority": 100,
          "tags": ["sambanova", "chat"]
        }
      ]
    }
  }
}

Direct mode vs Gateway mode

Direct mode (useGateway: false or gateway credentials absent): each model connects directly to the provider's API endpoint using a provider API key selected round-robin from the vault.

Gateway mode (useGateway: true + gatewaySecret + gatewayId): all requests go through the Cloudflare AI Gateway endpoint. The gateway is OpenAI-compatible, so all providers are exposed as a single OpenAI endpoint with the model prefixed by the provider name (e.g. groq/llama-3.3-70b-instruct). Two authorization headers are sent:

  • cf-aig-authorization: Bearer <gatewaySecret> — Cloudflare gateway token
  • Authorization: Bearer <provider-api-key> — provider key selected from the vault

Vault format

The vault is a JSON file (ai.json) encrypted with:

openssl enc -aes-256-cbc -a -pbkdf2 -iter 100000 -salt \
  -in ai.json -out ai.json.enc -pass pass:"${SECRET}"

...

Read more