Skip to content

Route API User Agents by Actual Provider Target#976

Open
jatmn wants to merge 3 commits intoGitlawb:mainfrom
hicap-oss:api-client-version
Open

Route API User Agents by Actual Provider Target#976
jatmn wants to merge 3 commits intoGitlawb:mainfrom
hicap-oss:api-client-version

Conversation

@jatmn
Copy link
Copy Markdown
Collaborator

@jatmn jatmn commented May 2, 2026

Warning

Do not approve this PR until @kevincodex1 has confirmation from moonshot.ai that the KimiCode provider no longer blocks openclaude-cli.

Summary

This PR fixes how OpenClaude reports its client identity across different network paths.

Previously, the code mixed together:

  • Anthropic compatibility traffic, which must keep the upstream-compatible claude-cli identity and compatibility version
  • non-first-party/OpenAI-compatible traffic, which should identify as openclaude-cli and use the current public build version

This change separates those cases so each request path reports the correct client name and version.

What Changed

1. Split Anthropic-owned vs provider-routed user agents

Updated the HTTP user-agent helpers so:

  • Anthropic-owned endpoints continue using claude-cli/<compatibility-version>
  • provider-routed non-first-party API traffic uses openclaude-cli/<current-build-version>

Files:

  • src/utils/http.ts

2. Make API client routing follow the actual request target

Updated getAnthropicClient() to pass its already-computed first-party decision into the provider-routed user-agent helper.

This ensures user-agent selection follows the real request routing, including providerOverride, instead of relying only on ambient environment variables.

Files:

  • src/services/api/client.ts

3. Add focused regression coverage

Expanded tests to cover:

  • first-party compatibility traffic
  • Anthropic-owned endpoints under third-party provider environment
  • non-first-party/OpenAI-compatible provider traffic
  • explicit first-party override behavior

Files:

  • src/utils/http.test.ts
  • src/utils/userAgent.test.ts

Why

We needed to fix two opposite problems at the same time:

  1. Anthropic-owned requests must preserve upstream-compatible identity and compatibility versioning so they continue to work with first-party filters and version gates.
  2. OpenAI-compatible and other non-first-party connections should no longer report the compatibility version (99.0.0) as the client version, and should instead surface the actual current build version.

This PR makes that split explicit and request-target-aware.

User Impact

  • Anthropic-owned compatibility-sensitive flows continue to behave like upstream where required.
  • OpenAI-compatible/non-first-party connections now report OpenClaude branding and the current build version instead of the compatibility version.
  • providerOverride requests now use the correct user-agent for the actual target they are routed to.

Validation

Ran:

bun test src/utils/http.test.ts src/utils/userAgent.test.ts
bun run build
node dist/cli.mjs --version

Observed:

  • focused tests passed
  • build completed successfully
  • built artifact reported 0.7.0 (OpenClaude)

Commits

  • 0a1c56c Split public build version from compatibility headers
  • 9f86de0 Route API user agents by actual provider target

jatmn added 3 commits May 1, 2026 18:18
Keep compatibility-sensitive claude-cli/claude-code user agents on MACRO.VERSION while adding a shared public build version helper for MCP-facing metadata.

Update MCP client metadata and MCP user-agent strings to report DISPLAY_VERSION where appropriate without reintroducing first-party version-gate regressions.

Add focused regression tests covering:
- public build version helper behavior
- API client user-agent compatibility behavior
Split Anthropic-owned endpoint user agents from provider-routed API traffic.

Keep compatibility-sensitive Anthropic requests on claude-cli/99.0.0 while using openclaude-cli with the current public build version for non-first-party/OpenAI-compatible connections.

Wire getAnthropicClient() to pass its providerOverride-aware first-party decision into the user-agent helper so per-request routing stays correct.

Expand focused tests to cover first-party compatibility traffic, Anthropic-owned endpoints under third-party env, non-first-party provider traffic, and explicit first-party override behavior.
@jatmn
Copy link
Copy Markdown
Collaborator Author

jatmn commented May 2, 2026

@kevincodex1 we cant merge this without confirmation from moonshot that they whitelisted openclaude-cli or all kimicode connections are blocked by their servers with this PR.

@techbrewboss
Copy link
Copy Markdown
Collaborator

Looks good to merge from the code review side. I verified the focused user-agent tests, API client/shim routing tests, and build all pass.

Holding off on approval per the PR note until the KimiCode provider confirmation is available.

Copy link
Copy Markdown
Collaborator

@gnanam1990 gnanam1990 left a comment

Choose a reason for hiding this comment

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

Code-side review (not approving — respecting the merge-block in the PR description until @kevincodex1 has the moonshot/KimiCode whitelist confirmation).

Verified locally

  • bun test src/utils/http.test.ts src/utils/userAgent.test.ts → 6 pass, 0 fail
  • Diff is clean and tightly scoped to user-agent splitting

Code is sound

  1. getUserAgent() (compatibility) and getProviderApiUserAgent() (provider-routed) are now properly separated, with MACRO.VERSION (99.0.0 compat) reserved for first-party and getPublicBuildVersion() (DISPLAY_VERSION → real build) for non-first-party. The claude-cliopenclaude-cli token swap on third-party is exactly what the rebrand wants.
  2. First-party decision is now driven by shouldUseFirstPartyAnthropicAuth(providerOverride) — same function gating auth — so per-request routing and UA selection cannot diverge. Good fix for the providerOverride-aware case.
  3. MCP version field switched to getPublicBuildVersion() while the MCP name: 'claude-code' is preserved (correctly — that field is documented as the upstream feature-gating identifier).
  4. No red flags: no tengu_*, no USER_TYPE === 'ant' re-introduced (the test only uses USER_TYPE as the existing env passthrough), no new network calls, no new deps, no provider routing changes beyond the UA helper rewiring.

One thing worth checking before lifting the block

The block is real — any provider that whitelisted by exact UA string (KimiCode, but possibly others) will start being rejected once non-first-party flips to openclaude-cli/<DISPLAY_VERSION>. Worth a quick scan beyond moonshot:

  • Groq, Mistral, MiniMax, AI/ML API, Hicap (#979), iFlytek (#824), NVIDIA NIM (#960) — anyone we've heard from about UA filtering?

If only moonshot is gated, the moonshot confirmation alone is enough. If other providers do UA filtering, may want to pre-notify them or hold for a coordinated rollout.

Holding off on approve until @kevincodex1 / @jatmn give the green light.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants