- 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: execClaudeWithProxy() was ignoring ANTHROPIC_MODEL from
user settings and always using hardcoded 'glm-4.6'.
Changes:
- Read model from user's settings file in GLMT proxy flow
- Update default model to glm-4.7 in base configs (matches presets)
- Update fallback models in transformer/response-builder
Closes#358
Co-Authored-By: Claude <noreply@anthropic.com>
- Use checkCliproxyUpdate() in checkLatestVersion() for correct repo
- Dynamic error messages based on backend in service-manager
- Dynamic error messages based on backend in cliproxy-executor
- Generic "CLIProxy" message in oauth-process (no backend context)
- Add backend field to BinaryManagerConfig type for installer context
- Thread backend parameter through tar/zip extractors to use correct names
- Delete existing binary before install to prevent mismatched binaries
- Track backend in session metadata for debugging/monitoring
- Validate and preserve backend field in config mergeWithDefaults
- Pass backend to registerSession for session tracking
The core issue was extractors calling getExecutableName() without the
backend parameter, causing it to default to 'plus' regardless of user
selection. This resulted in wrong binaries being extracted/renamed.
Root cause: fetchLatestVersion and fetchAllVersions were hardcoded to
CLIProxyAPIPlus repo, ignoring backend selection.
Changes:
- Add getGitHubApiUrls(backend) helper to types.ts
- Make fetchLatestVersion and fetchAllVersions backend-aware
- Make version list cache backend-specific (bin/{backend}/.version-list-cache.json)
- Update /api/cliproxy/versions route to use configured backend
- Allow version management even when proxy not running (ProxyStatusWidget)
- Show settings button in all states for easier access
- Add mutation key to useUpdateBackend for tracking
- Detect backend switching with useIsMutating in ProxyStatusWidget
- Disable install/controls during backend switch (prevents wrong-backend install)
- Reduce useCliproxyVersions staleTime from 1h to 5min for faster refresh
- Enable refetchOnWindowFocus for versions query
- Add backend parameter to version cache functions (read/write/path)
- Store cache at bin/{backend}/.version-cache.json instead of shared location
- Pass backend through checkForUpdates() and BinaryManager
- Add refetchType: 'all' to force immediate query refetch on backend change
- Add cliproxy-server-config query invalidation for consistency
- Add ProxyStatusWidget to Settings/Proxy page for quick start/stop access
- Disable backend selection when proxy is running with clear warning
- Removes UX friction: no need to navigate to CLIProxy page to stop instance
- Shows amber alert explaining why backend switch is blocked
User can now:
1. See proxy status directly in Settings
2. Stop proxy from Settings page
3. Change backend only when proxy is stopped
- Add useUpdateBackend mutation hook that invalidates related queries
- Reduce update-check stale time from 1hr to 5min + enable refetchOnWindowFocus
- Settings proxy page now uses mutation hook for proper query invalidation
- Make all CLIProxy labels dynamic based on backendLabel from API:
- cliproxy-header.tsx: page title
- app-sidebar.tsx: nav item label
- cliproxy-stats-overview.tsx: both offline and running descriptions
- model-preferences-grid.tsx: card description
- settings proxy section: descriptions for local/remote modes
- Fix API route to use DEFAULT_BACKEND constant instead of hardcoded 'plus'
Ensures backend switching in Settings immediately reflects in all CLIProxy pages.
- Add backend/backendLabel fields to CliproxyUpdateCheckResult
- Update proxy-status-widget to show backendLabel from API
- Update cliproxy page header to use backendLabel
Dashboard now shows "CLIProxy" or "CLIProxy Plus" based on configured
backend in config.yaml instead of hardcoded "CLIProxy Plus".
- Add backend param to isCLIProxyInstalled(), getCLIProxyPath(),
getInstalledCliproxyVersion(), installCliproxyVersion()
- Update getBinaryStatus() to pass backend to all helper functions
- Add getBackendLabel() helper for dynamic CLI messages
- Replace hardcoded "CLIProxy Plus" strings with dynamic labels
- Pass --backend flag through install/update command handlers
- Import CLIProxyBackend type from types.ts instead of redefining
Setting `cliproxy.backend: original` in config.yaml now correctly
uses the original backend for version pins and binary operations.
- Change requiresApiKey from optional to required boolean in CLI
- Add requiresApiKey: true to all existing presets for consistency
- Document 'ollama' placeholder as sentinel value in code comment
- Add trailing newline to ollama.svg
- Change CLI noApiKey to requiresApiKey to match UI convention
- Set apiKey='ollama' instead of empty string for local Ollama
- Align ollama-cloud descriptions between CLI/UI
- Keep https://ollama.com endpoint for direct API access
- Add Ollama SVG logo to ui/public/icons/
- Add icon property to both ollama and ollama-cloud presets
- Make API key field optional for local Ollama (show input with hint)
- Update placeholder: "Optional - only if auth is enabled"
- Allows power users with Ollama auth configured to provide key
- Add ollama (local) and ollama-cloud presets to UI provider-presets.ts
- Update profile-create-dialog to handle requiresApiKey: false
- Show "No API Key Required" info box for local Ollama
- Add --api-key ignored warning to CLI for local Ollama preset
- Add ollama-cloud to CLI help text preset list
Fixes edge cases identified in PR review:
- UI dashboard now has parity with CLI Ollama support
- Conditional API key validation in profile creation form
Local Ollama doesn't require an API key, but the CLI was still
prompting for one. This adds a `noApiKey` flag to provider presets
to mark providers that don't need authentication.
- Add `noApiKey?: boolean` property to ProviderPreset interface
- Set `noApiKey: true` for local Ollama (no key needed)
- All other presets unchanged (default to requiring API key)
- Skip API key prompt and show info message when noApiKey is true
Co-Authored-By: Claude <noreply@anthropic.com>
Local Ollama doesn't require an API key, but the CLI was still
prompting for one. This adds a `requiresApiKey` property to provider
presets to control whether the API key step is required.
- Add `requiresApiKey` property to ProviderPreset interface
- Set `requiresApiKey: false` for local Ollama (no key needed)
- Set `requiresApiKey: true` for OpenRouter and Ollama Cloud
- Skip API key prompt and show info message when not required
Co-Authored-By: Claude <noreply@anthropic.com>
Update README.md to include:
- Ollama and Ollama Cloud in the Built-in Providers table
- Ollama integration note with setup instructions
- ccs ollama in Basic Commands section
- Ollama example in Parallel Workflows
Ref: https://github.com/kaitranntt/ccs/pull/354
Co-Authored-By: Claude <noreply@anthropic.com>
Add support for Ollama as a provider in CCS, enabling users to use
local Ollama models (qwen3-coder, gpt-oss:20b, gpt-oss:120b) and
Ollama Cloud models (glm-4.7:cloud, qwen3-coder:480b).
Changes:
- Add base-ollama.settings.json for local Ollama (localhost:11434)
- Add base-ollama-cloud.settings.json for ollama.com cloud API
- Add 'ollama' and 'ollama-cloud' presets to provider-presets.ts
- Update help documentation in api-command.ts and help-command.ts
Usage:
ccs api create --preset ollama # Local Ollama
ccs api create --preset ollama-cloud # Ollama Cloud
Ref: https://github.com/kaitranntt/ccs/issues/353
Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive tests for getProjectDisplayName function
- Test various path structures including worktrees, nested projects, and edge cases
- Include regression tests for the reported bug cases
- Create separate utility file for better testability
Fixes session stats display where wrong fragments were shown
Related to: #348 (quota display), #103 (context display)
Replace session.projectPath.split('/').pop() with getProjectDisplayName()
to ensure the actual leaf folder name is shown instead of incorrect fragments.
Example fixes:
- /home/user/projects/my-app now shows "my-app" instead of "app"
- /home/user/workspaces/repo-name/worktrees/feature-branch now shows "feature-branch" instead of "branch"
Addresses potential issues with project name display in analytics dashboard.
Related to: #348 (quota display), #103 (context display)
Replace session.projectPath.split('/').pop() with getProjectDisplayName()
to ensure the actual leaf folder name is shown instead of incorrect fragments.
Example fixes:
- /home/user/projects/my-app now shows "my-app" instead of "app"
- /home/user/workspaces/repo-name/worktrees/feature-branch now shows "feature-branch" instead of "branch"
Addresses potential issues with project name display in analytics dashboard.
Related to: #348 (quota display), #103 (context display)