Commit Graph

507 Commits

Author SHA1 Message Date
YoVinchen a64e588cf8 feat(model-test): add provider model availability testing
Implement standalone model testing feature to verify provider API connectivity:
- Add ModelTestService for Claude/Codex/Gemini endpoint testing
- Create model_test_logs table for test result persistence
- Add test button to ProviderCard with loading state
- Include ModelTestConfigPanel for customizing test parameters
2025-12-04 00:53:25 +08:00
YoVinchen ab08b906ad fix(ui): update SettingsPage tab styles for improved appearance (#342) 2025-12-03 22:28:13 +08:00
YoVinchen 26753f3d66 Merge branch 'main' into feat/proxy-server
# Conflicts:
#	src/components/settings/SettingsPage.tsx
2025-12-03 22:19:44 +08:00
YoVinchen d783cbe745 style(config): format mcpPresets code style
Apply consistent formatting to createNpxCommand function and
sequential-thinking server configuration.
2025-12-03 21:55:53 +08:00
YoVinchen d304346514 refactor(ui): enhance RequestLogTable with filtering and pagination
UI improvements:
- Add filter bar with app type, provider name, model, status selectors
- Add date range picker (startDate/endDate)
- Add search/reset/refresh buttons

Pagination:
- Implement proper page-based pagination with page info display
- Show total count and current page range
- Add prev/next navigation buttons

Features:
- Default to last 24 hours filter
- Streamlined table columns layout
- Query invalidation on refresh
2025-12-03 21:54:41 +08:00
YoVinchen 1efa41082c feat(frontend): update usage types and API for pagination support
Types (usage.ts):
- Add isStreaming, firstTokenMs, durationMs to RequestLog
- Add PaginatedLogs interface with data, total, page, pageSize
- Change LogFilters: providerId -> appType + providerName

API (usage.ts):
- Change getRequestLogs params from limit/offset to page/pageSize
- Return PaginatedLogs instead of RequestLog[]
- Pass filters object directly to backend

Query (usage.ts):
- Update usageKeys.logs key generation for pagination
- Update useRequestLogs hook signature
2025-12-03 21:54:02 +08:00
wenyuan b1e4c37f9c fix(ui): update SettingsPage tab styles for improved appearance (#342) 2025-12-03 10:21:37 +08:00
YoVinchen 39964b5733 Merge branch 'main' into feat/proxy-server 2025-12-03 00:30:57 +08:00
YoVinchen d356f1e208 fix(ui): integrate usage dashboard and fix type errors
Add usage dashboard tab to settings page.
Fix UsageScriptModal TypeScript type annotations.
2025-12-03 00:27:01 +08:00
YoVinchen 434ffd559d feat(ui): add usage dashboard components
Add UsageDashboard with summary cards, trend chart, and data tables.
Implement model pricing configuration panel.
Add request log viewer with filtering and detail panel.
2025-12-03 00:25:41 +08:00
YoVinchen 38e8949152 feat(api): add frontend usage API and query hooks
Add TypeScript types for usage statistics.
Implement usage API with Tauri invoke calls.
Add TanStack Query hooks for usage data fetching.
2025-12-03 00:21:29 +08:00
YoVinchen c0122d717c feat(db): add usage tracking schema and types
Add database tables for proxy request logs and model pricing.
Extend Provider and error types to support usage statistics.
2025-12-03 00:16:40 +08:00
farion1231 74a2e9c08b fix(mcp): use browser-compatible platform detection for MCP presets
Replace Node.js process.platform check with navigator.userAgent-based
detection from @/lib/platform. The previous implementation using
process.platform failed in Tauri's browser environment, causing
Windows platform to always return false and not apply the required
'cmd /c' wrapper for npx commands.

This fix ensures that on Windows, MCP presets like sequential-thinking
correctly use 'cmd /c npx' format instead of direct 'npx', eliminating
the warning: "Windows requires 'cmd /c' wrapper to execute npx"

Changes:
- Import isWindows() from @/lib/platform instead of defining locally
- Remove incorrect process.platform-based detection
- Now properly detects Windows in browser/WebView environment
2025-12-02 15:43:14 +08:00
Jason 2347ac0ee0 fix(config): update DeepSeek default model from Exp to stable version 2025-12-01 22:37:01 +08:00
YoVinchen d12347d837 Merge branch 'main' into feat/proxy-server 2025-12-01 17:29:43 +08:00
Jason 58c5468bf6 fix(ui): prevent provider card hover scale from being clipped
Move 1px of horizontal padding from outer container to inner scroll
container, providing buffer space for the hover scale-[1.01] effect
without being cut off by overflow-hidden.
2025-12-01 16:03:20 +08:00
YoVinchen a35d112cd4 feat(proxy): implement provider adapter pattern with OpenRouter support
This major refactoring introduces a modular provider adapter architecture
to support format transformation between different AI API formats.

New features:
- Add ProviderAdapter trait for unified provider abstraction
- Implement Claude, Codex, and Gemini adapters with specific logic
- Add Anthropic ↔ OpenAI format transformation for OpenRouter compatibility
- Support model mapping from provider configuration (ANTHROPIC_MODEL, etc.)
- Add OpenRouter preset to Claude provider presets

Refactoring:
- Extract authentication logic into auth.rs with AuthInfo and AuthStrategy
- Move URL building and request transformation to individual adapters
- Simplify ProviderRouter to only use proxy target providers
- Refactor RequestForwarder to use adapter-based request/response handling
- Use whitelist mode for header forwarding (only pass necessary headers)

Architecture:
- providers/adapter.rs: ProviderAdapter trait definition
- providers/auth.rs: AuthInfo, AuthStrategy types
- providers/claude.rs: Claude adapter with OpenRouter detection
- providers/codex.rs: Codex (OpenAI) adapter
- providers/gemini.rs: Gemini (Google) adapter
- providers/models/: Anthropic and OpenAI API data models
- providers/transform.rs: Bidirectional format transformation
2025-12-01 16:01:06 +08:00
YoVinchen 0eec47fd64 Merge branch 'main' into feat/proxy-server 2025-12-01 14:13:03 +08:00
YoVinchen e9cb7098a5 Merge branch 'main' into feat/proxy-server
# Conflicts:
#	src/App.tsx
2025-12-01 13:33:32 +08:00
Jason 98084d61aa fix(ui): add independent scroll containers to fix scroll wheel on Linux
Providers page was using DndContext which may interfere with scroll wheel
events on Linux/Ubuntu WebKitGTK. Added independent scroll containers
with `overflow-y-auto` to all main pages, matching the pattern already
used by the MCP panel which works correctly.

Changes:
- App.tsx: Wrap ProviderList in independent scroll container
- SkillsPage: Use consistent h-[calc(100vh-8rem)] layout
- SettingsPage: Add overflow-hidden and overflow-x-hidden for consistency
2025-12-01 11:28:01 +08:00
Jason a627e1bb50 fix(config): update Codex default model and correct MiniMax URL
- Update Codex preset model from gpt-5-codex to gpt-5.1-codex
- Fix MiniMax English preset URL from minimaxi.io to minimax.io
2025-12-01 11:08:53 +08:00
YoVinchen c7ef4365b8 fix(proxy): resolve UI/UX issues and database constraint error
Simplify proxy control interface and fix database persistence issues:

Backend Fixes:
- Fix NOT NULL constraint error in proxy_config.created_at field
  * Use COALESCE to preserve created_at on updates
  * Ensure proper INSERT OR REPLACE behavior
- Remove redundant enabled field validation on startup
  * Auto-enable when user clicks start button
  * Persist enabled state after successful start
- Preserve enabled state during config updates
  * Prevent accidental service shutdown on config save

Frontend Improvements:
- Remove duplicate proxy enable switch from settings dialog
  * Keep only runtime toggle in ProxyPanel
  * Simplify user experience with single control point
- Hide proxy target button when proxy service is stopped
  * Add isProxyRunning prop to ProviderCard
  * Conditionally render proxy controls based on service status
- Update form schema to omit enabled field
  * Managed automatically by backend

Files: 5 changed, 81 insertions(+), 94 deletions(-)
2025-12-01 09:17:12 +08:00
YoVinchen 4c94e70f97 feat(proxy): implement local HTTP proxy server with multi-provider failover
Add a complete HTTP proxy server implementation built on Axum framework,
enabling local API request forwarding with automatic provider failover
and load balancing capabilities.

Backend Implementation (Rust):
- Add proxy server module with 7 core components:
  * server.rs: Axum HTTP server lifecycle management (start/stop/status)
  * router.rs: API routing configuration for Claude/OpenAI/Gemini endpoints
  * handlers.rs: Request/response handling and transformation
  * forwarder.rs: Upstream forwarding logic with retry mechanism (652 lines)
  * error.rs: Comprehensive error handling and HTTP status mapping
  * types.rs: Shared types (ProxyConfig, ProxyStatus, ProxyServerInfo)
  * health.rs: Provider health check infrastructure

Service Layer:
- Add ProxyService (services/proxy.rs, 157 lines):
  * Manage proxy server lifecycle
  * Handle configuration updates
  * Track runtime status and metrics

Database Layer:
- Add proxy configuration DAO (dao/proxy.rs, 242 lines):
  * Persist proxy settings (listen address, port, timeout)
  * Store provider priority and availability flags
- Update schema with proxy_config table (schema.rs):
  * Support runtime configuration persistence

Tauri Commands:
- Add 6 command endpoints (commands/proxy.rs):
  * start_proxy_server: Launch proxy server
  * stop_proxy_server: Gracefully shutdown server
  * get_proxy_status: Query runtime status
  * get_proxy_config: Retrieve current configuration
  * update_proxy_config: Modify settings without restart
  * is_proxy_running: Check server state

Frontend Implementation (React + TypeScript):
- Add ProxyPanel component (222 lines):
  * Real-time server status display
  * Start/stop controls
  * Provider availability monitoring
- Add ProxySettingsDialog component (420 lines):
  * Configuration editor (address, port, timeout)
  * Provider priority management
  * Settings validation
- Add React hooks:
  * useProxyConfig: Manage proxy configuration state
  * useProxyStatus: Poll and display server status
- Add TypeScript types (types/proxy.ts):
  * Define ProxyConfig, ProxyStatus interfaces

Provider Integration:
- Extend Provider model with availability field (providers.rs):
  * Track provider health for failover logic
- Update ProviderCard UI to display proxy status
- Integrate proxy controls in Settings page

Dependencies:
- Add Axum 0.7 (async web framework)
- Add Tower 0.4 (middleware and service abstractions)
- Add Tower-HTTP (CORS layer)
- Add Tokio sync primitives (oneshot, RwLock)

Technical Details:
- Graceful shutdown via oneshot channel
- Shared state with Arc<RwLock<T>> for thread-safe config updates
- CORS enabled for cross-origin frontend access
- Request/response streaming support
- Automatic retry with exponential backoff (forwarder)
- API key extraction from multiple config formats (Claude/Codex/Gemini)

File Statistics:
- 41 files changed
- 3491 insertions(+), 41 deletions(-)
- Core modules: 1393 lines (server + forwarder + handlers)
- Frontend UI: 642 lines (ProxyPanel + ProxySettingsDialog)
- Database/DAO: 326 lines

This implementation provides the foundation for advanced features like:
- Multi-provider load balancing
- Automatic failover on provider errors
- Request logging and analytics
- Usage tracking and cost monitoring
2025-12-01 02:41:36 +08:00
Jason f5f7dfed8c style: apply code formatting fixes
- Fix Prettier formatting in claudeProviderPresets.ts
- Fix cargo fmt trailing blank line in provider/mod.rs
2025-11-30 23:30:27 +08:00
Jason 5888c56f2a fix(config): correct MiniMax apiKeyUrl to minimaxi.com
Update apiKeyUrl domain to match official website URL.
Also update screenshots for all locales (en, ja, zh).
2025-11-30 23:03:09 +08:00
Jason c5cadb73bc fix(config): correct MiniMax apiKeyUrl domain from minimax.io to minimax.com 2025-11-29 23:03:19 +08:00
Jason 2643595012 fix(skills): target first span only when hiding select checkmark indicator 2025-11-29 21:36:16 +08:00
Jason 6ac4d1652c fix(skills): use theme-aware glass-card class for light mode compatibility
Replace hardcoded dark mode styles (bg-gray-900/40, border-white/10) with
the unified glass-card class that adapts to both light and dark themes.
2025-11-29 21:18:51 +08:00
Jason 3bf37cf0ff refactor(url): remove automatic trailing slash stripping from base URL inputs
- Remove `.replace(/\/+$/, "")` from all base URL handlers in useBaseUrlState.ts
- Remove trailing slash stripping in useCodexConfigState.ts
- Remove trailing slash normalization in providerConfigUtils.ts setCodexBaseUrl()
- Update i18n hints (en/ja/zh) to instruct users to avoid trailing slashes

This gives users explicit control over URL format rather than silently modifying input.
2025-11-29 20:52:29 +08:00
Jason 526c7406fa fix(ui): persist active provider card highlight when not hovered
The selected provider's visual highlight (background, border, glow)
was being overridden by .glass-card base styles due to CSS specificity.
Add dedicated .glass-card-active class to ensure active state persists.
2025-11-29 20:19:17 +08:00
Jason 9db85dd4dc style(css): consolidate global selector rules and remove duplicates
- Merge three separate `*` selector blocks into one for better maintainability
- Remove duplicate "Glassmorphism Utilities" comment
2025-11-29 20:03:19 +08:00
Jason 0f333d9e5b fix(tailwind): add missing shadcn/ui color mappings for opaque dialog backgrounds
The dialog backgrounds were transparent because Tailwind 3 requires explicit
color mappings in the config to use CSS variables. Added standard shadcn/ui
color mappings (background, foreground, card, primary, etc.) and removed
unnecessary overlayClassName overrides from dialog components.
2025-11-29 19:49:55 +08:00
Jason ba875552a6 style(mcp): align wizard modal with confirm dialog styling
- Use zIndex="alert" and semi-transparent overlay for consistency
- Apply border-b-0/border-t-0 bg-transparent to header/footer
- Replace emerald accent with blue to match app theme
- Use Input component instead of raw input elements
- Simplify button variants (outline for cancel)
2025-11-29 17:41:12 +08:00
Jason 7eac809689 feat(preset): add MiniMax international version and split promotions
- Add MiniMax en preset with international API endpoint (minimaxi.io)
- Split MiniMax partner promotion into CN and EN versions
- Remove unnecessary icon config from Aliyun and Alibaba Lingma presets
2025-11-28 22:27:23 +08:00
YoVinchen 0f959112b1 refactor(skill): remove skillsPath configuration (#310)
Remove the skillsPath field from SkillRepo and Skill structs since
recursive scanning now automatically discovers skills in all directories.
Simplify the UI by removing the path input field.
2025-11-28 16:26:28 +08:00
Jason 3878a16c4f fix: pre-release fixes for code formatting, i18n, and test suite
- Run cargo fmt to fix Rust code formatting (lib.rs)
- Add missing i18n keys: migration.success, agents.title (zh/en/ja)
- Replace hardcoded strings "Agents" and "MCP" with t() calls in App.tsx
- Fix test mocks and assertions:
  - Add providersApi.updateTrayMenu to useSettings.test.tsx mock
  - Update SettingsPage mock path in App.test.tsx
  - Fix toast message assertion in integration/SettingsDialog.test.tsx
  - Add autoSaveSettings to SettingsDialog component test mock
  - Fix loading state test to check spinner instead of title
  - Update import button name matching for selected file state
  - Fix save button test to switch to advanced tab first
  - Remove obsolete cancel button test (button no longer exists)

Test results improved from 99 passed / 17 failed to 104 passed / 11 failed
2025-11-28 15:53:25 +08:00
Jason 00f78e4546 feat(i18n): add Japanese language support
- Add complete Japanese translation file (ja.json)
- Update frontend types and hooks to support "ja" language option
- Add Japanese tray menu texts in Rust backend
- Add Japanese option to language settings component
- Update Zod schema to include Japanese language validation
- Add test case for Japanese language preference
- Update i18n documentation to reflect three-language support
2025-11-28 15:14:39 +08:00
Jason 924ad44e6c fix(usage): correct selectedTemplate initialization logic
Previously, selectedTemplate was initialized to null when no NEW_API
credentials were detected, which caused the credentials config section
to be hidden even for new configurations or GENERAL template users.

Now properly detects:
- NEW_API template (has accessToken or userId)
- GENERAL template (has apiKey or baseUrl)
- Default to GENERAL for new configurations (matches default code template)
2025-11-28 11:10:22 +08:00
Jason eecd6a3a2b refactor(usage): simplify usage script modal UI
- Remove redundant "Request Configuration" section (URL, method, headers, body editors)
- Move timeout and auto query interval fields to preset template section
- Simplify "Enable usage query" toggle styling
- Remove redundant hints and variables description
- Add i18n support for Base URL label
- Include "0 to disable" hint directly in auto interval label
2025-11-28 11:09:34 +08:00
Jason 6a9a0a7a7e feat(preset): add icon configuration to provider presets
- Add icon/iconColor fields to CodexProviderPreset and GeminiProviderPreset interfaces
- Configure icons for Claude presets (DeepSeek, Zhipu, Qwen, Kimi, MiniMax, DouBao, etc.)
- Configure icons for Codex presets (OpenAI, Azure, PackyCode)
- Configure icons for Gemini presets (Google, PackyCode)
- Fix handlePresetChange to pass icon fields when resetting form

This ensures preset icons are displayed in the icon picker when selecting a provider preset.
2025-11-27 23:28:11 +08:00
Jason fcb090dd15 fix(css): downgrade Tailwind CSS from v4 to v3.4 for better browser compatibility
Tailwind CSS v4 requires modern CSS features (@layer, @property, color-mix)
that are not supported in older WebView2 versions, causing styles to fail
on some Windows 11 systems.

Changes:
- Replace @tailwindcss/vite with postcss + autoprefixer
- Downgrade tailwindcss from 4.1.13 to 3.4.17
- Convert CSS imports from v4 syntax to v3 @tailwind directives
- Add darkMode: "selector" to tailwind.config.js
- Create postcss.config.js for PostCSS pipeline

This improves compatibility with older browsers and WebView2 runtimes
while maintaining the same visual appearance.
2025-11-27 22:55:14 +08:00
Jason 2c90ae3509 refactor(provider): use local settings for current provider selection
Complete the device-level settings separation for cloud sync support.

Backend changes:
- Modify switch() to update both local settings and database is_current
- Modify current() to read from local settings first, fallback to database
- Rename sync_current_from_db() to sync_current_to_live()
- Update tray menu to read current provider from local settings

Frontend changes:
- Update Settings interface: remove legacy fields (customEndpoints*, security)
- Add currentProviderClaude/Codex/Gemini fields
- Update settings schema accordingly

Test fixes:
- Update Gemini security tests to check ~/.gemini/settings.json
  instead of ~/.cc-switch/settings.json (security field was never
  stored in CC Switch settings)

This ensures each device maintains its own current provider selection
independently when database is synced across devices.
2025-11-27 11:42:19 +08:00
Jason 120ac92e77 refactor(gemini): improve config handling and code consistency
- Fix envObjToString to preserve custom environment variables
- Add bidirectional MCP format conversion (httpUrl <-> url)
- Merge provider config with existing settings.json instead of overwriting
- Remove redundant is_packycode_gemini function
- Simplify is_google_official_gemini using detect_gemini_auth_type
- Add handleGeminiModelChange for consistent field handling
2025-11-27 10:21:01 +08:00
Jason 7adc38eb53 feat(preset): add MiniMax as official partner with Black Friday promotion
- Mark MiniMax as partner with custom theme color (#f64551)
- Add Black Friday promotional text for Starter plan ($2/mo, 80% OFF)
- Update apiKeyUrl to MiniMax coding plan subscription page
2025-11-27 08:51:54 +08:00
Jason 3f28648931 fix(query): prevent redundant usage queries when switching apps
Add staleTime and gcTime to useUsageQuery to avoid triggering
unnecessary API calls when switching between app tabs. The staleTime
is set dynamically based on the auto-refresh interval (or 5 minutes
by default), and gcTime is set to 10 minutes to preserve cache after
component unmount.
2025-11-26 19:34:00 +08:00
Jason 90d530fa7a fix(ui): improve ConfirmDialog styling for better visual consistency
- Remove header/footer borders and backgrounds for compact alert style
- Use theme-aware overlay color (bg-background/80) instead of black
- Add zIndex="alert" to ensure dialog appears above other dialogs
2025-11-26 15:36:53 +08:00
Jason 5cd2e9fb88 refactor(provider): unify validation errors to use toast notifications
Change template parameter validation from form.setError to toast.error
for consistent UX across all required field validations.
2025-11-26 12:35:33 +08:00
Jason 8bf6ce2c25 feat(provider): add required field validation with toast notifications
- Add validation for provider name (required for all providers)
- Add validation for API endpoint and API Key (required for non-official providers)
- Use toast notifications instead of inline form errors for better visibility
- Move name validation from zod schema to handleSubmit for consistent UX
- Add i18n keys: endpointRequired, apiKeyRequired
2025-11-26 12:26:02 +08:00
Jason c41f3dcccb fix(preset): use ANTHROPIC_AUTH_TOKEN for DMXAPI and correct endpoint candidates
- Change DMXAPI preset from ANTHROPIC_API_KEY to ANTHROPIC_AUTH_TOKEN
- Fix endpointCandidates that were incorrectly copied from AiHubMix
2025-11-26 11:57:47 +08:00
Jason 7ffd3ba165 fix(provider): preserve custom endpoints when updating provider
- Replace INSERT OR REPLACE with UPDATE for existing providers to avoid
  triggering ON DELETE CASCADE on provider_endpoints table
- Fix endpoint merging logic to correctly mark database endpoints as
  isCustom when they overlap with preset endpoints

The root cause was that INSERT OR REPLACE performs DELETE + INSERT under
the hood, which triggered the foreign key cascade and deleted all
associated endpoints from provider_endpoints table.
2025-11-26 10:27:07 +08:00