Commit Graph

1024 Commits

Author SHA1 Message Date
tison 1b3c53d235 fix: always show name on hover (#2237)
Signed-off-by: tison <wander4096@gmail.com>
2026-04-22 23:19:52 +08:00
Jason 1f25411524 feat(presets): upgrade Kimi K2.5 to K2.6 in direct Moonshot configs
Bump model id and display name from K2.5 to K2.6 in Hermes, OpenClaw,
OpenCode, and Claude (direct api.moonshot.cn) presets. Pricing,
context window, and base URL are unchanged.

Add kimi-k2.6 row to model_pricing seed; no migration needed since
seed_model_pricing uses INSERT OR IGNORE and runs on every startup
via ensure_model_pricing_seeded. Old kimi-k2.5 row is kept to
preserve historical usage stats.

Nvidia aggregator forwards (moonshotai/kimi-k2.5) intentionally keep
the K2.5 SKU until Nvidia's catalog confirms K2.6.
2026-04-22 12:17:19 +08:00
Jason ae1fd2b662 feat(presets): add DDSHub Codex preset
DDSHub now exposes a Codex-compatible endpoint at the same host as
its Claude service. Base URL omits the /v1 suffix since the gateway
auto-routes OpenAI SDK paths.
2026-04-22 10:42:24 +08:00
Jason f4a9021461 feat(presets): add LemonData provider across all six apps
Register LemonData (third-party partner) preset for Claude, Codex,
Gemini, OpenCode, OpenClaw, and Hermes, plus icon assets and i18n
partner promotion copy (zh/en/ja). Claude preset uses
ANTHROPIC_API_KEY auth; OpenAI-compatible apps target gpt-5.4.
2026-04-22 10:39:17 +08:00
Jason 2274da0b8e style(hermes): use dashboard icon and move MCP to toolbar end
Swap ExternalLink for LayoutDashboard on the Hermes Web UI button —
clicking it may launch `hermes dashboard` rather than just open a URL,
so a panel-style glyph reads truer than a generic external-link icon.
Also reorder the toolbar so MCP sits in the final slot, matching the
claude/codex/gemini/opencode layout.
2026-04-21 23:05:52 +08:00
Jason 4dd11ab427 fix(usage): support Hermes and OpenClaw in usage query modal
Extend getProviderCredentials to read flat settingsConfig fields for
Hermes (snake_case base_url / api_key) and OpenClaw (camelCase baseUrl
/ apiKey), so the "official balance" template auto-selects for matching
providers like SiliconFlow.

Also refactor the BALANCE and TOKEN_PLAN test paths in handleTest to
reuse the precomputed providerCredentials instead of re-reading
env.ANTHROPIC_* directly, which previously caused empty key errors for
non-Claude apps even when the key was configured.
2026-04-21 22:40:53 +08:00
Jason 8e9452b7ec feat(hermes): launch dashboard from toolbar when Web UI is offline
When the Hermes Web UI probe fails, the toolbar entry now opens an info
confirm dialog offering to run `hermes dashboard` in the user's preferred
terminal. Accepting spawns it via a temp bash/batch script; `hermes
dashboard` itself opens the browser once ready, so we do not poll.
The Memory panel and Health banner keep the existing toast behavior.

Also corrects the stale `hermes web` hint in the offline toast (the real
command is `hermes dashboard`) and reorders Linux terminal detection to
try `which` before stat'ing /usr/bin, /bin, /usr/local/bin.
2026-04-21 21:11:15 +08:00
Jason db92f2b3b0 style(providers): apply prettier to common-config hooks
Reformat three hooks brought in from upstream #2191 so that
format:check passes in CI.
2026-04-21 12:05:48 +08:00
Jason eb1cd17ab2 fix(header): stop auto-compact from latching after maximize
useAutoCompact cached normalWidthRef = el.scrollWidth on every
non-compact resize, but per DOM spec scrollWidth === clientWidth
when content fits. Maximizing the window (content no longer
overflows) therefore wrote the container width into
normalWidthRef, making it impossible to re-enter compact when
the window was restored to its original size.

Move the assignment inside the overflow branch so the cache is
only written at the actual compact threshold, where scrollWidth
reflects the real content width.
2026-04-21 11:57:07 +08:00
Jason 29a28d2a74 style(header): unify toolbar icon button width across apps
Normalize all icon-only ghost buttons in the header toolbar to
32x32 (w-8 px-2). Previously Hermes/OpenClaw used default sm
padding (~40px) while Claude's Skills/Sessions used w-8 px-2,
so switching apps caused a width jump and put useAutoCompact's
cached normalWidthRef out of sync across apps.
2026-04-21 11:57:07 +08:00
Jason 1227e29d8b feat(skills): enable Hermes in unified Skills management
Wire hermes through SkillApps struct, DAO SQL, command parser, and
SKILLS_APP_IDS. Add a Skills entry to the Hermes toolbar. Simplify
skill_sync test fixtures to use SkillApps::default().
2026-04-21 11:57:07 +08:00
Jason 0be75668cc feat(hermes): align provider schema with Hermes Agent 0.10.0
Hermes 0.10.0 tightened custom_providers validation (commit 2cdae233):
invalid base_urls are rejected, unknown fields produce warnings, and
new fields (rate_limit_delay, bedrock_converse, key_env) landed.

- Add bedrock_converse to the api_mode selector (and i18n labels)
- Expose rate_limit_delay in a provider-level advanced panel
- Validate base_url client-side (URL shape, template-token friendly)
- Drop per-model max_tokens — not in _VALID_CUSTOM_PROVIDER_FIELDS
- Round-trip test asserts set_provider preserves rate_limit_delay /
  key_env / any unknown forward-compat field
2026-04-21 11:57:07 +08:00
Jason 111ddf8d73 style: apply prettier and rustfmt
No behavior changes. Brings three files back in line with the project
formatters (CI runs `pnpm format:check` and `cargo fmt --check`).
2026-04-21 11:57:07 +08:00
Jason c8d91298c7 fix(providers): drop legacy ANTHROPIC_REASONING_MODEL from Claude quick-set
The model-mapping quick-set button referenced an undefined `reasoningModel`
prop and wrote `ANTHROPIC_REASONING_MODEL`, which the backend explicitly
marks as deprecated legacy (see services/provider/mod.rs and
services/proxy.rs). Remove all three references so typecheck passes and
the button matches the provider model schema.
2026-04-21 11:57:07 +08:00
Jason 21a1518f9f refactor(hermes): drop "Auto" api_mode and require explicit protocol
Hermes' built-in api_mode detection only matches a handful of official
endpoints (api.openai.com, api.anthropic.com, api.x.ai, AWS Bedrock);
third-party / proxy endpoints silently fall back to chat_completions,
which causes opaque 401/404s on Anthropic-protocol or Codex-Responses
providers. The "Auto" option was misleading for the common third-party
case.

- Drop the "Auto" option from the API Mode dropdown; remove the
  HermesApiModeChoice sentinel type so writes always emit api_mode.
- Default new providers and legacy entries lacking api_mode to
  chat_completions (only persisted on user save).
- Deeplink imports now write api_mode: chat_completions explicitly
  instead of relying on URL heuristics; test renamed accordingly.
- Rename the "Codex Responses (Copilot / OpenCode)" label to
  "OpenAI Responses" to match OpenAI's /v1/responses naming.
2026-04-21 11:57:07 +08:00
Jason f57edfd697 refactor(hermes): share provider-source marker constants and write guard
After /simplify review of the P1-3 second wave, two small cleanups:

- Lift the `_cc_source` / `providers_dict` magic strings out of
  ProviderCard into a shared helper (`isHermesReadOnlyProvider`) and
  named constants in hermesProviderPresets.ts. Front-end and back-end
  now document the same marker contract in two mirrored places
  instead of drifting strings.

- Replace the duplicate `is_dict_only_provider` + `format!` branches
  at the top of `set_provider` / `remove_provider` with a single
  `ensure_provider_writable(config, name, verb)` guard. Future error
  copy tweaks only have to happen once.

No behaviour change; all 52 hermes_config tests stay green.
2026-04-21 11:57:07 +08:00
Jason abb305a82f feat(hermes): render providers: dict overlays as read-only cards
ProviderCard now detects Hermes provider entries sourced from the
v12+ `providers:` dict via the `_cc_source` marker that the backend
injects, and renders a "Hermes Managed" badge beside the title.
ProviderActions receives an `isReadOnly` prop that disables the Edit
and Delete buttons (with a tooltip pointing the user at Hermes Web
UI) while keeping Switch and Duplicate enabled — switching only
touches `model.*`, and duplicate lets users fork the overlay into
their own `custom_providers:` list.

Three-locale i18n keys `provider.managedByHermes` /
`provider.managedByHermesHint` added.
2026-04-21 11:57:07 +08:00
Jason 3f4739365e feat(hermes): surface providers: dict entries read-only
Hermes v12+ migrated some provider entries from the `custom_providers:`
list into a `providers:` dict (keyed by id). CC Switch previously
ignored that source entirely, leaving users blind to providers they had
configured via Hermes' own Web UI; the only feedback was a generic
migration warning in the health banner.

`get_providers()` now unions both sources, matching upstream
`get_compatible_custom_providers` dedup order (list wins on name
collision). Entries coming from the dict carry a `_cc_source =
"providers_dict"` marker plus the original `provider_key`, which the
UI layer will use to render them read-only. `set_provider` and
`remove_provider` now refuse to touch dict-only entries, steering the
user to Hermes Web UI. `sanitize_hermes_provider_keys` strips the UI
markers on write so they never reach YAML.

The `schema_migrated_v12` health warning copy reframes the situation:
entries are shown read-only in CC Switch rather than invisible.
2026-04-21 11:57:07 +08:00
Jason e10a300c80 fix(hermes): prevent YAML pollution and drop of OAuth mcp auth
DeepLink Hermes import was emitting camelCase (baseUrl / apiKey /
apiMode) that the Hermes runtime does not recognise, poisoning
`custom_providers:` entries on activation. The MCP sync path was
also stripping `auth: oauth` on round-trip, silently downgrading
OAuth-type servers to unauthenticated calls.

The Hermes deeplink branch now emits snake_case via a dedicated
builder; `sanitize_hermes_provider_keys` runs on both `set_provider`
and `get_providers` so legacy DB records heal on next access.
`HERMES_EXTRA_FIELDS` preserves `auth`. The `api_mode` dropdown gains
`codex_responses` (Copilot / OpenCode), and the schema-migrated
warning copy no longer hard-codes "v12" (upstream `_config_version`
is now 19).
2026-04-21 11:57:07 +08:00
Jason 185ac2be9b feat(hermes): memory enable switch + clearer migration warning copy
Replaces the greyed-out "Memory is disabled" banner with a real Switch
at the top of each memory tab. Users can now toggle Hermes' memory/user
blobs without leaving CC Switch; the underlying write goes through the
merge-aware `set_memory_enabled`, so budgets and external-provider
settings survive toggle operations. The new `useToggleHermesMemoryEnabled`
mutation invalidates the limits query so the Switch state and the
amber disabled-hint update in lockstep.

Reworks the `schema_migrated_v12` health banner copy to match the
simplified "CC Switch only manages custom_providers" posture — it now
tells users to reconcile migrated dict entries via Hermes Web UI,
instead of the earlier (and now inaccurate) "CC Switch reads both".
2026-04-21 11:57:07 +08:00
Jason b8a3534cb5 feat(settings): add Hermes config dir override with data-driven dispatch
Adds a dedicated Hermes row to the directory-override settings so users
can point CC Switch at alternate Hermes config locations (e.g. a second
profile directory for work/personal split). `get_config_dir` on the
Rust side already supports hermes; this just wires up the frontend row.

Wiring it through `useDirectorySettings` revealed a scaling problem:
every supported app required five parallel ternary chains across
`computeDefaultConfigDir`, `updateDirectory`, `browseDirectory`,
`resetDirectory`, and `updateDirectoryState`. Replaces those with two
lookup tables (`APP_DIRECTORY_META`, `DIRECTORY_KEY_TO_SETTINGS_FIELD`)
so adding the next app is two entries, not fifteen edit sites.

Drive-by cleanup from the same touch:
* `resetAllDirectories` takes a `ResolvedAppDirectoryOverrides` object
  instead of five positional optional strings.
* `setResolvedDirs` returns the same reference when the sanitized
  value is unchanged, so no-op edits don't cascade renders.

Also lands all i18n updates for this series (`hermesConfigDir` and
placeholder, Memory section's enable/disable/toggleFailed copy, and
the reworded `schemaMigratedV12` warning) in zh/en/ja together.
2026-04-21 11:57:07 +08:00
Jason acc6d795e4 feat(hermes): replace Prompts entry with Memory panel
Hermes has no slash-prompt concept (templates live as Skills), so the
Prompts tab for the Hermes app was always empty. Swap the toolbar Book
button for a Brain button that opens a new Memory panel editing
~/.hermes/memories/{MEMORY,USER}.md — Hermes' first-class memory store
which its Web UI exposes only as on/off toggles, never as an editor.

The panel shows each file in its own tab with a character-budget bar
read from config.yaml's nested memory.* section (memory_char_limit /
user_char_limit, default 2200 / 1375). Edits are written atomically;
Hermes picks them up on the next session start per MemoryStore.

