Skip to content

Add Zhipu / Z.AI usage monitoring - #10901

Closed
Pr1p wants to merge 2 commits into
stablyai:mainfrom
Pr1p:feat/zhipu-usage-monitor
Closed

Pr1p wants to merge 2 commits into
stablyai:mainfrom
Pr1p:feat/zhipu-usage-monitor

Conversation

@Pr1p

@Pr1p Pr1p commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

Adds a Zhipu / Z.AI usage meter so Orca can show GLM Coding Plan quota in the same places it already shows Claude, Codex, Gemini, MiniMax, Grok, Kimi, and OpenCode Go usage.

What Changed

  • Added Zhipu credential storage, IPC/preload APIs, and a settings section for saving, clearing, and importing compatible cc-switch credentials.
  • Added Zhipu quota fetching, base URL normalization, host allowlisting, and rate-limit state integration.
  • Wired Zhipu into the status bar, usage visibility rules, provider copy, settings search, localization catalog, and default status-bar migration.
  • Rebased onto latest origin/main, adapted the PR to the split rate-limit/preload/store test structure, and resolved stale conflicts from deleted/moved files.
  • Addressed bot feedback:
    • cached zhipuCredentialsConfigured off the hot getState() path;
    • fixed the StatusBar.tsx missing comma;
    • fixed isUsageEmptyState to pass the correct settings argument;
    • added coverage for Zhipu credential read failures and stale in-flight results after invalidation.

Why

Zhipu / Z.AI has a GLM Coding Plan quota model that users need to monitor while working. This follows the existing provider architecture instead of adding a separate one-off path, so settings, status-bar visibility, refresh state, and error handling behave consistently with the other usage providers.

Linked Issue

N/A — no upstream issue is linked for this external contribution.

Visual Proof

Before: N/A — Zhipu was not available as a usage provider.

After:

Zhipu usage status bar and usage panel

Testing

  • I manually tested these changes locally
    • Not re-manually exercised in this rebase pass; existing visual proof is retained above.
  • Automated tests added/updated, or explained why not below

Local checks run on Windows:

  • pnpm run typecheck:web
  • pnpm run typecheck:node
  • pnpm exec vitest run --config config/vitest.config.ts src/main/rate-limits/service-zhipu-usage.test.ts src/main/rate-limits/zhipu-fetcher.test.ts src/main/rate-limits/service-refresh-orchestration.test.ts src/main/rate-limits/service-minimax-usage.test.ts src/main/rate-limits/service-account-target-selection.test.ts src/main/rate-limits/service-inactive-account-previews.test.ts src/main/rate-limits/service-live-claude-usage.test.ts src/main/rate-limits/service-window-activation.test.ts
  • pnpm exec vitest run --config config/vitest.config.ts src/main/codex-accounts/service.test.ts src/main/ipc/register-core-handlers.test.ts src/main/ipc/rate-limits.test.ts src/main/runtime/rpc/methods/client-ui.test.ts src/main/zhipu/cc-switch-import.test.ts src/renderer/src/components/settings/ZhipuAccountsSection.test.tsx src/renderer/src/components/settings/accounts-search.test.ts src/renderer/src/components/settings/appearance-status-bar-search.test.ts src/renderer/src/components/stats/GrokUsagePane.test.tsx
  • pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/status-bar/status-bar-agent-gating.test.ts src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts src/renderer/src/components/status-bar/tooltip.test.ts src/renderer/src/components/status-bar/usage-error-copy.test.ts src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts src/renderer/src/store/slices/rate-limits.test.ts src/renderer/src/store/slices/ui-hydration-workspace-preferences.test.ts src/renderer/src/web/web-preload-api-agent-providers.test.ts src/preload/usage-provider-api.test.ts src/shared/rate-limit-types.test.ts
  • pnpm exec oxlint ... on the touched files
  • pnpm run verify:localization-catalog
  • pnpm run verify:localization-extraction
  • pnpm run verify:localization-coverage
  • pnpm run check:max-lines-ratchet
  • pnpm run build:electron-vite
  • git diff --check

AI Disclosure

Codex (GPT-5) was used to rebase the PR, resolve conflicts, address CodeRabbit/Greptile feedback, update tests, and refresh this PR description.

Review

Self-reviewed for:

  • provider integration consistency with existing usage providers;
  • secret handling and renderer IPC boundaries;
  • Windows/macOS/Linux behavior, including platform-aware Claude background PTY expectations in tests;
  • SSH/folder-workspace compatibility assumptions;
  • stale in-flight refresh protection when credentials change;
  • localization and status-bar default migration behavior.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: Zhipu tokens stay in main-process credential storage; renderer IPC exposes status only, not raw secrets. cc-switch import rejects non-Zhipu hosts.
  • Cross-platform: no shortcut/path assumptions were added; tests now account for Windows disabling hidden Claude background PTY/supplement behavior.
  • Remote SSH / folder workspaces: usage monitoring remains provider/config scoped and does not require a git worktree.
  • Mobile/backwards compatibility: new RateLimitState fields are additive, and status-bar hydration includes a one-shot migration for the default Zhipu item.
  • Performance: Zhipu credential presence is cached outside getState() to avoid sync filesystem work on renderer push paths.

Checklist

  • This PR is small and focused
    • Scoped to one new usage provider, though it necessarily touches settings, IPC, rate-limit state, status bar, and tests.
  • I explained what changed and why (including ELI5)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)
    • Full pnpm lint / full pnpm test were not run in this rebase pass; targeted oxlint, targeted tests, typechecks, localization checks, max-lines ratchet, and build:electron-vite passed locally.

Author

  • X / Twitter: @Pr1p_1998

Parking note: this PR is parked pending the stable usage-provider API / plugin system (tracked in #23580) — it will be ported to that surface when it lands, per the discussion there.

@Pr1p
Pr1p marked this pull request as ready for review July 27, 2026 09:49
@Pr1p
Pr1p marked this pull request as draft July 27, 2026 09:50
@Pr1p
Pr1p marked this pull request as ready for review July 27, 2026 09:51
@coderabbitai

coderabbitai Bot commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1318a411-9065-4ddd-98b8-f9d9575f129e

📥 Commits

Reviewing files that changed from the base of the PR and between 9b5538d and ec4fee4b2cf6653cf9f7baa22a2c6d99d4f93967.

📒 Files selected for processing (58)
  • src/main/codex-accounts/service-reset-credit-test-fixtures.ts
  • src/main/ipc/rate-limits.ts
  • src/main/ipc/register-core-handlers.test.ts
  • src/main/ipc/register-core-handlers.ts
  • src/main/ipc/zhipu-credentials.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/service-zhipu-usage.test.ts
  • src/main/rate-limits/service.ts
  • src/main/rate-limits/zhipu-fetcher.test.ts
  • src/main/rate-limits/zhipu-fetcher.ts
  • src/main/runtime/rpc/methods/client-ui-schemas.ts
  • src/main/runtime/rpc/methods/client-ui.test.ts
  • src/main/zhipu/cc-switch-import.test.ts
  • src/main/zhipu/cc-switch-import.ts
  • src/main/zhipu/zhipu-credential-store.ts
  • src/preload/api-types.ts
  • src/preload/api/agent-account-api.ts
  • src/preload/api/agent-usage-api.ts
  • src/preload/index.ts
  • src/renderer/src/components/settings/AccountsPane.tsx
  • src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx
  • src/renderer/src/components/settings/ZhipuAccountsSection.test.tsx
  • src/renderer/src/components/settings/ZhipuAccountsSection.tsx
  • src/renderer/src/components/settings/accounts-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-minimax-toggle-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-zhipu-toggle-search.ts
  • src/renderer/src/components/stats/GrokUsagePane.test.tsx
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/icons.tsx
  • src/renderer/src/components/status-bar/status-bar-agent-gating.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/renderer/src/components/status-bar/usage-error-copy.test.ts
  • src/renderer/src/components/status-bar/usage-error-copy.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/store/slices/rate-limits.test.ts
  • src/renderer/src/store/slices/rate-limits.ts
  • src/renderer/src/store/slices/ui-hydration-workspace-preferences.test.ts
  • src/renderer/src/store/slices/ui.ts
  • src/renderer/src/web/web-preload-api-agent-providers.test.ts
  • src/renderer/src/web/web-preload-api.ts
  • src/shared/persisted-ui-state-types.ts
  • src/shared/rate-limit-types.test.ts
  • src/shared/rate-limit-types.ts
  • src/shared/status-bar-defaults.ts
  • src/shared/ui-chrome-types.ts
  • src/shared/zhipu-usage.ts
🚧 Files skipped from review as they are similar to previous changes (39)
  • src/renderer/src/components/status-bar/usage-error-copy.test.ts
  • src/renderer/src/store/slices/rate-limits.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/components/status-bar/status-bar-agent-gating.test.ts
  • src/main/ipc/rate-limits.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/main/ipc/register-core-handlers.ts
  • src/renderer/src/store/slices/rate-limits.test.ts
  • src/renderer/src/components/stats/GrokUsagePane.test.tsx
  • src/renderer/src/components/status-bar/usage-error-copy.ts
  • src/shared/status-bar-defaults.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/store/slices/ui.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts
  • src/shared/rate-limit-types.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/main/zhipu/zhipu-credential-store.ts
  • src/renderer/src/components/status-bar/icons.tsx
  • src/shared/zhipu-usage.ts
  • src/renderer/src/components/settings/AccountsPane.tsx
  • src/renderer/src/components/settings/appearance-status-bar-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-zhipu-toggle-search.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.ts
  • src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx
  • src/main/zhipu/cc-switch-import.ts
  • src/main/zhipu/cc-switch-import.test.ts
  • src/renderer/src/components/settings/appearance-status-bar-minimax-toggle-search.ts
  • src/renderer/src/components/settings/ZhipuAccountsSection.test.tsx
  • src/main/runtime/rpc/methods/client-ui-schemas.ts
  • src/renderer/src/components/settings/accounts-search.ts
  • src/main/runtime/rpc/methods/client-ui.test.ts
  • src/renderer/src/web/web-preload-api.ts
  • src/main/ipc/zhipu-credentials.ts
  • src/preload/index.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/shared/rate-limit-types.ts
  • src/renderer/src/components/settings/ZhipuAccountsSection.tsx
  • src/main/rate-limits/zhipu-fetcher.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Adds Zhipu/Z.AI credential storage, cc-switch import, quota fetching, and rate-limit state management. Exposes credential and refresh operations through Electron IPC, preload APIs, and browser fallbacks. Adds Zhipu account settings, localized text, status-bar visibility, icons, provider routing, and usage indicators. Updates shared state contracts and persists a one-time migration that adds Zhipu to the default status-bar items. Adds tests for fetching, importing, IPC registration, renderer behavior, visibility rules, and state initialization.

Merge Risk: ⚪ Minimal · up to ec4fe

The PR adds Zhipu usage monitoring and its related settings, status-bar, credential, and quota-fetching integration without any identified current-head merge-blocking risk; it is merge-ready after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the primary change: adding Zhipu / Z.AI usage monitoring.
Description check ✅ Passed The description is detailed and covers the change, rationale, testing, visual proof, AI disclosure, compatibility considerations, and checklist. The required linked issue is marked N/A despite the tem…
  • Fix all pre-merge checks with AI

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 67080387-5860-47a9-8900-131da58ddde5

📥 Commits

Reviewing files that changed from the base of the PR and between 165e4e0 and 1ae47a972822fa47aedd14da4f3023a71398ca79.

📒 Files selected for processing (51)
  • src/main/codex-accounts/service.test.ts
  • src/main/ipc/rate-limits.ts
  • src/main/ipc/register-core-handlers.ts
  • src/main/ipc/zhipu-credentials.ts
  • src/main/rate-limits/service.test.ts
  • src/main/rate-limits/service.ts
  • src/main/rate-limits/zhipu-fetcher.test.ts
  • src/main/rate-limits/zhipu-fetcher.ts
  • src/main/runtime/rpc/methods/client-ui-schemas.ts
  • src/main/runtime/rpc/methods/client-ui.test.ts
  • src/main/zhipu/cc-switch-import.test.ts
  • src/main/zhipu/cc-switch-import.ts
  • src/main/zhipu/zhipu-credential-store.ts
  • src/preload/api-types.ts
  • src/preload/index.ts
  • src/renderer/src/components/settings/AccountsPane.tsx
  • src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx
  • src/renderer/src/components/settings/ZhipuAccountsSection.test.tsx
  • src/renderer/src/components/settings/ZhipuAccountsSection.tsx
  • src/renderer/src/components/settings/accounts-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-minimax-toggle-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-search.ts
  • src/renderer/src/components/settings/appearance-status-bar-zhipu-toggle-search.ts
  • src/renderer/src/components/stats/GrokUsagePane.test.tsx
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/icons.tsx
  • src/renderer/src/components/status-bar/status-bar-agent-gating.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/renderer/src/components/status-bar/usage-error-copy.test.ts
  • src/renderer/src/components/status-bar/usage-error-copy.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts
  • src/renderer/src/components/status-bar/usage-provider-settings-target.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/store/slices/rate-limits.test.ts
  • src/renderer/src/store/slices/rate-limits.ts
  • src/renderer/src/store/slices/ui.test.ts
  • src/renderer/src/store/slices/ui.ts
  • src/renderer/src/web/web-preload-api.test.ts
  • src/renderer/src/web/web-preload-api.ts
  • src/shared/rate-limit-types.test.ts
  • src/shared/rate-limit-types.ts
  • src/shared/status-bar-defaults.ts
  • src/shared/types.ts
  • src/shared/zhipu-usage.ts

Comment thread src/main/rate-limits/zhipu-fetcher.ts Resolved
@Pr1p

Pr1p commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Hi! I addressed the CodeRabbit findings in 8076d32 and re-ran the targeted tests plus localization verification. Happy to split out the cc-switch import if you prefer a smaller review surface.

@Pr1p

Pr1p commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the latest main (251c7da8) to resolve the merge conflicts. The conflict was limited to the i18n locale files, where main landed plugin copy in the same region this PR adds Zhipu copy — all five locales now carry both. Re-ran verify:localization-catalog, verify:localization-coverage, and typecheck:web locally; all green.

@@ -30,4 +30,5 @@ export function registerRateLimitHandlers(
)
ipcMain.handle('rateLimits:refreshMiniMax', () => rateLimits.refresh())
ipcMain.handle('rateLimits:refreshGrok', () => rateLimits.refreshGrok())
ipcMain.handle('rateLimits:refreshZhipu', () => rateLimits.refresh())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 refreshZhipu triggers a full provider refresh rather than a Zhipu-specific one

rateLimits:refreshZhipu is wired to rateLimits.refresh(), which refreshes every provider (Claude, Codex, Gemini, MiniMax, Grok, etc.) in parallel. By contrast, rateLimits:refreshGrok calls the dedicated rateLimits.refreshGrok(). When a user clicks "Refresh usage" in the Zhipu settings panel, all other provider fetches are triggered as a side-effect. This is consistent with the MiniMax pattern so it won't break anything, but if a dedicated refreshZhipu() method is ever added to RateLimitService (as was done for Grok), the IPC handler here will need to be updated in tandem.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@greptile-apps

greptile-apps Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR adds Zhipu / Z.AI as a new usage provider in Orca, following the same architecture used by MiniMax, Grok, and other existing providers. It wires Zhipu quota fetching through credential storage, IPC/preload APIs, rate-limit service orchestration, status-bar visibility, settings UI, localization, and one-shot migration of the default status-bar item.

  • Core fetch layer (zhipu-fetcher.ts, zhipu-credential-store.ts, cc-switch-import.ts): encrypted credential storage via safeStorage, host-allowlisted HTTP fetch against Zhipu's quota endpoint, and optional import from a local cc-switch SQLite database using read-only, parameterized queries.
  • Service integration (service.ts): generation-based stale-result protection when credentials change mid-flight, config-hash change detection for fetch gating, and isolated credential-read-failure handling so a broken Zhipu token does not abort other providers.
  • Renderer integration: ZhipuAccountsSection.tsx settings panel, status-bar visibility logic, tooltip copy, empty-state CTA, and a one-shot _zhipuStatusBarDefaultAdded migration flag — all following established provider patterns.

Confidence Score: 5/5

  • Safe to merge — the integration follows established provider patterns throughout, previously flagged syntax and argument errors are corrected, and credential handling is well-guarded.
  • The two previously reported bugs (missing comma in the usageSettings object and the extra argument passed to isUsageEmptyState) are both verified fixed in the current diff. Credential storage is encrypted via safeStorage, network requests are allowlist-gated, generation counters correctly discard stale in-flight results, and the service isolates Zhipu credential failures from all other providers. Test coverage addresses the key failure modes. No new correctness, security, or runtime issues were found.
  • No files require special attention. The IPC rate-limits handler wires refreshZhipu to the global refresh() rather than a provider-specific method (consistent with MiniMax), but this is a known trade-off documented in the previous review thread.

Important Files Changed

Filename Overview
src/main/rate-limits/zhipu-fetcher.ts New Zhipu usage fetcher — host allowlist validation, timeout chaining, graceful status mapping, and robust JSON parsing are all implemented correctly.
src/main/zhipu/zhipu-credential-store.ts Credential store follows the safeStorage envelope pattern used by other providers; cache invalidation and hardening on read/check are handled correctly.
src/main/zhipu/cc-switch-import.ts cc-switch import uses read-only SQLite with query_only pragma and parameterized queries; Zhipu host validation guards the imported base URL before saving.
src/main/ipc/zhipu-credentials.ts IPC handler validates argument types, delegates persistence to the credential store, and triggers invalidation + refresh consistently with other providers.
src/main/rate-limits/service.ts Zhipu is integrated into the fetch orchestration with generation-based stale-result protection, config-hash change detection, and isolated credential-read-failure handling.
src/renderer/src/components/status-bar/StatusBar.tsx Previously reported bugs (missing comma in usageSettings, wrong argument count to isUsageEmptyState) are both fixed in this revision; Zhipu is wired in consistently with MiniMax/Grok.
src/renderer/src/components/settings/ZhipuAccountsSection.tsx Settings component follows the established pattern; double-refresh after save (component calls refreshZhipuRateLimits after the IPC handler already triggers refresh) is benign and consistent with the MiniMax section.
src/renderer/src/components/status-bar/status-bar-provider-visibility.ts Zhipu correctly added to hasUsageProviderSettings, hasUsageProviderSettingsForProvider, and isUsageEmptyState; no gaps found.
src/shared/zhipu-usage.ts Allowlist and normalization helpers are clean; isZhipuUsageHost lowercases the host before lookup, which is correct.
src/renderer/src/store/slices/ui.ts Zhipu status-bar default migration follows the same one-shot flag pattern used for Grok, Kimi, MiniMax, and Antigravity.
src/main/rate-limits/service-zhipu-usage.test.ts Tests cover credential read failures, stale in-flight result protection, and state isolation from other providers.
src/main/ipc/rate-limits.ts rateLimits:refreshZhipu calls rateLimits.refresh() (full provider refresh) instead of a Zhipu-specific method, matching the MiniMax pattern but diverging from Grok's dedicated method.

Sequence Diagram

sequenceDiagram
    participant User as User (Renderer)
    participant ZSec as ZhipuAccountsSection
    participant IPC as IPC (zhipu-credentials)
    participant Store as ZhipuCredentialStore
    participant Svc as RateLimitService
    participant API as Zhipu API

    User->>ZSec: Paste token + Save
    ZSec->>IPC: zhipuCredentials:save(baseUrl, authToken)
    IPC->>Store: saveZhipuCredentials()
    IPC->>Svc: invalidateZhipuCredentialState()
    Note over Svc: zhipuFetchGeneration++, clear snapshot
    IPC->>Svc: refresh() (all providers)
    ZSec->>IPC: rateLimits:refreshZhipu (redundant, benign)
    IPC->>Svc: refresh() (all providers)

    Svc->>Store: readZhipuCredentials()
    alt credentials ok
        Svc->>API: GET /api/monitor/usage/quota/limit
        API-->>Svc: "{data:{limits:[TOKENS_LIMIT, TIME_LIMIT]}}"
        Svc-->>User: "zhipu: {status:"ok", session, monthly}"
    else credentials unreadable
        Svc-->>User: "zhipu: {status:"error", failureKind:"keychain-unavailable"}"
    else no credentials
        Svc-->>User: "zhipu: {status:"unavailable"}"
    end
Loading

Reviews (4): Last reviewed commit: "feat: add Zhipu / Z.AI usage monitoring" | Re-trigger Greptile

@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch from 251c7da to 3664e12 Compare July 30, 2026 18:36
Comment on lines +2089 to +2090
grokAuthConfigured: rateLimits.grokAuthConfigured
zhipuCredentialsConfigured: rateLimits.zhipuCredentialsConfigured

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Missing comma breaks object literal syntax

Line 2089 is missing a trailing comma after grokAuthConfigured: rateLimits.grokAuthConfigured. Without the comma, the next line (zhipuCredentialsConfigured) is an invalid continuation inside the object literal — this is a JavaScript syntax error that prevents the file from being parsed. The usageSettings object will never be constructed, so visibleZhipu, every getVisibleUsageProvider call, and all downstream status-bar visibility logic will fail at the component level.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/rate-limits/service.ts (1)

346-366: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

hasZhipuCredentials() reintroduces sync I/O on the hot getState() path.

zhipuCredentialsConfigured: hasZhipuCredentials() (Line 354) does a synchronous existsSync plus a conditional chmod (hardenExistingSecureFile) on every getState() call. getState() backs pushToRenderer(), which fires multiple times per fetch cycle and once per account inside the inactive-account fetch loops — this is exactly the "hot" path the file's own comment at Line 1613 calls out when explaining why Grok's sync auth-file probe was deliberately moved out of getState() into the fetch cycle (grokAuthConfigured is just a cached boolean field). Mirroring the Grok approach here (cache a zhipuCredentialsConfigured boolean updated once per runFetchAllCycle/resolveZhipuCredentials()) avoids adding sync filesystem/chmod calls to a path invoked far more frequently than the poll interval.

♻️ Proposed fix
-  private zhipuFetchGeneration = 0
+  private zhipuFetchGeneration = 0
+  private zhipuCredentialsConfigured = false
   ...
   getState(): RateLimitState {
     this.pruneInactiveClaudeState()
     this.pruneInactiveCodexState()
     return {
       ...this.state,
       minimaxCookieConfigured: hasMiniMaxSessionCookie(),
       grokAuthConfigured: this.grokAuthConfigured,
-      zhipuCredentialsConfigured: hasZhipuCredentials(),
+      zhipuCredentialsConfigured: this.zhipuCredentialsConfigured,
       ...
     }
   }
   ...
   // in runFetchAllCycle, alongside resolveZhipuCredentials():
+  this.zhipuCredentialsConfigured = hasZhipuCredentials()
🧹 Nitpick comments (1)
src/main/rate-limits/service.test.ts (1)

2255-2286: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for the Zhipu credential-read error path.

Current tests cover the happy path and zhipuCredentialsConfigured flag, but not readZhipuCredentials() throwing (exercising getZhipuCredentialError/keychain-unavailable) or invalidateZhipuCredentialState()'s generation-bump race handling, similar to what's likely covered for MiniMax elsewhere in this suite.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4fe9c9cf-5436-49e0-875e-58998286c3ea

📥 Commits

Reviewing files that changed from the base of the PR and between 251c7da8effbf2b94e76aaf09940ace663a85bb6 and 3664e12d6a53691fa638f699f4a498e488e51d34.

📒 Files selected for processing (6)
  • src/main/codex-accounts/service.test.ts
  • src/main/ipc/rate-limits.ts
  • src/main/ipc/register-core-handlers.ts
  • src/main/ipc/zhipu-credentials.ts
  • src/main/rate-limits/service.test.ts
  • src/main/rate-limits/service.ts

@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch from 3664e12 to 0cc4fa3 Compare August 1, 2026 16:43
Comment on lines 2143 to 2147
const isEmptyUsageState = isUsageEmptyState(
{ claude, codex, gemini, opencodeGo, kimi, antigravity, minimax, grok },
{ claude, codex, gemini, opencodeGo, kimi, antigravity, minimax, grok, zhipu },
usageSettings
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 isUsageEmptyState called with an extra argument, dropping the real settings

isUsageEmptyState accepts exactly two parameters: (providers, settings). This call passes three. At runtime: the first object (without zhipu) becomes providers, the second rate-limits snapshot becomes settings, and the actual usageSettings is the third argument — silently ignored by JavaScript.

Concrete failures this causes today:

  • isProviderSnapshotPending(providers.zhipu) is called with undefined (not null), so it returns false; the "don't show the CTA while Zhipu is loading" guard never fires.
  • hasUsageProviderSettings(settings) receives a ProviderRateLimits snapshot object; every property lookup (settings?.zhipuCredentialsConfigured, settings?.grokAuthConfigured, settings?.codexManagedAccounts, etc.) returns undefined/false, so the function always returns false. Any user whose only configured provider is Zhipu, Grok, MiniMax, or a managed Codex account will incorrectly see the "Set up usage tracking" empty-state CTA.

The correct call is:

const isEmptyUsageState = isUsageEmptyState(
  { claude, codex, gemini, opencodeGo, kimi, antigravity, minimax, grok, zhipu },
  usageSettings
)

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch 2 times, most recently from 7b36e27 to 9c6345b Compare August 10, 2026 00:48
@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch from 7a75fe3 to ec4fee4 Compare August 19, 2026 04:41
@Pr1p

Pr1p commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main and pushed ec4fee4b. Fixed the StatusBar syntax/empty-state issues, cached Zhipu credential status off getState(), and added coverage for credential-read errors plus stale in-flight invalidation. Local checks passed: typecheck:web, typecheck:node, targeted vitest suites, targeted oxlint, localization checks, max-lines ratchet, build:electron-vite, and git diff --check.\n\n@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

@Pr1p: I will review the latest changes in commit ec4fee4b, with focus on the reported fixes and the Zhipu usage-monitoring flow.


🧠 Learnings used
Learnt from: slashdevcorpse
Repo: stablyai/orca PR: 0
File: :0-0
Timestamp: 2026-07-16T19:10:55.339Z
Learning: For PR `#9052`, the `/* oxlint-disable max-lines */` suppression at Line 1 of the affected file is grandfathered and byte-identical to `origin/main`; the PR changes only Lines 4398–4403. `pnpm lint` and `check:max-lines-ratchet` pass, so this PR does not introduce a new max-lines bypass.

Learnt from: brennanb2025
Repo: stablyai/orca PR: 8488
File: src/renderer/src/i18n/locales/zh.json:5540-5540
Timestamp: 2026-07-13T05:59:52.957Z
Learning: In stablyai/orca, locale files under `src/renderer/src/i18n/locales/` (e.g., `zh.json`) follow a preservation/provenance contract: existing machine-translated values that predate a given PR should not be changed unless there is review evidence (e.g., a reviewed correction with documented rationale). A translation appearing in a diff does not necessarily mean it was intentionally changed — it may simply be present because surrounding parity leaves were removed. Global retranslation of existing machine values is an explicit non-goal, so flagging wording/quality issues in pre-existing machine translations without review evidence is not actionable and should be withdrawn if the author explains this.

Learnt from: tomdebres
Repo: stablyai/orca PR: 9614
File: src/renderer/src/i18n/locales/ja.json:4687-4689
Timestamp: 2026-07-21T06:40:47.031Z
Learning: In stablyai/orca locale JSON catalogs under `src/renderer/src/i18n/locales/`, `pnpm run sync:localization-catalog` may generate and preserve descriptive localization keys alongside SHA1-style keys. When reviewing keys such as `auto.components.sidebar.HostSectionHeaderMenu.skewUpdateServer` or `auto.components.sidebar.WorktreeList.hostServerOutdated`, do not require SHA1-only keys if catalog verification passes and existing nearby entries use the same descriptive-key convention. Inspect the full JSON nesting rather than inferring a missing path segment from an abbreviated diff hunk.

Learnt from: ioitiki
Repo: stablyai/orca PR: 9076
File: src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx:127-170
Timestamp: 2026-07-16T22:08:51.855Z
Learning: In the stablyai/orca renderer settings localization code, semantic locale keys are valid and should be preferred when they match established neighboring namespaces. For example, `src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx` uses semantic keys such as `AppearanceWindowSidebarSection.usagePercentageDisplayUsed` and `AppearancePane.statusBarDescription`, while `src/renderer/src/components/settings/appearance-sidebar-search.ts` uses semantic `appearance.search.leftSidebarAppearance.*` and `workspaceCardLayout.*` keys. Hash-based keys are generated for unnamed strings, not a universal requirement. Validate localization changes with `pnpm sync:localization-catalog`, `pnpm verify:localization-catalog`, and `pnpm verify:localization-coverage`.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch 2 times, most recently from c88bb5c to 99fd3c2 Compare September 2, 2026 14:59
Re-applied onto latest main; resolved service.ts Kimi refactor and 5 i18n locale conflicts.
@Pr1p
Pr1p force-pushed the feat/zhipu-usage-monitor branch from 150edc4 to 86cbc5f Compare September 26, 2026 04:01
# Conflicts:
#	src/main/ipc/register-core-handlers/register-core-handlers.test.ts
#	src/main/ipc/register-core-handlers/register-core-handlers.ts
#	src/main/rate-limits/rate-limit-service-test-harness.ts
#	src/main/rate-limits/service-account-target-selection.test.ts
#	src/main/rate-limits/service-inactive-account-previews.test.ts
#	src/main/rate-limits/service-live-claude-usage.test.ts
#	src/main/rate-limits/service-refresh-orchestration.test.ts
#	src/main/rate-limits/service-window-activation.test.ts
#	src/main/rate-limits/service/service-configuration.ts
#	src/main/rate-limits/service/service-full-cycle-preparation.ts
#	src/main/rate-limits/service/service-polling.ts
#	src/main/rate-limits/service/service-state.ts
#	src/main/rate-limits/service/service-types.ts
#	src/preload/index.ts
#	src/renderer/src/components/settings/AccountsPane.tsx
#	src/renderer/src/components/settings/AppearanceWindowSidebarSection.tsx
#	src/renderer/src/components/settings/accounts-search.ts
#	src/renderer/src/components/settings/appearance-status-bar-minimax-toggle-search.ts
#	src/renderer/src/components/settings/appearance-status-bar-search.ts
#	src/renderer/src/components/status-bar/StatusBarProviderSegment.tsx
#	src/renderer/src/components/status-bar/StatusBarVisibilityMenu.tsx
#	src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
#	src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
#	src/renderer/src/components/status-bar/tooltip.tsx
#	src/renderer/src/components/status-bar/usage-error-copy.ts
#	src/renderer/src/components/status-bar/usage-provider-settings-target.ts
#	src/renderer/src/components/status-bar/use-status-bar-controller.ts
#	src/renderer/src/store/slices/ui-hydration-workspace-preferences.test.ts
#	src/renderer/src/store/slices/ui/ui-slice-hydration-actions.ts
#	src/renderer/src/web/preload-api/web-agent-accounts-api.ts
#	src/shared/persisted-ui-state-types.ts
#	src/shared/rate-limit-state-factory.ts
#	src/shared/rate-limit-types.test.ts
#	src/shared/rate-limit-types.ts
#	src/shared/status-bar-defaults.ts
#	src/shared/ui-chrome-types.ts
@Pr1p

Pr1p commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the latest main and resolved all conflicts.

What the resolution does:

  • Keeps both the new Zhipu status-bar item and the recently-landed Cursor item side by side in every roster touched by the conflict (visibility, search, hydration defaults, IPC registration).
  • Adopts main's newer naming where it moved (e.g. getMiniMaxStatusBarToggleSearchEntry) and main's relocated hydrateStatusBarItems module, dropping the stale inline copy.
  • Ordering follows the canonical StatusBarItem enum: zhipu before cursor in the default-on hydration list.

Verification: node + web typecheck pass; targeted vitest suites (register-core-handlers, status-bar-provider-visibility, ui-hydration-workspace-preferences) pass — 79 tests green.

@Pr1p

Pr1p commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Cross-linking: the repeated per-provider wiring in this PR (scan worker registration, preload bridge, IPC surface, store, UI) is what motivated #23580 — a proposal to document a one-page spec for adding a usage provider and close the contract drift gaps. If it lands, future providers should not have to re-derive these steps by hand. I'm happy to write the doc once the scope is agreed.

@Pr1p

Pr1p commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

Closing — superseded by #24618, which now ships GLM Coding Plan usage natively as part of first-class ZCode/GLM support. That's the better home for it. If gaps show up later (deeper per-model meters and the like), the plan is to bring them as a plugin per #23580.

@Pr1p Pr1p closed this Oct 4, 2026
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.

2 participants