Commit Graph

450 Commits

  • 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.
  • fix: treat missing db file as error in manual backup to prevent false success toast
    backup_database_file() returning Ok(None) was silently resolved as null
    on the frontend, bypassing try/catch and showing a success toast without
    actually creating a backup file. Now None is converted to an explicit
    Err so the frontend correctly displays an error toast.
  • fix: remove last-provider deletion restriction for OMO/OMO Slim plugins
    OMO and OMO Slim are OpenCode plugins, not standalone apps — users
    should be able to fully remove them. Remove the count-based guard that
    prevented deleting the last active provider, and clean up the now-unused
    provider-count API surface across the full stack.
  • refactor: remove OMO common config two-layer merge system
    Each OMO provider now stores its complete configuration directly in
    settings_config.otherFields instead of relying on a shared OmoGlobalConfig
    merged at write time. This simplifies the data flow from a 4-tuple
    (agents, categories, otherFields, useCommonConfig) to a 3-tuple and
    eliminates an entire DB table, two Tauri commands, and ~1700 lines of
    merge/sync code across frontend and backend.
    
    Backend:
    - Delete database/dao/omo.rs (OmoGlobalConfig struct + get/save methods)
    - Remove get/set_config_snippet from settings DAO
    - Remove get/set_common_config_snippet Tauri commands
    - Replace merge_config() with build_config() in services/omo.rs
    - Simplify OmoVariant (remove config_key, known_keys)
    - Simplify import_from_local and build_local_file_data
    - Rewrite all OMO service tests
    
    Frontend:
    - Delete OmoCommonConfigEditor.tsx and OmoGlobalConfigFields.tsx
    - Delete src/lib/api/config.ts
    - Remove OmoGlobalConfig type and merge preview functions
    - Remove useGlobalConfig/useSaveGlobalConfig query hooks
    - Simplify useOmoDraftState (remove all common config state)
    - Replace OmoCommonConfigEditor with read-only JsonEditor preview
    - Clean i18n keys (zh/en/ja)
  • fix: enforce OMO ↔ OMO Slim cross-category mutual exclusion
    When activating an OMO provider, deactivate all OMO Slim providers
    in the same transaction and delete the Slim config file, and vice
    versa. This prevents both plugin variants from being active
    simultaneously.
  • chore: pre-release cleanup — remove debug logs, fix clippy warning, add missing ja translations, and format code
    - Remove 2 console.log statements from DeepLinkImportDialog
    - Fix clippy unnecessary_map_or: use is_some_and in live.rs
    - Add 17 missing Japanese i18n keys (skills, proxy, circuitBreaker, universalProvider)
    - Run prettier and cargo fmt to fix pre-existing formatting drift
  • perf: optimize session panel loading with parallel scan and head-tail JSONL reading
    - Parallelize 5 provider scans using std::thread::scope
    - Add read_head_tail_lines() to read only first 10 + last 30 lines from JSONL files, skipping potentially large middle sections
    - Cache Codex UUID regex with LazyLock to avoid repeated compilation
    - Skip expensive I/O in OpenCode when session title is already available
  • fix(opencode): add missing omo-slim category checks across add/form/mutation paths
    Several code paths only checked for "omo" category but missed "omo-slim",
    causing OMO Slim providers to be treated as regular OpenCode providers
    (triggering invalid write_live_snapshot, requiring manual provider key,
    and showing wrong form fields).
  • feat(workspace): make directory paths clickable and rename "Today's Note" to "Add Memory"
    Add open_workspace_directory Tauri command to open workspace/memory dirs
    in the system file manager. Rename dailyMemory.createToday across all locales.
  • feat(workspace): add full-text search for daily memory files
    Add backend search command that performs case-insensitive matching
    across all daily memory files, supporting both date and content queries.
    Frontend includes animated search bar (⌘F), debounced input, snippet
    display with match count badge, and search state preservation across
    edits.
  • refactor(provider): switch from full config overwrite to partial key-field merging (#1098)
    * refactor(provider): switch from full config overwrite to partial key-field merging
    
    Replace the provider switching mechanism for Claude/Codex/Gemini from
    full settings_config overwrite to partial key-field replacement, preserving
    user's non-provider settings (plugins, MCP, permissions, etc.) across switches.
    
    - Add write_live_partial() with per-app implementations for Claude (JSON env
      merge), Codex (auth replace + TOML partial merge), and Gemini (env merge)
    - Add backfill_key_fields() to extract only provider-specific fields when
      saving live config back to provider entries
    - Update switch_normal, sync_current_to_live, add, update to use partial merge
    - Remove common config snippet feature for Claude/Codex/Gemini (no longer
      needed with partial merging); preserve OMO common config
    - Delete 6 frontend files (3 components + 3 hooks), clean up 11 modified files
    - Remove backend extract_common_config_* methods, 3 Tauri commands,
      CommonConfigSnippets struct, and related migration code
    - Update integration tests to validate key-field-only backfill behavior
    
    * refactor(cleanup): remove dead code and redundant MCP sync after partial-merge refactor
    
    - Remove ConfigService legacy full-overwrite sync methods (~150 lines)
    - Remove redundant McpService::sync_all_enabled from switch_normal
    - Switch proxy fallback recovery from write_live_snapshot to write_live_partial
    - Remove dead ProviderService::write_gemini_live wrapper
    - Update tests to reflect partial-merge behavior (MCP preserved, not re-synced)
    
    * feat(claude): add Quick Toggles for common Claude Code preferences
    
    Add checkbox toggles for hideAttribution, alwaysThinking, and
    enableTeammates that write directly to the live settings file via
    RFC 7396 JSON Merge Patch. Mirror changes to the form editor using
    form.watch for reactive updates.
    
    * fix(provider): add missing key fields to partial-merge constants
    
    Add provider-specific fields verified against official docs to prevent
    key residue or loss during provider switching:
    
    - Claude: CLAUDE_CODE_SUBAGENT_MODEL (env), model (top-level)
    - Codex: review_model, plan_mode_reasoning_effort
    - Gemini: GOOGLE_API_KEY (official alternative to GEMINI_API_KEY)
    
    * fix(provider): expand partial-merge key fields for Bedrock, Vertex, Foundry and behavior settings
    
    Add missing env/top-level fields to CLAUDE_KEY_ENV_FIELDS and
    CLAUDE_KEY_TOP_LEVEL so that provider switching correctly replaces
    (and clears) credentials and flags for AWS Bedrock, Google Vertex AI,
    Microsoft Foundry, and provider behavior overrides like max output
    tokens and prompt caching.
    
    * feat(provider): add auth field selector for Claude providers (AUTH_TOKEN / API_KEY)
    
    Allow users to choose between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY
    when creating or editing custom Claude providers, persisted in meta.apiKeyField.
    
    * refactor(preset): remove AiHubMix hardcoded API_KEY in favor of generic auth selector
    
    AiHubMix was the only preset that hardcoded ANTHROPIC_API_KEY before the
    generic auth field selector was introduced. Now that users can freely
    choose between AUTH_TOKEN and API_KEY via the UI, remove the special-case
    and default AiHubMix to the standard ANTHROPIC_AUTH_TOKEN.
  • feat(backup): add hourly periodic backup timer during runtime
    Previously periodic backup only checked on startup. Now spawns a
    tokio interval task that checks every hour while the app is running.
  • feat(backup): add independent backup panel, configurable policy, and rename support
    Extract backup & restore into a standalone AccordionItem in Advanced settings.
    Add configurable auto-backup interval (disabled/6h/12h/24h/48h/7d) and retention
    count (3-50) via settings. Add per-backup rename with inline editing UI.
  • feat(backup): add pre-migration backup, periodic backup, backfill warning, and backup management UI
    Four improvements to the database backup mechanism:
    
    1. Auto backup before schema migration - creates a snapshot when
       upgrading from an older database version, providing a safety net
       beyond the existing SAVEPOINT rollback mechanism.
    
    2. Periodic startup backup - checks on app launch whether the latest
       backup is older than 24 hours and creates a new one if needed,
       ensuring all users have recent backups regardless of usage patterns.
    
    3. Backfill failure notification - switch now returns SwitchResult with
       warnings instead of silently ignoring backfill errors, so users are
       informed when their manual config changes may not have been saved.
    
    4. Backup management UI - new BackupListSection in Settings > Data
       Management showing all backup snapshots with restore capability,
       including a confirmation dialog and automatic safety backup before
       restore.
  • feat(settings): add first-run confirmation dialogs for proxy and usage features
    Prevent accidental activation of advanced features by showing a one-time
    info dialog. Once confirmed, the flag is persisted in settings.json and
    the dialog never appears again.
    
    - Proxy: confirmation when toggling proxy server ON for the first time
    - Usage: confirmation when enabling usage query inside UsageScriptModal
    - Enhanced ConfirmDialog with "info" variant (blue icon + default button)
    - Added i18n translations for zh, en, ja
  • feat(sessions): add session browsing for OpenCode and OpenClaw
    Add two new session providers following the existing convention-based
    pattern. OpenCode reads three-layer JSON storage, OpenClaw parses JSONL
    event streams. Wire up backend dispatch, frontend filter dropdown, icon
    mappings, toolbar button for OpenClaw, and i18n subtitle updates.
  • feat: more granular local environment checks (#870)
    * feat: more granular local environment checks
    
    * refactor: improve PR #870 with i18n, shadcn Select, and testable helpers
    
    - Extract is_valid_shell, is_valid_shell_flag, default_flag_for_shell
      to module-level #[cfg(windows)] functions for testability
    - Add unit tests for extracted helper functions
    - Replace native <select> with shadcn/ui Select components
    - Extract env badge ternary to ENV_BADGE_CONFIG Record lookup
    - Add i18n keys for env badges and WSL selectors (zh/en/ja)
    - Unify initial useEffect load path with loadAllToolVersions()
    
    * fix: prevent useEffect re-firing on wslShellByTool changes
    
    The useEffect that loads initial tool versions depended on
    loadAllToolVersions, which in turn depended on wslShellByTool.
    This caused a full re-fetch of all 4 tools every time the user
    changed a WSL shell or flag, racing with the single-tool refresh.
    
    Fix: use empty deps [] since this is a mount-only effect. The
    refresh button and shell/flag handlers cover subsequent updates.
    
    ---------
    
    Co-authored-by: Jason <farion1231@gmail.com>
  • refactor(provider): replace startup auto-import with manual import button
    Remove the startup loop in lib.rs that auto-imported default providers
    for Claude/Codex/Gemini. Move config snippet extraction logic into the
    import_default_config command so it works when triggered manually.
    
    Add an "Import Current Config" button to ProviderEmptyState, wired via
    useMutation in ProviderList (shown only for standard apps). Update i18n
    keys (zh/en/ja) with new button labels and revised empty state text.
  • chore(tray): hide Auto Failover shortcut from tray menu
    The Auto (Failover) toggle in the system tray is no longer shown.
    The feature remains fully functional via the Settings page.
    All related backend code (handle_auto_click, AUTO_SUFFIX, etc.)
    is preserved for easy re-enablement.