Wire /v1/usages for Kimi (OAuth + API key) and balance API for DeepSeek,
flag both providers with usage/usageApikey, and normalize their quotas
in the dashboard ProviderLimits parser.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Use w-full instead of min-w-0/flex-1 + overflow-x-auto so the hidden
quota chips wrap cleanly instead of stretching the row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wire Devin CLI as a routed provider that spawns the local `devin acp`
binary. Add the DevinCliExecutor, register it in the executor map, expose
its status through the cli-tools batch endpoint and devin-settings route,
and document setup in cliTools constants.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Initialize initConsoleLogCapture() via Next.js instrumentation register()
hook so logs are captured from startup in headless/Docker deployments, and
add X-Accel-Buffering/Cache-Control headers to the SSE stream route to
prevent reverse proxies from buffering the initial payload.
Real Cursor IDE now uses AgentService at agent.api5.cursor.sh (HTTP/2-only)
while 9router still spoke the retired ChatService at api2.cursor.sh with
outdated headers, producing HTTP 429 "Update Required". Add an executeAgent
path that builds an agent.v1.RunRequest Connect RPC over a raw http2 stream
and fetches the account-specific usable model catalog via GetUsableModels.
Also implement MCP tool calling over AgentService: encode OpenAI tools as
AgentRunRequest.mcp_tools (McpToolDefinition with google.protobuf.Value
input_schema), decode McpArgs tool calls, and forward them to the client as
OpenAI tool_calls so the client runs the tool and resumes in the next turn.
Reply to request_context_args with a non-empty RequestContext, to server
heartbeats with client_heartbeat, and to KV blob get/set with empty results,
so action queries no longer stall the stream. Fold the client system prompt
into the user message (custom_system_prompt makes the server return an empty
turn). Bump clientVersion to 3.12.17 and add the x-cursor-client-commit
header so the gateway identifies as a current Cursor IDE release.
Bump client_version to 0.144.6 (above the 0.144.0 gate in codex CLI's
manifest) so /codex/models no longer returns 200 with newest entries
silently filtered out. Add the originator: codex_cli_rs header used by
every other codex call site, and move the entry onto buildOAuthResolver
so token refresh on 401/403 and a warning field on empty results are
wired in, matching gemini-cli and grok-cli.
8b9cac1 swapped alicode-intl to the DashScope compatible-mode endpoint to
fix#2591 for standard DashScope keys, but that broke Coding Plan keys
(sk-sp-...) which only work on coding-intl.dashscope.aliyuncs.com. The two
key types use two different hosts and are not interchangeable.
- alicode-intl: revert to coding-intl endpoint (Coding Plan keys)
- alims-intl: new provider for dashscope-intl/compatible-mode (standard keys)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add separate model selectors for Grok Build main, general-purpose,
explore, and plan agents. Each override gets an independent 9Router
custom-model slot and context_window derived from 9Router model
capabilities. Preserve and restore pre-existing config on reset.
Share one /api/models fetch via useModelCaps cache, mount ModelSelectModal
only when open, stop double fetchModelAliases on CLI tool cards, and resolve
provider icons through a session 404 cache with missing PNGs + loading=lazy.
Also include Claude Exa MCP toggle (claude-settings + ClaudeToolCard) that
was already in the working tree.
Co-authored-by: Cursor <cursoragent@cursor.com>
Bulk-add named auto-generated keys by paste-line index, blind to existing
connection names. The backend upserts apikey connections by exact name
(connectionsRepo), so a colliding generated name silently replaced an
existing key instead of inserting a new one.
Add a collision-aware planner (src/shared/utils/bulkAdd.js) that gap-fills
the smallest free "<base> <n>" against both existing connection names and
names assigned earlier in the same batch, so a generated name is never
reused and the backend always inserts. Applies to auto-named lines, custom
name|apiKey lines, and Cloudflare name|apiKey|accountId lines.
Wire the planner into AddApiKeyModal and pass existing connection names
from the provider detail page. Add unit tests covering gap-fill, custom
names, Cloudflare 3-part format, and robustness.
Add Grok Build to Dashboard → CLI Tools. Apply writes a [model.9router]
custom model to ~/.grok/config.toml and sets [models].default, routing
the xAI Grok TUI through 9Router. Reset removes the slot and restores
the previous default.
Replace the overly-broad UPSTREAM_CONNECTION_RE regex (which matched all
provider IDs with UUID suffixes) with an x-9r-internal-models-fetch
header to detect cross-instance recursive /models fetches.
fetchCompatibleModelIds now sends the header when fetching upstream
/models; the GET handler detects it and skips dynamic fetching, breaking
the recursion loop while letting compatible providers (MLX, Ollama, vLLM)
list their models. Fixes#2626.
Add pxpipe as an experimental fifth Token Saver: Claude-format request
bodies above a configurable size threshold are rendered as dense PNGs
via the pxpipe-proxy library API (transformAnthropicMessages) before
dispatch, cutting estimated input tokens by ~35-60% on token-dense
contexts. Integration follows the Headroom pattern: applied to the final
body in chatCore just before dispatch, fail-open on any error/timeout.
Managed npm install into DATA_DIR/pxpipe, dynamic loader with per-version
cache-bust, JSONL event log with rotation, /api/pxpipe/* endpoints, Token
Saver card (marked experimental) + /dashboard/pxpipe page, and per-request
Activated/Skipped annotation in Request Details. Disabled by default.
- add Headroom extras status + install endpoints
- show Headroom version + code/ml extras in Token Saver UI
- fix Windows interpreter selection to read from env with headroom-ai
Bulk import now parses name|apiKey|accountId lines for Cloudflare AI and
forwards accountId via providerSpecificData, with a provider-specific
placeholder and format hint.
- Backup DB only on real SCHEMA_VERSION change, not every app version bump
- Kill idle MCP stdio bridge children to prevent orphan process leaks
- Add getDistinctProviders to avoid loading every row JSON blob (OOM fix)
- Update codex model list (gpt-5.6 sol/terra/luna, drop 5.3 codex variants)
- Reorder Claude default models (fable first)
Co-authored-by: Cursor <cursoragent@cursor.com>
- Switch dev default to Turbopack (5-14x faster compile); keep webpack as dev:webpack
- Tailwind v4 source() base so JIT scans identically under both bundlers
- Lazy-load @xyflow/react via next/dynamic to keep it out of the shared bundle
- optimizePackageImports for heavy barrel imports (xyflow, dnd-kit, material-symbols, marked)
- Replace blind setTimeout waits with TCP health-check (waitServerReady)
- Run checkForUpdate in parallel instead of blocking server spawn
- Background MITM/tunnel/cloudflared kills off the critical path
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose max in the Codex thinking dropdown for gpt-5.6-sol only (maps to
xhigh on wire; live probe rejected ultra). Include custom/kilo models
when computing provider thinking options so manually added gpt-5.6-sol
contributes its max level.
Co-authored-by: Cursor <cursoragent@cursor.com>
Estimate tokens for tool_use, tool_result, thinking, system, and tools
blocks instead of text only, so count_tokens no longer returns 0 for
structured content and breaks Claude Code auto-compaction (#2337).
Co-authored-by: Cursor <cursoragent@cursor.com>
Add a 9Router-side proxy so the Headroom dashboard and its data
endpoints (/stats, /health, /stats-history, /transformations/feed)
stay same-origin when opened remotely through the 9Router app, and
add an "Open Headroom Dashboard" link in the Token Saver modal.
Gate /api/headroom/proxy as LOCAL_ONLY (loopback + CLI token) to
match start/stop, and strip cookie/authorization when the Headroom
target is non-loopback to avoid leaking viewer credentials.
Co-authored-by: Cursor <cursoragent@cursor.com>
Normalize every provider to one cache-inclusive convention via
canonicalizeUsage() before persist, and price cached + cache_creation as
subsets of prompt_tokens in calculateCostFromTokens() to stop
double-counting. usageRepo now delegates cost math to a single source.
Surface Cached tokens/cost across dashboard (overview, tokens, cost,
details). Merge Claude message_start cache with message_delta output so
cache counts survive. Compatible LLM nodes now allow multiple API-key
connections (key pool).
Co-authored-by: Cursor <cursoragent@cursor.com>
Add read-only GET to inspect per-credit reset inventory (status, granted,
expiry, remaining) with a Quota Tracker modal. DRY the route via shared
connection/refresh helpers; keep existing consume POST unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Kimchi as a browser-token OAuth provider routed through its
OpenAI-compatible gateway. Discover live models for /v1/models and
provider models, normalize Claude-compatible requests, and wire up
provider connection tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
CodeBuddy CN bonus packs ("Bonus Pack N") are one-shot credits whose
CycleEndTime equals DeductionEndTime — they expire for good and never
replenish. The dashboard rendered their resetAt as "Reset in Xd",
implying a monthly refill.
Tag bonus packs recurring:false (refill packs recurring:true) in the
usage handler, forward the flag through parseQuotaData, and word the
quota table / progress bar as "Expires in" / "Expires at" for
one-shot packs.
Generalize Claude 5h auto-ping into a provider-generic scheduler and add
opt-in Codex auto-ping that warms the next 5h window via a tiny gpt-5.5
request when session.resetAt slides. Default off, per-connection toggle,
failure cooldown, blocking-quota skip, drains stream before success.
Closes#2107
Co-authored-by: Cursor <cursoragent@cursor.com>
Use getModelInfo instead of parseModel in /api/translator/translate
so custom OpenAI/Anthropic-compatible provider prefixes resolve
correctly, aligning the debug path with the runtime chat path.
Fixes#1083
Co-authored-by: Cursor <cursoragent@cursor.com>
Use full-page navigation after login/logout so the dashboard reloads
with the fresh auth cookie, and mark login/logout responses no-store.
Fixes#2100
Co-authored-by: Cursor <cursoragent@cursor.com>