diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 7af39e32b3..8d6814db2c 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -116,7 +116,7 @@ ocx logout | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research subscription gateway (same backend Hermes Agent uses). Device-grant login against `portal.nousresearch.com`; the access token is the per-request inference JWT. Mixed paid + `:free` model catalog (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) discovered live from the signed-in account. Refresh tokens are single-use and rotated on every refresh. | | `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | Initial login imports the installed, signed-in `kiro-cli` session (on Unix, install with `curl -fsSL https://cli.kiro.dev/install` | `bash`; on Windows PowerShell, use `irm 'https://cli.kiro.dev/install.ps1'` | `iex`; then run `kiro-cli login`). **Add account** logs `kiro-cli` out, starts a fresh browser login that switches the account used by `kiro-cli`, and stores account-scoped profile metadata. Existing OpenCodex accounts are preserved, and cancellation or failure restores the previous `kiro-cli` session. | | `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth over the Cloud Code Assist wire. Live discovery uses CCA's authenticated `v1internal:fetchAvailableModels` endpoint and publishes the agent models available to the signed-in account; the maintained catalog remains the fallback. | -| `cursor` | `cursor` | `https://api2.cursor.sh` | Experimental PKCE login, live HTTP/2 transport, and account-filtered model discovery. | +| `cursor` | `cursor` | `https://api2.cursor.sh` | Experimental PKCE login, live HTTP/2 transport with an opt-in HTTP/1.1 compatibility path, and account-filtered model discovery. | | `github-copilot` | `openai-chat` | `https://api.githubcopilot.com` | Experimental. GitHub device flow + `copilot_internal` exchange (VS Code OAuth client). Requires an active Copilot subscription; not an official third-party API. | After a terminal Nous refresh failure, run `ocx login nous` to reauthenticate. @@ -511,7 +511,9 @@ provider-wide adapter. To opt a model without a built-in default (for example Cursor is tracked separately as an experimental adapter. `adapter: "cursor"` appears in `ocx init` and the dashboard Add Provider picker as an experimental local config entry with Cursor's static fallback model catalog metadata. When a Cursor access token is configured, opencodex uses Cursor's -live HTTP/2 transport. Its bundled fallback seed includes `gpt-5.6-sol` / `terra` / `luna` (1M context), +live HTTP/2 transport. Set `upstreamHttpVersion: "http1.1"` when a proxy requires Cursor's HTTP/1.1 +compatibility path; the setting covers both inference and live model discovery and is exposed at +**Providers → Cursor → Settings → Cursor transport**. Its bundled fallback seed includes `gpt-5.6-sol` / `terra` / `luna` (1M context), regular/Fast rows for Grok 4.5 and 4.6 (500K), and `kimi-k3` (262K); live discovery decides which remain visible for the account. Grok 4.6 exposes `low` / `medium` / `high` / `xhigh` in both forms, while 4.5 stops at `high`. Fast requests send the matching base Grok model with separate `effort` diff --git a/docs-site/src/content/docs/reference/adapters.md b/docs-site/src/content/docs/reference/adapters.md index 93a1c42f63..8a9bd05c45 100644 --- a/docs-site/src/content/docs/reference/adapters.md +++ b/docs-site/src/content/docs/reference/adapters.md @@ -186,7 +186,10 @@ advertised effort control on those models as proof of upstream-native reasoning ## `cursor` -**Targets:** Cursor's `agent.v1.AgentService/Run` over HTTP/2 Connect streaming at `api2.cursor.sh`. +**Targets:** Cursor's `agent.v1.AgentService/Run` over HTTP/2 Connect streaming at `api2.cursor.sh` +by default. With `upstreamHttpVersion: "http1.1"` (or `"h1"`), uses Cursor's HTTP/1.1 +compatibility pair: `agent.v1.AgentService/RunSSE` for server output and +`aiserver.v1.BidiService/BidiAppend` for client messages. **Auth:** Cursor OAuth/access token from `provider.apiKey` or the forwarded authorization header. - Uses `runTurn` rather than the ordinary fetch/parse path. Requests, server events, tool arguments, @@ -195,6 +198,8 @@ advertised effort control on those models as proof of upstream-native reasoning - Replays conversation state through content-addressed blobs, maps server tool calls back to Codex, discovers live Cursor models through the protobuf `GetUsableModels` RPC, and retries only before a run request is committed to the wire. +- Honors `upstreamHttpVersion` for both live model discovery and inference. `auto`, `http2`, and `h2` + preserve the existing HTTP/2 transport; only `http1.1` and `h1` select compatibility mode. - Exposes Cursor Router as `cursor/auto` plus explicit `cursor/auto-cost`, `cursor/auto-balance`, and `cursor/auto-intelligence` entries. Explicit levels are encoded in `requested_model.parameters` while the legacy `cursor/auto` entry retains the account/team default. diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 2c1d2e3eef..d467b5cb5f 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -67,7 +67,7 @@ differing backup and rewrites known legacy namespaced selected ids to bare ids. | `adapter` | `string` | One of `openai-chat`, `openai-responses`, `anthropic`, `google`, `kiro`, `cursor`, `azure-openai` (or alias `azure`). | | `baseUrl` | `string` | Upstream API base URL. Most built-in fixed endpoints ignore a mismatch; collision-safe key presets preserve an older same-named custom destination. | | `requestPacing?` | `{ enabled, requestsPerMinute?, minIntervalMs?, models? }` | Optional client-side outbound request-start pacing, separate from upstream usage, billing, and rate-limit indicators. RPM is converted to an even interval; `minIntervalMs` may impose a longer interval. Provider limits apply across all models, while `models` entries use exact upstream model IDs (for example `nvidia/llama-3.1-nemotron-ultra-253b-v1`) and can only add delay. Queue waits do not consume the upstream response-header timeout. HTTP, Responses WebSocket, and explicit adapter `fetchResponse`/`runTurn` dispatches are covered. | -| `upstreamHttpVersion?` | `"auto" \| "http1.1" \| "h1" \| "http2" \| "h2"` | Pin the HTTP version used for upstream requests to this provider. Defaults to `auto`, which lets Bun negotiate. Set `http1.1` when a provider's HTTP/2 SSE stream stalls instead of delivering events — the symptom is a long-running streaming request that produces nothing and eventually times out. Management `POST`/`PATCH` accept `null` to clear it back to `auto`. | +| `upstreamHttpVersion?` | `"auto" \| "http1.1" \| "h1" \| "http2" \| "h2"` | Pin the HTTP version used for upstream requests to this provider. Defaults to `auto`, which lets Bun negotiate. An explicit pin requires an HTTPS target and fails locally when it cannot be honored. Set `http1.1` when a provider's HTTP/2 SSE stream stalls instead of delivering events — the symptom is a long-running streaming request that produces nothing and eventually times out. For Cursor, `http1.1`/`h1` selects its `RunSSE` + `BidiAppend` compatibility transport for inference and also pins live model discovery. Management `POST`/`PATCH` accept `null` to clear it back to `auto`. | | `responsesPath?` | `string` | Relative resource path for key-auth `openai-responses` requests. It must start with `/` and contain no scheme, query, or fragment. | | `supportsServiceTier?` | `boolean` | Tri-state canonical Fast capability fallback. `true` publishes Fast in the catalog, satisfies service-tier routing requirements, contributes a supported fingerprint, and lets fast mode inject the provider's canonical wire value on a compatible final adapter. `false` strips the field and never injects, and exact model declarations cannot reopen it. Absent leaves the provider unclassified: fast mode does not inject or normalize a canonical caller value, and caller values obey the final wire's forwarding permission (`chatServiceTier` on Chat; passthrough on Responses). The registry classifies canonical OpenAI (`true`), DeepSeek, and Volcengine Ark (`false`); set it explicitly only for custom gateways that genuinely support tiers. | | `modelSupportsServiceTier?` | `Record` | Exact upstream model capability overrides. Exact `true` enables canonical Fast for that model; exact `false` narrows provider defaults. An explicit provider-level `supportsServiceTier: false` remains fail-closed and cannot be reopened. Exact `true` does not authorize foreign caller-tier forwarding on Chat. Undeclared models fall back to provider-wide behavior. Management `PATCH /api/providers` merges entries and accepts `null` to clear one. | @@ -294,6 +294,14 @@ so passthrough stays byte-for-byte identical. ## Cursor provider (`adapter: "cursor"`) The Cursor bridge is experimental. After `ocx login cursor`, add or edit `providers.cursor`. + +If a proxy cannot carry Cursor's default HTTP/2 stream, set `upstreamHttpVersion` to `"http1.1"` +or its `"h1"` alias. +This switches inference to Cursor's `RunSSE` + `BidiAppend` compatibility transport and uses +HTTP/1.1 for `GetUsableModels` discovery as well. The value requires an HTTPS `baseUrl`. Leave it +unset or use `"auto"` for the existing HTTP/2 behavior. In the dashboard choose +**Providers → Cursor → Settings → Cursor transport**. + Cursor Router's optimization ladder is exposed as separate Codex ids because the picker cannot render Cursor-specific model parameters: @@ -330,8 +338,8 @@ Cursor server-driven local tools are disabled by default. Codex continues using } ``` -Set the field on `providers.cursor`, not at the top level. In the dashboard use **Providers → Cursor -→ Edit JSON**, save, then restart. Legacy `unsafeAllowNativeLocalExec: true` equals +Set `nativeLocalExec` on `providers.cursor`, not at the top level. In the dashboard use **Providers +→ Cursor → Edit JSON**, save, then restart. Legacy `unsafeAllowNativeLocalExec: true` equals `nativeLocalExec: "on"` only when `nativeLocalExec` is unset. MCP, screen recording, and computer use are controlled separately by `mcpServers` and `desktopExecutor`. diff --git a/docs-site/src/content/docs/zh-cn/guides/providers.md b/docs-site/src/content/docs/zh-cn/guides/providers.md index b65ab443f3..4e924458ee 100644 --- a/docs-site/src/content/docs/zh-cn/guides/providers.md +++ b/docs-site/src/content/docs/zh-cn/guides/providers.md @@ -101,7 +101,7 @@ ocx logout | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research 订阅网关(与 Hermes Agent 使用同一后端)。通过设备授权登录 `portal.nousresearch.com`;access 令牌是每个请求的 inference JWT。付费 + `:free` 模型混合目录(`tencent/hy3:free`、`stepfun/step-3.7-flash:free` 等)会从已登录账户实时发现。Refresh 令牌是单次使用,每次刷新都会轮换。 | | `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | 首次登录会导入已安装并已登录的 Kiro CLI 会话(Unix 使用 `curl -fsSL https://cli.kiro.dev/install` | `bash`;Windows PowerShell 使用 `irm 'https://cli.kiro.dev/install.ps1'` | `iex`;然后运行 `kiro-cli login`)。**添加账户**会先退出 `kiro-cli`,再启动新的浏览器登录,从而切换 `kiro-cli` 自身使用的账户,并保存账户范围的配置文件元数据。现有 OpenCodex 账户会保留;如果取消或失败,则恢复之前的 `kiro-cli` 会话。 | | `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | 通过 Cloud Code Assist 协议使用 Google OAuth。实时发现调用已认证的 CCA `v1internal:fetchAvailableModels` 端点,并仅发布当前登录账户可用的 agent 模型;维护中的目录仍作为回退。 | -| `cursor` | `cursor` | `https://api2.cursor.sh` | 实验性 PKCE 登录、HTTP/2 传输和按账号筛选的模型发现。 | +| `cursor` | `cursor` | `https://api2.cursor.sh` | 实验性 PKCE 登录、带可选 HTTP/1.1 兼容路径的 HTTP/2 传输,以及按账号筛选的模型发现。 | | `github-copilot` | `openai-chat` | `https://api.githubcopilot.com` | 实验性。GitHub 设备流 + `copilot_internal` 交换(VS Code OAuth 客户端)。需要有效的 Copilot 订阅;不是官方第三方 API。 | Nous refresh 发生终止性失败后,请运行 `ocx login nous` 重新认证。 @@ -365,7 +365,9 @@ adapter。若要将没有内置默认值的模型(例如 `gpt-5.4-nano`)接 Cursor 作为单独的实验性 adapter 进行跟踪。`adapter: "cursor"` 会作为实验性本地配置出现在 `ocx init` 和 dashboard Add Provider picker 中,并保存 Cursor 的静态回退模型目录 metadata。配置 -Cursor access token 后,opencodex 会使用 Cursor live HTTP/2 transport。内置回退列表包含上下文为 +Cursor access token 后,opencodex 会使用 Cursor live HTTP/2 transport。代理要求 Cursor 的 +HTTP/1.1 兼容路径时,可设置 `upstreamHttpVersion: "http1.1"`;该设置同时覆盖推理与实时模型发现, +并可在 **Providers → Cursor → 设置 → Cursor 传输协议** 中选择。内置回退列表包含上下文为 1M 的 `gpt-5.6-sol` / `terra` / `luna`、上下文为 500K 的 Grok 4.5/4.6 普通与 Fast 条目,以及上下文为 262K 的 `kimi-k3`;最终显示哪些模型由账号的实时发现结果决定。Grok 4.6 的两种形式均提供 `low` / `medium` / `high` / `xhigh`,而 4.5 最高为 `high`。Fast 请求会发送对应的 Grok 基础模型, diff --git a/docs-site/src/content/docs/zh-cn/reference/adapters.md b/docs-site/src/content/docs/zh-cn/reference/adapters.md index dc39d307b7..07dbfcf441 100644 --- a/docs-site/src/content/docs/zh-cn/reference/adapters.md +++ b/docs-site/src/content/docs/zh-cn/reference/adapters.md @@ -123,8 +123,10 @@ Kiro 的 assistant 文本本身没有可靠的回合结束标记,但终止的 ## `cursor` -**目标:** `api2.cursor.sh` 上采用 HTTP/2 Connect streaming 的 -`agent.v1.AgentService/Run`。 +**目标:** 默认使用 `api2.cursor.sh` 上采用 HTTP/2 Connect streaming 的 +`agent.v1.AgentService/Run`。配置 `upstreamHttpVersion: "http1.1"`(或 `"h1"`)后,改用 +Cursor 的 HTTP/1.1 兼容传输:通过 `agent.v1.AgentService/RunSSE` 接收 server output,并通过 +`aiserver.v1.BidiService/BidiAppend` 发送 client message。 **认证:** `provider.apiKey` 或转发 authorization header 中的 Cursor OAuth/access token。 - 使用 `runTurn`,而不是常规 fetch/parse 路径。请求、server event、工具参数、usage checkpoint @@ -132,6 +134,8 @@ Kiro 的 assistant 文本本身没有可靠的回合结束标记,但终止的 Connect message。 - 经 content-addressed blob 重放对话状态,把 server tool call 映射回 Codex,用 protobuf `GetUsableModels` RPC 发现实时 Cursor 模型,并且只在 run request 尚未 commit 到 wire 前重试。 +- 模型实时发现和推理都会遵守 `upstreamHttpVersion`。`auto`、`http2` 与 `h2` 保持原有 HTTP/2 + transport;只有 `http1.1` 与 `h1` 会选择兼容模式。 - 保留 `cursor/grok-4.5-fast` 作为可选模型,但向 Cursor 发送规范的 `grok-4.5` 模型,并将独立的 `effort` 和 `fast=true` 值放入 `requested_model.parameters`。 - Cursor 原生本地 filesystem/shell/network 执行默认被拒绝。显式 `mcpServers` 与 diff --git a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md index 0393dcc569..f37f372cfd 100644 --- a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md +++ b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md @@ -220,7 +220,15 @@ affinity。这些策略不能规避 provider enforcement。 ## Cursor 提供者(`adapter: "cursor"`) -Cursor 桥接是实验性的。执行 `ocx login cursor` 之后,添加或编辑 `providers.cursor`。Cursor Router 的优化层级会作为独立的 Codex id 暴露,因为选择器无法渲染 Cursor 特定的模型参数: +Cursor 桥接是实验性的。执行 `ocx login cursor` 之后,添加或编辑 `providers.cursor`。 + +如果代理无法承载 Cursor 默认的 HTTP/2 stream,请将 `upstreamHttpVersion` 设置为 +`"http1.1"` 或其别名 `"h1"`。推理会切换到 Cursor 的 `RunSSE` + `BidiAppend` 兼容传输,`GetUsableModels` +实时发现也会使用 HTTP/1.1。该配置要求 `baseUrl` 使用 HTTPS。保持未设置或使用 `"auto"`, +则继续使用现有 HTTP/2 行为。 +在仪表板中,可通过 **Providers → Cursor → 设置 → Cursor 传输协议** 进行选择。 + +Cursor Router 的优化层级会作为独立的 Codex id 暴露,因为选择器无法渲染 Cursor 特定的模型参数: | Codex model | Cursor Router mode | | --- | --- | @@ -251,7 +259,7 @@ Cursor 由服务端驱动的本地工具默认是禁用的。Codex 继续使用 } ``` -请将该字段设置在 `providers.cursor` 上,而不是顶层。在仪表板中,使用 **Providers → Cursor → Edit JSON**,保存,然后重启。旧的 `unsafeAllowNativeLocalExec: true` 仅在未设置 `nativeLocalExec` 时,才等同于 `nativeLocalExec: "on"`。MCP、屏幕录制和 computer use 由 `mcpServers` 和 `desktopExecutor` 单独控制。 +请将 `nativeLocalExec` 设置在 `providers.cursor` 上,而不是顶层。在仪表板中,使用 **Providers → Cursor → Edit JSON**,保存,然后重启。旧的 `unsafeAllowNativeLocalExec: true` 仅在未设置 `nativeLocalExec` 时,才等同于 `nativeLocalExec: "on"`。MCP、屏幕录制和 computer use 由 `mcpServers` 和 `desktopExecutor` 单独控制。 每个 `mcpServers.` 都可以接受 `command`(stdio)或 `url`(Streamable HTTP)。stdio 还接受 `args`、`env` 和 `cwd`;HTTP 接受 `headers`。两者都支持 `enabled`(默认 true)和 `toolPrefix`。`desktopExecutor` 接受 `computerUseCommand`、`recordScreenCommand`、`cwd`、`env` 和 `timeoutMs`(默认 `30000`)。命令通过 `sh -c` 执行,从 stdin 读取一个 JSON 请求,并且必须向 stdout 写入一个 JSON 结果。 diff --git a/gui/src/components/provider-workspace/ProviderSettings.tsx b/gui/src/components/provider-workspace/ProviderSettings.tsx index fe9725e6a5..1509e13a14 100644 --- a/gui/src/components/provider-workspace/ProviderSettings.tsx +++ b/gui/src/components/provider-workspace/ProviderSettings.tsx @@ -27,6 +27,11 @@ const EMPTY_MODELS: string[] = []; type ChoicesStatus = "idle" | "loading" | "ready" | "error"; type PacingRule = { requestsPerMinute?: number; minIntervalMs?: number }; type PacingStatus = { enabled: boolean; queued: number; nextSlotInMs: number; lastStartedAt?: number; lastModelId?: string }; +type CursorHttpVersion = "http2" | "http1.1"; + +function effectiveCursorHttpVersion(value: WorkspaceItem["upstreamHttpVersion"]): CursorHttpVersion { + return value === "http1.1" || value === "h1" ? "http1.1" : "http2"; +} function numberDraft(value: number | undefined): string { return value === undefined ? "" : String(value); } function positiveRpm(value: string): number | undefined { @@ -67,6 +72,7 @@ export default function ProviderSettings({ const initialAuth = String(item.authMode ?? (item.keyOptional ? "local" : "key")); const liveModelDiscoverySupported = providerSupportsLiveModelDiscovery(item.name, item); const savedLiveModels = liveModelDiscoverySupported ? item.liveModels !== false : false; + const savedCursorHttpVersion = effectiveCursorHttpVersion(item.upstreamHttpVersion); const [adapter, setAdapter] = useState(item.adapter); const [baseUrl, setBaseUrl] = useState(item.baseUrl); const [defaultModel, setDefaultModel] = useState(item.defaultModel ?? ""); @@ -75,6 +81,7 @@ export default function ProviderSettings({ const [note, setNote] = useState(item.note ?? ""); const [allowPrivateNetwork, setAllowPrivateNetwork] = useState(item.allowPrivateNetwork ?? false); const [liveModels, setLiveModels] = useState(savedLiveModels); + const [cursorHttpVersion, setCursorHttpVersion] = useState(savedCursorHttpVersion); const [saving, setSaving] = useState(false); const [msg, setMsg] = useState<{ ok: boolean; text: string } | null>(null); const [accountMode, setAccountMode] = useState<"pool" | "direct">(item.codexAccountMode ?? "pool"); @@ -102,6 +109,7 @@ export default function ProviderSettings({ setNote(item.note ?? ""); setAllowPrivateNetwork(item.allowPrivateNetwork ?? false); setLiveModels(savedLiveModels); + setCursorHttpVersion(savedCursorHttpVersion); setPacingEnabled(item.requestPacing?.enabled === true); setPacingRpm(numberDraft(item.requestPacing?.requestsPerMinute)); setPacingDelay(numberDraft(item.requestPacing?.minIntervalMs)); @@ -109,7 +117,7 @@ export default function ProviderSettings({ setMsg(null); setModeMsg(null); queueMicrotask(() => setEndpointChoice(matchChoiceId(baseUrlChoices, item.baseUrl))); - }, [item.adapter, item.baseUrl, item.defaultModel, item.authMode, item.apiKeyTransport, item.keyOptional, item.note, item.allowPrivateNetwork, savedLiveModels, item.requestPacing, baseUrlChoices]); + }, [item.adapter, item.baseUrl, item.defaultModel, item.authMode, item.apiKeyTransport, item.keyOptional, item.note, item.allowPrivateNetwork, savedLiveModels, savedCursorHttpVersion, item.requestPacing, baseUrlChoices]); /* eslint-enable react-hooks/set-state-in-effect */ // Account mode syncs on its own: a mode PATCH refresh must not reset an in-progress @@ -185,7 +193,8 @@ export default function ProviderSettings({ || (adapter.trim() === "anthropic" && authMode === "key" && apiKeyTransport !== (item.apiKeyTransport ?? "x-api-key")) || note.trim() !== (item.note ?? "") || allowPrivateNetwork !== (item.allowPrivateNetwork ?? false) - || liveModels !== savedLiveModels; + || liveModels !== savedLiveModels + || (adapter.trim() === "cursor" && cursorHttpVersion !== savedCursorHttpVersion); const pacingDirty = pacingSignature(pacingDraft) !== pacingSignature(item.requestPacing); const formDirty = dirty || pacingDirty; @@ -242,6 +251,9 @@ export default function ProviderSettings({ // Keep omitted legacy values omitted unless the user actually changes this toggle. // Otherwise an unrelated settings save manufactures `liveModels: true` provenance. if (liveModelDiscoverySupported && liveModels !== (item.liveModels !== false)) patch.liveModels = liveModels; + if (adapter.trim() === "cursor" && cursorHttpVersion !== savedCursorHttpVersion) { + patch.upstreamHttpVersion = cursorHttpVersion === "http1.1" ? "http1.1" : null; + } if (supportsApiKeyTransport) patch.apiKeyTransport = apiKeyTransport; else if (item.apiKeyTransport !== undefined) patch.apiKeyTransport = ""; } @@ -287,7 +299,8 @@ export default function ProviderSettings({ setAdapter(item.adapter); setBaseUrl(item.baseUrl); setDefaultModel(item.defaultModel ?? ""); setAuthMode(initialAuth); setApiKeyTransport(item.apiKeyTransport ?? "x-api-key"); - setNote(item.note ?? ""); setAllowPrivateNetwork(item.allowPrivateNetwork ?? false); setLiveModels(savedLiveModels); setMsg(null); + setNote(item.note ?? ""); setAllowPrivateNetwork(item.allowPrivateNetwork ?? false); setLiveModels(savedLiveModels); + setCursorHttpVersion(savedCursorHttpVersion); setMsg(null); setPacingEnabled(item.requestPacing?.enabled === true); setPacingRpm(numberDraft(item.requestPacing?.requestsPerMinute)); setPacingDelay(numberDraft(item.requestPacing?.minIntervalMs)); setPacingModels({ ...(item.requestPacing?.models ?? {}) }); setEndpointChoice(matchChoiceId(baseUrlChoices, item.baseUrl)); @@ -356,6 +369,20 @@ export default function ProviderSettings({ setBaseUrl(e.target.value)} readOnly={plainBaseUrlLocked} disabled={plainBaseUrlLocked} /> )} + {adapter.trim() === "cursor" && ( + + )}