Skip to content

feat(oauth): add Qoder CN (qoder.cn) as a first-class provider - #18580

Open
Junior-HJ wants to merge 1 commit into
cheaper-inference:release/v3.8.53from
Junior-HJ:feat/qoder-cn-site
Open

Junior-HJ wants to merge 1 commit into
cheaper-inference:release/v3.8.53from
Junior-HJ:feat/qoder-cn-site

Conversation

@Junior-HJ

Copy link
Copy Markdown
Contributor

What

Adds Qoder CN (qoder.cn) as a first-class provider, with no change to the existing global qoder entry.

Previously the only way to reach the China deployment was to point the global Qoder OAuth env vars (QODER_OAUTH_*) at qoder.cn. That conflated two separate accounts — a CN session and a global session could not both exist, and the model-scoped throttle work in flight (#18572) would see them as the same provider.

Why a dedicated entry

  • Separate slot. qoder-cn is its own registry id, canonical provider row and OAuth config, so a CN account and a global account never race for the same connection.
  • Single source of truth for models. The CN entry reuses qoderProvider.models rather than copying the catalog; a model added upstream lands on both sites.
  • Global entry untouched. qoderProvider (id, baseUrl, executor, headers) is byte-identical to before — asserted by a test.

Security note (Hard Rule #11)

An earlier revision of QODER_CONFIG embedded a literal client_id/client_secret for qoder.cn; #7866 removed exactly that. This PR does not reintroduce it: the CN client credentials stay env-only (QODER_CN_OAUTH_CLIENT_ID / QODER_CN_OAUTH_CLIENT_SECRET), and QODER_CN_CONFIG.enabled is false unless both are provided. A regression test asserts the retired literals never reappear.

Changes

File
open-sse/config/providers/registry/qoder/cn/index.ts new — qoder-cn entry on api.qoder.cn, executor qoder, shared model catalog
open-sse/config/providers/index.ts registers qoder-cn
src/lib/oauth/constants/oauth.ts QODER_CN_CONFIG (env-only, qoder.cn endpoints)
src/lib/oauth/qoderSite.ts new — site resolver (global / cn) and site headers
src/lib/oauth/qoderMachineId.ts new — stable UUID v4 machine id
src/shared/constants/providers/oauth.ts canonical qoder-cn provider row
tests/unit/qoder-cn-site.test.ts new — 9 tests

The site resolver and machine id are ported from magpie's internal/qoder/endpoints.go (SiteOf, NewMachineID), which documents that Qoder CN's CLI authenticates with the device token itself and keeps a stable machine id.

Verification

  • node --import tsx/esm --test tests/unit/qoder-cn-site.test.ts → 9/9 pass (written failing first: ERR_MODULE_NOT_FOUND)
  • node --import tsx/esm --test tests/unit/qoder-oauth-config.test.ts → 2/2 pass (the existing "Qoder defaults must not point to qoder.cn" guard still holds for the global config)
  • node --import tsx scripts/check/check-provider-consistency.ts → OK — 296 REGISTRY, 381 canonical, 0 registry-only
  • tsc -p tsconfig.typecheck-core.json --noEmit → clean
  • eslint on all touched files → clean
  • prettier --check → clean

tests/unit/qoder-executor.test.ts fails in this environment (spawn … qodercli ENOENT) both with and without this change — its stub is a #!/bin/sh script that Windows cannot execute. Pre-existing, not a regression.

⚠️ base-red inherited

release/v3.8.53 is currently red: #17219 ([free-catalog-evidence] tokenharbor/claude-haiku-5.5:free: missing evidence). Any CI failures traced to that issue are inherited, not caused here.

Qoder's China deployment was reachable only by pointing the global Qoder
OAuth env vars at qoder.cn, which conflated two accounts that must not race
for the same slot. Add qoder-cn as its own registry entry with its own host,
OAuth config and canonical provider row.

The CN entry reuses the global executor and model catalog so a model added
upstream lands on both sites, and the global entry stays byte-identical.

Browser OAuth keeps the CN client credentials env-only (QODER_CN_OAUTH_*):
an earlier revision embedded a literal client_id/client_secret for qoder.cn
and cheaper-inference#7866 removed exactly that under Hard Rule cheaper-inference#11, so nothing is reintroduced.

Includes the site resolver, the stable UUID v4 machine id ported from
magpie's internal/qoder/endpoints.go, and unit coverage for both.

This branch has not been deployed

No deployments
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.

1 participant