Also extract useDarkMode to src/hooks/useDarkMode.ts — the codebase
already repeats the same MutationObserver pattern in 12+ places; this
PR introduces the shared hook and uses it once, leaving the migration
of the other copies to a follow-up.
2026-04-21 11:57:07 +08:00
Jason 088b47b08a refactor(hermes): delegate deep config to Hermes Web UI
Slim the Hermes surface in CC Switch to match its core positioning —
cross-client provider switching and shared MCP/prompts/skills — and
delegate deep configuration (model, agent, env, skills, cron, logs)
to the Hermes Web UI at http://127.0.0.1:9119.

- Drop AgentPanel/EnvPanel/ModelPanel and their mutation commands,
  hooks, types, and i18n keys across zh/en/ja.
- Add open_hermes_web_ui Tauri command that probes /api/status and
  launches the URL in the system browser. Hermes injects its own
  session token into the returned HTML, so CC Switch doesn't need
  to touch auth.
- Surface the launcher from the Hermes toolbar and the health banner
  via a shared useOpenHermesWebUI() hook; the offline error code is
  defined once per side and referenced across the contract.
- Keep read-only access to model.provider so ProviderList can still
  highlight the active supplier; apply_switch_defaults continues to
  write the top-level model section when switching providers.

Net diff: +152 / -1253.
2026-04-21 11:57:06 +08:00
Jason 041f74db18 fix(presets): refresh stale context windows for DeepSeek and Claude 1M
- DeepSeek V3.2 / R1 (Hermes, OpenClaw): 64K → 128K context
- DeepSeek R1 max output: 8K → 64K (includes CoT tokens)
- Claude Opus 4.7 / Sonnet 4.6 via OpenRouter: 200K → 1M context
2026-04-21 11:57:06 +08:00
Jason ce5c3e5c6a fix(presets): refresh stale model IDs and backfill Hermes model lists
- Bump NewAPI universal preset to Claude 4.7 / Sonnet 4.6 / Haiku 4.5 and
  Gemini 3.1; fix opusModel mistakenly pointing to Sonnet
