Repository navigation
feat(gateway): add Kilo device login and team selection - #15111
Conversation
…and address review feedback
…llback for defaults
…ults fallback field
…esolved gateway base
feat(gateway): add Kilo device login and team selection
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (12 files)
The three findings from the previous review are resolved in this increment: the token regex now matches v1 ( Previous Review Summary (commit 9535ebe)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 9535ebe)Status: 3 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (31 files)
Notes: the plugin/RPC/TUI wiring was verified against the actual plugin API and v1 sources; the Reviewed by deepseek-v4.1-flash · Input: 97.9K · Output: 28.4K · Cached: 1.2M |
|
@marius-kilocode my counter-verification showed no issues whatsoever but I think having no Kilo bot warnings around would be good? |
feat(gateway): replace Kilo catalog from Gateway and enforce team scope
…roved poll email check
|
@WebReflection thanks, rechecked and fixed the bot comments. Let's get this merged before it scope creeps. |
feat(gateway): add per-request Kilo headers, body sanitization, and error contract
Stacked on #15060.
Part of #14991 (and #13750), PR 1 of the Gateway series. Plan unit
U-E1-03(login and team foundation). Supersedes #14998.What Problem This Solves
On the
v2branch, thekiloprovider used upstream'spackages/core/src/plugin/provider/kilo.ts, which only sendsHTTP-Referer: https://opencode.ai/andX-Title: opencode. It had no device authorization flow, no profile or team selection, noX-KILOCODE-ORGANIZATIONIDheader, and no anonymous fallback when signed out.script/dev-isolated.tsworked around this by reading the v1 login from~/.local/share/kilo/auth.json.Why This Change Was Made
Following the architecture in #14991 and #15060:
packages/kilo-gateway-core(@kilocode/gateway-core) with zero@opencode/*imports (enforced bytest/boundary.test.ts):KiloServer: server URL fromKILO_API_URL(defaulthttps://api.kilo.ai) or embedded before the final:of a development token (fromToken), and/api/gatewaybase URL.KiloDevice: device authorization (POST /api/device-auth/codesandGET /api/device-auth/codes/{code}), request timeouts capped at the remaining code lifetime, interruption support, and exponential backoff on network errors, timeouts, 408, 429, or 5xx until code expiry.KiloProfile:GET /api/profiledecoding (supporting both nesteduserand flat shapes) and the v1defaultOrganizationIdrule (preferselectedOrganizationIdwhen valid, otherwise fall back to the first team only whenhasPersonalAccount === false).KiloAccount: environment token lookup (KILO_API_KEY>KILOCODE_TOKEN>KILO_AUTH_CONTENT), server and team precedence (token-embedded server > login server >KILO_API_URL;KILO_ORG_ID> selected team > login default), andANONYMOUS_KEY = "anonymous".KiloHeaders:HTTP-Referer: https://kilocode.ai,X-Title: Kilo Code,X-KILOCODE-EDITORNAME,X-KILOCODE-FEATURE, andX-KILOCODE-ORGANIZATIONID.src/testing.ts: local Gateway fixture exported as@kilocode/gateway-core/testing(compiled intodist/testing.jssoverify-package.tstarball packing resolves it cleanly).packages/core/src/kilocode/gateway.ts,gateway-rpc.ts):KiloPlugininpackages/core/src/plugin/provider.ts.deviceOAuth method (Kilo Gateway (Device Authorization)), setsbaseURLand Kilo provider headers, gives environment tokens (KILO_API_KEY,KILOCODE_TOKEN,KILO_AUTH_CONTENT) precedence over stored credentials, and enableskilowithapiKey: "anonymous"when signed out.kilocode.gatewayRPC (profileandorganization.set), persists the team choice per connection in plugin storage, and broadcastsrpc.kilocode.gateway.organizationglobally viaBus.Service({ global: true }) so all open locations reload./teams(packages/tui/src/kilocode/gateway.tsx):Select Account (<email>)) when the user belongs to one or more teams./teams(team,org,orgs) to switch between Personal Account and teams at any time.bun dev(script/dev-isolated.ts):~/.local/share/kilo/auth.jsontoken reuse sobun devstarts cleanly signed out withkilo/kilo-auto/free.Shared upstream files changed
packages/core/src/plugin/provider.tsKiloPluginwithKiloGatewayPluginuntil the Kilo host registers built-in plugins viaSdkPlugins.register(U-E0-01).packages/core/test/plugin/provider-kilo.test.tskilocode.gatewayinProviderPluginsin place ofopencode.provider.kilo.packages/core/package.json@kilocode/gateway-corefor the built-in adapter.packages/sdk/script/verify-package.tskilo-gateway-corebeforecorein the SDK pack check.turbo.json@kilocode/gateway-core#testsobun turbo test --affectedruns the package tests in CI.packages/tui/src/component/dialog-integration.tsxchooseKiloAccountafter a Kilo Gateway login completes (TuiPluginhas no post-connect hook).packages/tui/src/plugin/builtins.tsKiloTeams(/teams) until the Kilo host owns the TUI built-in list (U-E0-01).User Impact
/connect-> Kilo Gateway offers Kilo Gateway (Device Authorization) alongside API key./teams(/team,/org,/orgs) switches between Personal Account and teams.kilo/kilo-auto/freeworks out of the box with theanonymouskey and a paid model returns"You need to sign in to use this model."Evidence
Automated checks
bun script/check-opencode-annotations.ts:ok (39 shared files against 4d9678a79d6)bun script/check-shared-patches.ts:okbun run --cwd packages/kilo-gateway-core typecheck && bun run --cwd packages/kilo-gateway-core build: passbun run --cwd packages/core typecheck: passbun run --cwd packages/tui typecheck: passbun test --cwd packages/kilo-gateway-core: 18 pass, 0 failbun test --cwd packages/core test/kilocode/gateway.test.ts test/plugin/provider-kilo.test.ts: 11 pass, 0 failbun test --cwd packages/tui test/kilocode/gateway.test.ts: 2 pass, 0 failCLI & TUI Self-Test
kilo/kilo-auto/free):env KILO_V2_PROFILE=$(mktemp -d) bun dev run --standalone "Reply with only the word PONG."->PONG(pass).kilo/deepseek/deepseek-v4.1-flash):env KILO_V2_PROFILE=$(mktemp -d) bun dev run --standalone -m kilo/deepseek/deepseek-v4.1-flash "Reply with only PONG."->Error: You need to sign in to use this model.(pass).KILO_API_KEY+KILO_ORG_ID):env KILO_API_KEY=... KILO_ORG_ID=... KILO_V2_PROFILE=$(mktemp -d) bun dev run --standalone -m kilo/deepseek/deepseek-v4.1-flash "Reply with only the word PONG."->PONG(pass)./teamsdialog: