feat: live multi-provider quota panel (#1278)
* feat: live provider quota panel (Claude + Codex) Adds Claude and Codex plan usage to the context window percentage circle tooltip, querying their respective APIs directly using existing CLI auth tokens. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address review feedback - restore quota trigger, guard NaN date - Re-add triggerFetch() on agent idle/error in agent status subscription - Guard formatResetsAtLabel against NaN from malformed API date strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: resolve composer conflict and stub subscribe in websocket tests * feat(quota): add cursor, copilot, zai, grok, and kimi quota UI and improve type safety * feat(quota): make Claude and Codex pluggable, and map additional quota/credits metrics * security(quota): fix shell injection vulnerability by migrating exec to execFile * revert: restore original scripts/dev.ps1 and packages/desktop/scripts/dev.ps1 * Fix i18n resource test expectation * Fix quota tooltip empty-provider state * Preserve zero values in Grok quota * Fix empty quota fetch state * Ignore quota frames in relay reconnect tests * Persist refreshed Codex tokens to source auth file * fix(quota): read Claude OAuth credentials from the macOS login Keychain On macOS, Claude Code stores its OAuth credential in the login Keychain (generic-password item, service "Claude Code-credentials"), not in ~/.claude/.credentials.json — that file usually does not exist there, so the Claude provider's existsSync check failed and macOS users silently got no Claude quota. Read it via the macOS `security` CLI (its ACL only trusts /usr/bin/security to decrypt; a native Keychain read would prompt), and stay read-only there since Claude Code owns the refresh/persist. Linux and Windows keep using ~/.claude/.credentials.json unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix quota keychain timeout and local host reconciliation * Fix terminal notification test quota stub * Ignore quota frames in terminal notification tests * fix(quota): bypass Claude token refresh on macOS Keychain-backed logins * fix(dev): update local dev daemon port to 6768 on Windows scripts/dev.ps1 * fix(dev): bypass Unix dev-daemon.sh on Windows in dev.ps1 * fix(client): handle and dispatch provider_quota event in DaemonClient * fix(desktop): fix PowerShell quote stripping in desktop dev.ps1 config seeding * fix(desktop): execute config update via temp file to avoid PowerShell quoting bugs * fix(desktop): fix concurrently command invocation on Windows in dev.ps1 * fix(desktop): resolve path escaping and environment setting syntax errors in dev.ps1 for Windows * Add on-demand provider usage views * Fix Cursor usage billing dates * Move provider usage renderer coverage to e2e * Use provider manifest for quota fetchers * Add provider usage fetch timeouts * Reshape provider usage fetchers --------- Co-authored-by: ABorakati <ABorakati@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com> Co-authored-by: lumingjun <lumingjun@bytedance.com>
This commit is contained in:
co-authored by
ABorakati
Claude Sonnet 4.6
Mohamed Boudra
lumingjun
parent
2b0740ff84
commit
acea7f3d24
@@ -4,6 +4,7 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$DesktopDir = (Resolve-Path "$ScriptDir\..").Path
|
||||
$AppDir = (Resolve-Path "$DesktopDir\..\app").Path
|
||||
$RootDir = (Resolve-Path "$DesktopDir\..\..").Path
|
||||
$env:PATH = "$RootDir\node_modules\.bin;$env:PATH"
|
||||
|
||||
# Build the Electron main process
|
||||
npm run build:main
|
||||
@@ -78,18 +79,27 @@ if (-not $env:PASEO_LISTEN) { $env:PASEO_LISTEN = "127.0.0.1:$DevDaemonPort" }
|
||||
# ONLY seed the script-managed home: never rewrite a user-supplied PASEO_HOME
|
||||
# (that could clobber a production config.json with the dev port + wildcard CORS).
|
||||
if ($PaseoHomeManaged) {
|
||||
node -e '
|
||||
const fs = require("fs");
|
||||
const [path, port] = [process.argv[1], process.argv[2]];
|
||||
$env:TMP_CFG_PATH = "$($env:PASEO_HOME)/config.json"
|
||||
$env:TMP_CFG_PORT = $DevDaemonPort
|
||||
$TmpScript = [System.IO.Path]::GetTempFileName() + ".js"
|
||||
$ScriptContent = @"
|
||||
const fs = require('fs');
|
||||
const path = process.env.TMP_CFG_PATH;
|
||||
const port = process.env.TMP_CFG_PORT;
|
||||
let cfg = {};
|
||||
try { cfg = JSON.parse(fs.readFileSync(path, "utf8")); } catch {}
|
||||
try { cfg = JSON.parse(fs.readFileSync(path, 'utf8')); } catch(e) {}
|
||||
cfg.version = cfg.version || 1;
|
||||
cfg.daemon = cfg.daemon || {};
|
||||
cfg.daemon.listen = `127.0.0.1:${port}`;
|
||||
cfg.daemon.listen = '127.0.0.1:' + port;
|
||||
cfg.daemon.cors = cfg.daemon.cors || {};
|
||||
cfg.daemon.cors.allowedOrigins = ["*"];
|
||||
cfg.daemon.cors.allowedOrigins = ['*'];
|
||||
fs.writeFileSync(path, JSON.stringify(cfg, null, 2));
|
||||
' "$($env:PASEO_HOME)/config.json" $DevDaemonPort
|
||||
"@
|
||||
Set-Content -Path $TmpScript -Value $ScriptContent
|
||||
node $TmpScript
|
||||
Remove-Item $TmpScript -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:\TMP_CFG_PATH -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:\TMP_CFG_PORT -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
Write-Host " (custom PASEO_HOME - leaving its config.json untouched)"
|
||||
}
|
||||
@@ -107,9 +117,9 @@ Write-Host @"
|
||||
"@
|
||||
|
||||
# Launch Metro + Electron together, kill both on exit
|
||||
& "$RootDir\node_modules\.bin\concurrently" `
|
||||
concurrently `
|
||||
--kill-others `
|
||||
--names "metro,electron" `
|
||||
--prefix-colors "magenta,cyan" `
|
||||
"cd `"$AppDir`" && `$env:PASEO_WEB_PLATFORM = `"electron`"; npx expo start --port $($env:EXPO_PORT)" `
|
||||
"cd `"$AppDir`" && cross-env PASEO_WEB_PLATFORM=electron npx expo start --port $($env:EXPO_PORT)" `
|
||||
"npx wait-on tcp:$($env:EXPO_PORT) && npx electron `"$DesktopDir`""
|
||||
|
||||
Reference in New Issue
Block a user