- Bump Gemini Native (Claude preset) to gemini-3.1-pro / gemini-3-flash
- Bump TheRouter Gemini preset to gemini-3.1-pro
- Backfill models[] + suggestedDefaults for 15 Hermes anthropic_messages
  presets:
    * Bailian For Coding: qwen3-coder-plus / qwen3-max
    * Kimi For Coding: kimi-for-coding
    * 13 third-party Claude proxies: claude-opus-4-7 / sonnet-4-6 /
      haiku-4-5-20251001
- Add Claude Haiku 4.5 entry to Hermes OpenRouter model list
2026-04-21 11:57:06 +08:00
Jason 3255b17185 feat(hermes): switch eligible presets to chat_completions + GPT-5.4
Migrate 18 Hermes provider presets from anthropic_messages to
chat_completions to sidestep known upstream Hermes bugs (model-name
dot-mangling in normalize_model_name, api_mode drop after v11->v12
migration, and auxiliary_client OpenAI hardcode).

Native providers now target each vendor's official OpenAI-compatible
endpoint with correct model IDs: Kimi (kimi-k2.5-preview on /v1),
Bailian (compatible-mode/v1 with Qwen3 defaults), Xiaomi MiMo, Longcat
(/openai/v1), Zhipu GLM (/api/paas/v4), ModelScope, MiniMax, SiliconFlow,
and Novita (/v3/openai).

