Skip to content

Port upstream 0.69.0: z.ai unavailable quota instead of fabricated 0% - #696

Draft
Finesssee wants to merge 2 commits into
port/upstream-0.69.0from
port/micro-0.69.0-zai-unavailable-quota
Draft

Finesssee wants to merge 2 commits into
port/upstream-0.69.0from
port/micro-0.69.0-zai-unavailable-quota

Conversation

@Finesssee

Copy link
Copy Markdown
Collaborator

Summary

z.ai quota parsing no longer fabricates a 0% Coding Plan window when the response has no recognized limits.

  • Empty or wholly unrecognized limits produce an informational primary ("Unavailable", no bar) plus the detail row "Coding Plan usage: Unavailable / Check Usage Dashboard for complete plan usage."
  • Mixed responses keep the recognized windows and add "Additional quota: Unavailable" (or "Coding Plan usage" when only MCP is recognized).
  • Unknown string limit types are skipped without requiring legacy fields.
  • Entries with a missing/non-string type, or a recognized entry that does not deserialize, fail with "Unsupported z.ai quota entry. Check Usage Dashboard for plan usage."; a missing/non-array limits envelope fails with "Unsupported z.ai quota format. Check Usage Dashboard for plan usage."
  • Analytics/model-usage handling is untouched (not present in the Rust provider).

Upstream reference

Ported / Deferred

  • Ported: all behavior above; fixtures mirror the upstream ZaiProviderTests shapes (FUTURE_LIMIT, FUTURE_POINTS_POOL, missing/null/numeric type, pointsPool envelope).
  • Kept Win-only legacy compatibility: tokens / mcp legacy types remain recognized limits.
  • Deferred: none. The upstream August reset-payload test is a plugin-runtime test; its behavior is already covered by the existing five-hour reset plausibility tests.

Validation

Toolchain +1.98.0, E-core wrappers, slot-1.

  • cargo fmt --all: clean
  • cargo clippy --workspace --all-targets -- -D warnings: pass
  • cargo test -p codexbar zai -- --test-threads=4: 46 passed, 0 failed

Affected areas

  • Provider (z.ai): rust/src/providers/zai/
  • Docs: docs/PROVIDERS.md
  • Settings / tray / float bar code changes: none (existing informational-window and display-detail rendering is reused)

UI proof

Pending: coordinator will capture CUA proof on a fresh build.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

Thermo-nuclear review

Verdict: the design is sound (informational primary + one transient ProviderDisplayDetail is the right reuse of existing abstractions, and the row title/id selection matches upstream zai.js at v0.69.0). No file crosses 1k lines (zai/mod.rs 679, tests.rs 551). Four things fall short of the bar and get fixed in a follow-up commit.

  1. Correctness: a signal-less recognized entry still fabricates a 0% window. recognized_limits only rejects entries whose type is missing or whose fields fail to deserialize. Every ZaiLimit field is Option, so {"type":"TOKENS_LIMIT"} (no percentage/usage/limit/used/currentValue/remaining) deserializes and compute_percent returns 0.0, which is exactly the fabricated bar this PR exists to remove. Upstream parseLimit throws "Unsupported z.ai quota entry" for a recognized entry without its required numeric fields. Fix: reject a recognized entry that carries no quota signal at all.
  2. Inline error mapping in the network function, untested. The Category::Data -> "Unsupported z.ai quota format" mapping lives inside async fetch_usage_api, and non_array_limit_container_is_a_data_error only asserts serde's own classify(), not the mapping. Extract a pure parse_quota_body(&[u8]) and test the real mapping (data-shape error vs syntax error).
  3. Option<Option<_>> + flatten in an already ~150-line parse_quota_response. The unavailable-row construction (then(...) producing Option<Option<_>>, silent and_then swallow, id/title branch) is a special case bolted into a busy function. Move it into a dedicated unavailable_quota_detail(has_token_limits) helper returning Option<ProviderDisplayDetail>.
  4. Avoidable entry.clone() per limit in recognized_limits: ZaiLimit::deserialize(entry) works on &Value directly.

Noted, not changing:

  • parse_quota_response now returns ZaiParsedQuota, which churns ~15 test call sites (.usage). The alternative (recomputing skipped/recognized counts outside the parser) would duplicate classification, so the small struct is the lesser evil.
  • is_token_limit_type(Option<&str>) mirrors ZaiLimit.limit_type: Option<String>; the Some(..) wrapping in recognized_limits is a wart but converting to &str would just move it to the other call sites.
  • Local ZaiLimit accepts non-integer/missing unit/number (legacy flat shape support), stricter than upstream only via finding 1. Legacy tokens/mcp types and top-level limits are intentionally kept.
  • UI: informational primary "Unavailable" plus the detail row is an established pattern (Grok, Copilot, aiand); CUA proof is pending a fresh build.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

Addressed the thermo-nuclear review in "Address thermo review":

  1. A recognized entry with no quota signal (no percentage, usage, limit, used, currentValue or remaining) is now rejected as "Unsupported z.ai quota entry" instead of producing a fabricated 0% window. New test covers {"type":"TOKENS_LIMIT"} and a bare TIME_LIMIT.
  2. Extracted a pure parse_quota_body(&[u8]); the test now checks the real mapping (shape error gives the Usage Dashboard message, syntax error keeps the parser message).
  3. Moved the unavailable-row construction into unavailable_quota_detail(has_token_limits), removing the Option<Option<_>> and flatten.
  4. recognized_limits deserializes from &Value without entry.clone().

Validation (+1.98.0): cargo fmt --all clean, clippy --workspace --all-targets -D warnings pass, cargo test -p codexbar zai: 47 passed, 0 failed.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

CUA proof

Build commit: d337464 (PR head) plus uncommitted proof-only patches (not in the PR): (1) rust/src/logging.rs config_root() honors CODEXBAR_PROOF_CONFIG_ROOT for isolated config; (2) rust/src/providers/zai/settings.rs normalized_https_url() also accepts http://127.0.0.1 so the real fetch -> parse -> bridge -> UI path runs against a local mock. Exact diff: proof-only.diff in the proof dir.

Commands: bash launch.sh trayPanel unsupported, bash launch.sh trayPanel mixed (local mock z.ai server on 127.0.0.1:18696, isolated config, empty provider homes, dummy key), driven with cua-driver serve / call list_windows / call get_window_state --screenshot-out-file. mock.log confirms the real GET reached the mock in both scenarios.

# Scenario Assertion Result
A1 unsupported (FUTURE_POINTS_POOL only) z.ai card with plan "pro", no 0% bar, no "0%" / "100% left" text PASS
A2 unsupported Primary row is informational "Unavailable", no bar PASS
A3 unsupported "Coding Plan usage: Unavailable" + "Check Usage Dashboard for complete plan usage." PASS
A4 unsupported No error banner, no other provider identity shown PASS
B1 mixed (TOKENS_LIMIT 25% + pool) Real window with bar at 25% used (UI is in "used" mode, equals 75% left) PASS
B2 mixed "Additional quota: Unavailable" with same hint; no "Coding Plan usage" row PASS
C both Webview stays dark under theme auto (settings theme "auto") PASS

Observation (cosmetic, not a defect of the PR's logic): in the detail row the value "Unavailable" and the hint text render adjacent with no separator ("Unavailable" immediately followed by "Check Usage Dashboard...").

Screenshots (local, not committed): C:\Users\FSOS\AppData\Local\Win-CodexBar\port-audit\proof\696\shots\A-tray.png, ...\shots\B-tray.png. No personal data visible.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

Port re-review: z.ai unavailable quota instead of fabricated 0% (#696, GAP row 22 of 0.69.0)

Re-checked the branch at the current head d3374643 against the 0.69.0 manifest spec for item #22 / PR 8 (upstream steipete#4091, z.ai quota-shape hardening) and the thermo/fix/proof thread.

What I verified at the current head:

  • No fabricated 0%: empty or wholly unrecognized limits produce no window; the primary is informational "Unavailable" with the detail row "Coding Plan usage: Unavailable / Check Usage Dashboard for complete plan usage". A mixed response keeps the recognized windows and adds "Additional quota: Unavailable" (title mirrors upstream via unavailable_quota_detail(has_token_limits)). Unknown string limit types are skipped without requiring legacy fields. A recognized entry with no quota signal at all ({"type":"TOKENS_LIMIT"} with no percentage/usage/limit/used/currentValue/remaining, or a bare TIME_LIMIT) is now rejected as "Unsupported z.ai quota entry" instead of fabricating 0% — the thermo blocker, fixed with tests.
  • Error mapping: parse_quota_body(&[u8]) is a pure function now; the shape error yields the Usage Dashboard message, a syntax error keeps the parser message ("Unsupported z.ai quota format/entry. Check Usage Dashboard for plan usage."). Malformed entries and unsupported envelopes fail closed.
  • Structure: the Option<Option<_>> + flatten construction is gone (moved into the helper), and recognized_limits deserializes from &Value without the per-limit entry.clone(). Analytics stay untouched.
  • Existing evidence at this head: thermo review (4 findings, all fixed), validation (fmt/clippy clean, zai 47 passed) and a CUA proof at d3374643 driving the real fetch→parse→bridge→UI path against a local mock (unsupported scenario: no 0% bar, informational Unavailable row, correct hint, no error banner; mixed scenario: real 25% window plus the Additional-quota row; dark theme; no personal data).

Result: no new findings. The port matches the upstream fail-closed quota semantics; the one cosmetic observation from the proof (value and hint text render adjacent with no separator in the detail row) is a rendering nit on main's detail-row pipeline, not a defect of this port. Files under the cap; no dependency, locale or bridge change.

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