Skip to content

fix(kimi): adopt live kimi-code token instead of OAuth refresh - #120

Open
yesme wants to merge 32 commits into
onllm-dev:mainfrom
yesme:fix/kimi-adopt-live-cli-token
Open

fix(kimi): adopt live kimi-code token instead of OAuth refresh#120
yesme wants to merge 32 commits into
onllm-dev:mainfrom
yesme:fix/kimi-adopt-live-cli-token

Conversation

@yesme

@yesme yesme commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

When Kimi Code is running, onWatch was still calling POST /api/oauth/token (or skipping refresh entirely if Auto refresh tokens was off). Refresh-token rotation invalidates the live CLI session, and an idle/expired disk token then 401s forever even though the CLI is alive.

If a kimi-code process is detected, onWatch now adopts the access token the CLI already wrote to ~/.kimi-code/credentials/kimi-code.json and does not OAuth-refresh. Credential cache also invalidates when the file mtime/size changes, so a CLI persist is picked up on the next poll.

OAuth refresh is unchanged when kimi-code is not running and Settings → Auto refresh tokens is on.

Changes

  • internal/api/kimi_process.go: detect a live kimi-code process (same idea as skipping Anthropic refresh while Claude Code is running)
  • internal/api/kimi_client.go: while the CLI is live, use the disk access token; re-read on 401; never rotate the refresh token
  • internal/api/kimi_credentials.go: reload credentials when the file mtime/size changes instead of waiting out the 30s cache
  • docs/KIMI_SETUP.md: document the live-CLI vs idle-CLI refresh policy

Test plan

  • go test -race ./internal/api/ -run 'TestKimi|TestLoadKimi|TestIsKimi|TestDetectKimi'
  • Restart onWatch with kimi-code running: poll should succeed after the CLI writes kimi-code.json, with no POST /api/oauth/token
  • Logs should show skip-OAuth while the CLI is live (live kimi-code owns the refresh token / adopting access token)
  • Quit kimi-code, enable Auto refresh tokens, wait for access expiry: onWatch may OAuth-refresh and rewrite the credentials file
  • Auto refresh tokens off + no CLI: still no OAuth (existing setting)

yesme and others added 30 commits July 14, 2026 23:22
Add Settings → Providers controls to drag-reorder header tabs and set
custom display names (emoji allowed). Preferences persist in SQLite and
apply on the next dashboard load.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Pin header actions so custom/long tab labels scroll inside the tab
strip instead of squeezing out the refresh timestamp.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Register Grok (and Kimi) in the provider catalog so Settings can list
and toggle them. When a saved tab order omits a newly available
provider, insert it before the All / API Integrations tabs.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Catalog only lists providers implemented on this branch; Kimi stays
in the separate Kimi PR. Default label map still knows "kimi" for
forks that merge both.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Fork main integration for local runtime testing.
…order-and-labels)

Fork main integration for local runtime testing. Keeps Kimi Code and
Grok catalog entries alongside tab order/labels.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Only list providers with Dashboard visibility on in the tab reorder
list, and make the custom Tab name field obvious with a pencil label.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
… 401

kimi-code access tokens last ~15 minutes. Auto-detect was copying the
access token into NewKimiClient as staticToken, which skipped disk re-read
and OAuth refresh for the whole daemon lifetime — after expiry every poll
returned unauthorized even while ~/.kimi-code credentials stayed valid.

- Pass empty token for KimiAutoToken so the client uses the kimi-code store
- On usages 401, re-read disk then force-refresh (access can be dead before
  expires_at); still never touch kimi-cli paths
- Regression test for unexpired-but-401 force refresh
Anthropic /api/oauth/usage now returns top-level companion fields such as
limits (array), spend (unrelated object), and booleans alongside quota
buckets. Decoding the whole payload as map[string]*AnthropicQuotaEntry
failed with:

  cannot unmarshal array into Go value of type api.AnthropicQuotaEntry

Add a custom UnmarshalJSON that keeps null/object quota entries and
ignores non-quota metadata. Enhances onllm-dev#84 by also dropping non-quota
objects (spend) and skipping per-key decode errors so one bad companion
field cannot take down the entire Anthropic poll.

Fixes onllm-dev#82.
Related: onllm-dev#84.
Grok and Kimi fell through to the OpenAI icon class in the menubar
popover (providerIconClass default). Grok's static asset was also a
placeholder plus-circle, and Kimi had no asset at all.