Aggregators (Shengsuanyun, AiHubMix, DMXAPI, Compshare, TheRouter)
default to GPT-5.4 on chat_completions, mirroring the Codex preset
lineup. TheRouter omits gpt-5.4-pro since that variant is Responses-only
and Hermes implements only chat_completions. OpenRouter's existing
openai/gpt-5 entry is bumped to openai/gpt-5.4.

Claude-only proxies are left on anthropic_messages; their Codex
counterparts use wire_api=responses, so there is no evidence their
chat_completions endpoints serve OpenAI models.
2026-04-21 11:57:06 +08:00
Jason b4e29be8a0 chore(hermes): prune unused official presets and fix Nous endpoint
Remove the Anthropic, OpenAI, and Google AI presets from the Hermes
preset list. They were placeholder samples introduced when the Hermes
module first landed and do not match the actual user paths in
CC Switch (Claude / Codex go through OAuth, Gemini Native is its own
adapter), and the upstream endpoints are not reachable for most of
the target users anyway.

Fix the Nous Research preset: its base_url was a fabricated domain
(inference.nous.hermes.dev) that has never resolved. Point it at the
real Nous Portal endpoint (inference-api.nousresearch.com/v1) and
add apiKeyUrl so users can jump straight to portal.nousresearch.com
to provision a key.

Drop the now-orphan providerForm.presets.{anthropic,openai,googleai}
i18n keys from zh / en / ja since no preset references them anymore.
2026-04-21 11:57:06 +08:00
Jason 8d6353699c feat(presets): sync Claude provider presets to Hermes
Import 38 Claude presets into Hermes by mapping env-style
ANTHROPIC_BASE_URL/AUTH_TOKEN to flat base_url/api_key, deriving
api_mode from apiFormat (anthropic_messages or chat_completions),
deduping ANTHROPIC_*_MODEL into models[], and pointing
suggestedDefaults at ANTHROPIC_MODEL. Skip OAuth-only presets
(Codex, Copilot), Bedrock SigV4, Gemini Native, and the three
already shipped on the Hermes side (OpenRouter, Anthropic,
DeepSeek). Place Shengsuanyun at the head of the Hermes array so
the partner shows first in the preset panel.

In the Claude preset list, restore Shengsuanyun back ahead of
Gemini Native. The Gemini Native preset (#1918) was inserted
between Claude Official and Shengsuanyun, which made the
third_party category register first in the reduce-based grouping
and pushed the aggregator block (and Shengsuanyun) behind it.

Backfill the missing providerForm.presets translations across zh,
en, and ja (openrouter, anthropic, openai, googleai, deepseek,
together; plus shengsuanyun for en and ja) so existing Hermes
preset names no longer render literal i18n keys.
2026-04-21 11:57:06 +08:00
Jason 828ec2ce07 fix(hermes): show active provider and wire add/enable/remove actions
Switching a Hermes provider previously only fired a toast because the frontend treated Hermes as non-additive (unlike backend AppType::is_additive_mode, which lists OpenCode | OpenClaw | Hermes) and relied on the unused is_current DB flag for highlighting. Align the UI model with the backend:

- Include Hermes in ProviderActions' isAdditiveMode so the main button switches between "Add" and "Remove".
- Drive the "current" highlight from model.provider (via useHermesModelConfig) instead of the DB is_current field; model.provider is Hermes's real SSOT for the active provider.
- Reuse OpenClaw's set-as-default button slot to expose an "Enable" action on Hermes that calls switchProvider, so providers already in config can be activated without re-adding. switch_normal + apply_switch_defaults already atomically update custom_providers and model.provider, so no backend change is needed.
- Invalidate liveProviderIds + modelConfig + health in parallel after add/update/delete/switch via a new invalidateHermesProviderCaches helper, replacing four copies of three sequential awaits.
2026-04-21 11:57:06 +08:00
Jason 497a543c1b feat(hermes): add API mode dropdown and per-provider model editor in form
The Hermes provider form previously only exposed Base URL and API Key,
forcing users to drop into the Model panel to hand-edit model IDs after
adding a provider. Following OpenClaw's shape, the form now carries:

- An API Mode selector (auto-detect / chat_completions / anthropic_messages).
  "auto" is a UI-only sentinel — selecting it deletes api_mode from the
  config so the YAML doesn't leak a redundant field.
- A model list editor where the first row is badged as the default and
  each row has a collapsible Advanced panel for context_length and
  max_tokens. Adding/removing rows uses a UUID-keyed ref so typing in
  one input doesn't drop focus when another row is added.
- A Fetch Models button that pulls /v1/models from the configured
  endpoint and exposes the catalog in a per-row dropdown, identical to
  OpenClaw's flow. The vendor grouping is memoized so keystrokes don't
  trigger a reduce+sort per model row — Radix DropdownMenuContent does
  not lazy-mount, so the inner JSX evaluates on every render regardless
  of whether the menu is open.

Three-locale i18n keys are added together (zh/en/ja).
2026-04-21 11:57:06 +08:00
Jason f935bac633 feat(hermes): bind per-provider models to top-level model: on switch
Hermes custom_providers entries now carry an ordered models array
(id / context_length / max_tokens) plus suggestedDefaults. The backend
serializes the array to the YAML dict shape Hermes expects on write and
inverts it on read, preserving insertion order via the preserve_order
feature on serde_json.

When a user switches providers, switch_normal calls apply_switch_defaults
so the top-level model.default / model.provider follow the selected
provider's first model. Previously switching a Hermes provider only
shuffled custom_providers[] and left Hermes pointing at whatever
model.provider was set before.

Seven existing Hermes presets now ship with a curated models list so
switching lands on a working default without a detour through the
Model panel.
2026-04-21 11:57:06 +08:00
Jason 5d3cd7eb85 fix(icons): replace placeholder Hermes icon with Nous brand artwork
The previous Hermes icon was an inline purple "H" SVG unrelated to the
real Hermes Agent brand. Replace it with the official Nous Research
avatar sourced from hermes-agent/landingpage/icon-512.png, routed
through iconUrls as a Vite URL import. The PNG is post-processed to
strip the 4px black rectangle border (cropped inward by 6px and pasted
back onto a 512x512 transparent canvas). Also switch defaultColor to
black to match the monochrome artwork when the asset falls back to an
initial glyph.
2026-04-21 11:57:06 +08:00
Jason 1684cb3233 feat(presets): migrate all aggregator and Bedrock presets to Claude Opus 4.7
- OpenClaw: replace opus-4-6 with opus-4-7 across 17 aggregator presets
  (id, name, primary, modelCatalog); AWS Bedrock entry rewritten to new
  SKU anthropic.claude-opus-4-7 (drops -v1 and dated suffix per official
  4.7 model card) and pricing corrected to $5/$25/$0.50/$6.25 during the
  SKU swap, aligning with schema.rs source of truth
- OpenCode: same replacement for 13 aggregators plus
  OPENCODE_PRESET_MODEL_VARIANTS entries for @ai-sdk/amazon-bedrock and
  @ai-sdk/anthropic, plus AWS Bedrock provider models map
- OpenRouter / TheRouter / GitHub Copilot in claudeProviderPresets use
  dot-style id; update to anthropic/claude-opus-4.7 (missed by 509d2250)
- omo: switch agent/category recommended to opus-4-7; replace key in
  OMO_BACKGROUND_TASK_PLACEHOLDER priority map
- hermes_config.rs: update doc comments and test fixtures to opus-4-7;
  Hermes ModelPanel placeholder and i18n defaultHint examples follow
- i18n unspecifiedHigh category description bumped to 'Claude Opus 4.7
  max variant' to match omo recommended
- Test fixtures updated: therouter preset assertion and opencode Bedrock
  variant lookup now check for opus-4-7
- Sonnet 4.6 / Haiku 4.5 untouched - no official 4.7 release for them
2026-04-21 11:57:06 +08:00
Jason 83c3c3b494 feat(pricing): add Claude Opus 4.7 with adaptive thinking and Bedrock SKU
- Seed claude-opus-4-7 pricing (same tier as 4.6: $5 / $25 / $0.50 /
  $6.25 per million tokens). Relies on incremental INSERT OR IGNORE
  seeding; no SCHEMA_VERSION bump needed.
- Whitelist opus-4-7 in thinking optimizer so it uses adaptive
  thinking + max effort + 1M context beta, matching 4.6 behavior.
- Bump default OPUS model in PIPELLM and AWS Bedrock (AKSK / API Key)
  presets to 4.7. Bedrock SKU drops the -v1 suffix per the official
  4.7 model card (anthropic.claude-opus-4-7 and
  global.anthropic.claude-opus-4-7).
2026-04-21 11:57:06 +08:00
Jason 50431b7ec9 feat(usage-script): add User-Agent header to New API template
Align the New API usage query template with the GENERAL template by
including "User-Agent: cc-switch/1.0" in its request headers, so
cc-switch requests are identifiable in provider server logs and less
likely to be blocked by UA-based rate limiting on some New API
deployments.
2026-04-21 11:57:06 +08:00
Jason 8b65a31c7c feat(claude): upgrade effort toggle from "high" to "max"
Per Anthropic's effort parameter docs, "high" is the API default and
setting effortLevel="high" is equivalent to omitting the field entirely.
The toggle previously produced no effect.

Claude Opus 4.6, Sonnet 4.6, and Opus 4.7 now support a "max" level
that enables unconstrained reasoning. Rename the checkbox (effortHigh
-> effortMax) and write effortLevel="max" when toggled on. Existing
"high" values in user configs are left untouched.

Updates zh/en/ja locales and user-manual entries accordingly.
2026-04-21 11:57:06 +08:00
Jason 0ca36b9d51 fix: address Hermes review findings (5 medium issues)
- Add missing Hermes MCP import on first launch (lib.rs)
- Add Hermes branch in ProviderForm defaultValues fallback
- Include Hermes in session manager subtitle (zh/en/ja)
- Rename check_openclaw_stream to check_additive_app_stream
- Cache parsed HERMES_DEFAULT_CONFIG to avoid repeated JSON.parse
2026-04-21 11:57:06 +08:00
Jason e8953c286f feat: implement Hermes session manager with SQLite + JSONL support (Phase 6)
- Add hermes.rs session provider with dual-source scanning:
  SQLite (state.db) as primary, JSONL transcripts as fallback
- Dynamic schema discovery via PRAGMA table_info for SQLite resilience
- Use read_head_tail_lines for efficient JSONL metadata extraction
  (head 30 lines for metadata, tail 10 for last_active_at)
- Support both flat and nested JSONL message formats
- Add SQLite session loading and transactional deletion
- Register hermes in parallel session scan (thread::scope)
- Add "hermes" to frontend ProviderFilter type
- 7 unit tests covering JSONL parsing, SQLite source parsing, deletion
2026-04-21 11:57:06 +08:00
Jason 240969d8c7 feat: add Hermes UI components, presets, and config panels (Phase 8)
- Add 7 provider presets (OpenRouter, Anthropic, OpenAI, Google, DeepSeek, Together, Nous)
- Create HermesFormFields + useHermesFormState for provider form integration
- Create Model/Agent/Env config panels with save/load functionality
- Create HermesHealthBanner for config warnings
- Add hermes icon (violet winged H) to icon system
- Integrate into App.tsx: 3 new view types (hermesModel/hermesAgent/hermesEnv),
  sidebar buttons (Brain/Bot/KeyRound), health banner, session support
- Integrate into ProviderForm: presets, form state, key validation, rendering
- Integrate into AddProviderDialog: universal tab exclusion, providerKey, base_url extraction
- Add i18n keys for all Hermes UI (zh/en/ja)
2026-04-21 11:57:06 +08:00
Jason a0b585992a feat: add Hermes frontend types, API layer, and hooks (Phase 7)
- Add "hermes" to AppId union type and all exhaustive Record<AppId>
- Add HermesModelConfig, HermesAgentConfig, HermesEnvConfig types
- Add hermes field to VisibleApps, McpApps, ProxyTakeoverStatus
- Create src/lib/api/hermes.ts with Tauri invoke wrappers
- Create src/hooks/useHermes.ts with 5 query + 3 mutation hooks
- Register hermes in APP_IDS, APP_ICON_MAP (violet color scheme)
- Split MCP_SKILLS_APP_IDS into MCP_APP_IDS (includes hermes) and
  SKILLS_APP_IDS (excludes hermes, since Hermes has no Skills support)
- Wire hermes additive-mode into App.tsx (remove/duplicate handlers),
  ProviderList.tsx (live provider ID query + In Config badge),
  mutations.ts (cache invalidation on switch/add/delete)
- Add Hermes checkbox to McpFormModal
- Add basic hermes i18n keys (en/zh/ja)
2026-04-21 11:57:06 +08:00
Jason 701e7d9581 fix: surface backend error details in proxy toast messages
The takeover.failed i18n template lacked the {{detail}} placeholder
and three useProxyStatus onError callbacks omitted the detail variable,
so proxy start/stop/takeover failures all displayed a generic message
regardless of the underlying cause.
2026-04-21 11:57:06 +08:00
Jason e4c34b34e7 fix: remove ANTHROPIC_REASONING_MODEL to decouple thinking from model selection (#2081)
ANTHROPIC_REASONING_MODEL was a non-official env var that forced all
requests with thinking params to use a single "reasoning model",
overriding the user's /model selection. Since new Claude Code versions
send adaptive thinking by default, this caused /model to silently fail.

- Remove reasoning_model field and has_thinking_enabled() from model_mapper
- Simplify map_model() to pure type-based matching (haiku/sonnet/opus)
- Remove reasoning model UI field from provider form
- Retain ANTHROPIC_REASONING_MODEL in ENV_EXCLUDES and override-key
  cleanup lists so legacy configs don't leak into common config
2026-04-21 11:57:06 +08:00
Jason eab0a69d2c fix: unify weekly_limit tier label to match official 7-day naming 2026-04-21 11:57:06 +08:00
Jason 4e790ac059 fix: hide unknown subscription quota tiers from provider card UI 2026-04-21 11:57:06 +08:00
chengww c5b15dd25e fix(claude-plugin): sync current provider config to settings.json (#1905)
* fix(claude-plugin): sync current provider config to settings.json on toggle enable

- Extract syncClaudePluginIfChanged to share logic between autoSaveSettings and saveSettings
- Fix P1: enableClaudePluginIntegration toggle in General tab now actually syncs ~/.claude/settings.json
- Fix P2: check syncCurrentProvidersLiveSafe() return value and show toast on failure
- Fix P3: sync providers on both enable and disable, not just enable
- Fix P4: avoid double syncCurrentProvidersLiveSafe when plugin toggle + dir change happen together
- Remove duplicate comment
- Add missing providersApi.getCurrent/getAll mocks in tests

* style: reformat after rebase onto main

Prettier flagged a line-break introduced by the openclaw directory
change (from main) after rebase.

* fix(claude-plugin): read prev enabled state from live cache to avoid stale closure

syncClaudePluginIfChanged compared enabled against data?.enableClaudePluginIntegration
captured in a useCallback closure. After invalidateQueries + refetch, the React
Query cache is up to date, but the consuming hook's closure does not see the new
value until React re-renders. Quick on->off toggles could therefore skip
applyClaudePluginConfig, leaving ~/.claude/config.json in the previously enabled
state even though settings.json was persisted as disabled.

Read the previous value synchronously from queryClient.getQueryData(["settings"])
before saveMutation.mutateAsync(), then pass it to the helper as prevEnabled.
getQueryData bypasses the closure and reflects the live cache at call time.

Test covers the race: closure data stays at false while the cache reports true;
the helper must still call applyClaudePluginConfig({ official: true }).

---------

Co-authored-by: Jason <farion1231@gmail.com>
2026-04-21 11:56:13 +08:00
zxZeng cc77a040e2 fix: common config checkbox state not persisting for Codex/Claude/Gemini (#2191)
修复:Codex/Claude/Gemini 通用配置勾选状态无法正确保存的问题

Co-authored-by: 曾兴 <zengx@gantsoftware.com>
2026-04-21 11:04:31 +08:00
hengm3467 1b345fbefb Add StepFun and StepFun en Step Plan presets (#2155)
* Add StepFun CN and EN presets

* Add StepFun 2603 model presets

* Make StepFun 2603 the default model

* Revert StepFun branding assets
2026-04-21 10:46:26 +08:00
Franklin 34349a2743 Add OpenClaw config directory settings (#1518)
Co-authored-by: 张斌 <zhangbin25@xiaomi.com>
2026-04-20 08:44:38 +08:00
King 8ba92b5470 feat(ui): add quick-set button for model mapping fields (#2179)
* feat(ui): add quick-set button for model mapping fields

Add a "一键设置" (Quick Set) button in the model mapping section to
simplify provider configuration. When users enter a model name in any
of the five model fields, they can now click this button to populate
all fields with that same value.

This addresses the UX friction of manually filling all five model
mapping fields (主模型, 推理模型, Haiku, Sonnet, Opus) when the
provider uses the same model name across all request types.

Implementation:
- Add Wand2 icon import from lucide-react
- Insert quick-set button alongside existing fetch-models button
- Logic picks first non-empty model value and applies to all fields
- Show success toast after applying
- Disabled state when all model fields are empty
- Add i18n strings for zh, en, ja locales

Relates to user feedback about tedious model configuration workflow.

* style(ui): format ClaudeFormFields component code

Apply consistent code formatting to ClaudeFormFields.tsx following
project linting rules. Includes multi-line import statements and
improved readability for conditional expressions.
2026-04-19 21:42:17 +08:00
hotelbe 87635e7fc6 feat(copilot): add GitHub Enterprise Server support (#2175)
* feat(copilot): add GitHub Enterprise Server support

* fix(copilot): address GHES PR review findings (P1 + 2×P2)

- P1: Use composite account ID (domain:user_id) for GHES to prevent
  cross-instance ID collisions; github.com keeps plain numeric ID for
  backward compatibilit
- P2-a: Use get_api_endpoint() for model list URL with automatic
  fallback to static URL when dynamic endpoint resolution fails
- P2-b: Add normalize_github_domain() as backend SSOT for domain
  normalization (lowercase, strip protocol/path/query, reject userinfo)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 20:29:46 +08:00