Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host. Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean. Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
5.6 KiB
title, version, lastUpdated
| title | version | lastUpdated |
|---|---|---|
| Cursor Provider in Docker Environments | 3.8.50 | 2026-08-17 |
Cursor Provider in Docker Environments
When OmniRoute runs inside Docker, the legacy Import from Cursor IDE /
cursor-agent flows fail because the container cannot see the host Cursor
install. Use Login with Cursor (deep-control PKCE) instead.
Why IDE / CLI Import Fails in Docker
- Filesystem isolation — Auto-import looks for Linux paths such as
~/.config/Cursor/User/globalStorage/state.vscdbinside the container. On Docker Desktop for macOS the host IDE DB is not mounted by default, and the container OS is Linux even when the host is Darwin. - No
cursor-agentbinary — Official OmniRoute images do not shipcursor-agent. Available Models previously shelled out tocursor-agent --list-modelsand fell back to a static catalog. - Wrong binary — Do not bind-mount a macOS
cursor-agentinto a Linux container. It will not execute.
Recommended: Login with Cursor
- Open Dashboard → Providers → Cursor.
- Choose the Login with Cursor tab.
- Click Login with Cursor — OmniRoute opens
https://cursor.com/loginDeepControl?…in your host browser. - Approve the login in the browser, then return to the dashboard. OmniRoute
polls
api2.cursor.sh/auth/polluntil tokens arrive. - OmniRoute stores access + refresh tokens and refreshes them via
https://api2.cursor.sh/auth/exchange_user_api_key.
This path does not require Cursor IDE or cursor-agent inside the container.
Model discovery
With a logged-in connection, Available Models / Auto-Sync prefers Cursor’s
HTTP AiService/AvailableModels catalog using the connection bearer token.
If that fails, OmniRoute still tries host cursor-agent (when present), then
the static registry seed.
OmniRoute always exposes auto in the catalog (display “Auto”), plus
OpenCodex-style router modes auto-cost, auto-balance, and
auto-intelligence. On the wire these map to Cursor’s default model
(with an optimization ModelParameter for the three variants). Prefer
cu/auto when premium models are out of usage — Auto often still has budget.
Live catalog is exclusive when synced
After a successful Cursor model sync (cursor-agent --list-models → persisted
synced catalog, or the bearer-authenticated AvailableModels fetch above), the
dashboard, /v1/models, and Test All list:
- Models returned by the live sync
- Injected auto-router ids:
auto,auto-cost,auto-balance,auto-intelligence - Operator custom models (Import / manual) — never pruned by sync
The large static registry under
open-sse/config/providers/registry/cursor/ is offline fallback only. When
synced is empty (or discovery fails), listing falls back to that registry.
Effort-suffixed ids (for example claude-4.6-sonnet-high) may still be
requested at runtime: resolveRequestedModel strips the suffix into a wire
ModelParameter. Exclusive listing intentionally hides those static variants
from Test All so probes match what Cursor actually returns as available.
Helpers
providerUsesExclusiveSyncedListing("cursor"|"cu")—src/lib/providers/modelListingCapability.tsmergeProviderModelListing— dashboard mergeensureCursorAutoCatalogEntry— auto* inject on discovery + listingshouldSuppressStaticModelForExclusiveListing—/v1/modelsstatic loop
Provider Limits (quota)
Usage → Provider Limits for Cursor uses Bearer APIs on api2.cursor.sh
(GetCurrentPeriodUsage → usage summary → auth/usage) after PKCE or token
import. The legacy cookie/cursor.com dashboard path remains a last fallback
for older IDE-imported sessions.
Windows typically include Total, Auto + Composer, and API. If limits look empty, re-run Login with Cursor or re-import tokens (IDE import alone is no longer required).
Empty turns / out of usage
When Cursor accepts a Run but returns no assistant text (common when premium
usage is exhausted), OmniRoute surfaces an actionable 429 (quota cues) or
502 with guidance — not a bare “Provider returned empty content”. Streaming
failures such as not_found: AI Model Not Found (usage window exhausted) are
classified as Cursor rate limit / usage exceeded and keep that message
through the SSE pipeline (the shared empty-stream guard does not overwrite an
already-emitted error). Check Provider Limits, try model auto, or raise
Cursor plan limits.
Client version (headless)
Without a local cursor-agent install, OmniRoute resolves
x-cursor-client-version via env CURSOR_AGENT_CLI_VERSION, then a disk-cached
scrape of the Cursor installer script, then a pinned build id. Override with
CURSOR_AGENT_CLI_VERSION when needed.
Fallback: Manual Token Import
If you cannot complete browser login:
-
On the host, extract tokens from Cursor’s
state.vscdb:sqlite3 "$HOME/Library/Application Support/Cursor/User/globalStorage/state.vscdb" \ "SELECT key, value FROM ItemTable WHERE key IN ('cursorAuth/accessToken','cursorAuth/refreshToken','storage.serviceMachineId');" -
Open Import token in the Cursor auth modal.
-
Paste Access Token and, when available, Refresh Token (required for automatic refresh). Machine ID is optional.
Access-token-only imports still work but will expire without a refresh token — re-import when chat returns authentication errors.
Related
- Zed Docker guidance:
docs/providers/ZED-DOCKER.md - OpenCodex Cursor login reference (external): https://github.com/lidge-jun/opencodex/blob/main/src/oauth/cursor.ts