Development environment setup - #22432
Conversation
- Add CURSOR to LlmProviders enum
- Add /cursor/{endpoint:path} pass-through route with Basic Auth
- Add /cursor to mapped_pass_through_routes for proper routing
- Create CursorPassthroughLoggingHandler for Logs page visibility
- Classifies operations (agent:create, agent:list, models:list, etc.)
- Logs model as cursor/cursor:<operation> for clean Logs display
- Tracks cost as $0 (subscription-based, no per-request pricing)
- Add Cursor to UI: provider enum, logo, credential fields
- Add provider_create_fields.json entry for LLM Credentials UI
- Add 18 unit tests covering route, auth, logging, and classification
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
- Replace placeholder Cursor logo with official hexagonal logo from lobehub - Add docs/pass_through/cursor.md with full tutorial matching a2a_cost_tracking style - Quick Start: add creds on UI, start proxy, launch agent, view logs - Examples: all Cursor Cloud Agents API endpoints - Advanced: virtual key usage - Screenshots: credential form, logs page, log detail view - Add Cursor to sidebars.js under Pass-through Endpoints - Add screenshots to docs/my-website/img/ Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
|
Cursor Agent can help with this pull request. Just |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
…l_list) The pass-through route now checks litellm.credential_list as a fallback when CURSOR_API_KEY env var is not set. This means adding credentials via the UI (Models + Endpoints → LLM Credentials) works without any config.yaml or environment variable setup. Credential lookup order: 1. passthrough_endpoint_router (config.yaml with use_in_pass_through) 2. litellm.credential_list (credentials added via UI) 3. CURSOR_API_KEY environment variable Also respects api_base from UI credentials if set. Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Greptile SummaryThis PR adds native pass-through support for Cursor Cloud Agents, allowing users to manage Cursor agents via the LiteLLM proxy. The implementation follows established patterns (Cohere, Gemini, etc.) with a dedicated route (
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py | Adds /cursor/{endpoint:path} pass-through route with Basic Auth encoding, following the same pattern as the Cohere route. Clean implementation. |
| litellm/proxy/pass_through_endpoints/llm_provider_handlers/cursor_passthrough_logging_handler.py | New logging handler with request classification for Cursor Cloud Agents API operations. Well-structured with proper error handling and fallback. |
| litellm/proxy/pass_through_endpoints/success_handler.py | Integrates Cursor handler into the pass-through logging chain. The is_cursor_route method contains dead code in its loop that can never return True, but the method still works correctly via its early return paths. |
| litellm/types/utils.py | Adds CURSOR to LlmProviders enum. Single-line, low-risk change. |
| litellm/proxy/_types.py | Adds /cursor to LiteLLMRoutes pass-through list. Single-line change consistent with other providers. |
| tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cursor_passthrough_logging_handler.py | Well-structured unit tests covering request classification, route detection, and logging handler behavior. All tests use mocks — no real network calls. |
| tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py | Adds 4 new tests for the Cursor proxy route covering Basic Auth, missing API key, custom API base, and agent launch. All properly mocked. |
| ui/litellm-dashboard/src/components/provider_info_helpers.tsx | Adds Cursor to the UI provider enum, logo map, provider map, and placeholder model. Follows existing patterns exactly. |
| litellm/proxy/public_endpoints/provider_create_fields.json | Adds Cursor provider configuration with api_key and api_base credential fields. Follows existing JSON schema pattern. |
| docs/my-website/docs/pass_through/cursor.md | New documentation page for Cursor Cloud Agents pass-through with Quick Start, API examples, and endpoint reference table. |
| docs/my-website/sidebars.js | Adds Cursor doc page to the pass-through section of the sidebar in alphabetical order. |
Sequence Diagram
sequenceDiagram
participant Client
participant LiteLLM Proxy
participant cursor_proxy_route
participant create_pass_through_route
participant Cursor API
Client->>LiteLLM Proxy: POST /cursor/v0/agents<br/>Authorization: Bearer <litellm-key>
LiteLLM Proxy->>cursor_proxy_route: Route matched
cursor_proxy_route->>cursor_proxy_route: get_credentials("cursor")
cursor_proxy_route->>cursor_proxy_route: Base64 encode API key for Basic Auth
cursor_proxy_route->>create_pass_through_route: target=api.cursor.com/v0/agents<br/>custom_headers={Authorization: Basic ...}<br/>custom_llm_provider="cursor"
create_pass_through_route->>Cursor API: POST /v0/agents<br/>Authorization: Basic <base64(key:)>
Cursor API-->>create_pass_through_route: 200 {id, name, status}
create_pass_through_route->>LiteLLM Proxy: PassThroughEndpointLogging
LiteLLM Proxy->>LiteLLM Proxy: is_cursor_route() → CursorPassthroughLoggingHandler
LiteLLM Proxy->>LiteLLM Proxy: _classify_cursor_request() → "cursor:agent:create"
LiteLLM Proxy-->>Client: 200 {id, name, status}
Last reviewed commit: 9f5b31d
| def is_cursor_route( | ||
| self, url_route: str, custom_llm_provider: Optional[str] = None | ||
| ): | ||
| """Check if the URL route is a Cursor Cloud Agents API route.""" | ||
| if custom_llm_provider == "cursor": | ||
| return True | ||
| parsed_url = urlparse(url_route) | ||
| if parsed_url.hostname and "api.cursor.com" in parsed_url.hostname: | ||
| return True | ||
| for route in self.TRACKED_CURSOR_ROUTES: | ||
| if route in url_route: | ||
| path = parsed_url.path if parsed_url.scheme else url_route | ||
| if path.startswith("/v0/"): | ||
| return custom_llm_provider == "cursor" | ||
| return False |
There was a problem hiding this comment.
Dead code in is_cursor_route loop
The for loop on lines 422-426 can never return True. Here's why:
- Line 417-418: if
custom_llm_provider == "cursor", returnTrueimmediately. - Line 419-421: if hostname is
api.cursor.com, returnTrueimmediately. - Line 426:
return custom_llm_provider == "cursor"— but we already knowcustom_llm_provider != "cursor"(that was handled in step 1), so this always evaluates toFalse.
The method works correctly in practice because the proxy route always passes custom_llm_provider="cursor", which is caught by the early return. However, the loop gives a false impression of additional detection logic. Consider simplifying:
| def is_cursor_route( | |
| self, url_route: str, custom_llm_provider: Optional[str] = None | |
| ): | |
| """Check if the URL route is a Cursor Cloud Agents API route.""" | |
| if custom_llm_provider == "cursor": | |
| return True | |
| parsed_url = urlparse(url_route) | |
| if parsed_url.hostname and "api.cursor.com" in parsed_url.hostname: | |
| return True | |
| for route in self.TRACKED_CURSOR_ROUTES: | |
| if route in url_route: | |
| path = parsed_url.path if parsed_url.scheme else url_route | |
| if path.startswith("/v0/"): | |
| return custom_llm_provider == "cursor" | |
| return False | |
| def is_cursor_route( | |
| self, url_route: str, custom_llm_provider: Optional[str] = None | |
| ): | |
| """Check if the URL route is a Cursor Cloud Agents API route.""" | |
| if custom_llm_provider == "cursor": | |
| return True | |
| parsed_url = urlparse(url_route) | |
| if parsed_url.hostname and "api.cursor.com" in parsed_url.hostname: | |
| return True | |
| return False |
* feat: add Cursor Cloud Agents as a native pass-through provider
- Add CURSOR to LlmProviders enum
- Add /cursor/{endpoint:path} pass-through route with Basic Auth
- Add /cursor to mapped_pass_through_routes for proper routing
- Create CursorPassthroughLoggingHandler for Logs page visibility
- Classifies operations (agent:create, agent:list, models:list, etc.)
- Logs model as cursor/cursor:<operation> for clean Logs display
- Tracks cost as $0 (subscription-based, no per-request pricing)
- Add Cursor to UI: provider enum, logo, credential fields
- Add provider_create_fields.json entry for LLM Credentials UI
- Add 18 unit tests covering route, auth, logging, and classification
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
* fix: use correct Cursor logo from lobehub, add documentation page
- Replace placeholder Cursor logo with official hexagonal logo from lobehub
- Add docs/pass_through/cursor.md with full tutorial matching a2a_cost_tracking style
- Quick Start: add creds on UI, start proxy, launch agent, view logs
- Examples: all Cursor Cloud Agents API endpoints
- Advanced: virtual key usage
- Screenshots: credential form, logs page, log detail view
- Add Cursor to sidebars.js under Pass-through Endpoints
- Add screenshots to docs/my-website/img/
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
* docs: simplify Cursor doc - UI-only flow, no config.yaml needed
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
* fix: cursor pass-through reads credentials from UI (litellm.credential_list)
The pass-through route now checks litellm.credential_list as a fallback
when CURSOR_API_KEY env var is not set. This means adding credentials
via the UI (Models + Endpoints → LLM Credentials) works without any
config.yaml or environment variable setup.
Credential lookup order:
1. passthrough_endpoint_router (config.yaml with use_in_pass_through)
2. litellm.credential_list (credentials added via UI)
3. CURSOR_API_KEY environment variable
Also respects api_base from UI credentials if set.
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Relevant issues
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🆕 New Feature
📖 Documentation
Changes
This PR introduces native pass-through support for Cursor Cloud Agents, allowing users to manage Cursor agents via the LiteLLM proxy.
Key Changes:
CURSORtoLlmProvidersenum and implemented a dedicated pass-through route (/cursor/{endpoint:path}) with Basic Authentication. This enables direct forwarding of requests to the Cursor Cloud Agents API.CursorPassthroughLoggingHandlerto accurately classify and log Cursor API operations (e.g.,cursor:agent:create,cursor:models:list) in the LiteLLM Logs page. Since Cursor's API is subscription-based, costs are tracked as $0.00 per request.provider_info_helpers.tsx,provider_create_fields.json) to allow users to easily add Cursor API credentials via the LLM Credentials UI, withhttps://api.cursor.comas the default API Base.docs/pass_through/cursor.md) with a simplified, UI-focused tutorial on how to add Cursor credentials, make API calls through the proxy, and view logs, matching the existinga2a_cost_trackingstyle.