Skip to content

fix(providers): match the OpenCode Go destination canonically - #5165

Merged
lidge-jun merged 1 commit into
lidge-jun:devfrom
agentHits:fix/opencode-go-canonical-url
Sep 19, 2026
Merged

lidge-jun merged 1 commit into
lidge-jun:devfrom
agentHits:fix/opencode-go-canonical-url

Conversation

@agentHits

@agentHits agentHits commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to the review on #5067 (abhisheksharma2411): isOpenCodeGoDestination string-compared URLs, so an operator row like https://OpenCode.ai/zen/go/v1 or https://opencode.ai:443/zen/go/v1 silently missed the patient 429 fallback with no indication why. Both the row URL and the registry candidates (including destinationAliases) now go through the shared normalizedBaseUrl from quota/vendor-probes-key — lowercased origin, default ports dropped, userinfo/query/fragment refused — so destination identity is answered in one place. The fail-closed direction is unchanged: anything unparsable still gets no fallback.

Verification

  • bun test tests/providers/rate-limit-retry.test.ts — 18 pass, 0 fail, including a new canonical-match test (uppercase host, explicit :443, trailing slash match; userinfo, query, look-alike host refuse).
  • bun test tests/providers/provider-quota.test.ts tests/providers/provider-account-quota.test.ts — 238 pass, 0 fail.
  • bun run typecheck — clean.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed (code comment carries the contract).
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults (authMode gate untouched; unparsable URLs still fail closed).

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes
    • Improved OpenCode Go endpoint recognition for URLs with trailing slashes, mixed-case hostnames, or explicit default ports.
    • Prevented look-alike hosts and URLs containing user information, query parameters, or fragments from being incorrectly recognized.
    • Improved retry behavior by applying the appropriate patient retry policy to valid OpenCode Go destinations.

@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: a4d88bcd-903e-4659-8f26-255c044920c2

📥 Commits

Reviewing files that changed from the base of the PR and between 118c66a and 8631aaa.

📒 Files selected for processing (3)
  • src/providers/key-failover.ts
  • src/providers/quota/vendor-probes-key.ts
  • tests/providers/rate-limit-retry.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The change reuses the shared URL canonicalizer for OpenCode Go destination detection. It adds canonical matching tests for trailing slashes, host casing, default ports, query strings, userinfo, and look-alike hosts.

Changes

OpenCode Go destination matching

Layer / File(s) Summary
Expose shared URL canonicalization
src/providers/quota/vendor-probes-key.ts
normalizedBaseUrl is now exported. Its signature and implementation are unchanged.
Canonicalize failover destination checks
src/providers/key-failover.ts, tests/providers/rate-limit-retry.test.ts
isOpenCodeGoDestination normalizes the provider URL and registry candidates before comparison. The tests verify equivalent canonical URLs and rejection of query strings, userinfo, and look-alike hosts.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: canonical matching for OpenCode Go destinations in provider logic.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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 bug Something isn't working label Sep 19, 2026
@github-actions

github-actions Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request is already Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers: @lidge-jun @Ingwannu

@lidge-jun
lidge-jun force-pushed the fix/opencode-go-canonical-url branch from c553ae5 to 8631aaa Compare September 19, 2026 12:32
@agentHits
agentHits marked this pull request as ready for review September 19, 2026 12:53
@github-actions
github-actions Bot marked this pull request as draft September 19, 2026 12:55
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 34 / 80

OpenCode Go로 요청을 보내다 서버가 "잠깐 너무 많다"(429)고 하면, 키를 갈아타지 않고 조금 기다렸다가 같은 주소로 다시 보낸다. #5067이 그 기다림을 넣었다. 주소를 글자 그대로 비교해서, https://OpenCode.ai/zen/go/v1이나 https://opencode.ai:443/zen/go/v1은 같은 곳인데도 기다림을 못 받았다. 왜 빠졌는지는 화면에 안 남았다.

이 PR은 양쪽 주소를 normalizedBaseUrl에 넣고 비교한다. 호스트는 소문자로, 443 같은 기본 포트는 빼고, 끝의 /는 지운다. 주소에 아이디·비밀번호, ? 뒤 값, # 뒤 값이 있으면 기다림을 안 준다. 못 읽는 주소도 안 준다. 레지스트리에 적힌 공식 주소와 별칭을 같은 함수로 본다. 테스트는 대문자, :443, 끝 슬래시는 통과하고, 쿼리·계정정보·opencode.ai.evil.net 같은 흉내 호스트는 거절한다. 기준 브랜치는 dev다. 아직 초안이고, 설명의 준비 체크는 네 칸 모두 비어 있다.