Replace grok.svg with the brand monochrome mark, add kimi.svg, and wire
both into menubar CSS masks + providerIconClass.
Tray title used selected_quotas click order, so configuring provider
list as Codex → Anthropic → Grok still showed 17%·15%·7% (Codex·Grok·Anthropic).

Re-sort multi_provider selected_quotas by providers_order during
Settings.Normalize so tray title matches the menubar list order.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Web Settings > Menubar saved providers_order/visible_providers as "codex"
for single-account setups, while menubar cards always use account-scoped
IDs ("codex:1"). Exact-match filtering then dropped Codex after reorder/save.

- Match bare base keys to account-scoped cards in filter/sort/options
- Always emit codex:<id> from the settings provider list when profiles exist
- Tray selected_quotas ordering also accepts bare "codex" in providers_order

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Grok and Kimi current payloads only set snake_case resets_at and never
computed timeUntilReset. Menubar normalizeQuotas only reads camelCase
keys (resetsAt/renewsAt + timeUntilReset), so reset countdown lines were
empty for both providers.

Align with Anthropic/Codex/Cursor: set resetsAt, timeUntilReset, and
timeUntilResetSeconds (keep resets_at for dashboard JS compatibility).

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Menubar hard-coded labels like "Kimi Code" / "Codex - default" ignored
dashboard_provider_labels (Settings tab rename). Load the same label
map and resolveProviderTabLabel for every menubar card; multi-account
Codex/MiniMax only append " - <account>" when more than one account.

Also show renamed titles in the web Menubar provider-order list.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Add a monochrome brand mark left of each provider tab label using CSS
mask-image so the icon follows tab text color (active/hover).

Includes OpenRouter, Cursor, API Integrations, and All icons alongside
existing provider SVGs.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
CSS mask-image icons disappeared when browsers kept an immutable
style.css?v=… cache from before the icon rules existed. Use real
<img> tags with absolute /static/icons paths so brand marks always
paint next to tab labels.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Paint provider tab icons with CSS mask + currentColor so they track
tab text color across light/dark tokens, hover, and active accents.
Use absolute icon URLs on each tab via --provider-tab-icon; SVG fills
are solid black for reliable mask alpha.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Replace verbose \"Last updated: HH:MM:SS Asia/Shanghai\" with
\"Updated HH:MM:SS UTC+8\". Full IANA zone stays in the tooltip.
Reset labels use the same short offset for consistency.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Opening the tray popover reloaded /menubar every time, so WKWebView
showed a blank shell then re-painted. Preload the page at menubar
start, skip full navigation when the URL is already loaded, and soft-
refresh snapshot data via JS when reopening.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Allow users to disable OAuth refresh-and-write of coding-harness
credentials so onWatch does not compete with Claude/Kimi/Codex CLIs
for one-time refresh tokens. Defaults to enabled for existing behavior.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Add a GNOME Shell extension that reuses the macOS /menubar Web UI for
Linux: top-bar multi-provider % with monochrome icons, hover/click
WebKitGTK panel host, panel-aware icon tinting, system dark passthrough
for WebView, and a native close bridge so X no longer navigates to
dashboard/login.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Safari often fails CSS mask-image when the URL is supplied via a custom
property, so provider tabs rendered without glyphs. Switch to real
<img> tags (always paint) and invert monochrome SVGs in dark theme.
Normalize icon SVGs to 24x24 black fills for reliable sizing.

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
Dashboard CLI strip preferred shorter windows first, since they are
usually exhausted sooner:

1. Gemini 5h
2. Gemini Weekly
3. Claude + GPT 5h
4. Claude + GPT Weekly

Co-authored-by: Grok 4.5 (high effort) <302482056+a-grok-build-bot[bot]@users.noreply.github.com>
IDE GetUserStatus and RetrieveUserQuotaSummary both treat Gemini Pro and
Flash as one shared quota. Splitting them into two cards showed identical
usage and looked like a bug. Group all Gemini models under a single
"Gemini Quota" pool; keep legacy pro/flash keys as aliases.

Co-authored-by: Grok <[email protected]>
yesme and others added 2 commits July 21, 2026 14:19
fix(antigravity): merge Pro and Flash into shared Gemini pool
A running kimi-code process owns the refresh-token chain. Calling
POST /api/oauth/token from onWatch rotates that token and invalidates
the live CLI session. When kimi-code is detected, skip OAuth, re-read
kimi-code.json (including mtime/size changes), and use the access token
the CLI already wrote. OAuth refresh stays for the idle-CLI path when
Auto refresh tokens is enabled.

Co-authored-by: Grok 4.6 <281844019+a-claude-code-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant