Skip to content

[Feature]: complete GLM Coding Plan quota support for open.bigmodel.cn #1168

Closed

Description

@c3right

Area

Provider quota / account plans

Current status

This request is partially implemented.

Current dev already contains a Z.AI GLM Coding Plan quota probe in:

src/providers/quota.ts

That implementation currently supports the api.z.ai Coding Plan route and projects GLM quota information into OpenCodex's existing normalized quota model.

The remaining work is to support the independently verified Zhipu BigModel Coding Plan contract at:

https://open.bigmodel.cn

and to parse the actual data.limits[] response shape rather than assuming one fixed set of flattened fields.

Confirmed BigModel endpoint

Live validation against a Zhipu GLM Coding Plan V1 individual subscription succeeded with:

GET https://open.bigmodel.cn/api/monitor/usage/quota/limit
Authorization: <API_KEY>

Important:

Authorization

contains the API key directly for this endpoint.

Do not prepend:

Bearer

unless separately verified for the specific host.

The model-routing base associated with this account can be:

https://open.bigmodel.cn/api/coding/paas/v4

What prevents this today?

The current OpenCodex quota implementation recognizes:

https://api.z.ai
https://api.z.ai/api/coding/paas/v4

but not:

https://open.bigmodel.cn
https://open.bigmodel.cn/api/coding/paas/v4

The current Z.AI probe also assumes a response shape containing fields such as:

fiveHourPercent
fiveHourUsage
weeklyPercent
weeklyUsage

The verified BigModel response instead exposes quota windows through:

data.limits[]

with explicit window metadata.

Therefore the current Z.AI probe should not be treated as complete support for the BigModel Coding Plan contract.

Verified response-driven parsing

The upstream response contains quota entries such as:

type = TOKENS_LIMIT
unit = 3
percentage = <used percentage>
nextResetTime = <reset timestamp>

Observed mapping:

unit = 3 -> rolling five-hour token window
unit = 6 -> weekly token window

The parser should use those explicit units instead of inferring window identity from reset ordering.

For example:

unit=3
percentage=72
nextResetTime=<timestamp>

should normalize to:

fiveHourPercent = 72
fiveHourResetAt = <timestamp>

And, when present:

unit=6
percentage=31
nextResetTime=<timestamp>

should normalize to:

weeklyPercent = 31
weeklyResetAt = <timestamp>

Plan-version behavior

Do not hard-code the presence of weekly or monthly limits based on the product name.

Live validation showed a V1 individual Coding Plan returning only:

5-hour used: 1%
5-hour remaining: 99%
weekly window: absent

That is a valid response.

Different Coding Plan generations may expose additional windows.

The contract should therefore be response-driven:

  • parse only limits actually returned by the upstream;
  • unit=3 is the confirmed rolling five-hour window;
  • unit=6 is the confirmed weekly window when present;
  • missing weekly/monthly windows are normal;
  • unknown future unit values should not be guessed;
  • if useful, unknown verified windows can be preserved as bounded custom windows until their meaning is established.

What OpenCodex should do

1. Recognize BigModel Coding Plan hosts

Extend the canonical host admission for the GLM Coding Plan quota probe to include the verified BigModel route.

At minimum:

https://open.bigmodel.cn/api/coding/paas/v4

The credential must never be sent to lookalike or arbitrary configured hosts.

2. Use the correct BigModel quota endpoint

For BigModel Coding Plan:

GET https://open.bigmodel.cn/api/monitor/usage/quota/limit

with the host-specific authentication contract.

Do not redirect credentials to another host.

3. Parse data.limits[]

Treat the returned limit rows as the source of truth.

Known mappings:

TOKENS_LIMIT + unit=3 -> five-hour window
TOKENS_LIMIT + unit=6 -> weekly window

Use:

percentage
nextResetTime

for normalized usage/reset values.

4. Preserve current Z.AI behavior

Supporting BigModel must not regress the existing:

api.z.ai

quota path.

If the two services expose materially different request/auth/response contracts, keep their parsing branches explicit rather than pretending they are identical because they belong to the same provider family.

5. Fail safely

Quota probing is observational only.

A failed, unsupported, malformed, or unavailable quota request must not affect:

  • model routing;
  • API-key use for inference;
  • normal provider availability.

Do not expose API keys or raw upstream quota bodies through the normal management API or Dashboard.

Expected Dashboard behavior

For an account returning only the V1 five-hour limit:

GLM Coding Plan