src/providers/key-failover.ts - 비교 함수를 src/providers/quota/vendor-probes-key.ts에서 가져온다. 그 파일은 사용량을 서버에 물어보는 모듈이다. 요청을 보내는 쪽이 이미 key-failover를 불러오므로, 429 판별이 사용량 조사 모듈까지 같이 읽게 된다. 같은 파일 48행 isCanonicalOpenCodeGoBaseUrl은 레지스트리가 아니라 파일 안 상수 https://opencode.ai/zen/go/v1만 본다. 지금 두 문자열은 같다. 나중에 한쪽만 고치면, 사용량 판정과 429 재시도가 다른 주소를 공식으로 보게 된다.

normalizedBaseUrl - 주석은 쿼리나 프래그먼트가 있으면 절대 안 맞는다고 적는다. Node에서 주소 끝이 ?만, 또는 #만일 때는 search와 hash가 빈 문자열이라 공식 주소와 같다. ?x=1#x는 거절된다. 테스트는 #x를 안 넣었다. 서버는 # 뒤를 받지 않아서, #만 붙은 주소가 재시도를 받는 것은 해롭지 않다. 주석만 코드보다 세다.

메인테이너의 판단이 필요한 지점

함수를 사용량 파일에 둘지, 짧은 공용 파일로 뺄지. 동작은 맞고, 누가 누구를 불러오는지만 어색하다.

URL 해석기가 https://opencode.ai/zen/go/v1/../v1..를 접어서 공식 주소와 같다고 본다. 예전 글자 비교는 이걸 거절했다. 같은 곳으로 보는 쪽을 유지하면 된다.

너의 추천

막는 버그는 없다. 대문자와 :443은 이 고침이 맞춘다. 합치기 전에 normalizedBaseUrl을 사용량 모듈 밖으로 빼서, key-failover가 그 파일을 직접 안 보게 하는 편이 낫다. isCanonicalOpenCodeGoBaseUrl도 그 함수와 레지스트리 주소를 같이 쓰면 두 판정이 안 갈라진다. 그 정리를 이 PR에 억지로 넣지 않아도, 고침 자체는 닫을 이유가 없다.

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

Follow-up to the review on lidge-jun#5067: isOpenCodeGoDestination string-compared URLs, so an uppercase hostname or an explicit default port silently missed the patient 429 fallback. Both sides now go through the shared normalizedBaseUrl from quota/vendor-probes-key (lowercased origin, default ports dropped, userinfo/query/fragment refused), keeping destination identity answered in one place. Alias support is unchanged.
@agentHits
agentHits force-pushed the fix/opencode-go-canonical-url branch from 8631aaa to 24f9972 Compare September 19, 2026 14:34
@github-actions
github-actions Bot marked this pull request as ready for review September 19, 2026 16:18
@lidge-jun
lidge-jun merged commit 5c943d9 into lidge-jun:dev Sep 19, 2026
10 of 12 checks passed
lidge-jun added a commit that referenced this pull request Sep 19, 2026
…inline

The OpenCode Go destination test added by #5165 carried an inline
https URL with userinfo. privacy:scan reads source text, so its email
detector saw the password and host as an address and failed the gates
job on dev, blocking every branch that merged current dev.

isAllowedEmail already carries one URL-userinfo exemption for a
chatgpt.com fixture, so adding a second entry was available and is the
wrong fix. That allowlist is what keeps the detector able to fail on a
real address, and each entry spends a little of that. Assembling the
URL through the username and password setters removes the literal
entirely and leaves nothing to exempt.

The input under test does not change. new URL with the same path and
those two setters serializes to exactly the string it replaces, so the
case still proves that a base URL carrying userinfo refuses the patient
same-target fallback.

No local suite, focused test, typecheck or build was run. Exact-head
hosted CI is the execution evidence.
lidge-jun added a commit that referenced this pull request Sep 19, 2026
…inline (#5195)

The OpenCode Go destination test added by #5165 carried an inline
https URL with userinfo. privacy:scan reads source text, so its email
detector saw the password and host as an address and failed the gates
job on dev, blocking every branch that merged current dev.

isAllowedEmail already carries one URL-userinfo exemption for a
chatgpt.com fixture, so adding a second entry was available and is the
wrong fix. That allowlist is what keeps the detector able to fail on a
real address, and each entry spends a little of that. Assembling the
URL through the username and password setters removes the literal
entirely and leaves nothing to exempt.

The input under test does not change. new URL with the same path and
those two setters serializes to exactly the string it replaces, so the
case still proves that a base URL carrying userinfo refuses the patient
same-target fallback.

No local suite, focused test, typecheck or build was run. Exact-head
hosted CI is the execution evidence.

Co-authored-by: lidge-jun <lidge-jun@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants