Skip to content

feat(qwen): add Token Plan (Team Edition) provider#94419

Merged
steipete merged 2 commits into
openclaw:mainfrom
oliver-mee:feat/qwen-token-plan
Jul 9, 2026
Merged

feat(qwen): add Token Plan (Team Edition) provider#94419
steipete merged 2 commits into
openclaw:mainfrom
oliver-mee:feat/qwen-token-plan

Conversation

@oliver-mee

@oliver-mee oliver-mee commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

OpenClaw supports Qwen Standard, Coding Plan, and OAuth, but not Alibaba Cloud Token Plan (Team Edition) as a first-class provider. Token Plan users currently need a large manual provider definition, and Alibaba's documented bailian-token-plan example must remain an exact custom-provider contract rather than becoming a canonical catalog alias.

Closes #94418.

Why This Change Was Made

This adds canonical qwen-token-plan support with:

  • Global/Singapore and China/Beijing onboarding choices and dedicated endpoints.
  • The current exact 14-model Token Plan chat catalog.
  • Model-specific thinking behavior for Qwen, DeepSeek, Kimi, GLM, and MiniMax, including replay and tool-call wire constraints.
  • Native streaming-usage compatibility and isolated QWEN_TOKEN_PLAN_API_KEY handling.
  • Independent runtime compatibility for Alibaba's documented bailian-token-plan custom-provider ID.

bailian-token-plan intentionally has runtime hooks only—no built-in auth, discovery catalog, static catalog, or environment variables—so existing custom transport, credentials, model rows, and explicit thinking formats remain authoritative.

Config-risk metric: +2 provider IDs, +2 auth choices, +1 environment variable, +2 native endpoints, and +14 catalog rows. All additions are additive; no existing provider ID or config shape changes.

User Impact