5-hour
1% used · 99% remaining
Resets: <local reset time>

For a newer account returning both known windows:

GLM Coding Plan

5-hour
72% used · 28% remaining
Resets: <time>

Weekly
31% used · 69% remaining
Resets: <date/time>

Do not render a fake weekly row when the upstream did not return one.

Acceptance criteria

  • OpenCodex has a GLM/Z.AI quota-probe foundation.
  • open.bigmodel.cn/api/coding/paas/v4 is recognized as an eligible Coding Plan configuration.
  • BigModel quota requests use the verified canonical quota endpoint.
  • BigModel authentication uses its verified host-specific contract.
  • data.limits[] is parsed response-first.
  • unit=3 maps to the rolling five-hour quota.
  • unit=6 maps to the weekly quota when present.
  • Missing weekly/monthly windows are accepted normally.
  • Unknown window units are not silently misclassified.
  • nextResetTime is normalized and displayed when supplied.
  • Existing api.z.ai quota behavior remains covered.
  • Quota-probe failure never breaks inference.
  • Credentials and raw quota payloads remain out of normal logs/UI responses.
  • Tests cover BigModel V1 five-hour-only and multi-window responses.

Checks

  • Current dev implementation was re-audited.
  • Existing Z.AI quota work is acknowledged rather than duplicated.
  • Live BigModel endpoint behavior has been provided by the reporter.
  • BigModel-specific contract implemented and verified.

Activity

  1. github-actions commented on Aug 7, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  2. c3right commented on Aug 7, 2026

    @c3right
    Author

    Additional live validation and an important plan-version nuance:

    I tested the quota endpoint against my own Zhipu GLM Coding Plan V1 individual subscription on 2026-08-07. The request succeeded and returned a rolling 5-hour token window only:

    5-hour used: 1%
    5-hour remaining: 99%
    next reset: 2026-08-07T16:00:05+08:00
    weekly window: not present in this response
    

    This should not be interpreted as "GLM Coding Plan has no weekly/monthly quota" in general. Zhipu has shipped multiple generations of Coding Plan subscriptions, and the quota shape differs by plan generation. My V1 individual plan has no weekly limit. Later plan generations (including V2 and newer offerings) may expose additional weekly and/or monthly limits.

    Therefore I suggest the adapter avoid hard-coding quota windows from a product/version name. Instead:

    • Treat data.limits[] as the source of truth for the current account.
    • Parse only windows actually returned by the upstream API.
    • Keep unit=3 as the observed rolling 5-hour token window.
    • Keep unit=6 as the observed weekly token window when present.
    • If newer plan generations expose additional window/unit values (for example a monthly limit), preserve them as separate/custom windows until their semantics are verified rather than guessing.
    • Missing weekly/monthly rows should be normal and should not make the quota probe fail.

    In other words, the desired behavior is capability/response-driven rather than plan-version-driven: a V1 account may render only the 5-hour row, while newer subscriptions can render additional rows when the API reports them.

    The endpoint itself was verified live for the V1 individual plan:

    GET https://open.bigmodel.cn/api/monitor/usage/quota/limit
    Authorization: <API_KEY>

    No local Codex/OpenCodex configuration needs to be modified to perform this read-only quota query.

  3. changed the title [-]Add Zhipu GLM Coding Plan quota support (5-hour usage and reset time)[/-] [+][Feature]: complete GLM Coding Plan quota support for open.bigmodel.cn[/+] on Aug 9, 2026
  4. github-actions commented on Aug 9, 2026

    @github-actions
    Contributor

    Maintainer decision respected

    A maintainer has reopened this issue. The automated closure has been deactivated.

  5. reopened this on Aug 9, 2026
  6. Ingwannu commented on Aug 11, 2026

    @Ingwannu
    Owner

    Confirmed against current dev@87e3ff9f63aa9e210d37e73fb5b64cc939ee03d5: this is a real, still-open integration gap.

    fetchZaiQuota() currently admits only https://api.z.ai[/api/coding/paas/v4], sends Authorization: Bearer ..., and parses flattened percent fields. A provider configured for https://open.bigmodel.cn/api/coding/paas/v4 is rejected before any request, so its key is not leaked, but data.limits[] quota reporting is not implemented. This is also not closed by #1197: that PR added the BigModel registry/routing metadata, not the host-specific quota probe.

    The requested direction is valuable, but the credential boundary should not be implemented from field descriptions alone. Before a PR is mergeable, please attach one fully redacted real response fixture that preserves the exact data, limits[], type, unit, percentage, and nextResetTime shapes and types. No key, account id, or unrelated metadata is needed.

    A narrow implementation should then:

    1. keep api.z.ai and open.bigmodel.cn as separate canonical host/auth/parser branches;
    2. send the direct key only to the exact BigModel quota origin with redirects disabled;
    3. map only verified TOKENS_LIMIT rows (unit=3 to 5-hour, unit=6 to weekly), accept a missing weekly row, and avoid guessing unknown units;
    4. preserve the current Z.AI behavior and make every probe failure observational-only;
    5. cover five-hour-only, multi-window, malformed/unknown-unit, canonical-host, redirect, and credential-non-disclosure regressions.

    After that, this should still require an exact-head live BigModel account test plus the normal CI matrix before merge. I am keeping the issue open rather than creating a speculative adapter from prose-only payload evidence.

  7. c3right commented on Aug 13, 2026

    @c3right
    Author

    Following the maintainer request, here is a real response fixture from the verified BigModel Coding Plan quota endpoint. The payload contains no API key, Authorization header, account id, user id, email, phone, or other account-identifying value; the upstream nesting, field names, values, and JSON types are preserved.

    Request contract used:

    GET https://open.bigmodel.cn/api/monitor/usage/quota/limit
    Authorization: <API_KEY>

    Real response fixture:

    {
      "code": 200,
      "msg": "操作成功",
      "data": {
        "limits": [
          {
            "type": "TIME_LIMIT",
            "unit": 5,
            "number": 1,
            "usage": 100,
            "currentValue": 0,
            "remaining": 100,
            "percentage": 0,
            "nextResetTime": 1788921262994,
            "usageDetails": [
              {
                "modelCode": "search-prime",
                "usage": 0
              },
              {
                "modelCode": "web-reader",
                "usage": 0
              },
              {
                "modelCode": "zread",
                "usage": 0
              }
            ]
          },
          {
            "type": "TOKENS_LIMIT",
            "unit": 3,
            "number": 5,
            "percentage": 1,
            "nextResetTime": 1786626122911
          }
        ],
        "level": "lite"
      },
      "success": true
    }

    Two contract details from this real fixture seem worth pinning explicitly:

    1. nextResetTime is returned here as a numeric Unix epoch timestamp in milliseconds, not an ISO date string.
    2. data.limits[] can contain non-token rows alongside token rows (TIME_LIMIT + unit=5 appears in the same response as TOKENS_LIMIT + unit=3). So the parser should gate on type === "TOKENS_LIMIT" before interpreting token-window unit values, rather than classifying rows from unit alone.

    For this account, the token quota row is TOKENS_LIMIT + unit=3, with percentage=1; no TOKENS_LIMIT + unit=6 weekly row is present in this response.

  8. c3right commented on Aug 13, 2026

    @c3right
    Author

    Additional plan-generation context for the fixture I posted above:

    • The real response fixture above is from my legacy GLM Coding Plan V1 Lite subscription.
    • That V1 Lite plan has only the rolling 5-hour token limit; it does not have a weekly or monthly token window.
    • There was also a historical V2 generation, which did include a weekly token limit.
    • V1 and V2 are no longer open for new purchases. New subscriptions now use the current/latest Coding Plan generation.

    So the fixture above should be treated as evidence for the real legacy V1 Lite response contract, not as evidence that the currently sold Coding Plan has only a 5-hour window, and not as a complete description of every historical/current plan generation.

    This is another reason I think the adapter should remain response-driven rather than plan-name/version-driven: parse the data.limits[] rows actually returned for the current account, map only unit semantics that are independently verified, accept absent weekly/monthly rows normally, and avoid inferring a plan generation from the set of returned windows.

    I have not provided a real response fixture for the currently sold/latest Coding Plan here, so its exact additional window/unit shape should remain unassumed until separately verified.

  9. c3right commented on Aug 13, 2026

    @c3right
    Author

    Additional clarification on the real V1 Lite fixture above:

    The TIME_LIMIT + unit=5 row is not a monthly GLM model-token quota. It represents the shared monthly call allowance bundled with the Coding Plan for these three MCP capabilities:

    • search-prime — web search
    • web-reader — webpage reading
    • zread — open-source repository reading

    In the fixture, usageDetails[] is the per-MCP breakdown inside that shared pool, while the parent row carries the aggregate allowance/usage/remaining values and the next reset timestamp.

    So the parser should not infer quota meaning from unit alone. It should branch on type first:

    • TOKENS_LIMIT rows are model-token quota windows; for the evidence currently available, unit=3 is the 5-hour token window and unit=6 is the weekly token window when present.
    • TIME_LIMIT + unit=5 in this V1 Lite fixture is a separate MCP/tool-call monthly allowance, not a monthly model-token window.

    This real row would be useful as a regression case for non-token rows must not be misclassified as model-token quota. It also reinforces keeping the implementation response-driven rather than assigning semantics from unit values in isolation.

  10. lidge-jun commented on Aug 19, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 65 / 80

    현재 dev의 GLM Coding Plan 쿼터 프로브는 api.z.ai만 인정합니다. src/providers/quota.ts의 isCanonicalZaiBaseUrl()은 https://api.z.ai와 https://api.z.ai/api/coding/paas/v4만 통과시키고, fetchZaiQuota()는 호스트가 아니면 요청 전에 null을 반환합니다. https://open.bigmodel.cn은 여기 없습니다. 그래서 BigModel 계정은 키를 보내기 전에 거절되며, 동시에 쿼터 UI도 비어 있습니다.

    이슈가 원하는 것은 검증된 BigModel 계약입니다. GET https://open.bigmodel.cn/api/monitor/usage/quota/limit에 API 키를 Authorization에 그대로 넣고, data.limits[]의 unit으로 창을 읽어야 합니다. 이슈와 실측 픽스처는 unit=3을 5시간 토큰 창, unit=6을 주간 창으로 매핑합니다. 지금 파서는 fiveHourPercent 같은 평탄 필드만 찾으므로, 설령 호스트를 열어줘도 응답을 정규화하지 못합니다.

    프로바이더 호환에서 헤더가 중요합니다. 현재 코드는 Authorization: Bearer ${apiKey}를 붙입니다. BigModel 실측은 Bearer를 붙이지 말라고 했고, 호스트별로 검증되지 않은 스킴을 쓰면 안 됩니다. 호스트 allowlist를 넓히기만 하고 Bearer를 그대로 보내면 쿼터 엔드포인트에 잘못된 자격 증명을 넣는 셈입니다.

    위생적으로 TIME_LIMIT/unit=5를 월간 모델 토큰으로 오인하면 안 됩니다. 코멘트 픽스처는 그것이 search-prime/web-reader/zread MCP 월간 호출 한도라고 명확히 합니다. V1 Lite는 5시간 창만 있고 주간 창이 없을 수 있으니, 없는 창을 0%로 채우면 풀 용량처럼 보입니다.

    해결방안은 BigModel 호스트를 별도 분기로 인정하고, 해당 호스트만 검증된 Authorization 스킴과 limits[] 파서를 쓰는 것입니다. unit으로 창을 식별하고, 없는 창은 생략하며, MCP TIME_LIMIT은 모델 토큰 창과 분리합니다. 패치는 추측하지 않으며, 현재 트리에 open.bigmodel.cn 분기는 없습니다.

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

  11. added a commit that references this issue on Aug 30, 2026
    015fedb
  12. Ingwannu commented on Aug 30, 2026

    @Ingwannu
    Owner

    Resolved on dev by #2976, merged as 015fedb63c446db98a71cd6b5b8ef91fb43f1b9a.

    The landed change covers the verified issue boundaries:

    • exact open.bigmodel.cn quota origin with raw Authorization and redirects disabled;
    • existing api.z.ai Bearer behavior preserved;
    • response-driven five-hour/weekly token-window parsing;
    • MCP TIME_LIMIT rows excluded from model-capacity ranking;
    • absent windows remain absent;
    • a successful later MCP-only response authoritatively clears stale cached model windows instead of preserving them as a transient failure.

    I reran tests/provider-quota.test.ts on the merged PR head under isolated runtime homes: 110 passed, 0 failed, and the exact-head platform CI was green. A future dedicated MCP allowance display can be tracked separately; it is no longer mixed into model quota.

  13. lidge-jun commented on Aug 30, 2026

    @lidge-jun
    Owner

    Implemented on dev via #2976 as 015fedb.

  14. added a commit that references this issue on Sep 14, 2026
    8affeab
  15. added a commit that references this issue on Sep 17, 2026
    27bad8b
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

    account-poolOAuth, credentials, Codex pool, quota, failover, plansenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions