Skip to content

[WRONG BRANCH] feat(cursor): live GetUsableModels.maxMode decode + OAuth poll fail-fast - #2323

Merged
lidge-jun merged 2 commits into
codex/senpi-cursor-t03from
codex/senpi-cursor-t04
Aug 22, 2026
Merged

[WRONG BRANCH] feat(cursor): live GetUsableModels.maxMode decode + OAuth poll fail-fast#2323
lidge-jun merged 2 commits into
codex/senpi-cursor-t03from
codex/senpi-cursor-t04

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

  • T06: decode the maxMode field from GetUsableModels and return it alongside model ids so callers can honor it instead of hardcoding RequestedModel.maxMode to false. The field already exists in the generated proto (agent_pb.ts:2667).
  • T07 (senpi #905): OAuth poll fail-fasts on 400/401/403/410 instead of burning the transient-error budget. 404 remains "not approved yet"; 429 keeps polling.

Stacked on #2322 (T05 unknown-exec typed reply).

Verification

  • bun test tests/cursor-oauth.test.ts tests/cursor-discovery.test.ts tests/cursor-static-catalog.test.ts tests/cursor-hardening.test.ts tests/cursor-effort-suffix.test.ts — 86 pass / 0 fail
  • bun run typecheck — exit 0

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 21, 2026 23:56
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 013609d8-c357-4168-9c36-e46699397801

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 21, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f61b82d8c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!isValidModelDiscoveryModelId(id) || seenIds.has(id)) continue;
seenIds.add(id);
ids.push(id);
if ((model as { maxMode?: boolean }).maxMode === true) maxModeIds.add(id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate max-mode metadata into run requests

When GetUsableModels marks a model with maxMode=true, this new set exists only in the fetch result: src/codex/catalog/provider-fetch.ts:1226-1236 reads only models and caches catalog rows without the capability, while src/adapters/cursor/protobuf-request.ts:964-969 still always writes maxMode: false. Consequently T06 never changes an outbound request, including requests for max-mode/1M-window models; carry this metadata through the canonical catalog and request derivation and verify that a decoded true reaches RequestedModel.

AGENTS.md reference: src/AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

Comment thread src/oauth/cursor.ts
Comment on lines +131 to +132
if (response.status === 400 || response.status === 401 || response.status === 403 || response.status === 410) {
throw new Error(`Cursor auth login rejected (HTTP ${response.status})`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Let terminal poll rejections escape the retry catch

For a 400, 401, 403, or 410 response, this new error is thrown inside the surrounding try, so the catch immediately treats it as a transient error. A single definitive rejection therefore keeps polling, and three such responses produce the generic Too many consecutive errors message instead of failing fast with the status. Re-throw a distinguishable terminal error outside the transient handling and add a regression asserting one fetch attempt for each terminal status.

AGENTS.md reference: src/AGENTS.md:L24-L26

Useful? React with 👍 / 👎.

Comment thread src/oauth/cursor.ts
Comment on lines +134 to +135
// 429 keeps polling; the backoff already slows down.
if (response.status === 429) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Back off after rate-limited poll responses

When the poll endpoint returns 429, this direct continue bypasses both the delay increase and the error-state reset. Repeated rate limits therefore continue at the original one-second cadence despite the comment claiming that backoff slows them down, and any earlier consecutiveErrors remain charged against a later transient failure. Update the delay and relevant state before continuing, with a focused 429-sequence regression.

AGENTS.md reference: src/AGENTS.md:L24-L26

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 56 / 80

지금 dev HEAD 6e2a6b6b0. 이 시간 #2325(#2289) + #2324(#2296) 착지. 이 PR 베이스는 dev가 아님. codex/senpi-cursor-t03 = #2322(T05). 그 아래 #2321 드래프트, #2320 T01. 드래프트 아님. 파일 3. +17/-6. gh api pulls/2323/files: src/adapters/cursor/live-models.ts +5/-2, src/oauth/cursor.ts +7, tests/cursor-hardening.test.ts +5/-4. T06 GetUsableModels maxMode 디코드 + T07 OAuth poll fail-fast. 한 PR에 레인 둘. 스플릿 PR 아님.

T06. GetUsableModelsResponse.models는 이미 ModelDetails. proto optional bool max_mode = 7 (agent_pb.ts:2616-2619). 이 PR은 ok 분기에 maxModeIds?: Set<string>를 붙임. maxMode === true만 셋에 넣음. 캐스트는 불필요. 호출자가 안 씀. provider-fetch.ts:1235-1236liveResult.models만 필터. provider-routes.ts:772-776도 개수 메시지. 런 요청은 protobuf-request.ts:964-966RequestedModel.maxMode: false 하드코딩 (proto field 2, agent_pb.ts:2664-2667). 본문 주장이 callers honor. 와이어는 그대로 false. 디코드만 하고 안 씀. maxModeIds는 빈 Set이어도 항상 붙음. 그래서 기존 toEqual({ ok: true, models })가 깨짐. 테스트를 objectContaining으로 헐겁게 함. maxMode=true 픽스처 0.

T07. 지금 pollCursorAuth (cursor.ts:117-146)는 404만 pending. 그 외 non-ok는 throw 후 catch가 consecutiveErrors를 올림. 3이면 Too many consecutive errors during Cursor auth polling. 이 PR은 400/401/403/410 throw를 try 안에 넣음. catch가 그대로 삼킴. 1–2번은 폴링 유지. 3번은 메시지까지 바뀜. fail-fast가 아님. 429 continue는 맞음. 테스트 파일에 poll 401/400/410/429 케이스 0. tests/cursor-oauth.test.ts는 404→200, abort, missing tokens만. refresh 쪽 401 fail-fast 테스트(:109-114)는 이미 있음. poll은 그 패턴을 안 따라감.

막힘. (1) T07 throw를 catch 밖으로 빼거나, catch에서 login rejected를 재throw 해라. 안 그러면 senpi #905가 노옵임. (2) T06은 protobuf-request.ts:966 maxModemaxModeIds.has(modelId)로 연결하기 전엔 사용자 체감 0. 카탈로그 Set을 GUI에 뿌리지 말고 런 빌더로 넘겨라. 연결 전엔 타입만 넓히지 말 것. (3) 테스트가 핵심을 안 잠금. maxMode=true → Set 포함, false/absent → 미포함. poll 401 1회 종료, 429는 폴링 유지. (4) T06이랑 T07은 파일 레인 다름. 크기는 작음. 쪼개기 전에 T07 catch부터 고쳐라.

types.ts/config.ts 안 만짐. 스플릿 안 씹힘. 리베이스하지 말고 닫으라는 케이스 아님. 스플릿이 무효화한 중복도 아님. 이 PR만 현재 HEAD에 올리지 말 것. #2322/#2321/#2320 스택. #2318이랑 파일 안 겹침. #2307이랑 합치지 말 것. #2188 L1–L9 사이드카 + routed vision(#2306) 이미 dev. x_search 넣지 말 것. Grok OAuth Chat 기본(#2255), GUI opt-in Responses(#2266)랑 다른 레인임. 프리뷰 배포 아님. 카탈로그는 Ox Alpha x-preview-f-free + deepseek-v4-flash-vision-exp. v2.29.0 태그됨. v2.30.0-preview.20260821 있음. 비전공자 유지. T07이 catch에 삼켜지고 T06이 미연결 + 스택 3단이라 56.

해결방안: 닫지 말 것. T07부터. 400/401/403/410은 catch가 재시도하면 안 됨. 재throw 또는 try 밖으로. 429 continue 유지. 404 pending 유지. 테스트: 401 1회 throw, 429 2회+ 후 200, 404→200 기존 유지. T06은 protobuf-request.ts가 Set을 honor하기 전엔 타입 확장을 머지하지 말거나, honor 커밋을 같은 스택에 붙여라. objectContaining 완화를 되돌리고 maxMode=true 픽스처를 넣어라. #2322 머지 후 리베이스. 라벨 건드리지 말 것. 스플릿이 live-models.ts/oauth/cursor.ts를 옮기면 리베이스하지 말고 닫고 다시 짜라. 지금은 그 정도 아님.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun
lidge-jun force-pushed the codex/senpi-cursor-t03 branch from 0162bc2 to a92fd4e Compare August 22, 2026 01:49
…instead of silence (#2322)

T05 (senpi contract): a frame that cannot be answered gets a typed in-band
error + stream-close so the server unblocks with a known failure. Previously
this returned an empty reply (silence), which is the stall class senpi
explicitly refused. #116 was about an unhandled throw propagating to
failAndClear and killing the whole gRPC connection; a typed ExecClientThrow
does not do that.

Research unit: devlog/_plan/260822_senpi_cursor_transfer/090 T05.
…ast on definitive rejections

T06: decode the maxMode field from GetUsableModels and return it alongside
model ids so callers can honor it instead of hardcoding RequestedModel.maxMode
to false. The field already exists in the generated proto (agent_pb.ts:2667).

T07 (senpi #905): OAuth poll fail-fasts on 400/401/403/410 instead of burning
the transient-error budget. 404 remains 'not approved yet'; 429 keeps polling.

Research unit: devlog/_plan/260822_senpi_cursor_transfer/090 T06+T07.
@lidge-jun
lidge-jun force-pushed the codex/senpi-cursor-t04 branch from f61b82d to 56eb69f Compare August 22, 2026 01:52
@github-actions github-actions Bot changed the title feat(cursor): live GetUsableModels.maxMode decode + OAuth poll fail-fast [WRONG BRANCH] feat(cursor): live GetUsableModels.maxMode decode + OAuth poll fail-fast Aug 22, 2026
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • wrong target branch (codex/senpi-cursor-t03); retarget to dev.

What to do

  • Retarget this PR to dev — all contributions go to dev.

Its title has been prefixed with [WRONG BRANCH].
Automatic draft conversion failed (token cannot change draft status). Please convert this pull request to a draft manually. The required enforce-target check will keep failing until every issue above is resolved.

@github-actions
github-actions Bot marked this pull request as draft August 22, 2026 01:53
@lidge-jun
lidge-jun marked this pull request as ready for review August 22, 2026 01:56
@lidge-jun
lidge-jun merged commit 13bbf54 into codex/senpi-cursor-t03 Aug 22, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant