Repository navigation
feat(gateway): add Kilo device login and team selection - #15064
Conversation
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Previous Review Summaries (2 snapshots, latest commit 0e7bfa7)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 0e7bfa7)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Notes: incremental review of Previous review (commit 04142b6)Status: No Issues Found | Recommendation: Merge Files Reviewed (31 files)
Notes: verified the device poll backoff/expiry bounds, request timeout follows the remaining code lifetime, env/credential/team precedence ( Reviewed by deepseek-v4.1-flash · Input: 53.4K · Output: 18.1K · Cached: 729.3K |
| } | ||
|
|
||
| export function gateway(server: string) { | ||
| return `${normalize(server)}/api/gateway` |
There was a problem hiding this comment.
These addresses were changed in main, please make sure it's in sync.
|
@chrarnoldus all addressed. I am merging not to make this less complicated with the other PR's. If you find something please flag then I will follow up. |
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: