Commit Graph

529 Commits

  • chore(release): update release notes, changelog and macOS minimum version for v3.12.3
    Update CHANGELOG.md with full v3.12.3 entry, create release notes in
    three languages (en/zh/ja), bump macOS minimumSystemVersion from 10.15
    to 12.0 (Monterey) to match actual runtime requirements, and update
    README version badges and links.
  • feat(skills): add restore and delete for skill backups
    Introduce list/restore/delete commands for skill backups created during
    uninstall. Restore copies files back to SSOT, saves the DB record, and
    syncs to the current app with rollback on failure. Delete removes the
    backup directory after a confirmation dialog. ConfirmDialog gains a
    configurable zIndex prop to support nested dialog stacking.
  • feat(skills): auto-backup skill files before uninstall
    Create a local backup under ~/.cc-switch/skill-backups/ before removing
    skill directories. The backup includes all skill files and a meta.json
    with original skill metadata. Old backups are pruned to keep at most 20.
    The backup path is returned to the frontend and shown in the success
    toast. Bump version to 3.12.3.
  • fix(proxy): enable gzip compression for non-streaming proxy requests
    Non-streaming requests were forced to use `Accept-Encoding: identity`,
    preventing upstream response compression and increasing bandwidth usage.
    
    Now only streaming requests conservatively keep `identity` to avoid
    decompression errors on interrupted SSE streams. Non-streaming requests
    let reqwest auto-negotiate gzip and transparently decompress responses.
  • fix: revert incorrect o-series max_completion_tokens in Responses API path
    Responses API uses max_output_tokens for all models including o-series.
    The o-series max_completion_tokens fix should only apply to Chat Completions API.
  • fix(proxy): use max_completion_tokens for o1/o3 series models (#1451)
    * fix(proxy): use max_completion_tokens for o1/o3 series models
    
    When converting Anthropic requests to OpenAI format for o1/o3 series
    models (like o1-mini, o3-mini), use max_completion_tokens instead of
    max_tokens to avoid unsupported_parameter errors.
    
    Fixes #1448
    
    * fix: revert incorrect o-series max_completion_tokens in Responses API path
    
    Responses API uses max_output_tokens for all models including o-series.
    The o-series max_completion_tokens fix should only apply to Chat Completions API.
    
    ---------
    
    Co-authored-by: Hajen Teowideo <hajen.teowideo@example.com>
    Co-authored-by: Jason Young <44939412+farion1231@users.noreply.github.com>
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat: add Tool Search domain restriction bypass with active-installation patching
    Resolve the active `claude` command from PATH and apply an equal-length
    byte patch to remove the domain whitelist check. Backups are stored in
    ~/.cc-switch/toolsearch-backups/ (SHA-256 of path) so they survive
    Claude Code version upgrades. The patch auto-reapplies on app startup
    when the setting is enabled.
    
    Frontend checks PatchResult.success and rolls back the setting on failure.
  • fix: replace implicit app inference with explicit selection for Skills import and sync
    Skills import previously inferred app enablement from filesystem presence,
    causing incorrect multi-app activation when the same skill directory existed
    under multiple app paths. Now the frontend submits explicit app selections
    via ImportSkillSelection, and schema migration preserves a snapshot of
    legacy app mappings to avoid lossy reconstruction.
    
    Also adds reconciliation to sync_to_app (removes disabled/orphaned symlinks)
    and MCP sync_all_enabled (removes disabled servers from live config).
  • fix: merge Codex MCP restore backup entries during takeover
    When proxy takeover is active, update_live_backup_from_provider rebuilds the Codex restore snapshot from the current provider and common-config state. We were then replacing the new mcp_servers table with the previous backup's table wholesale, which meant stopping takeover could restore stale MCP entries and silently discard MCP changes made through provider/common-config updates.
    
    Change the backup preservation step to merge MCP entries by server id instead of replacing the entire table. New provider/common-config MCP definitions now win on conflict, while backup-only servers are retained so live-only MCP state still survives a hot-switch.
    
    Add regression coverage for the existing preservation case and for the conflict case where both the old backup and the new provider define the same MCP server.
  • fix: make Codex TOML base_url editing section-aware
    Rewrite setCodexBaseUrl/extractCodexBaseUrl to understand TOML section
    boundaries, ensuring base_url is written into the correct
    [model_providers.<name>] section instead of being appended to file end.
    
    - Add section-aware TOML helpers in providerConfigUtils.ts
    - Extract shared update_codex_toml_field/remove_codex_toml_base_url_if
      in codex_config.rs, deduplicate proxy.rs TOML editing logic
    - Replace scattered inline base_url regexes with extractCodexBaseUrl()
    - Add comprehensive tests for both Rust and TypeScript implementations
  • fix: prevent common config loss during proxy takeover and stabilize snippet lifecycle
    - Make sync_current_provider_for_app takeover-aware: update restore
      backup instead of overwriting live config when proxy is active
    - Introduce explicit "cleared" flag for common config snippets to
      prevent auto-extraction from resurrecting user-cleared snippets
    - Reorder startup: extract snippets from clean live files before
      restoring proxy takeover state
    - Add one-time migration flag to skip legacy commonConfigEnabled
      migration on subsequent startups
    - Add regression tests for takeover backup preservation, explicit
      clear semantics, and migration flag roundtrip
  • Preserve common config during proxy takeover
    Update takeover backup generation to rebuild effective provider settings with common config applied before saving restore snapshots.
    
    Keep Codex mcp_servers entries when hot-switching providers under takeover so restore does not drop live-only MCP config.
    
    Migrate legacy providers with inferred common-config usage to explicit commonConfigEnabled=true markers during startup and default imports, and cover the new behavior with proxy and provider regression tests.
  • fix: avoid FK constraint failure when restoring provider_health during WebDAV sync
    Split LOCAL_ONLY_TABLES into SYNC_SKIP_TABLES (export) and
    SYNC_PRESERVE_TABLES (import). provider_health is skipped on export
    but no longer restored on import, since it has a foreign key on
    providers(id, app_type) that may not match the remote dataset.
    Health data is ephemeral and rebuilds automatically at runtime.
  • feat: add StepFun provider presets and step-3.5-flash (#1369)
    * feat: add StepFun provider presets
    
    * docs: regroup StepFun pricing entry
    
    * docs: tweak StepFun zh label
    
    * style: apply prettier fixes
    
    * Revert "style: apply prettier fixes"
    
    This reverts commit cff7bf2e65.
  • feat: add OpenClaw User-Agent toggle, default off
    Add a switch in the OpenClaw provider form to optionally send a browser
    User-Agent header. The toggle defaults to off — only providers that
    explicitly include headers in their preset or config will have it enabled.
    
    Remove the previous auto-injection logic that force-added User-Agent on
    every preset load and new provider creation.
  • feat: show failover toggle independently on main page with confirm dialog
    Add enableFailoverToggle setting to control failover toggle visibility
    on the main page, decoupled from proxy takeover state. First-time
    enable shows a ConfirmDialog (same pattern as proxy toggle). The toggle
    row is placed in the Auto Failover accordion section in settings.
  • feat: apply common config as runtime overlay instead of materialized merge
    Common config snippets are now dynamically overlaid when writing live
    files, rather than being pre-merged into provider snapshots at edit time.
    This ensures that updating a snippet immediately takes effect for the
    current provider and automatically propagates to other providers on
    their next switch.
    
    Key changes:
    - Add write_live_with_common_config() overlay pipeline
    - Strip common config from live before backfilling provider snapshots
    - Normalize provider snapshots on save to keep them snippet-free
    - Add explicit commonConfigEnabled flag in ProviderMeta (Option<bool>)
    - Migrate legacy providers on snippet save (infer flag from subset check)
    - Add Codex TOML snippet validation in set_common_config_snippet
    - Stabilize onConfigChange callbacks with useCallback in ProviderForm
  • refactor: consolidate periodic maintenance timer and add vacuum/rollup
    Change periodic timer from hourly backup-only to daily maintenance that
    includes backup, incremental auto-vacuum, and usage rollup in a single
    pass.
  • feat: add dual-layer versioning to WebDAV sync (protocol v2 + db-v6)
    Separate protocol version from database compatibility version in WebDAV
    sync paths. Upload writes to v2/db-v6/<profile>, download falls back to
    legacy v2/<profile> when current path has no data. Extend manifest with
    optional dbCompatVersion field and add legacy layout detection to UI.
  • feat: add usage daily rollups, incremental auto-vacuum, and sync-aware backup
    - Add usage_daily_rollups table (schema v6) to aggregate proxy request
      logs into daily summaries, reducing query overhead for statistics
    - Add rollup_and_prune DAO that aggregates old detail logs (>N days)
      into rollup rows and deletes the originals
    - Update all usage stats queries to UNION detail logs with rollup data
    - Introduce incremental auto-vacuum for SQLite, with startup and
      periodic cleanup of old stream_check_logs and request log rollups
    - Split backup export/import into full vs sync variants: WebDAV sync
      now skips local-only table data (proxy_request_logs,
      stream_check_logs, provider_health, proxy_live_backup,
      usage_daily_rollups) while preserving them on import
    - Add enable_logging guard to skip request log writes when disabled
    - Apply cargo fmt formatting fixes across multiple modules
  • feat: add session deletion with per-provider cleanup and path safety
    Add delete_session Tauri command dispatching to provider-specific deletion
    logic for all 5 providers (Claude, Codex, Gemini, OpenCode, OpenClaw).
    Includes path traversal protection via canonicalize + starts_with validation,
    session ID verification against file contents, frontend confirmation dialog
    with optimistic cache updates, i18n keys (zh/en/ja), and component tests.
  • feat: overhaul OpenClaw config panels with JSON5 round-trip write engine
    - Add json-five crate for JSON5 serialization preserving comments and formatting
    - Rewrite openclaw_config.rs with comment-preserving JSON5 read/write engine
    - Add Tauri commands: get_openclaw_live_provider, write_openclaw_config_section
    - Redesign EnvPanel as full JSON editor with structured error handling
    - Add tools.profile selection (minimal/coding/messaging/full) to ToolsPanel
    - Add legacy timeout migration support to AgentsDefaultsPanel
    - Add OpenClawHealthBanner component for config validation warnings
    - Add supporting hooks, mutations, utility functions, and unit tests
  • fix: correct OpenAI ChatCompletion to Anthropic Messages streaming conversion
    Rewrite tool call handling in streaming format conversion to properly
    track multiple concurrent tool blocks with independent Anthropic content
    indices. Fix block interleaving (thinking/text/tool_use) with correct
    content_block_start/stop events, buffer tool arguments until both id and
    name are available, and add tool result message conversion in transform.
  • refactor: deduplicate and improve OpenAI Responses API conversion
    - Extract shared map_responses_stop_reason and build_anthropic_usage_from_responses into transform_responses.rs as pub(crate)
    - Align cache token extraction priority: OpenAI nested details as fallback, direct Anthropic fields as override
    - Extract resolve_content_index helper to eliminate 3x copy-paste in streaming_responses.rs
    - Add streaming reasoning/thinking event handlers (response.reasoning.delta/done)
    - Add explanatory comment to transform_response heuristic detection
    - Add openai_responses to api_format doc comment and needs_transform test
    - Add explicit no-op match arms for lifecycle events
    - Add promptCacheKey to TS ProviderMeta type
    - Update toast i18n key to be generic for both OpenAI formats (zh/en/ja)
  • feat: add OpenAI Responses API format conversion (api_format = "openai_responses")
    Support Anthropic ↔ OpenAI Responses API format conversion alongside existing
    Chat Completions conversion. The Responses API uses a flat input/output structure
    with lifted function_call/function_call_output items and named SSE lifecycle events.
  • feat: add Bedrock request optimizer (PRE-SEND thinking + cache injection) (#1301)
    * feat: add Bedrock request optimizer (PRE-SEND thinking + cache injection)
    
    Add a PRE-SEND request optimizer that enhances Bedrock API requests
    before forwarding, complementing the existing POST-ERROR rectifier system.
    
    New modules:
    - thinking_optimizer: 3-path model detection (adaptive/legacy/skip)
      - Opus 4.6/Sonnet 4.6: adaptive thinking + effort max + 1M context beta
      - Legacy models: inject extended thinking with max budget
      - Haiku: skip (no modification)
    - cache_injector: auto-inject cache_control breakpoints (max 4)
      - Injects at tools/system/assistant message positions
      - TTL upgrade for existing breakpoints (5m → 1h)
    
    Gate: only activates for Bedrock providers (CLAUDE_CODE_USE_BEDROCK=1)
    Config: stored in SQLite settings table, default OFF, user opt-in
    UI: new Optimizer section in RectifierConfigPanel with 3 toggles + TTL
    
    18 unit tests covering all paths. Verified against live Bedrock API.
    
    * chore: remove docs/plans directory
    
    * fix: address code review findings for Bedrock request optimizer
    
    P0 fixes:
    - Replace hardcoded Chinese with i18n t() calls in optimizer panel,
      add translation keys to zh/en/ja locale files
    - Fix u64 underflow: max_tokens - 1 → max_tokens.saturating_sub(1)
    - Move optimizer from before retry loop to per-provider with body
      cloning, preventing Bedrock fields leaking to non-Bedrock providers
    
    P1 fixes:
    - Replace .map() side-effect pattern with idiomatic if-let (clippy)
    - Fix module alphabetical ordering in mod.rs
    - Add cache_ttl whitelist validation in set_optimizer_config
    - Remove #[allow(unused_assignments)] and dead budget decrement
    
    ---------
    
    Co-authored-by: Keith (via OpenClaw) <keithyt06@users.noreply.github.com>
    Co-authored-by: Jason <farion1231@gmail.com>
  • feat: add first-run confirmation dialog for stream check
    Show an informational dialog when users first click the health check
    button, explaining its limitations (OAuth providers, relay services,
    Bedrock). The dialog persists the confirmation in settings so it only
    appears once per device.
  • fix: support openai_chat api_format in stream check
    Stream Check always used Anthropic Messages API format, causing false
    failures for providers with api_format="openai_chat" (e.g. NVIDIA).
    Now detects api_format from provider meta/settings_config and uses
    the correct endpoint (/v1/chat/completions) and headers accordingly.
  • fix: 修复最小化到托盘后应用过一段时间自动退出的问题 (#1245)
    ExitRequested 事件处理器无条件执行清理并调用 std::process::exit(0),
    导致 api.prevent_exit() 被完全抵消。当隐藏窗口的 WebView 被 Windows
    后台优化策略回收、窗口对象销毁后,Tauri 运行时检测到无存活窗口自动
    触发 ExitRequested,应用随即退出。
    
    通过 ExitRequested 的 code 字段区分两种场景:
    - code 为 None(运行时自动触发):仅 prevent_exit(),保持托盘后台运行
    - code 为 Some(_)(用户主动 app.exit()):执行清理后退出
    
    Closes #728
  • docs: reorganize docs directory structure
    - Delete 9 completed planning/roadmap documents
    - Move 23 release notes into docs/release-notes/ with simplified filenames
    - Update all cross-references in READMEs, CHANGELOG, and release notes
    - Remove dangling doc reference in deeplink/mod.rs
  • docs: add OpenClaw coverage and complete settings docs for user manual
    - Add OpenClaw as the 5th supported app across all doc chapters (1-3, 5)
    - Add OpenClaw provider presets table to 2.1-add.md (30 presets)
    - Add OpenClaw config section to 5.1-config-files.md (JSON5 format)
    - Complete 1.5-settings.md with missing sections: app visibility,
      skill sync method, terminal settings, proxy tab, WebDAV cloud sync,
      backup/restore, and log configuration
    - Fix deeplink parser.rs to accept 'opencode' and 'openclaw' app types
    - Update 5.3-deeplink.md with new app type parameters
    - Remove incorrect OpenCode references from proxy docs (4.1-4.4)
  • feat: auto-extract common config snippets from live files on first run
    During app startup, iterate all app types and extract non-provider-specific
    config fields from live configuration files into the database. This runs
    only when no snippet exists yet for a given app type, enabling incremental
    extraction as new apps are configured.
  • revert: restore full config overwrite + Common Config Snippet (revert 992dda5c)
    Revert the partial key-field merging refactoring introduced in 992dda5c,
    along with two dependent commits (24fa8a18, 87604b18) that referenced
    the now-removed ClaudeQuickToggles component.
    
    The whitelist-based partial merge approach had critical issues:
    - Non-whitelisted custom fields were lost during provider switching
    - Backfill permanently stripped non-key fields from the database
    - Whitelist required constant maintenance to track upstream changes
    
    This restores the proven "full config overwrite + Common Config Snippet"
    architecture where each provider stores its complete configuration and
    shared settings are managed via a separate snippet mechanism.
    
    Reverted commits:
    - 24fa8a18: context-aware JSON editor hint + hide quick toggles
    - 87604b18: hide ClaudeQuickToggles when creating
    - 992dda5c: partial key-field merging refactoring
    
    Restored:
    - Full config snapshot write (write_live_snapshot) for Claude/Codex/Gemini
    - Full config backfill (settings_config = live_config)
    - Common Config Snippet UI and backend commands
    - 6 frontend components/hooks for common config editing
    - configApi barrel export and DB snippet methods
    
    Removed:
    - ClaudeQuickToggles component
    - write_live_partial / backfill_key_fields / patch_claude_live
    - All KEY_FIELDS constants
  • fix: add import button for OpenCode/OpenClaw empty state and remove auto-import on startup
    Previously OpenCode and OpenClaw auto-imported providers from live config
    on app startup, which could confuse users. Now they follow the same
    pattern as Claude/Codex/Gemini: manual import via the empty state button.
  • chore: bump version to v3.11.0 and add release notes
    - Update version numbers in package.json, Cargo.toml, tauri.conf.json
    - Add CHANGELOG.md entry for v3.11.0
    - Add trilingual release notes (zh/en/ja)
    - Update user manual version info