diff --git a/.github/workflows/daily-issues-recap.yml b/.github/workflows/daily-issues-recap.yml index cba067883..41709c7ef 100644 --- a/.github/workflows/daily-issues-recap.yml +++ b/.github/workflows/daily-issues-recap.yml @@ -46,7 +46,7 @@ jobs: # Get today's date range TODAY=$(date -u +%Y-%m-%d) - opencode run -m opencode/claude-sonnet-4-5 "Generate a daily issues recap for the OpenCode repository. + opencode run -m kilo/anthropic/claude-sonnet-4.5 "Generate a daily issues recap for the OpenCode repository. TODAY'S DATE: ${TODAY} diff --git a/.github/workflows/daily-pr-recap.yml b/.github/workflows/daily-pr-recap.yml index e32e87dcc..ccee05a67 100644 --- a/.github/workflows/daily-pr-recap.yml +++ b/.github/workflows/daily-pr-recap.yml @@ -45,7 +45,7 @@ jobs: run: | TODAY=$(date -u +%Y-%m-%d) - opencode run -m opencode/claude-sonnet-4-5 "Generate a daily PR activity recap for the OpenCode repository. + opencode run -m kilo/anthropic/claude-sonnet-4.5 "Generate a daily PR activity recap for the OpenCode repository. TODAY'S DATE: ${TODAY} diff --git a/.github/workflows/docs-update.yml b/.github/workflows/docs-update.yml index 24b057638..3a74f1d10 100644 --- a/.github/workflows/docs-update.yml +++ b/.github/workflows/docs-update.yml @@ -49,7 +49,7 @@ jobs: env: OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} with: - model: opencode/gpt-5.2 + model: kilo/openai/gpt-5.2 agent: docs prompt: | Review the following commits from the last ${{ env.LOOKBACK_HOURS }} hours and identify any new features that may need documentation. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ba80a6954..e82f0d45c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,6 +67,8 @@ jobs: working-directory: packages/opencode run: bun script/seed-e2e.ts env: + KILO_API_KEY: ${{ secrets.KILO_API_KEY }} + KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} OPENCODE_DISABLE_SHARE: "true" OPENCODE_DISABLE_LSP_DOWNLOAD: "true" OPENCODE_DISABLE_DEFAULT_PLUGINS: "true" @@ -79,13 +81,15 @@ jobs: OPENCODE_E2E_PROJECT_DIR: ${{ github.workspace }} OPENCODE_E2E_SESSION_TITLE: "E2E Session" OPENCODE_E2E_MESSAGE: "Seeded for UI e2e" - OPENCODE_E2E_MODEL: "opencode/gpt-5-nano" + OPENCODE_E2E_MODEL: "kilo/openai/gpt-5-nano" - name: Run opencode server if: matrix.settings.name != 'windows' working-directory: packages/opencode run: bun dev -- --print-logs --log-level WARN serve --port 4096 --hostname 127.0.0.1 & env: + KILO_API_KEY: ${{ secrets.KILO_API_KEY }} + KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} OPENCODE_DISABLE_SHARE: "true" OPENCODE_DISABLE_LSP_DOWNLOAD: "true" OPENCODE_DISABLE_DEFAULT_PLUGINS: "true" @@ -111,6 +115,8 @@ jobs: run: ${{ matrix.settings.command }} env: CI: true + KILO_API_KEY: ${{ secrets.KILO_API_KEY }} + KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} OPENCODE_DISABLE_SHARE: "true" OPENCODE_DISABLE_LSP_DOWNLOAD: "true" OPENCODE_DISABLE_DEFAULT_PLUGINS: "true" diff --git a/.opencode/command/commit.md b/.opencode/command/commit.md index 826002919..a03b0f1bb 100644 --- a/.opencode/command/commit.md +++ b/.opencode/command/commit.md @@ -1,6 +1,6 @@ --- description: git commit and push -model: opencode/glm-4.7 +model: kilo/z-ai/glm-4.7 subtask: true --- diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index b9fa6e939..888c4b7e0 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -4,7 +4,11 @@ // "enterprise": { // "url": "https://enterprise.dev.opencode.ai", // }, - "provider": {}, + "provider": { + "kilo": { + "options": {}, + }, + }, "mcp": { "context7": { "type": "remote", diff --git a/packages/app/script/e2e-local.ts b/packages/app/script/e2e-local.ts index 2c7be2ad9..e352d4331 100644 --- a/packages/app/script/e2e-local.ts +++ b/packages/app/script/e2e-local.ts @@ -70,7 +70,7 @@ const serverEnv = { OPENCODE_E2E_PROJECT_DIR: repoDir, OPENCODE_E2E_SESSION_TITLE: "E2E Session", OPENCODE_E2E_MESSAGE: "Seeded for UI e2e", - OPENCODE_E2E_MODEL: "opencode/gpt-5-nano", + OPENCODE_E2E_MODEL: "kilo/openai/gpt-5-nano", OPENCODE_CLIENT: "app", } satisfies Record diff --git a/packages/kilo-gateway/src/api/constants.ts b/packages/kilo-gateway/src/api/constants.ts index cb6900ef1..794df6dea 100644 --- a/packages/kilo-gateway/src/api/constants.ts +++ b/packages/kilo-gateway/src/api/constants.ts @@ -3,11 +3,17 @@ * Centralized configuration for all API endpoints, headers, and settings */ -/** Base URL for Kilo API */ -export const KILO_API_BASE = "https://api.kilo.ai" +/** Environment variable for custom Kilo API URL */ +export const ENV_KILO_API_URL = "KILO_API_URL" + +/** Default Kilo API URL */ +export const DEFAULT_KILO_API_URL = "https://api.kilo.ai" + +/** Base URL for Kilo API - can be overridden by KILO_API_URL env var */ +export const KILO_API_BASE = process.env[ENV_KILO_API_URL] || DEFAULT_KILO_API_URL /** Default base URL for OpenRouter-compatible endpoint */ -export const KILO_OPENROUTER_BASE = "https://api.kilo.ai/api/openrouter" +export const KILO_OPENROUTER_BASE = `${KILO_API_BASE}/api/openrouter` /** Device auth polling interval in milliseconds */ export const POLL_INTERVAL_MS = 3000 diff --git a/packages/kilo-gateway/src/api/models.ts b/packages/kilo-gateway/src/api/models.ts index 0e6728f6b..ba4193666 100644 --- a/packages/kilo-gateway/src/api/models.ts +++ b/packages/kilo-gateway/src/api/models.ts @@ -1,7 +1,7 @@ import { z } from "zod" import { getKiloUrlFromToken } from "../auth/token.js" import { DEFAULT_HEADERS } from "../headers.js" -import { KILO_OPENROUTER_BASE, MODELS_FETCH_TIMEOUT_MS } from "./constants.js" +import { KILO_API_BASE, KILO_OPENROUTER_BASE, MODELS_FETCH_TIMEOUT_MS } from "./constants.js" /** * OpenRouter model schema @@ -61,9 +61,7 @@ export async function fetchKiloModels(options?: { const organizationId = options?.kilocodeOrganizationId // Construct base URL - const defaultBaseURL = organizationId - ? `https://api.kilo.ai/api/organizations/${organizationId}` - : KILO_OPENROUTER_BASE + const defaultBaseURL = organizationId ? `${KILO_API_BASE}/api/organizations/${organizationId}` : KILO_OPENROUTER_BASE const baseURL = options?.baseURL ?? defaultBaseURL diff --git a/packages/kilo-gateway/src/api/notifications.ts b/packages/kilo-gateway/src/api/notifications.ts index bd3c9585b..e61e5aa67 100644 --- a/packages/kilo-gateway/src/api/notifications.ts +++ b/packages/kilo-gateway/src/api/notifications.ts @@ -1,5 +1,6 @@ // kilocode_change - new file import { z } from "zod" +import { KILO_API_BASE } from "./constants.js" /** * Kilo notification schema @@ -38,7 +39,7 @@ export async function fetchKilocodeNotifications(options: { const token = options.kilocodeToken if (!token) return [] - const url = "https://api.kilo.ai/api/users/notifications" + const url = `${KILO_API_BASE}/api/users/notifications` try { const response = await fetch(url, { diff --git a/packages/kilo-gateway/src/index.ts b/packages/kilo-gateway/src/index.ts index c1ce3e7c6..8ad49436a 100644 --- a/packages/kilo-gateway/src/index.ts +++ b/packages/kilo-gateway/src/index.ts @@ -70,6 +70,8 @@ export type { // Constants // ============================================================================ export { + ENV_KILO_API_URL, + DEFAULT_KILO_API_URL, KILO_API_BASE, KILO_OPENROUTER_BASE, POLL_INTERVAL_MS, diff --git a/packages/kilo-gateway/src/types.ts b/packages/kilo-gateway/src/types.ts index 5cfa55233..d61c598f0 100644 --- a/packages/kilo-gateway/src/types.ts +++ b/packages/kilo-gateway/src/types.ts @@ -76,7 +76,8 @@ export interface KiloProviderOptions { /** * Base URL for the KiloCode API - * @default "https://api.kilo.ai/api/openrouter/" + * Can be overridden by KILO_API_URL environment variable + * @default "https://api.kilo.ai" */ baseURL?: string diff --git a/packages/opencode/script/seed-e2e.ts b/packages/opencode/script/seed-e2e.ts index ba2155cb6..0384a2c2e 100644 --- a/packages/opencode/script/seed-e2e.ts +++ b/packages/opencode/script/seed-e2e.ts @@ -1,7 +1,7 @@ const dir = process.env.OPENCODE_E2E_PROJECT_DIR ?? process.cwd() const title = process.env.OPENCODE_E2E_SESSION_TITLE ?? "E2E Session" const text = process.env.OPENCODE_E2E_MESSAGE ?? "Seeded for UI e2e" -const model = process.env.OPENCODE_E2E_MODEL ?? "opencode/gpt-5-nano" +const model = process.env.OPENCODE_E2E_MODEL ?? "kilo/openai/gpt-5-nano" const parts = model.split("/") const providerID = parts[0] ?? "opencode" const modelID = parts[1] ?? "gpt-5-nano" diff --git a/packages/opencode/src/provider/model-cache.ts b/packages/opencode/src/provider/model-cache.ts index 438b1bfc8..deba50254 100644 --- a/packages/opencode/src/provider/model-cache.ts +++ b/packages/opencode/src/provider/model-cache.ts @@ -204,11 +204,11 @@ export namespace ModelCache { // Get from Env const env = Env.all() - if (env.KILOCODE_TOKEN) { - options.kilocodeToken = env.KILOCODE_TOKEN + if (env.KILO_API_KEY) { + options.kilocodeToken = env.KILO_API_KEY } - if (env.KILOCODE_ORGANIZATION_ID) { - options.kilocodeOrganizationId = env.KILOCODE_ORGANIZATION_ID + if (env.KILO_ORG_ID) { + options.kilocodeOrganizationId = env.KILO_ORG_ID } log.debug("auth options resolved", { diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 41ab12a0e..87d123608 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -7,6 +7,7 @@ import { Flag } from "../flag/flag" import { lazy } from "@/util/lazy" import { Config } from "../config/config" // kilocode_change import { ModelCache } from "./model-cache" // kilocode_change +import { KILO_OPENROUTER_BASE } from "@kilocode/kilo-gateway" // kilocode_change // Try to import bundled snapshot (generated at build time) // Falls back to undefined in dev mode when snapshot doesn't exist @@ -138,8 +139,8 @@ export namespace ModelsDev { providers["kilo"] = { id: "kilo", name: "Kilo Gateway", - env: [], - api: ensureTrailingSlash(providerBaseURL), + env: ["KILO_API_KEY"], + api: ensureTrailingSlash(KILO_OPENROUTER_BASE), npm: "@kilocode/kilo-gateway", models: kiloModels, } diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index f06bf150c..fddda4b37 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -488,13 +488,12 @@ export namespace Provider { }, // kilocode_change start kilo: async (input) => { + const env = Env.all() const hasKey = await (async () => { - const env = Env.all() if (input.env.some((item) => env[item])) return true if (await Auth.get(input.id)) return true const config = await Config.get() if (config.provider?.["kilo"]?.options?.apiKey) return true - if (config.provider?.["kilo"]?.options?.kilocodeToken) return true return false })() @@ -505,9 +504,18 @@ export namespace Provider { } } + // Build options from KILO_* env vars + const options: Record = {} + if (env.KILO_ORG_ID) { + options.kilocodeOrganizationId = env.KILO_ORG_ID + } + if (!hasKey) { + options.apiKey = "anonymous" + } + return { autoload: Object.keys(input.models).length > 0, - options: hasKey ? {} : { apiKey: "anonymous" }, + options, } }, // kilocode_change end diff --git a/packages/web/src/content/docs/agents.mdx b/packages/web/src/content/docs/agents.mdx index 3b545d421..282775c4f 100644 --- a/packages/web/src/content/docs/agents.mdx +++ b/packages/web/src/content/docs/agents.mdx @@ -331,7 +331,7 @@ If you don’t specify a model, primary agents use the [model globally configure } ``` -The model ID in your Kilo CLI config uses the format `provider/model-id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex. +The model ID in your Kilo CLI config uses the format `provider/model-id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `kilo/openai/gpt-5.2-codex` for GPT 5.2 Codex. --- diff --git a/packages/web/src/content/docs/models.mdx b/packages/web/src/content/docs/models.mdx index 08b8f2e20..bbf74ce1f 100644 --- a/packages/web/src/content/docs/models.mdx +++ b/packages/web/src/content/docs/models.mdx @@ -58,7 +58,7 @@ Kilo CLI config. } ``` -Here the full ID is `provider_id/model_id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex. +Here the full ID is `provider_id/model_id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `kilo/openai/gpt-5.2-codex` for GPT 5.2 Codex. If you've configured a [custom provider](/docs/providers#custom), the `provider_id` is key from the `provider` part of your config, and the `model_id` is the key from `provider.models`. diff --git a/packages/web/src/content/docs/zen.mdx b/packages/web/src/content/docs/zen.mdx index 389eec6c1..3679316ea 100644 --- a/packages/web/src/content/docs/zen.mdx +++ b/packages/web/src/content/docs/zen.mdx @@ -88,9 +88,9 @@ You can also access our models through the following API endpoints. | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -The [model id](/docs/config/#models) in your OpenCode config -uses the format `opencode/`. For example, for GPT 5.2 Codex, you would -use `opencode/gpt-5.2-codex` in your config. +The [model id](/docs/config/#models) in your Kilo config +uses the format `kilo/`. For example, for GPT 5.2 Codex, you would +use `kilo/openai/gpt-5.2-codex` in your config. ---