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.
3.6 KiB
title, version, lastUpdated
| title | version | lastUpdated |
|---|---|---|
| Cursor Image Generation | 3.8.49 | 2026-07-23 |
Cursor Image Generation
OmniRoute exposes Cursor plan image generation on POST /v1/images/generations through the same provider id as chat: cursor (alias cu).
| Field | Value |
|---|---|
IMAGE_PROVIDERS id |
cursor |
| Format | cursor-agent-image |
| Auth | Same OAuth / API-key connection as chat (provider_connections.provider = "cursor") |
| Models | cursor/auto, cursor/composer-2, cursor/composer-2.5 |
Why the Agent CLI
Cursor chat in OmniRoute uses agent.v1.AgentService/Run (protobuf). That path rejects built-in client tools (shell, write, …). Image generation is a Cursor-native tool executed by the agent CLI against the seat. The image handler therefore spawns agent with a locked prompt and a per-request temp workspace (same shape as community seat bridges), then returns OpenAI-compatible b64_json.
Access restriction (Hard Rules #15 + #17)
This is the only IMAGE_PROVIDERS format that spawns a child process (the agent
binary). Because POST /v1/images/generations is shared by ~40 other, non-spawning
image providers that remote callers legitimately use, the whole route is not
classified LOCAL_ONLY — instead handleCursorAgentImageGeneration enforces its own
gate using the trusted AUTHZ_HEADER_PEER_LOCALITY verdict the authz pipeline stamps
on every request (from the real TCP peer, never the spoofable Host header): only
loopback and lan callers may reach the spawn; everything else (including a leaked
API key replayed over a public tunnel) gets 403 before any credential lookup or
process spawn happens. See src/server/authz/policies/management.ts for the same
policy applied to the rest of the LOCAL_ONLY tier.
Concurrency gate is module-level (single-instance limitation)
CURSOR_IMG_MAX_CONCURRENT is enforced by an in-memory counter/queue scoped to the
Node module instance (open-sse/handlers/imageGeneration/providers/cursorAgentImage.ts).
It correctly limits concurrent agent spawns within one OmniRoute process, but does
not coordinate across multiple processes/instances sharing the same Cursor seat
(e.g. a multi-replica deployment) — each instance enforces its own independent limit.
For a single-instance deployment (the default) this is exact; horizontally scaled
deployments should keep CURSOR_IMG_MAX_CONCURRENT conservative per instance or route
Cursor image traffic to a single instance.
Requirements
- A connected Cursor account in the dashboard (OAuth or
crsr_…API key). - The Cursor Agent binary available to the OmniRoute process:
- env
CURSOR_AGENT_BIN=/path/to/agent, or ~/.local/bin/agent, orproviderSpecificData.agentBinon the Cursor connection.
- env
Optional tuning:
| Env | Default | Meaning |
|---|---|---|
CURSOR_IMG_TIMEOUT_MS |
210000 |
Per-image wall clock |
CURSOR_IMG_MAX_CONCURRENT |
2 |
Shared-seat concurrency gate |
CURSOR_IMG_MODEL |
(request model / auto) |
Override CLI --model |
Example
curl -sS https://<host>/v1/images/generations \
-H "Authorization: Bearer <omni-api-key>" \
-H "Content-Type: application/json" \
-d '{"model":"cursor/auto","prompt":"a lantern in fog","size":"1024x1024"}'
Generation typically takes 1–2 minutes. Prefer an internal network path; edge proxies with ~100s timeouts will fail.
LiteLLM
Register an image model with mode: image_generation, api_base: http://omniroute:20128/v1, and model: openai/cursor/auto (or bare cursor/auto depending on your LiteLLM version).