Skip to content

feat(wework): add Wegent quota display - #2401

Merged
qdaxb merged 2 commits into
mainfrom
feature/wegent-quota
Aug 4, 2026
Merged

qdaxb merged 2 commits into
mainfrom
feature/wegent-quota

Conversation

@qdaxb

@qdaxb qdaxb commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add cloud quota parsing from /quota/claude/quota, including source labels, remaining values, and usage-rate calculation.
  • Show the full quota source name in the lower-left menu and General settings, while the tray uses an ASCII abbreviation of up to five letters.
  • Add an independent cloud-quota tray preference and render compact two-line quota text in the macOS tray icon without leaking a line above the menu bar.
  • Document the new tray and quota behavior in Chinese and English.

Root cause

The quota endpoint response was treated as a generic empty/zero value, the API usage-rate field was interpreted with the wrong scale, and macOS tray titles could not reliably represent the desired two-line layout. The change derives the percentage from used divided by total quota, preserves negative remaining values, and renders tray text through the existing native tray image path.

Validation

  • pnpm --filter wework lint
  • pnpm --filter wework typecheck
  • pnpm --filter wework exec vitest run (268 files, 2656 tests passed)
  • cargo test --manifest-path wework/src-tauri/Cargo.toml --lib (122 tests passed)
  • Pre-commit and pre-push quality checks passed

Summary by CodeRabbit

  • New Features
    • Added cloud quota usage alongside Codex usage in the desktop settings menu.
    • Added separate controls for displaying cloud quota and Codex usage in the system tray.
    • Tray titles, tooltips, and menus now show quota sources, remaining amounts, and usage rates.
    • Added localized English and Simplified Chinese labels and descriptions.
    • Cloud quota values refresh automatically while connected and handle loading, errors, and unavailable data.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Wegent quota data and formatting

Layer / File(s) Summary
Quota response and display service
wework/src/api/quota.ts, wework/src/api/wegentUsage.ts, wework/src/api/wegentUsage.test.ts
Quota responses include cloud quota details. The new service retrieves authenticated data, formats localized values, calculates usage rates, and preserves negative remaining values. Tests cover formatting, connection states, and request credentials.

Settings and tray integration

Layer / File(s) Summary
Settings and desktop quota menu
wework/src/components/settings/GeneralSettingsPage.tsx, wework/src/components/layout/DesktopSettingsMenu.tsx, wework/src/i18n/locales/*, docs/*/wegent/user-guide/settings/desktop-app-preferences.md
Settings expose a separate Wegent tray toggle. The desktop menu loads and displays Wegent quota details with connected, loading, error, and login states. Localization and user documentation describe the new display.
Preference persistence and tray title flow
wework/src/tauri/appPreferences.ts, wework/src/tauri/appPreferences.test.ts, wework/src/pages/WorkbenchPage.tsx, wework/src/tauri/trayUsageTitle.ts, wework/src/tauri/trayUsageTitle.test.ts, wework/src/components/settings/*test.tsx
The Wegent tray preference defaults to enabled and supports validated updates across preference models. WorkbenchPage refreshes Wegent usage every 60 seconds and combines it with Codex usage in tray titles and tooltips.

macOS tray rendering

Layer / File(s) Summary
Native usage text composition
wework/src-tauri/Cargo.toml, wework/src-tauri/src/lib.rs
macOS tray usage text uses native fonts, antialiasing, proportional resizing, platform-specific dimensions, and status-icon composition. macOS tests cover rendering, sizing, visible pixels, and fallback behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WorkbenchPage
  participant WegentUsage
  participant QuotaAPI
  participant Tray
  WorkbenchPage->>WegentUsage: refresh usage with cloud credentials
  WegentUsage->>QuotaAPI: request authenticated quota data
  QuotaAPI-->>WegentUsage: return quota details
  WegentUsage-->>WorkbenchPage: return formatted Wegent display
  WorkbenchPage->>Tray: combine Codex and Wegent titles and tooltips
  Tray->>Tray: compose macOS usage text with status icon
Loading

Possibly related PRs

Suggested reviewers: micro66

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Wegent quota display support.
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.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/wegent-quota

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.

@qdaxb
qdaxb marked this pull request as ready for review August 4, 2026 04:16
@qdaxb
qdaxb enabled auto-merge August 4, 2026 04:21

@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: 4

🧹 Nitpick comments (2)
wework/src/components/layout/DesktopSettingsMenu.test.tsx (1)

172-178: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the test to match its new assertions.

The test now asserts that the Codex label and the Wegent label render. The name only describes the removal of the old account and quota rows.

Rename it, for example to renders the Codex and Wegent quota rows instead of the old account summary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/DesktopSettingsMenu.test.tsx` around lines 172 -
178, Rename the test case around renderMenu from “does not render the old
account or quota summary row” to a name describing that the Codex and Wegent
quota rows render instead of the old account summary, matching its current
assertions.
wework/src/components/settings/GeneralSettingsPage.test.tsx (1)

102-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the disconnected cloud connection.

The mock at lines 106-113 always returns isConnected: true. The new code adds two branches that this suite never exercises: the early return in the fetch effect and the label fallback when the connection is inactive.

Make the mock configurable, then add a test that asserts the toggle falls back to workbench.general_settings_tray_wegent_usage and that getWegentUsageDisplay is not called.

🧪 Proposed mock change
+const cloudConnectionMock = vi.hoisted(() => ({
+  current: {
+    isConnected: true,
+    apiBaseUrl: 'https://wegent.example.com/api',
+    token: 'token',
+    serviceKey: 'test-cloud',
+  },
+}))
+
 vi.mock('`@/features/cloud-connection/useCloudConnection`', () => ({
-  useOptionalCloudConnection: () => ({
-    isConnected: true,
-    apiBaseUrl: 'https://wegent.example.com/api',
-    token: 'token',
-    serviceKey: 'test-cloud',
-  }),
+  useOptionalCloudConnection: () => cloudConnectionMock.current,
 }))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/settings/GeneralSettingsPage.test.tsx` around lines 102
- 113, Make the useOptionalCloudConnection mock configurable, then add a
disconnected-connection test covering the fetch effect’s early return: assert
the toggle uses the workbench.general_settings_tray_wegent_usage fallback label
and getWegentUsageDisplay is not called.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/api/wegentUsage.ts`:
- Around line 24-25: Replace the navigator.language-based isEnglishLocale check
with the selected Wework application locale, keeping quota data unlocalized in
this API module. Move user-facing quota formatting to a caller that uses the
local `@/hooks/useTranslation` wrapper, or pass the selected locale into the
formatter so manually chosen interface language controls the output.
- Around line 77-78: Update the sourceText construction in the quota usage
display to use the full data.quota_source value for settings, menu, and tooltip
text, preserving the localized quota suffix. Keep extractQuotaSourceLabel
limited to the compact tray title path so full names such as “Anthropic Cloud”
and non-ASCII sources are not truncated.

In `@wework/src/components/layout/DesktopSettingsMenu.tsx`:
- Around line 143-165: Extract the duplicated Wegent usage fetching into a
shared useWegentUsage hook: in
wework/src/components/layout/DesktopSettingsMenu.tsx lines 143-165 and
wework/src/components/settings/GeneralSettingsPage.tsx lines 98-125, replace the
effects (and GeneralSettingsPage’s cloudQuotaName state) with the hook, which
must own connection checks, getWegentUsageDisplay, cancellation, loading, and
error state; derive GeneralSettingsPage’s label from the hook’s sourceText. In
wework/src/components/layout/DesktopSettingsMenu.tsx lines 87-123, consolidate
the remaining Codex and Wegent manual-refresh logic into one helper
parameterized by the loader and state setters.
- Around line 364-381: Update the quota display conditional in
DesktopSettingsMenu around wegentUsage.status so quota_load_failed is shown only
when wegentQuotaError indicates the fetch failed. For a successful response with
no available quota source, render a separate empty-state translation, while
preserving the existing login message for disconnected users and the
available-quota display.

---

Nitpick comments:
In `@wework/src/components/layout/DesktopSettingsMenu.test.tsx`:
- Around line 172-178: Rename the test case around renderMenu from “does not
render the old account or quota summary row” to a name describing that the Codex
and Wegent quota rows render instead of the old account summary, matching its
current assertions.

In `@wework/src/components/settings/GeneralSettingsPage.test.tsx`:
- Around line 102-113: Make the useOptionalCloudConnection mock configurable,
then add a disconnected-connection test covering the fetch effect’s early
return: assert the toggle uses the workbench.general_settings_tray_wegent_usage
fallback label and getWegentUsageDisplay is not called.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a754821f-6782-45ef-afc1-047f13a9ea55

📥 Commits

Reviewing files that changed from the base of the PR and between 7494925 and 309d68c.

📒 Files selected for processing (21)
  • docs/en/wegent/user-guide/settings/desktop-app-preferences.md
  • docs/zh/wegent/user-guide/settings/desktop-app-preferences.md
  • wework/src-tauri/Cargo.toml
  • wework/src-tauri/src/lib.rs
  • wework/src/api/quota.ts
  • wework/src/api/wegentUsage.test.ts
  • wework/src/api/wegentUsage.ts
  • wework/src/components/layout/DesktopSettingsMenu.test.tsx
  • wework/src/components/layout/DesktopSettingsMenu.tsx
  • wework/src/components/settings/AppshotsSettingsPage.test.tsx
  • wework/src/components/settings/BrowserSettingsPage.test.tsx
  • wework/src/components/settings/ContextSettingsPage.test.tsx
  • wework/src/components/settings/GeneralSettingsPage.test.tsx
  • wework/src/components/settings/GeneralSettingsPage.tsx
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/zh-CN/common.json
  • wework/src/pages/WorkbenchPage.tsx
  • wework/src/tauri/appPreferences.test.ts
  • wework/src/tauri/appPreferences.ts
  • wework/src/tauri/trayUsageTitle.test.ts
  • wework/src/tauri/trayUsageTitle.ts

Comment on lines +24 to +25
function isEnglishLocale(): boolean {
return typeof navigator !== 'undefined' && navigator.language.toLowerCase().startsWith('en')

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.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Use the selected Wework locale for quota text.

navigator.language uses the system locale. It does not use the manually selected Wework interface language. A user who selects English in Wework on a Chinese system receives Chinese quota strings.

Keep quota data unlocalized in this API module. Format user-facing strings in a caller that uses @/hooks/useTranslation, or pass the selected application locale into the formatter.

As per coding guidelines, new wework/src/**/*.{ts,tsx} code must use the local @/hooks/useTranslation wrapper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/api/wegentUsage.ts` around lines 24 - 25, Replace the
navigator.language-based isEnglishLocale check with the selected Wework
application locale, keeping quota data unlocalized in this API module. Move
user-facing quota formatting to a caller that uses the local
`@/hooks/useTranslation` wrapper, or pass the selected locale into the formatter
so manually chosen interface language controls the output.

Source: Coding guidelines

Comment on lines +77 to +78
const sourceLabel = extractQuotaSourceLabel(data.quota_source)
const sourceText = english ? `${sourceLabel} quota` : `${sourceLabel}额度`

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the full quota source name outside the tray.

sourceText uses sourceLabel, but sourceLabel is truncated to five ASCII letters. A source such as Anthropic Cloud becomes Anthr quota. A non-ASCII source becomes Quota额度.

Use data.quota_source for settings, menu, and tooltip text. Restrict extractQuotaSourceLabel to the compact tray title only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/api/wegentUsage.ts` around lines 77 - 78, Update the sourceText
construction in the quota usage display to use the full data.quota_source value
for settings, menu, and tooltip text, preserving the localized quota suffix.
Keep extractQuotaSourceLabel limited to the compact tray title path so full
names such as “Anthropic Cloud” and non-ASCII sources are not truncated.

Comment on lines +143 to +165
useEffect(() => {
if (!cloudConnection.isConnected) return

let cancelled = false
getWegentUsageDisplay({
isConnected: cloudConnection.isConnected,
apiBaseUrl: cloudConnection.apiBaseUrl,
token: cloudConnection.token,
})
.then(data => {
if (!cancelled) setWegentUsage(data)
})
.catch(() => undefined)

return () => {
cancelled = true
}
}, [
cloudConnection.apiBaseUrl,
cloudConnection.isConnected,
cloudConnection.serviceKey,
cloudConnection.token,
])

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Extract the Wegent usage fetch into one shared hook. Both components copy the same effect: skip when disconnected, call getWegentUsageDisplay with the connection fields, guard the result with a cancelled flag, and depend on apiBaseUrl, isConnected, serviceKey, and token. Two copies of this logic will drift, and each copy handles errors differently.

  • wework/src/components/layout/DesktopSettingsMenu.tsx#L143-L165: replace this effect with a shared useWegentUsage() hook that owns the fetch, the cancellation guard, and the loading and error state.
  • wework/src/components/settings/GeneralSettingsPage.tsx#L98-L125: replace this effect and the cloudQuotaName state with the same hook, and derive the label from the returned sourceText.
  • wework/src/components/layout/DesktopSettingsMenu.tsx#L87-L123: loadCodexUsage and loadWegentUsage differ only in the fetch function and the state setters. After the hook exists, collapse the remaining manual-refresh path into one helper that takes the loader and the setters.

As per coding guidelines: "Before adding code, search for and reuse existing components, services, utilities, and patterns; extract shared logic instead of duplicating it."

📍 Affects 2 files
  • wework/src/components/layout/DesktopSettingsMenu.tsx#L143-L165 (this comment)
  • wework/src/components/settings/GeneralSettingsPage.tsx#L98-L125
  • wework/src/components/layout/DesktopSettingsMenu.tsx#L87-L123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/DesktopSettingsMenu.tsx` around lines 143 - 165,
Extract the duplicated Wegent usage fetching into a shared useWegentUsage hook:
in wework/src/components/layout/DesktopSettingsMenu.tsx lines 143-165 and
wework/src/components/settings/GeneralSettingsPage.tsx lines 98-125, replace the
effects (and GeneralSettingsPage’s cloudQuotaName state) with the hook, which
must own connection checks, getWegentUsageDisplay, cancellation, loading, and
error state; derive GeneralSettingsPage’s label from the hook’s sourceText. In
wework/src/components/layout/DesktopSettingsMenu.tsx lines 87-123, consolidate
the remaining Codex and Wegent manual-refresh logic into one helper
parameterized by the loader and state setters.

Source: Coding guidelines

Comment on lines +364 to +381
{!wegentQuotaLoading && !wegentQuotaError ? (
wegentUsage.status === 'available' ? (
<div className="space-y-0.5 text-xs leading-5 text-text-secondary">
<div className="flex items-start justify-between gap-3">
<span className="min-w-0 whitespace-nowrap">{wegentUsage.sourceText}</span>
<span className="shrink-0 whitespace-nowrap font-semibold text-text-primary">
{wegentUsage.value}
</span>
</div>
<div className="text-text-muted">{wegentUsage.detail}</div>
</div>
) : (
<div className="py-1 text-sm leading-[18px] text-text-secondary">
{cloudConnection.isConnected
? t('workbench.quota_load_failed', '额度信息获取失败')
: t('workbench.account_cloud_login', '登录 Wegent')}
</div>
)

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report a load failure when the quota fetch succeeded.

Lines 376-380 show quota_load_failed whenever wegentUsage.status !== 'available' and the user is connected. The fetch at line 113 can succeed and still return a non-available status, for example when the account has no quota source. In that case the panel claims that the fetch failed.

Distinguish "fetch failed" from "no quota available". Use wegentQuotaError for the failure case only, and add a separate empty-state string for a successful response without quota.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/DesktopSettingsMenu.tsx` around lines 364 - 381,
Update the quota display conditional in DesktopSettingsMenu around
wegentUsage.status so quota_load_failed is shown only when wegentQuotaError
indicates the fetch failed. For a successful response with no available quota
source, render a separate empty-state translation, while preserving the existing
login message for disconnected users and the available-quota display.

@qdaxb
qdaxb added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 9e6a9b7 Aug 4, 2026
68 of 88 checks passed
@qdaxb
qdaxb deleted the feature/wegent-quota branch August 4, 2026 06:57
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