fix(hermes): Windows 上 Hermes 供应商配置不生效#4680
Conversation
On Windows, CC Switch hardcoded `~/.hermes` as the Hermes config directory, but Hermes resolves it through `get_hermes_home()`: `HERMES_HOME` env var, then a platform default (Windows `%LOCALAPPDATA%\hermes`, mac/Linux `~/.hermes`). So CC Switch wrote configs where Hermes never reads them and provider changes had no effect (refs farion1231#3178). `get_hermes_dir()` now mirrors Hermes' own resolution order: 1. `settings.hermes_config_dir` — CC Switch explicit override 2. `HERMES_HOME` env var — trimmed, non-empty, taken as-is (no `~` expansion, matching Hermes' `Path(val)`) 3. platform default — Windows reads the `LOCALAPPDATA` env var (the exact value Hermes reads, not a re-derived Known-Folder path) and falls back to `~\AppData\Local\hermes`; mac/Linux keep `~/.hermes` Relation to farion1231#3470: that PR dropped `HERMES_HOME` for "consistency with Codex/Claude". But unlike those tools Hermes treats `HERMES_HOME` as a first-class mechanism (its own Windows installer sets it), so ignoring it reintroduces the same mismatch for relocated installs. This keeps it. Tests cover HERMES_HOME precedence, settings-override > HERMES_HOME, blank HERMES_HOME fall-through, the platform-correct default, and a pure `windows_local_hermes_dir` helper exercising the LOCALAPPDATA-set and LOCALAPPDATA-empty fallback paths on every host.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24df0a8cb6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…APPDATA `get_hermes_dir()` now consults `HERMES_HOME` (all platforms) and `LOCALAPPDATA` (Windows). The `with_test_home` helper only neutralized `CC_SWITCH_TEST_HOME`, so an ambient `HERMES_HOME` — which Hermes' own Windows installer sets — would make tests that write `get_hermes_config_path()` escape the temp home and touch a real Hermes config (and the same hazard exists via `LOCALAPPDATA` on Windows). Clear and restore both env vars in `with_test_home`. This is safe: only this module reads those env vars, and `dirs` uses the Known-Folder API rather than the env var. Adds a test asserting both are neutralized inside `with_test_home`. Addresses the Codex review comment on farion1231#4680.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e20d361e4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
`windows_local_hermes_dir` checked `OsStr::is_empty()` on the raw value, but
Hermes does `os.environ.get("LOCALAPPDATA", "").strip()`. A whitespace/padded
`LOCALAPPDATA` would make CC Switch write under the literal padded path while
Hermes trims and falls back, hiding the config from Hermes. Trim before the
empty check, matching the existing `HERMES_HOME` handling. Adds
`windows_local_hermes_dir_trims_localappdata`.
Addresses the Codex review comment on farion1231#4680.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1becac58e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fn default_hermes_dir() -> PathBuf { | ||
| windows_local_hermes_dir( | ||
| std::env::var_os("LOCALAPPDATA").as_deref(), | ||
| &crate::config::get_home_dir(), |
There was a problem hiding this comment.
Use Hermes' home fallback for blank LOCALAPPDATA
On Windows when LOCALAPPDATA is unset or blank, upstream _get_platform_default_hermes_home falls back to Path.home() / "AppData" / "Local", but this call passes CC Switch's get_home_dir(), which resolves the profile via Windows Known Folder instead of the USERPROFILE/HOMEDRIVE environment values Python uses. In stripped launcher/service environments where LOCALAPPDATA is blank and Python's home env points elsewhere, CC Switch writes under the Known Folder profile while Hermes reads its Path.home() fallback, hiding the config again.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
@farion1231 大佬评估下, Codex、Claude 对抗性的评审结果是建议不再修改:
我核查了这条 P2,结论是:这个边界技术上成立,但倾向于本 PR 暂不继续改代码。
原因如下:
-
这条路径只会在 Windows 下
LOCALAPPDATA未设置或为空时触发。正常的 CC Switch 桌面 App 运行环境中,LOCALAPPDATA应该始终存在;而只要它存在,本 PR 已经直接读取并 trim 这个 env var,与 Hermes 自身读取的值保持一致。 -
blank
LOCALAPPDATA之后的 fallback 目前使用get_home_dir()是有意保持 CC Switch 内部一致性。get_home_dir()是项目里统一的 home 解析入口,Windows 下使用 Known Folder profile,并且已经被~/.claude、~/.codex、CC Switch 数据目录,以及 macOS/Linux 的~/.hermes分支复用。 -
如果只为了 Hermes 的这个极窄 fallback 单独增加
USERPROFILE/HOMEDRIVE/HOMEPATH解析,会让get_hermes_dir()成为项目里唯一一条 PythonPath.home()风格的例外路径,同时也会扩大测试里需要隔离和 restore 的全局 env 范围。
所以我的判断是:主路径已经和 Hermes 对齐,这个 fallback 分支更适合保持 CC Switch 现有 home 语义。如果维护者认为即使在 blank LOCALAPPDATA 的异常环境下也必须完全对齐 Python Path.home(),我也可以再补一个小的 focused helper 和对应测试。
Summary / 概述
该 PR 修复 CC Switch 的 Hermes home/config directory 解析与 Hermes 自身行为不一致的问题。
Windows 上 Hermes 默认读取
%LOCALAPPDATA%\hermes,并且会优先读取非空HERMES_HOME。此前 CC Switch 在未配置hermes_config_diroverride 时固定回落到~/.hermes,导致 provider config、Hermes skills 等写入 CC Switch 认为的目录,但 Hermes 实际不会读取。~/.hermes%LOCALAPPDATA%\hermes,缺失或为空时回退%USERPROFILE%\AppData\Local\hermesHERMES_HOME~/.hermesHERMES_HOMEhermes_config_dirget_hermes_dir()的功能~/.hermesRoot Cause / 根因
get_hermes_dir()之前只处理 CC Switch 的settings.hermes_config_diroverride,否则直接返回~/.hermes。但 Hermes 自身的
get_hermes_home()会按以下顺序解析 home directory:HERMES_HOME;其中 Windows 平台默认目录来自
LOCALAPPDATA,不是~/.hermes。因此在 Windows 上会出现:CC Switch 写入C:\Users\<user>\.hermes\config.yaml,而 Hermes 实际读取C:\Users\<user>\AppData\Local\hermes\config.yaml,表现为 CC Switch 中的 provider 编辑或 Hermes skills 同步不生效。Fix / 修复方式
get_hermes_dir()现在按以下优先级解析:settings.hermes_config_dir:CC Switch 显式 override,保持最高优先级;HERMES_HOME:trim 后非空则使用,行为对齐 Hermes;%LOCALAPPDATA%\hermes,缺失或为空时回退%USERPROFILE%\AppData\Local\hermes~/.hermes同时新增纯函数
windows_local_hermes_dir(),让 WindowsLOCALAPPDATA与 fallback 逻辑可以在非 Windows CI 上稳定覆盖。两个实现选择是刻意保留的:
LOCALAPPDATA环境变量HERMES_HOMEHERMES_HOME是 Hermes 的一等 home directory 机制;忽略它会让 relocated / custom profile 安装重新写入错误目录。Relationship to #3470 / 与 #3470 的关系
#3470 也在修复 Windows 默认目录从
~/.hermes到%LOCALAPPDATA%\hermes的问题。本 PR 与 #3470 的主要差异:
HERMES_HOMELOCALAPPDATA环境变量,而不是重新推导 Known Folder path,避免与 Hermes 实际读取值产生偏差。LOCALAPPDATA存在、缺失、为空三类 Windows 路径分支,使该逻辑在非 Windows CI 上也能被测试。Related Issue / 关联 Issue
Fixes #3178
Fixes #3811
Related #3470
已检索
HERMES_HOME、LOCALAPPDATA hermes、ccswitch hermes 模型等相关 issues。#2973 已由 #3267 处理;#4648 是 CN 版 Hermesstate.db路径探测问题,和本 PR 修复的 Hermes home/config/skills 目录解析不是同一范围。Screenshots / 截图
Real-machine verification on Windows. This PR only changes Rust-side path resolution (no UI changes); the screenshots below are end-to-end proof that the config now lands where Hermes actually reads it.
Before — Hermes' model picker does not list the
baomiao-oneapiprovider. CC Switch wroteconfig.yamlto~/.hermes, which Hermes on Windows never reads, so the provider configured in CC Switch was invisible to Hermes.After — Hermes lists the
baomiao-oneapiprovider with its 4 models (deepseek-v4-flash,deepseek-v4-pro,kimi-k2.7,qwen3.7-plus). CC Switch now writes to%LOCALAPPDATA%\hermes, where Hermes actually reads its config.Testing / 测试
新增/覆盖的关键测试:
hermes_home_env_takes_precedence_over_platform_defaultsettings_override_takes_precedence_over_hermes_homeblank_hermes_home_falls_through_to_platform_defaultdefault_hermes_dir_without_override_is_platform_correctwindows_local_hermes_dir_uses_localappdata_when_setwindows_local_hermes_dir_falls_back_to_home_when_localappdata_missing_or_emptycargo fmt --check --manifest-path src-tauri/Cargo.tomlcargo clippy --manifest-path src-tauri/Cargo.toml -- -D warningscargo test --manifest-path src-tauri/Cargo.tomlSource References / 参考
Out of Scope / 非本次范围
~/.hermes/config.yaml中留下旧配置,升级后可能需要重新保存一次或手动迁移到 Hermes 实际 home directory。Checklist / 检查清单