Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docs-site/src/content/docs/ja/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,16 @@ filtered incomplete になります。実際のツール呼び出しを伴わな

## `cursor`

**対象:** `api2.cursor.sh` の HTTP/2 Connect ストリーミング
`agent.v1.AgentService/Run`。
**対象:** デフォルトでは `api2.cursor.sh` の HTTP/2 Connect ストリーミング
`agent.v1.AgentService/Run`。`upstreamHttpVersion: "http1.1"`(または `"h1"`)では Cursor の
HTTP/1.1 互換トランスポートを使い、サーバー出力を `agent.v1.AgentService/RunSSE`、クライアント
メッセージを `aiserver.v1.BidiService/BidiAppend` で送受信します。この設定は inference と live
model discovery の両方に適用されます。
**認証:** `provider.apiKey` または転送された authorization ヘッダーの Cursor OAuth/access token。

- 通常の fetch/parse 経路の代わりに `runTurn` を使います。リクエスト、サーバーイベント、ツール引数、使用量 checkpoint、クライアントレスポンスは `cursor/gen/agent_pb.ts` の `@bufbuild/protobuf` スキーマでエンコードしたのち Connect メッセージとして framing します。
- content-addressed blob で対話状態を再生し、サーバーツール呼び出しを Codex に再マッピングします。protobuf の `GetUsableModels` RPC でリアルタイム Cursor モデルを探し、run リクエストが wire に commit される前だけリトライします。
- ツールなしで正常終了したターンでは、返された ConversationStateStructure をプロセスローカルに保持し、検証済みの線形継続で checkpoint を再利用します。tool-result ターンでは、対象メッセージ境界が判明している場合、最後に正常終了したターンの checkpoint に未収録の suffix だけを追加します。ref のない prefix lookup は、記憶済みの Cursor conversation または安定した client thread(制限付きの Desktop session/thread fallback を含む)があり、同じ provider conversation が所有する checkpoint が一意に一致する場合だけ許可します。それ以外は full replay に戻ります。compaction、helper/shadow の分離、account/model の不一致、ref の欠落、decode の失敗、forced-fresh recovery、invalid_argument retry でも full replay を使います。プロセスを再起動するとメモリ内 store は失われ、full replay になります。Cursor Connect は権威ある cache_read_tokens を公開しないため、OpenCodex usage は cache-hit counter ではありません。制限付き Desktop fallback が保存するのはプロセスローカルで HMAC から導出した owner だけで、raw session/thread header や OAuth/authorization material を checkpoint state に書き込みません。OAuth-backed live transport とアカウントで絞り込む live model discovery は実験的です。ログインと transport の設定は [provider guide](/ja/guides/providers/) と [Cursor provider configuration](/ja/reference/configuration/providers/#cursor-provider-adapter-cursor) を参照してください。checkpoint reuse 自体は自動で、ユーザー設定はありません。
- `cursor/grok-4.5-fast` は選択可能なモデルとして維持しつつ、Cursor には正規の `grok-4.5`
モデルを送信し、個別の `effort` および `fast=true` 値は `requested_model.parameters` に格納します。
- Cursor ネイティブのローカルファイルシステム/shell/network 実行はデフォルトで拒否します。明示的な `mcpServers` と `desktopExecutor` 統合はそれぞれ別の opt-in です。`unsafeAllowNativeLocalExec` はより広い組み込み executor を有効にし、Codex の承認/サンドボックスルールを迂回します。
Expand Down
20 changes: 16 additions & 4 deletions docs-site/src/content/docs/ko/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,11 @@ commentary로 유지하고 비공개 완료 툴을 한 번 검증합니다.

## `cursor`

**대상:** `api2.cursor.sh`의 HTTP/2 Connect 스트리밍
`agent.v1.AgentService/Run`.
**대상:** 기본값은 `api2.cursor.sh`의 HTTP/2 Connect 스트리밍
`agent.v1.AgentService/Run`입니다. `upstreamHttpVersion: "http1.1"` 또는 `"h1"`을 설정하면
Cursor의 HTTP/1.1 호환 조합을 사용합니다. 서버 출력은 `agent.v1.AgentService/RunSSE`, 클라이언트
메시지는 `aiserver.v1.BidiService/BidiAppend`로 전송합니다. 이 설정은 추론과 live model
discovery에 모두 적용됩니다.
**인증:** `provider.apiKey` 또는 전달된 authorization 헤더의 Cursor OAuth/access token.

- 일반 fetch/parse 경로 대신 `runTurn`을 사용합니다. 요청, 서버 이벤트, 툴 인자, 사용량 checkpoint,
Expand All @@ -151,11 +154,20 @@ commentary로 유지하고 비공개 완료 툴을 한 번 검증합니다.
재시도합니다.
- 도구 없이 정상 완료된 턴 뒤에는 Cursor가 돌려준 ConversationStateStructure를 프로세스 로컬
store에 보관하고, 검증된 선형 이어말하기에서는 전체 root history를 다시 만들지 않고 그
checkpoint를 재사용합니다. tool-result 턴은 마지막 정상 완료 턴의 checkpoint에 커버되지 않은
suffix만 붙입니다. compaction, helper/shadow 격리, 계정/모델 불일치, 없는 ref, decode 실패,
checkpoint를 재사용합니다. tool-result 턴은 커버된 메시지 경계를 알 수 있을 때만 마지막 정상
완료 턴의 checkpoint에 커버되지 않은 suffix를 붙입니다. ref 없는 prefix 조회는 기억된 Cursor
대화 또는 안정적인 클라이언트 스레드
(범위가 제한된 Desktop session/thread 대체 식별자 포함)와 같은 provider 대화가 소유한
checkpoint가 있을 때만 허용하며, 그 외에는 full replay합니다.
compaction, helper/shadow 격리, 계정/모델 불일치, 없는 ref, decode 실패,
forced-fresh 복구, invalid_argument 재시도는 기존 full replay로 돌아갑니다. 프로세스 재시작은
메모리 store를 버리고 full replay합니다. Cursor Connect는 권위 있는 cache_read_tokens를 주지
않으므로 OpenCodex usage만 보고 cache hit라고 단정하지 않습니다.
범위가 제한된 Desktop 대체 식별자는 프로세스 로컬 HMAC 파생 소유자만 보관하며, 원본
session/thread 헤더나 OAuth/authorization 자료를 checkpoint 상태에 쓰지 않습니다. OAuth 기반
live transport와 계정별 live model discovery는 아직 실험 기능입니다. 로그인과 transport 설정은
[공급자 가이드](/ko/guides/providers/)와 [Cursor 공급자 설정](/ko/reference/configuration/providers/#cursor-provider-adapter-cursor)을
참고하세요. checkpoint 재사용 자체는 자동이며 사용자 설정이 없습니다.
- `cursor/grok-4.5-fast`는 선택 가능한 모델로 유지하되, Cursor에는 정식 `grok-4.5` 모델을 보내고
별도의 `effort`, `fast=true` 값은 `requested_model.parameters`에 담습니다.
- Cursor 네이티브 로컬 파일시스템/shell/network 실행은 기본적으로 거부합니다. 명시적인
Expand Down
8 changes: 8 additions & 0 deletions docs-site/src/content/docs/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,18 @@ compatibility pair: `agent.v1.AgentService/RunSSE` for server output and
in a process-local store and reuses that checkpoint on the next validated linear continuation
instead of rebuilding the full root history. Tool-result turns reuse the last completed-turn
checkpoint plus only the uncovered suffix when the covered message boundary is known.
Ref-less prefix lookup requires a remembered Cursor conversation or stable client thread
(including the bounded Desktop session/thread fallback) and a checkpoint owned by that same
provider conversation; otherwise it full-replays.
Comment thread
luvs01 marked this conversation as resolved.
Compaction, helper/shadow isolation, account/model mismatch, missing refs, decode failures,
forced-fresh recovery, and invalid_argument retries fall back to the existing full replay. A
process restart drops the in-memory store and full-replays. Cursor Connect still does not expose
authoritative cache_read_tokens, so OpenCodex usage is not a cache-hit counter.
The bounded Desktop fallback stores only a process-local HMAC-derived owner; raw session/thread
headers and OAuth/authorization material are never written to checkpoint state. Cursor's
OAuth-backed live transport and account-filtered model discovery remain experimental; see the
[provider guide](/guides/providers/) and [Cursor provider configuration](/reference/configuration/providers/#cursor-provider-adapter-cursor)
for login and transport settings. Checkpoint reuse itself is automatic and has no user setting.
- 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`,
Expand Down
24 changes: 22 additions & 2 deletions docs-site/src/content/docs/ru/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ incomplete. `TOOL_USE` без фактического вызова инстру

## `cursor`

**Назначение:** `agent.v1.AgentService/Run` Cursor поверх потокового HTTP/2 Connect на
`api2.cursor.sh`.
**Назначение:** по умолчанию `agent.v1.AgentService/Run` Cursor поверх потокового HTTP/2 Connect
на `api2.cursor.sh`. При `upstreamHttpVersion: "http1.1"` (или `"h1"`) используется совместимый
транспорт HTTP/1.1: `agent.v1.AgentService/RunSSE` для вывода сервера и
`aiserver.v1.BidiService/BidiAppend` для сообщений клиента. Эта настройка применяется и к
inference, и к live model discovery.
**Аутентификация:** Cursor OAuth/access token из `provider.apiKey` или из переданного заголовка
authorization.

Expand All @@ -155,6 +158,23 @@ authorization.
- Воспроизводит состояние диалога через content-addressed blob'ы, отображает серверные вызовы
инструментов обратно в Codex, обнаруживает актуальные модели Cursor через protobuf RPC
`GetUsableModels` и повторяет попытки только до того, как run-запрос зафиксирован на wire.
- После успешно завершённого хода без инструментов хранит возвращённую ConversationStateStructure
локально в процессе и повторно использует checkpoint для проверенного линейного продолжения. Ходы
с результатом инструмента используют checkpoint последнего завершённого хода и только ещё не
охваченный suffix, когда известна граница охваченных сообщений. Поиск по префиксу без ref разрешён
только при наличии запомненного разговора Cursor или стабильного идентификатора client thread
(включая ограниченный fallback по Desktop session/thread) и единственного совпадающего checkpoint,
принадлежащего тому же разговору provider; иначе выполняется full replay. Compaction, изоляция
helper/shadow, несовпадение account/model, отсутствие ref, ошибки decode, forced-fresh recovery и
повтор после invalid_argument также используют full replay. Перезапуск процесса удаляет хранилище
из памяти и приводит к full replay. Cursor Connect не предоставляет достоверный
cache_read_tokens, поэтому usage OpenCodex не является счётчиком cache hit. Ограниченный Desktop
fallback хранит только владельца, выведенного через HMAC локально в процессе; исходные заголовки
session/thread и данные OAuth/authorization в checkpoint state не записываются. Live transport с
OAuth и фильтрация live model discovery по аккаунту остаются экспериментальными. Настройки входа
и transport описаны в [руководстве по провайдерам](/ru/guides/providers/) и
[конфигурации провайдера Cursor](/ru/reference/configuration/providers/#cursor-provider-adapter-cursor).
Повторное использование checkpoint выполняется автоматически и не имеет пользовательской настройки.
- Сохраняет `cursor/grok-4.5-fast` доступной для выбора, но отправляет Cursor каноническую модель
`grok-4.5`, помещая отдельные значения `effort` и `fast=true` в `requested_model.parameters`.
- Нативное для Cursor локальное выполнение операций с файловой системой/shell/сетью по умолчанию
Expand Down
13 changes: 13 additions & 0 deletions docs-site/src/content/docs/zh-cn/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ Cursor 的 HTTP/1.1 兼容传输:通过 `agent.v1.AgentService/RunSSE` 接收
Connect message。
- 经 content-addressed blob 重放对话状态,把 server tool call 映射回 Codex,用 protobuf
`GetUsableModels` RPC 发现实时 Cursor 模型,并且只在 run request 尚未 commit 到 wire 前重试。
- 对不含工具且正常完成的 turn,会在进程本地保存返回的 ConversationStateStructure,并在经过验证的
线性 continuation 中复用 checkpoint。tool-result turn 会在已知覆盖消息边界时,复用最后一个已完成
turn 的 checkpoint,并只追加尚未覆盖的 suffix。无 ref 的 prefix lookup 仅在存在已记忆的 Cursor
conversation 或稳定 client thread(包括受限的 Desktop session/thread fallback),且唯一匹配的
checkpoint 由同一 provider conversation 所有时才允许;否则执行 full replay。compaction、
helper/shadow 隔离、account/model 不匹配、ref 缺失、decode 失败、forced-fresh recovery 以及
invalid_argument 重试也会回退到 full replay。进程重启会丢弃内存 store 并执行 full replay。
Cursor Connect 不提供权威的 cache_read_tokens,因此 OpenCodex usage 不是 cache hit 计数器。
受限的 Desktop fallback 只保存进程本地由 HMAC 派生的 owner;原始 session/thread header 与
OAuth/authorization 材料不会写入 checkpoint state。基于 OAuth 的 live transport 和按账号过滤的
live model discovery 仍是实验功能;登录与 transport 设置参见[提供商指南](/zh-cn/guides/providers/)
和 [Cursor 提供商配置](/zh-cn/reference/configuration/providers/#cursor-provider-adapter-cursor)。
checkpoint 复用本身是自动的,没有用户设置。
- 模型实时发现和推理都会遵守 `upstreamHttpVersion`。`auto`、`http2` 与 `h2` 保持原有 HTTP/2
transport;只有 `http1.1` 与 `h1` 会选择兼容模式。
- 保留 `cursor/grok-4.5-fast` 作为可选模型,但向 Cursor 发送规范的 `grok-4.5` 模型,并将独立的
Expand Down
12 changes: 7 additions & 5 deletions src/adapters/cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { createCursorKvStore, type CursorKvStore } from "./cursor/kv-store";
import { mapCursorServerMessage } from "./cursor/message-mapper";
import {
createCursorRequest,
cursorClientThreadOwner,
cursorCoveredPrefixDigest,
cursorInstructionDigest,
} from "./cursor/request-builder";
Expand Down Expand Up @@ -265,12 +266,13 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
request = createCursorRequest(_parsed, { forceFreshConversation: true });
rekeyContextUsage(failedConversationId, request.conversationId);
_parsed._cursorConversationId = request.conversationId;
// Persist recovery for store:false clients that only send a parent thread id, so the
// next turn does not recompute the stale deterministic thread hash. Isolated helper /
// compaction turns must not park their throwaway id under the parent thread key.
if (_parsed._clientThreadId && _parsed._cursorIsolateConversation !== true) {
// Persist recovery for store:false clients that send any stable Cursor thread owner, so
// the next turn does not recompute the stale deterministic thread hash. Isolated helper /
// compaction turns must not park their throwaway id under the parent or Desktop owner.
const threadOwner = cursorClientThreadOwner(_parsed);
if (threadOwner && _parsed._cursorIsolateConversation !== true) {
rememberCursorThreadConversation(
_parsed._clientThreadId,
threadOwner,
request.conversationId,
_parsed._cursorIdentityScope,
);
Expand Down
25 changes: 15 additions & 10 deletions src/adapters/cursor/checkpoint-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export function commitCursorCheckpoint(input: {
}

export function getCursorCheckpointForPrefix(input: {
conversationId: string;
prefixDigest: string;
systemDigest: string;
coveredMessageCount: number;
Expand All @@ -244,17 +245,21 @@ export function getCursorCheckpointForPrefix(input: {
}): CursorCheckpointSnapshot | undefined {
prune();
const refs = store.prefixIndex.get(input.prefixDigest);
if (!refs || refs.size !== 1) return undefined;
const [ref] = refs;
if (!ref) return undefined;
const snapshot = getCursorCheckpoint(ref);
if (!snapshot) return undefined;
if (!refs) return undefined;
const identityScope = input.identityScope?.trim() || "local";
if (snapshot.systemDigest !== input.systemDigest) return undefined;
if (snapshot.coveredMessageCount !== input.coveredMessageCount) return undefined;
if (snapshot.identityScope !== identityScope) return undefined;
if (snapshot.modelId !== input.modelId) return undefined;
return snapshot;
let foundRef: string | undefined;
for (const ref of refs) {
const snapshot = store.snapshots.get(ref);
if (!snapshot) continue;
if (snapshot.conversationId !== input.conversationId) continue;
if (snapshot.systemDigest !== input.systemDigest) continue;
if (snapshot.coveredMessageCount !== input.coveredMessageCount) continue;
if (snapshot.identityScope !== identityScope) continue;
if (snapshot.modelId !== input.modelId) continue;
if (foundRef) return undefined;
foundRef = ref;
}
return getCursorCheckpoint(foundRef);
}

export function getLatestCursorCheckpoint(
Expand Down
Loading
Loading