Skip to content

Standalone CLI cannot use z.ai Start Plan providers (e.g. ZCODE WEEKEND BUILD) — analysis + proposed patch #248

Closed

Description

@Erencv

Summary

zcode-app-cli cannot use account:zai-start-plan providers even when the account is actively entitled to one. Z.ai's ZCODE WEEKEND BUILD promo (a start-plan grant — 500M GLM-5.3-Flash tokens, visible in Desktop under "Start Plan") is therefore Desktop-only. I traced this to a handful of standalone-mode gates plus one credential-mapping detail, verified each experimentally, and opened a draft PR (#249) implementing the fix in this repo's patch layer — happy to adapt or withdraw it per your feedback.

Environment

  • zcode-app-cli 3.17.1-42 (runtime 0.17.1), macOS arm64, Node 26
  • ZCode Desktop sharing ~/.zcode/v2/ (OAuth-logged-in; individual coding plan + active start-plan promo)

Reproduction

$ zcode --model account:zai-start-plan/GLM-5.3-Flash --prompt 'ok'
Error: Provider Registry 中不存在 Model: account:zai-start-plan/GLM-5.3-Flash

The TUI /model picker likewise lists only account:zai-individual-coding-plan/*, while Desktop's host log confirms the entitlement is live and Desktop uses it:

billing/balance → plans:[{plan_id:"zcode-v3-start-plan-1030-wk", name:"ZCODE WEEKEND BUILD", status:"active"}],
hasActiveStartPlan:true, providerId:"account:zai-start-plan"

Root cause

The bundled catalog (vendor/provider/zcode-builtin.json) does ship account:zai-start-plan (access {type:"zhipu-account", mode:"start-plan"}, models GLM-5.3-Flash / GLM-5.2 / GLM-5-Turbo). The gates are in the standalone account paths of vendor/zcode.cjs (labels from the bundler's r(sym,"label") markers):

  1. Enumeration — readStandaloneCodingPlanCatalog yields only mode==="individual-coding-plan" providers, so the start-plan provider never reaches the registry (the error above).

  2. Uniqueness assertion — resolveStandaloneCodingPlanProvider filters catalog providers by family and requires exactly one; fixing (1) naively would break login, so this needs a start-plan exclusion in the same change.

  3. Identity mapping — identity is read per provider id (standaloneAccountIdentityCredentialKey); a start-plan provider has no stored identity of its own, so both the entitlement snapshot (readStandaloneAccountProviderConfigSnapshot) and the request path treat it as credential-less. The identity is account-scoped, so mapping start-plan reads to the family's coding-plan identity is factually correct (verified below).

  4. Request-mode check — createStandaloneProviderRuntimeHeadersPort's refreshBeforeModelRequest throws 请求身份无效 for any non-individual-coding-plan mode.

  5. Request credential — the subtle one. The two plan products are served from different domains with different credentials:

    coding plan start plan
    endpoint api.z.ai/... zcode.z.ai/api/v1/zcode-plan/...
    accepted auth coding-plan api-key / exchanged project JWT the zcode-scoped JWT (zcodejwttoken credential) + the runtime's signed headers

    With 1–4 patched, start-plan requests still 401: the manual path attaches the coding-plan api-key, the OAuth path attaches the exchanged api.z.ai project JWT (verified with a fetch hook dumping outbound headers, plus a curl matrix against zcode-plan/anthropic/v1/messages). Authenticating with the zcodejwttoken credential instead makes requests pass; the runtime's own anti-bot signing transport does the rest.

Verification

With the corresponding five edits applied to the local bundle (the draft PR encodes them as runtime-start-plan-patches.ts):

  • zcode --model account:zai-start-plan/GLM-5.3-Flash --prompt … succeeds headlessly; /model lists the three start-plan models and switching works
  • A real turn completes and Desktop's Start Plan balance decreases accordingly (billing is domain-isolated: zcode-plan can only draw the start-plan bucket, so there is no risk of silently spending the paid plan)
  • New unit test covers the fixture patch, the identity mapping behavior and idempotency

Scope question

This deliberately widens what a standalone client may do with an account's own, already-granted entitlement: no protocol forgery — requests are still built and signed by the genuine runtime, and Desktop behaves identically. If you'd rather keep this package conservative and see the fix land in zai-org/ZCode upstream instead, I'm happy to file it there and close the PR — guidance appreciated.

Activity

  1. kingsword09 commented on Nov 1, 2026

    @kingsword09
    Owner

    Resolved by #251, now merged into main. Start Plan uses the existing shared ZCode OAuth session without a separate login, and the maintainer has verified it locally with a Start Plan account. All PR CI checks passed. Thank you @Erencv for the detailed investigation and initial implementation in #249; your contribution is credited in #251. Closing this issue as completed.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions