Add hook injection at profile creation time (not just runtime):
- profile-writer.ts: inject on API profile create/update
- variant-settings.ts: inject on CLIProxy variant create
Hooks now present immediately after profile creation.
Ensure all hook-related modules use getCcsDir() from environment.ts
for consistent test isolation. Prevents tests from touching the user's
real ~/.ccs/ directory during test runs.
Changes:
- hook-config.ts: Use getCcsDir() for hookConfigPath
- hook-installer.ts: Use getCcsDir() for HOOK_SOURCE_PATH
- profile-hook-injector.ts: Use getCcsDir() for hook sources
- CLAUDE.md: Add test isolation rules
- remove removeHookConfig() call from uninstallWebSearchHook()
- add removeMigrationMarker() cleanup
- update postuninstall.js to only clean CCS files
- global ~/.claude/settings.json is never touched
- ensureProfileHooks() injects hooks into profile settings
- migrateGlobalHook() one-time migration from global settings
- removeMigrationMarker() cleanup for uninstall
- export from barrel files for module access
- save selected provider to localStorage on both pages
- restore selection on page load
- validate saved provider still exists before restoring
- improves UX by eliminating need to re-select provider after reload
- treat models with resetTime but null/missing remainingFraction as 0%
- matches CLIProxy Management Center behavior
- enables accurate Claude reset time display when quota exhausted
- mark primary models at 0% as exhausted for red styling
- Remove early return for paused accounts in quota fetcher
- Check both auth/ and auth-paused/ directories when reading auth data
- Allows users to see quota status of paused accounts to know when to unpause
- Remove "Exhausted" text in tooltip, just show 0% in red (saves width)
- Remove tier group headers, use delimiter lines between tiers
- Show full model names (Claude Opus 4.5 (Thinking), etc.)
- Show "Exhausted" in percentage column instead of appending to name
- Add all known primary models when exhausted
- Replace generic "Claude/GPT (Exhausted)" with actual model names
- Group models by tier with visual headers:
- Claude & GPT (primary, weekly limits)
- Gemini 3 (high capability)
- Gemini 2.5 (mid tier)
- Other
- When primary models exhausted, show known models with "(Exhausted)" label
- Add border separators between tier groups for visual clarity
When Claude/GPT models are exhausted (0%), API removes them from response.
Added getModelsWithExhaustedIndicator() to prepend synthetic "Claude/GPT
(Exhausted)" entry with 0% when primary models missing. Styled in red for
visibility. Applied to both account-item and flow-viz account-card tooltips.
- include GPT models in primary quota filter (not just Claude)
- return 0% when Claude/GPT missing from API (exhausted, not 100%)
- fallback to all models for reset time when primary exhausted
- add getClaudeResetTime to match getMinClaudeQuota logic
- weekly Claude resets now show absolute date (01/27, 12:07)
- daily Gemini resets no longer overshadow Claude weekly limits
- move BulkActionBar above account list (was at bottom)
- only show bar when selections exist (cleaner default)
- add selection checkbox to each AccountItem
- highlight selected accounts with ring + background
- Add visible pause/resume toggle button to AccountCard in flow-viz
(appears on hover or when paused, with tooltip)
- Pass pause toggle props from AuthMonitor through AccountFlowViz
- Remove redundant pause/resume from account-item dropdown menu
(keeps only "Set as default" and "Remove account")
- Add paused state to AccountData type with opacity indication
Reverts the expandable ProviderCard design back to click-to-navigate.
The pause toggle feature is preserved in AccountItem cards in Provider
Editor, not in the Live Account Monitor overview.
- Remove expandable account list component
- Remove unused pause/resume/solo mutations from AuthMonitor
- Restore original ProviderCard props interface
- Keep acc.paused opacity-50 for visual indication on dots
- add pause/play button left of user avatar
- paused accounts show play icon (green) and dimmed card
- active accounts show pause icon
- includes loading spinner and tooltip
- add ExpandableAccountList for inline account management
- add expand/collapse to ProviderCard with smooth transitions
- wire pause/resume/solo mutations to auth-monitor index
- add paused field to AccountRow type for UI display
- add BulkActionBar component for multi-select pause/resume
- add AccountItem with individual pause toggle and solo button
- fix solo button disabled logic for consistency
- add selection state and bulk operations to AccountsSection
- Add centralized mock infrastructure in tests/mocks/:
- mock-fetch.ts: Bun native fetch interception
- mock-http-server.ts: Fake server responses (no ports)
- fixtures/responses.ts: Preset response constants
- types.ts: Mock type definitions
- Refactor https-tunnel-proxy.test.ts:
- Remove TEST_CERT constant (~50 lines)
- Remove real HTTPS server creation
- Use invalid hosts for error path testing
- 26/26 tests pass in ~430ms
- Refactor remote-token-uploader.test.ts:
- Replace 7 real HTTP servers with mockFetch
- Reduce from 422 to 289 lines
- 18/18 tests pass in ~120ms
- Add global test timeout (10s) in bunfig.toml
Test suite: 10+ min → 14 seconds
Root cause: fetchLatestCliproxyVersion() and checkCliproxyUpdate()
ignored the caller's backend selection, always re-computing from config.
This caused --update to report wrong version when config wasn't synced.
Changes:
- Add optional backend param to fetchLatestCliproxyVersion()
- Add optional backend param to checkCliproxyUpdate()
- Pass effectiveBackend in binary-service.ts calls
- Pass backend in cliproxy-stats-routes.ts web endpoints
Fixes inconsistent version reporting when switching between
CLIProxyAPI (original) and CLIProxyAPIPlus backends.