feat(hermes): Batch 1 §A + §B + P1-3 lazy_deps 优化 - 占位修 + 中文硬编码清 + 自定义 venv 适配

## §A channels.js 占位路由处理
- /h/channels 当前是 487 字节 placeholder
- 已确认 sidebar 没挂入口(getNavItems 不含 channels)
- 路由表保留但加注释表明这是 reserved,完整实现见 Batch 3

## §B config.js i18n 化(清理 5 处硬编码)
- "重新加载" / "保存配置" / "saving…" / "loading…" / "raw yaml editor"
- "配置已保存,建议重启 Hermes Gateway 生效" toast
- 抽 7 个新键到 locales/modules/engine.js(3 语言):
  · hermesConfigEyebrow / hermesConfigReload / hermesConfigSave
  · hermesConfigSaveSuccess / hermesConfigStatusSaving
  · hermesConfigStatusLoading / hermesConfigStatusReady

## P1-3 lazy_deps 校对稿优化(commit b852ebb 的补丁)
hermes_venv_python() 增加 HERMES_PYTHON 环境变量优先级:
1. HERMES_PYTHON env var(适配 brew / uv tool / 容器等自定义 venv)
2. ~/.hermes-venv/{bin/python | Scripts/python.exe}(默认)

allow_lazy_installs 守门:经核实内核 tools.lazy_deps.ensure 内部已检查
security.allow_lazy_installs,禁用时抛 FeatureUnavailable,Rust 端已捕捉
并友好返回错误(无需额外代码)。

## 累计
- 3 个修改文件(hermes/index.js + config.js + engine.js + hermes.rs)
- 7 个新 i18n 键 × 3 语言
- cargo check ✓ + npm build ✓
This commit is contained in:
晴天
2026-05-14 04:51:16 +08:00
parent efade55f61
commit 832bb9a6ef
4 changed files with 27 additions and 5 deletions

View File

@@ -2164,7 +2164,19 @@ pub async fn hermes_read_config_full() -> Result<Value, String> {
// ---------------------------------------------------------------------------
/// 找到 Hermes venv 的 Python 解释器路径
///
/// 优先级P1-3 优化):
/// 1. 环境变量 `HERMES_PYTHON` — 适配自定义 venvbrew / uv tool / 容器等非默认路径)
/// 2. ~/.hermes-venv/bin/python (Unix) 或 ~/.hermes-venv/Scripts/python.exe (Windows)
fn hermes_venv_python() -> Option<PathBuf> {
// 1. HERMES_PYTHON 环境变量优先
if let Ok(custom) = std::env::var("HERMES_PYTHON") {
let p = PathBuf::from(custom);
if p.exists() {
return Some(p);
}
}
// 2. 默认 venv 位置
let venv_dir = dirs::home_dir()?.join(".hermes-venv");
#[cfg(target_os = "windows")]
let py = venv_dir.join("Scripts").join("python.exe");

View File

@@ -116,6 +116,8 @@ export default {
{ path: '/h/lazy-deps', loader: () => import('./pages/lazy-deps.js') },
{ path: '/h/services', loader: () => import('./pages/services.js') },
{ path: '/h/config', loader: () => import('./pages/config.js') },
// Batch 1 §A: /h/channels 当前是 placeholder487 字节 stub— 暂不挂 nav
// 完整实现见 Batch 3待 Hermes 渠道完整支持时启用 sidebar 入口
{ path: '/h/channels', loader: () => import('./pages/channels.js') },
{ path: '/h/env', loader: () => import('./pages/env-editor.js') },
// 共用页面(引擎无关)

View File

@@ -26,13 +26,13 @@ export function render() {
el.innerHTML = `
<div class="hm-hero">
<div class="hm-hero-title">
<div class="hm-hero-eyebrow">HERMES AGENT · CONFIG</div>
<div class="hm-hero-eyebrow">${t('engine.hermesConfigEyebrow')}</div>
<h1 class="hm-hero-h1">${t('engine.hermesConfigTitle')}</h1>
<div class="hm-hero-sub">~/.hermes/config.yaml</div>
</div>
<div class="hm-hero-actions">
<button class="hm-btn hm-btn--ghost hm-btn--sm" id="hm-config-reload" ${loading || saving ? 'disabled' : ''}>重新加载</button>
<button class="hm-btn hm-btn--cta hm-btn--sm" id="hm-config-save" ${loading || saving ? 'disabled' : ''}>保存配置</button>
<button class="hm-btn hm-btn--ghost hm-btn--sm" id="hm-config-reload" ${loading || saving ? 'disabled' : ''}>${t('engine.hermesConfigReload')}</button>
<button class="hm-btn hm-btn--cta hm-btn--sm" id="hm-config-save" ${loading || saving ? 'disabled' : ''}>${t('engine.hermesConfigSave')}</button>
</div>
</div>
@@ -40,7 +40,7 @@ export function render() {
<div class="hm-panel-header">
<div class="hm-panel-title">config.yaml</div>
<div class="hm-panel-actions">
<span class="hm-muted">${saving ? 'saving' : loading ? 'loading' : 'raw yaml editor'}</span>
<span class="hm-muted">${saving ? t('engine.hermesConfigStatusSaving') : loading ? t('engine.hermesConfigStatusLoading') : t('engine.hermesConfigStatusReady')}</span>
</div>
</div>
<div class="hm-panel-body" style="padding:0">
@@ -76,7 +76,7 @@ export function render() {
draw()
try {
await api.hermesConfigRawWrite(yaml)
toast('配置已保存,建议重启 Hermes Gateway 生效', 'success')
toast(t('engine.hermesConfigSaveSuccess'), 'success')
} catch (err) {
error = String(err?.message || err).replace(/^Error:\s*/, '')
toast(error, 'error')

View File

@@ -429,6 +429,14 @@ export default {
chatSlashPort: _('端口', 'Port', '埠'),
chatSlashModel: _('模型', 'Model', '模型'),
chatSlashRedirect: _('正在跳转到 {page}...', 'Redirecting to {page}...', '正在跳轉到 {page}...'),
// Batch 1 §B: Hermes config.js 编辑器(去掉硬编码)
hermesConfigEyebrow: _('HERMES AGENT · 配置', 'HERMES AGENT · CONFIG', 'HERMES AGENT · 設定'),
hermesConfigReload: _('重新加载', 'Reload', '重新載入'),
hermesConfigSave: _('保存配置', 'Save', '儲存設定'),
hermesConfigSaveSuccess: _('配置已保存,建议重启 Hermes Gateway 生效', 'Saved. Restart Hermes Gateway to take effect.', '已儲存設定,建議重啟 Hermes Gateway 生效'),
hermesConfigStatusSaving: _('保存中…', 'Saving…', '儲存中…'),
hermesConfigStatusLoading: _('加载中…', 'Loading…', '載入中…'),
hermesConfigStatusReady: _('raw yaml 编辑器', 'raw yaml editor', 'raw yaml 編輯器'),
// 停止流式
chatStop: _('停止', 'Stop', '停止'),
chatStopped: _('已停止当前回复', 'Run stopped', '已停止目前回覆'),