Users can onboard with qwen-token-plan or qwen-token-plan-cn, authenticate with a region-matched Token Plan key, and select models such as qwen-token-plan/qwen3.7-plus. Existing bailian-token-plan/* configurations continue using their explicitly configured transport and catalog.

Token Plan is documented for interactive coding and agent use. The provider docs warn against cron, unattended batch, and application-backend use that can violate the subscription terms.

Evidence

  • Testbox tbx_01kx3r67gg3788ydbktswk1x2dActions run 29029979874: extension production/test types passed; 62 stream behavior tests passed.
  • Testbox tbx_01kx3rrnapm9etmm41yw1sq5dsActions run 29030650617: 93 Qwen plugin tests passed after rebasing onto current main.
  • Testbox tbx_01kx3s68spj9h41yfeqwxpxnw2dActions run 29031140942: the complete docs gate passed after regenerating docs/docs_map.md, including markdown lint, MDX validation, 0 broken links, and the generated-map check.
  • Exact-head hosted CI run 29044964642 passed at 41d3aba1660bedfddd64cddad931c99503d9dd55: 70 successful checks, 27 skipped, 1 neutral, no failures.
  • Plugin inventory generation check, targeted extension lint/format, JSON parsing, and git diff --check passed.
  • Direct AWS Crabbox cbx_cac8973735b8 used a fresh public-network lease with no Tailscale or instance role. Every untrusted run fetched PR feat(qwen): add Token Plan (Team Edition) provider #94419, verified exact head 41d3aba1660bedfddd64cddad931c99503d9dd55, and injected only QWEN_TOKEN_PLAN_API_KEY without printing it.
  • Packaged install proof (run_42ddb175423c, corrected catalog projection run_6e37435ce5bb): built and integrity-checked the OpenClaw tarball, installed it into an empty prefix, installed packed @openclaw/qwen-provider through npm-pack:, onboarded Global Token Plan with an environment-backed ref, and loaded the plugin as a trusted official install. Gateway start/restart health passed in run_3de82699f9b6.
  • The packaged catalog exposed exactly the 14 current chat rows and excluded image-generation-only qwen-image-2.0 and wan2.7-image, matching Alibaba's current exact allowlist after excluding its four dedicated image-generation rows.
  • Global OpenAI-compatible live turns all returned HTTP 200 through Alibaba's documented Singapore endpoint: qwen3.7-plus text (run_d4adc29225fa), one-call read tool (run_6fe6dad65c19), and generated color-marker vision (run_ac2e7ab2bd37); thinking-off kimi-k2.7-code (run_7f9917a79372) and MiniMax-M2.5 (run_aba73f8599bf); deepseek-v4-pro max/tool then off/replay in one session (run_be02dfa638e0, run_d7ad1299c6e6); glm-5.2 max/tool (run_6a881cdac00a); and advertised deepseek-v3.2 availability (run_703b790ca40c).
  • Exact manual bailian-token-plan retained its one-row custom catalog and anthropic-messages transport, then completed a real HTTP 200 /v1/messages turn (run_68519df9b5d0).
  • China onboarding wrote the documented Beijing endpoint and 14-row catalog (run_ec81d94f1c3c). A China live turn was intentionally not attempted because no separately scoped China key was available; the Global key was not reused cross-region.
  • Invalid Global auth reached the exact endpoint, failed as authentication, exited 1, and did not echo the placeholder credential (run_9da2493884b2).
  • Source-blind behavior validation: 7/8 tasks pass; no failed or inconclusive clause. The sole blocked subtask is the conditional China live/cross-region proof requiring a separate China key.
  • Fresh whole-diff Codex autoreview (GPT-5.6) found no accepted or actionable findings; overall verdict: patch correct (0.91 confidence).

The implementation preserves contributor credit with Co-authored-by: Oliver Mee <[email protected]>.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 18, 2026
@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 3:58 PM ET / 19:58 UTC.

Summary
The PR adds qwen-token-plan and runtime-only bailian-token-plan support across the qwen plugin, onboarding/auth metadata, static catalogs, docs, generated provider inventory, endpoint classification, config validation, and tests.

PR surface: Source +925, Tests +1101, Docs +81, Other +57. Total +2164 across 22 files.

Reproducibility: not applicable. as a strict bug reproduction: current main lacks Token Plan support, and the PR evidence proves the new live onboarding and gateway path rather than reproducing a broken existing contract.

Review metrics: 1 noteworthy metric.

  • Provider/Auth Surface: 2 provider ids, 2 auth choices, 1 env var, 2 endpoint hosts, 14 catalog rows added. These additions become setup, auth, routing, documentation, and support contracts that maintainers should accept before merge.

Stored data model
Persistent data-model change detected: vector/embedding metadata: extensions/qwen/stream.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #94418
Summary: this PR is the candidate implementation for the Alibaba Token Plan provider request; the Bailian/Coding Plan reasoning and usage-accounting items are adjacent but distinct provider-support work.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Get explicit maintainer acceptance for the bundled Token Plan and Bailian provider contract.

Risk before merge

  • [P1] The new provider ids, auth choices, env var, endpoint hosts, model defaults, docs, and catalog rows become supported setup/auth/routing contracts for existing and future users.
  • [P1] The runtime-only bailian-token-plan owner deliberately maps a documented custom-provider id into qwen-owned behavior without built-in auth/catalog, so maintainers should accept that boundary before merge.
  • [P1] The branch is mergeable but behind the current base, so landing may need a routine refresh and review of the three-way result.

Maintainer options:

  1. Accept the provider contract (recommended)
    Maintainers can explicitly own the new Token Plan provider ids, auth choices, env var, catalog defaults, endpoint hosts, and Bailian runtime compatibility path before landing.
  2. Narrow Bailian before merge
    Remove or defer the runtime-only bailian-token-plan owner if maintainers want Token Plan support without taking on the adjacent custom-provider compatibility contract yet.
  3. Pause for externalization
    If bundled qwen support is not the desired ownership boundary, pause or close the PR and route the capability to an external plugin or custom-provider documentation path.

Next step before merge

  • [P2] Manual review is needed because the unresolved blocker is maintainer ownership of new provider/auth/env/catalog contracts, not a concrete mechanical repair.

Maintainer decision needed

  • Question: Should OpenClaw bundle qwen-token-plan and runtime-only bailian-token-plan as qwen-owned provider/auth/catalog contracts in this PR?
  • Rationale: The patch is not just a bug fix: it creates new provider ids, setup/auth choices, env var documentation, endpoint hosts, catalog defaults, and a legacy Bailian runtime owner that become product and compatibility commitments.
  • Likely owner: steipete — steipete is assigned to the PR and history connects them to the qwen provider and provider endpoint surfaces touched here.
  • Options:
    • Accept bundled Token Plan contract (recommended): Land the qwen-token-plan provider plus runtime-only bailian-token-plan compatibility path after any needed branch refresh, treating these ids and auth/docs/catalog surfaces as supported.
    • Drop Bailian runtime ownership: Keep qwen-token-plan but remove or defer bailian-token-plan behavior until maintainers choose a separate Coding Plan/Bailian ownership contract.
    • Route outside bundled core: Close or pause this PR and ask for Token Plan support to ship as an external plugin or documentation-only custom provider recipe.

Security
Cleared: No concrete security or supply-chain regression was found; the sensitive new API-key path uses existing qwen auth/dotenv handling and the PR does not change workflows, dependencies, lockfiles, or lifecycle scripts.

Review details

Best possible solution:

Accept the bundled Token Plan and Bailian compatibility contract explicitly, then refresh if needed and land; otherwise narrow the PR to the provider surface maintainers want to own.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a strict bug reproduction: current main lacks Token Plan support, and the PR evidence proves the new live onboarding and gateway path rather than reproducing a broken existing contract.

Is this the best way to solve the issue?

Yes, if maintainers accept the product boundary: the qwen plugin is the right owner for Alibaba/Qwen Token Plan behavior, existing custom provider configuration is a workaround with poorer onboarding, and no current built-in provider already covers this path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against ee9d9ea6dbb7.

Label changes

Label justifications:

  • P2: This is a bounded provider-onboarding feature with live proof and compatibility review needs, not an urgent outage or data-loss issue.
  • merge-risk: 🚨 compatibility: The PR adds provider ids, config validation overlay behavior, docs, model defaults, static catalog rows, and a runtime custom-provider owner that affect upgrade and support contracts.
  • merge-risk: 🚨 auth-provider: The PR adds API-key auth choices, a new env var, provider routing metadata, and Alibaba Token Plan endpoint hosts.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): PR comments provide after-fix live output for Global and CN Token Plan onboarding, model listing, and direct gateway HTTP 200 reasoning responses with secrets redacted.
  • proof: sufficient: Contributor real behavior proof is sufficient. PR comments provide after-fix live output for Global and CN Token Plan onboarding, model listing, and direct gateway HTTP 200 reasoning responses with secrets redacted.
Evidence reviewed

PR surface:

Source +925, Tests +1101, Docs +81, Other +57. Total +2164 across 22 files.

View PR surface stats
Area Files Added Removed Net
Source 11 935 10 +925
Tests 6 1102 1 +1101
Docs 4 100 19 +81
Config 0 0 0 0
Generated 0 0 0 0
Other 1 58 1 +57
Total 22 2195 31 +2164

What I checked:

  • Repository policy read and applied: Root and scoped policy make provider routing, auth, config/default additions, setup, startup checks, and plugin/provider ownership compatibility-sensitive review surfaces; this PR touches those surfaces. (AGENTS.md:31, ee9d9ea6dbb7)
  • Current main does not already implement the requested provider: Current main's qwen manifest contains the existing qwen/modelstudio provider ids but not qwen-token-plan or bailian-token-plan, so this PR is still the candidate implementation rather than obsolete work. (extensions/qwen/openclaw.plugin.json:8, ee9d9ea6dbb7)
  • PR state and checks: GitHub reports this PR open and mergeable but behind, with head 41d3aba, proof-sufficient/readiness labels, steipete assigned, and no failing or pending status checks in the 98-check rollup. (41d3aba1660b)
  • Provider manifest surface added: The PR manifest adds qwen-token-plan and bailian-token-plan provider ids, Token Plan endpoints, providerRequest capabilities, the static Token Plan catalog, setup env key QWEN_TOKEN_PLAN_API_KEY, and provider auth choices. (extensions/qwen/openclaw.plugin.json:8, 41d3aba1660b)
  • Runtime registration shape: qwen-token-plan is registered with auth, catalog, static catalog, streaming compatibility, stream wrapper, and thinking profile; bailian-token-plan is registered as a runtime-only legacy custom-config owner without built-in auth/catalog/staticCatalog. (extensions/qwen/index.ts:338, 41d3aba1660b)
  • Catalog and model contract: The Token Plan catalog is an exact 14-model allowlist with provider-specific endpoint constants and Token Plan reasoning constraints. (extensions/qwen/models.ts:19, 41d3aba1660b)

Likely related people:

  • steipete: History and PR metadata connect steipete to the qwen provider introduction, provider endpoint metadata work, current PR commits, and assignment for this provider-surface decision. (role: feature introducer and likely decision owner; confidence: high; commits: e3ac0f43df3e, 2d593958839c, f8cc655dba87; files: extensions/qwen/index.ts, extensions/qwen/models.ts, extensions/qwen/openclaw.plugin.json)
  • Vincent Koç: Recent qwen/catalog work touches the same provider catalog and generated metadata area, making this a plausible secondary reviewer signal. (role: recent adjacent area contributor; confidence: medium; commits: e085fa1a3ffd; files: extensions/qwen/openclaw.plugin.json, docs/plugins/plugin-inventory.md, scripts/lib/official-external-provider-catalog.json)
  • NianJiuZst: Prior PR review identified the endpoint-classification and bailian alias concerns that shaped the current branch, so their review context is directly relevant. (role: prior reviewer; confidence: medium; files: extensions/qwen/openclaw.plugin.json, extensions/qwen/stream.ts, extensions/qwen/index.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-06-26T07:20:32.086Z sha af066eb :: needs changes before merge. :: [P2] Regenerate provider catalog surfaces
  • reviewed 2026-07-09T15:07:38.523Z sha af066eb :: needs changes before merge. :: [P2] Regenerate provider catalog surfaces
  • reviewed 2026-07-09T16:13:47.316Z sha dbb60cf :: needs maintainer review before merge. :: none
  • reviewed 2026-07-09T19:47:08.620Z sha 41d3aba :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jun 18, 2026
@NianJiuZst

Copy link
Copy Markdown
Contributor

PR #94419 Review

Verdict: Request changes — at least one blocker + one config-surface smell + several smaller concerns.

This is a real, useful feature with clean structure, but it ships with a runtime bug, a config-surface addition for an unverified compat case, and a few design choices I want to talk through before this lands.


TL;DR

Bug Token-plan base URLs are not registered in providerEndpoints, so vision models on this provider will silently fail to route to the modelstudio media-understanding path.
Config smell bailian-token-plan alias is added as a "compat" case, but the name has zero shipped users in this repo and the citation is a paragraph in an issue, not a documented shipped config.
Design Separating qwen-token-plan into its own provider is justified (materially different catalog). Mostly clean.
Tests Good coverage of catalog, base URL swap, manifest/runtime auth-choice lock.
Ready to ship? No. Fix the providerEndpoints bug; reconsider the bailian-token-plan alias.

1. Blocker: missing providerEndpoints entries → vision routing silently broken

extensions/qwen/openclaw.plugin.json declares:

"providerEndpoints": [
  {
    "endpointClass": "modelstudio-native",
    "baseUrls": [
      "https://coding-intl.dashscope.aliyuncs.com/v1",
      "https://coding.dashscope.aliyuncs.com/v1",
      "https://dashscope.aliyuncs.com/compatible-mode/v1",
      "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
    ]
  },
  { "endpointClass": "qwen-portal-native", "baseUrls": ["https://portal.qwen.ai/v1"] }
]

The new qwen-token-plan provider's base URLs are not in this list:

  • https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1
  • https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1

The runtime resolution at src/agents/provider-attribution.ts:415-444 falls through to endpointClass: "custom" for any URL not matched in the manifest, and src/media-understanding/image.ts:300-302 specifically branches on modelstudio-native to route vision requests:

return (
  capabilities.endpointClass === "openrouter" ||
  capabilities.endpointClass === "modelstudio-native" ||
  (model.provider.toLowerCase() === "openrouter" && capabilities.endpointClass === "default")
);

Impact: 5 of the 12 catalog models on the new provider are vision-capable (qwen3.7-plus, qwen3.6-plus, qwen3.6-flash, kimi-k2.6, kimi-k2.5 — all have input: ["text", "image"]). Without the modelstudio-native class, image understanding for these models silently won't be advertised as supported, and the request-routing layer will treat this as an opaque "custom" provider.

The sibling providers got this right:

  • qwen main → URLs in providerEndpoints[0].baseUrlsmodelstudio-native
  • qwen-oauth → URL in providerEndpoints[1].baseUrlsqwen-portal-native
  • qwen-token-plannot in providerEndpointscustom

Fix: add the two token-plan URLs to providerEndpoints[0].baseUrls. The endpointClass: "modelstudio-native" is the right class because the PR reuses the modelstudio transport (Bearer auth, openai-completions, shared stream wrapper, same thinking handling — that's exactly what modelstudio-native is for).

"baseUrls": [
  "https://coding-intl.dashscope.aliyuncs.com/v1",
  "https://coding.dashscope.aliyuncs.com/v1",
  "https://dashscope.aliyuncs.com/compatible-mode/v1",
  "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
  "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
  "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
]

This is a small, correct addition. Please add it before merge.


2. Config-surface smell: bailian-token-plan alias is not a shipped contract

The PR adds bailian-token-plan to four places:

  1. providers list (openclaw.plugin.json:7)
  2. providerAuthAliases (openclaw.plugin.json:10)
  3. providerRequest.family (openclaw.plugin.json:51-53)
  4. aliases on the registered provider (index.ts:286)
  5. A test assertion (index.test.ts:73)

…all to support the claim that "Alibaba's reference config names this provider bailian-token-plan".

I checked. bailian-token-plan does not appear anywhere in the OpenClaw repo. Not in docs/, not in tests, not in fixtures, not in src/. The only references are in this PR and in the source issue. The "Alibaba reference config" is a claim in the issue body, not a citation of a shipped contract.

Compare with the existing qwen-portal / qwen-cli aliases, which the author cites as the same pattern. Those aliases are real shipped compat:

  • src/agents/auth-profiles/doctor.ts:20,33qwen-portal is in shipped doctor migration code
  • Migration logic exists for users upgrading with old qwen-portal auth profiles

bailian-token-plan has none of that. It's an alias invented to match a hypothetical future config.

Per AGENTS.md:

Compatibility is opt-in. "Shipped" means reachable from a release Git tag; main/GitHub/PR/unreleased code is not shipped.
Config/env surface bar is high; openclaw.json and environment variables are already large. Before adding a config option or env var, first prove existing product behavior, provider selection, defaults, or doctor migration cannot solve it. Prefer removing or consolidating config/env options when touching these surfaces.

Recommendation: drop the bailian-token-plan alias from this PR. Let users with that name in their config get a clear "unknown provider" error during onboarding. The first user who actually has an Alibaba reference config with this name can file a "this didn't work for me" issue, and the alias can be re-added with that as evidence.

If a maintainer explicitly wants the alias in this PR, ask the author to attach a real Alibaba reference config (e.g., a snippet of the recommended openclaw.json from Alibaba's docs that uses bailian-token-plan) to the PR description. Without that, the alias is premature config surface.


3. What's good (a lot, actually)

  • Provider separation is justified. The catalog is materially different (12 specific reasoning-capable models, fixed across regions). Reusing the existing qwen provider with a 5th+6th auth method would have forced buildQwenModelCatalogForBaseUrl to grow a token-plan branch, which is worse than a new provider.
  • Reuses shared SDK helpers. createProviderApiKeyAuthMethod from openclaw/plugin-sdk/provider-auth-api-key, createModelCatalogPresetAppliers from openclaw/plugin-sdk/provider-onboard, createPayloadPatchStreamWrapper — all correct picks per extensions/AGENTS.md "Reuse shared family helpers first."
  • Region is a base-URL swap, not a duplicated catalog. The author correctly factored the two regions into a QwenTokenPlanRegion type and a resolveQwenTokenPlanBaseUrl(region) helper. This is the right shape.
  • Catalog models are spread at write time. buildQwenTokenPlanProvider uses Object.assign({}, model) to clone each ModelDefinitionConfig before returning — same pattern as the existing buildQwenProvider / buildQwenOAuthProvider. Prevents shared-reference mutation across catalog calls. ✓
  • ReadonlyArray<ModelDefinitionConfig> for the catalog constant. Good for type safety. ✓
  • The stream.ts isQwenProviderId update (stream.ts:20) is the right shape — it's a hardcoded list today, but at least the new provider is added so the thinking wrapper applies. (See §6 for a refactor suggestion on this list.)
  • Tests are well-targeted:
    • provider-catalog.test.ts — base URL swap, model count, exclusion of image-gen models, no hardcoded compat
    • index.test.ts — manifest/runtime auth-choice lock invariant
    • All 29 qwen extension tests pass per author
  • createModelCatalogPresetAppliers usage mirrors the existing qwen / qwen-oauth preset appliers. Pattern-consistent.
  • The new env var name QWEN_TOKEN_PLAN_API_KEY — this one is justified, unlike bailian-token-plan. The existing qwen plugin uses QWEN_API_KEY everywhere, but that's the same env var for four auth methods on the same provider. Two auth methods on a different provider reading the same env var would be ambiguous. New env var is the right call.
  • Comment in models.ts:30-37 explaining why this is a separate provider, why OpenAI-compatible (not Anthropic), and why all models are reasoning: true — this is exactly the kind of context the codebase wants preserved.
  • Real behavior proof is solid — live calls against the Beijing gateway, 12 models verified, both delivery-mirror and reasoning_content observed. Author flagged the environment constraint (older config schema on the test box blocking full openclaw onboard) honestly.

4. Smaller concerns

4a. MiniMax-M2.5 model ID is unverified in this repo

MiniMax-M2.5 appears in this PR's catalog and nowhere else. The actual minimax provider in this repo uses MiniMax-M2.7 (default) and MiniMax-M3 (latest). I can't independently confirm that MiniMax-M2.5 is a real model on Alibaba's token-plan gateway. The author claims live verification — fair — but the model name doesn't match any other identifier in the codebase. Consider whether this should be MiniMax-M2.5 (Alibaba's listing) or MiniMax-M2.7 (the minimax provider's actual model). Not blocking, but a maintainer may want to ask the author to confirm the exact name on the gateway UI.

4b. The existing qwen main provider has no staticCatalog, the new one does

  • qwen main: only catalog.run (line 156-168 of index.ts)
  • qwen-token-plan: both catalog.run and staticCatalog.run (line 290-307 of new index.ts)

Without staticCatalog, openclaw models list --provider qwen doesn't work unless the user has an API key configured. The new qwen-token-plan does it the right way (you can list token-plan models without a key). This is an inconsistency the new provider improves on. Consider also adding staticCatalog to the existing qwen main provider as a follow-up. (Out of scope for this PR — just flagging.)

4c. qwen-token-plan and qwen-oauth both use api-key and api-key-cn as methodIds

  • qwen-oauth: methodId: "api-key" (one method)
  • qwen-token-plan: methodIds: ["api-key", "api-key-cn"]

The methodIds are scoped to the provider, so no collision. But if you ever wanted to use a single qwen mega-provider with all four methods (standard/coding/token-plan/oauth × cn/global), the methodIds would need to be namespaced. Not a problem today. Noting only for future refactor awareness.

4d. qwen3.6-plus has different reasoning flags across providers

  • Existing OAuth catalog (openclaw.plugin.json:101-113): reasoning: false
  • New token-plan catalog (models.ts new code): reasoning: true

The author verified all 12 token-plan models return reasoning_content from the gateway, so the new value is correct for the token-plan gateway. The OAuth gateway does not. Documented, fine.

4e. MiniMax-M2.5 is in the test exclusion list

provider-catalog.test.ts:38-39:

expect(modelIds).not.toContain("qwen-image-2.0");
expect(modelIds).not.toContain("wan2.7-image");

These are image-generation models that the author says are intentionally excluded. Are these real model IDs on the token-plan gateway? They don't appear elsewhere in the repo. If they're hypothetical/future model IDs being excluded preemptively, that's fine; if they were just made up, this assertion is meaningless. The author should confirm the source.

4f. setup.providers doesn't list bailian-token-plan

openclaw.plugin.json adds bailian-token-plan to the providers list and providerRequest.family, but setup.providers only has qwen-token-plan. If the alias is removed (per §2), this is moot. If kept, the alias should probably be in setup.providers too for setup hints to surface.

4g. The runtime test asserts the alias, locking in the compat case

index.test.ts:73:

expect(provider.aliases).toEqual(["bailian-token-plan"]);

If §2 is resolved by dropping the alias, this assertion needs updating to expect(provider.aliases).toEqual([]) or similar. If §2 is rejected and the alias is kept, the test should also assert that the alias actually resolves through the manifest providerAuthAliases and providerRequest.family entries, so the manifest is locked in too.


5. Manifest/auth-choice consistency test — good

index.test.ts:78-95 locks the invariant that every runtime auth[*].wizard.choiceId must have a matching manifest.providerAuthChoices[].choiceId with the same provider. This is exactly the kind of test that prevents the "manifest drifted from runtime" failure mode. Keep it. Consider also asserting that every manifest providerAuthChoices[].choiceId has a matching runtime auth method (other direction) so neither side can drift.


6. Refactor follow-up (not for this PR)

extensions/qwen/stream.ts:13-24 is a hardcoded list of provider IDs that grows with every new qwen provider. There are now 8 of them. The list exists because the thinking wrapper needs to know "is this a Qwen provider". A future refactor could derive this from a QwenProviderId union type or read from the registered providers' shared manifest metadata, so the list doesn't drift when new providers are added. Not blocking, but the smell grows with every new entry.


7. Non-issues (checked)

  • createQwenTokenPlanAuthMethod closes over region correctly — each call creates a fresh method with the right applyConfig. ✓
  • applyQwenTokenPlanConfig uses the SDK createModelCatalogPresetAppliers with proper typing. ✓
  • buildQwenTokenPlanProvider does not set apiKey — that's handled by the catalog run function. ✓
  • api.ts exports are correctly grouped (new QWEN_TOKEN_PLAN_* constants, new buildQwenTokenPlanProvider). ✓
  • stream.ts:20 adds the new provider to isQwenProviderId so the thinking wrapper applies. ✓
  • normalizeQwenOAuthContent / patchQwenOAuthPayload correctly skip the new provider (they check isQwenOAuthProviderId which does NOT include qwen-token-plan). ✓
  • The docs/providers/qwen.md table addition is consistent with the existing rows. ✓

8. What I want to see before merge

Must fix:

  1. Add the two token-plan base URLs to providerEndpoints[0].baseUrls in openclaw.plugin.json so vision routing works. (Blocker — silently broken otherwise.)
  2. Either drop the bailian-token-plan alias + its 4 manifest entries + the test assertion, or attach a citation of an actual Alibaba-shipped config that uses this ID.

Should fix:
3. Confirm MiniMax-M2.5 and the two image-gen exclusion IDs (qwen-image-2.0, wan2.7-image) are real Alibaba model IDs from the token-plan gateway, not invented.
4. Update the test invariant to also assert the reverse direction (manifest → runtime) so neither side can drift.

Nice to have (follow-up):
5. staticCatalog for the existing qwen main provider (consistency with the new one).
6. Refactor isQwenProviderId in stream.ts to derive from a shared provider-id union or manifest metadata.


Reviewing this in good faith — the author did the work, verified live, and the structure is mostly clean. The two blockers are: (a) the missing providerEndpoints entry, which is a real runtime bug, and (b) the bailian-token-plan alias, which is config surface without a shipped contract. Both are easy fixes. Ping me on a re-review when ready.

oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 18, 2026
…pper

The bailian-token-plan compatibility alias was not in isQwenProviderId, so
alias-configured Token Plan models hit wrapQwenProviderStream, failed the gate,
and skipped the thinking payload handling that qwen-token-plan gets. Add the
alias to the gate plus a regression test covering the alias path. Addresses the
Codex/ClawSweeper review finding on PR openclaw#94419.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
@oliver-mee

Copy link
Copy Markdown
Contributor Author

Thanks for the catch, this was a real gap. Fixed in 35e1259.

The bailian-token-plan alias was missing from isQwenProviderId in extensions/qwen/stream.ts, so wrapQwenProviderStream returned undefined for alias-configured models and they skipped the Token Plan thinking wrapper that qwen-token-plan gets. I added the alias to that gate so it follows the same stream path, and added a regression test in extensions/qwen/stream.test.ts asserting the wrapper engages for a bailian-token-plan openai-completions reasoning model.

Validation: pnpm test extensions/qwen (30 pass, including the new alias test) and pnpm tsgo:extensions clean. Rebased onto the latest branch tip after the main merge.

The bundled-provider-surface acceptance question is still yours to decide; happy to route this to a third-party plugin instead if you would prefer not to add another bundled Alibaba provider.

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 18, 2026
…sion routing

The qwen-token-plan base URLs were not in providerEndpoints, so they resolved
to endpointClass "custom" and the media-understanding layer (which gates vision
routing on "modelstudio-native") would not advertise image support for the 5
vision-capable token-plan models. Add both region URLs to the modelstudio-native
class, matching the transport they already reuse. Addresses review feedback on PR openclaw#94419.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 18, 2026
…urface)

The bailian-token-plan alias had no shipped contract in the repo (unlike the
qwen-portal / qwen-cli aliases, which have real doctor-migration code). Per
AGENTS.md (compatibility is opt-in, config-surface bar is high) and review
feedback on PR openclaw#94419, remove the alias from the providers list,
providerAuthAliases, modelCatalog.aliases, providerRequest, the registration
aliases, the qwen stream gate, the docs note, and the tests. Canonical
qwen-token-plan is unaffected. The alias can be re-added later with a real
user-supplied Alibaba config as evidence.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 18, 2026
@oliver-mee

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review, genuinely useful. Both blockers are addressed.

1. providerEndpoints / vision routing, fixed in d185805. Added both token-plan base URLs to the modelstudio-native class in providerEndpoints, so the 5 vision-capable models (qwen3.7-plus, qwen3.6-plus, qwen3.6-flash, kimi-k2.6, kimi-k2.5) classify correctly and image understanding is advertised. You were right that this was silently broken; modelstudio-native is the correct class since the provider reuses that transport.

2. bailian-token-plan alias, dropped in 39226d3. Agreed, this was premature config surface with no shipped contract (unlike qwen-portal/qwen-cli, which have real doctor-migration code). Removed it from the providers list, providerAuthAliases, modelCatalog.aliases, providerRequest, the registration aliases, the qwen stream gate, the docs note, and the tests. Canonical qwen-token-plan is unchanged. If a user later hits this with a real Alibaba config that uses the name, it can come back with that as evidence.

On the should-fixes:

  • MiniMax-M2.5 is a text/reasoning model (input: ["text"]), not an image model. It is a real model on the token-plan gateway, verified live (HTTP 200 with reasoning_content). The name differs from the minimax provider's MiniMax-M2.7/M3 because this is Alibaba's token-plan listing, not MiniMax's direct API.
  • qwen-image-2.0 and wan2.7-image are real image-generation models on Alibaba's published token-plan page, intentionally excluded from this chat catalog (the test asserts they stay out).
  • The manifest/runtime auth-choice test already runs both directions: it asserts manifestChoiceIds equals runtimeChoiceIds, so neither side can drift.

Follow-ups (agree these are out of scope here): staticCatalog for the main qwen provider, and deriving the isQwenProviderId list from shared metadata. Happy to pick those up separately.

Ready for re-review when you have a moment.

@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 18, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 19, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 22, 2026
@oliver-mee
oliver-mee force-pushed the feat/qwen-token-plan branch from 2209b07 to af066eb Compare June 26, 2026 06:49
oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 26, 2026
…pper

The bailian-token-plan compatibility alias was not in isQwenProviderId, so
alias-configured Token Plan models hit wrapQwenProviderStream, failed the gate,
and skipped the thinking payload handling that qwen-token-plan gets. Add the
alias to the gate plus a regression test covering the alias path. Addresses the
Codex/ClawSweeper review finding on PR openclaw#94419.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 26, 2026
…sion routing

The qwen-token-plan base URLs were not in providerEndpoints, so they resolved
to endpointClass "custom" and the media-understanding layer (which gates vision
routing on "modelstudio-native") would not advertise image support for the 5
vision-capable token-plan models. Add both region URLs to the modelstudio-native
class, matching the transport they already reuse. Addresses review feedback on PR openclaw#94419.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
oliver-mee added a commit to oliver-mee/openclaw that referenced this pull request Jun 26, 2026
…urface)

The bailian-token-plan alias had no shipped contract in the repo (unlike the
qwen-portal / qwen-cli aliases, which have real doctor-migration code). Per
AGENTS.md (compatibility is opt-in, config-surface bar is high) and review
feedback on PR openclaw#94419, remove the alias from the providers list,
providerAuthAliases, modelCatalog.aliases, providerRequest, the registration
aliases, the qwen stream gate, the docs note, and the tests. Canonical
qwen-token-plan is unaffected. The alias can be re-added later with a real
user-supplied Alibaba config as evidence.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@oliver-mee

Copy link
Copy Markdown
Contributor Author

Refreshed for the 14-model head, addressing the ClawSweeper proof ask.

  • Docs updated to 14 models (docs/providers/qwen.md): added glm-5.2 and kimi-k2.7-code, which the catalog already ships and tests. The paragraph previously read 12.
  • Real-behavior proof refreshed against the current head (in the PR body): a real OpenClaw build onboards qwen-token-plan-cn with a live sk-sp- key and models list shows all 14 models with Auth = yes and qwen3.7-plus as default. The two models added since the last proof, kimi-k2.7-code and glm-5.2, were also exercised directly against the gateway (HTTP 200 with reasoning_content). Key redacted, throwaway config deleted.
  • Rebased onto current main (now at 751a6c23f0, "fix(signal): avoid duplicate cli missing note", fix(signal): avoid duplicate signal-cli missing note #96932, near v2026.4.19-beta.2) to clear staleness. Clean rebase, no conflicts; the diff is exactly the qwen Token Plan change (11 files, +471/-12).

On validation: pnpm tsgo:extensions, pnpm lint (oxlint, all shards), and pnpm format:docs:check are clean. pnpm test extensions/qwen is 30 passed, 1 failed. The one failure (provider-catalog.test.ts > opts native Qwen baseUrls into streaming usage only inside the extension) is pre-existing on main and unrelated to this change: it asserts every native qwen model carries compat, but the upstream qwen3.5-plus model has none. This PR's models.ts change is purely additive and does not touch qwen3.5-plus, buildQwenProvider, or applyQwenNativeStreamingUsageCompat, so the same test fails on a clean main checkout.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot removed the status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. label Jun 26, 2026
@oliver-mee

Copy link
Copy Markdown
Contributor Author

Addressed the remaining region-proof gap. The PR body now includes direct live proof for the Global/Intl auth choice too, not just CN:

  • qwen-token-plan (Global, ap-southeast-1): onboarded with a live Global sk-sp- key on the same OpenClaw build; models list shows all 14 models with Auth = yes and qwen3.7-plus as default.
  • Direct Global gateway calls return HTTP 200 with reasoning_content (qwen3.7-plus, glm-5.2).

So both published auth choices (CN/Beijing and Global/Singapore) now have current-head live evidence. Key redacted, throwaway config deleted.

The remaining item is the maintainer product-acceptance call on owning a bundled Alibaba Token Plan provider, which is yours to make.

@clawsweeper re-review

@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Land-ready proof for 41d3aba1660bedfddd64cddad931c99503d9dd55:

  • Exact-head hosted CI: run 29044964642, 70 successful checks, 27 skipped, 1 neutral, no failures.
  • Focused/Testbox proof: Qwen production/test types + 62 stream tests (tbx_01kx3r67gg3788ydbktswk1x2d, Actions 29029979874); full six-file Qwen suite, 93 tests (tbx_01kx3rrnapm9etmm41yw1sq5ds, Actions 29030650617); docs gate including generated map and 0 broken links (tbx_01kx3s68spj9h41yfeqwxpxnw2d, Actions 29031140942).
  • Packaged user path on fresh direct AWS Crabbox cbx_cac8973735b8: node scripts/package-openclaw-for-docker.mjs, bash scripts/plugin-npm-publish.sh --pack extensions/qwen, global tarball install, openclaw plugins install npm-pack:<qwen.tgz> --force, non-interactive qwen-token-plan onboarding with an environment-backed ref, 14-row model listing, and packaged Gateway start/restart passed (run_42ddb175423c, corrected catalog projection run_6e37435ce5bb, restart run_3de82699f9b6).
  • Separate interactive Global turns all returned HTTP 200: Qwen text (run_d4adc29225fa), Qwen read tool (run_6fe6dad65c19), generated-marker vision (run_ac2e7ab2bd37), Kimi thinking-off (run_7f9917a79372), MiniMax thinking-off (run_aba73f8599bf), DeepSeek V4 max/tool then off/replay (run_be02dfa638e0, run_d7ad1299c6e6), GLM 5.2 max/tool (run_6a881cdac00a), and deepseek-v3.2 availability (run_703b790ca40c).
  • Exact manual bailian-token-plan retained its custom one-row catalog and anthropic-messages transport, then completed a real /v1/messages turn (run_68519df9b5d0). Invalid Global auth reached the endpoint, failed as authentication, exited 1, and did not echo the placeholder credential (run_9da2493884b2).
  • China onboarding wrote the documented Beijing endpoint and 14-row catalog (run_ec81d94f1c3c). No China live call was made because no separately scoped China key was available; the Global key was not reused cross-region.
  • Source-blind behavior validation: no failed or inconclusive clause; seven user tasks pass, with only the conditional China live subtask blocked by the missing separate key.
  • Fresh whole-diff GPT-5.6 autoreview: no accepted/actionable findings; patch correct (0.91 confidence).
  • Repo-native review artifacts validate as READY FOR /prepare-pr, findings 0.

Proceeding through the required Testbox-backed prepare and merge wrappers.

@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

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

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Alibaba Model Studio Token Plan (Team Edition) provider

3 participants