diff --git a/scripts/dev-api.js b/scripts/dev-api.js index 6f813de..f1a1884 100644 --- a/scripts/dev-api.js +++ b/scripts/dev-api.js @@ -6437,7 +6437,7 @@ const handlers = { : 'hermes-agent @ git+https://github.com/NousResearch/hermes-agent.git' const installArgs = method === 'uv-pip' ? ['pip', 'install', pkg] - : ['tool', 'install', pkg, '--python', '3.11'] + : ['tool', 'install', '--force', pkg, '--python', '3.11'] const result = spawnSync(uv, installArgs, { env: { ...process.env, PATH: hermesEnhancedPath(), GIT_TERMINAL_PROMPT: '0' }, timeout: 600000, diff --git a/src-tauri/src/commands/hermes.rs b/src-tauri/src/commands/hermes.rs index b9a62d7..ec7d862 100644 --- a/src-tauri/src/commands/hermes.rs +++ b/src-tauri/src/commands/hermes.rs @@ -946,7 +946,7 @@ async fn install_via_uv_tool( }; let mut cmd = tokio::process::Command::new(uv_path); - cmd.args(["tool", "install", &pkg, "--python", "3.11"]); + cmd.args(["tool", "install", "--force", &pkg, "--python", "3.11"]); // 配置 PyPI 镜像(extras 的依赖仍从 PyPI 下载) if let Some(mirror) = pypi_mirror_url() { diff --git a/src/engines/hermes/pages/setup.js b/src/engines/hermes/pages/setup.js index 80f38b3..883b607 100644 --- a/src/engines/hermes/pages/setup.js +++ b/src/engines/hermes/pages/setup.js @@ -33,6 +33,7 @@ export function render() { let hermesInfo = null let logs = [] let installing = false + let installError = null let progress = 0 let unlisten = null @@ -132,35 +133,51 @@ export function render() { const btnText = installing ? `${ICONS.spinner} ${t('engine.installingBtn')}` : `${ICONS.rocket} ${t('engine.installBtn')}` const btnDisabled = installing ? 'disabled' : '' + // 错误提示块 + const errorBlock = installError ? ` +
+
+ ${ICONS.error} +
+
${t('engine.installFailed')}
+
${esc(installError)}
+
+
+
+ ` : '' + + // 进度 + 日志区(安装中或安装失败后都显示) + const hasLogs = installing || logs.length > 0 + const progressBlock = hasLogs ? ` +
+
+
+ ${installError ? t('engine.installFailed') : progress >= 100 ? t('engine.installSuccess') : t('engine.installingBtn')} + ${Math.min(progress, 100)}% +
+
+
+
${logs.map(l => `
${esc(l)}
`).join('')}
+
+ ` : ` +
+
${ICONS.check} ${t('engine.installInfoUv')}
+
${ICONS.check} ${t('engine.installInfoCore')}
+
+ + ${t('engine.installInfoExtrasLater')} +
+
+ ` + return `

${t('engine.installTitle')}

${t('engine.installDescSimple')}

- - ${installing || progress > 0 ? ` -
-
-
- ${progress >= 100 ? t('engine.installSuccess') : t('engine.installingBtn')} - ${Math.min(progress, 100)}% -
-
-
-
${logs.map(l => `
${esc(l)}
`).join('')}
-
- ` : ` -
-
${ICONS.check} ${t('engine.installInfoUv')}
-
${ICONS.check} ${t('engine.installInfoCore')}
-
- - ${t('engine.installInfoExtrasLater')} -
-
- `} - + ${errorBlock} + ${progressBlock}
- +
` @@ -352,6 +369,7 @@ export function render() { // --- 安装流程 --- async function doInstall() { installing = true + installError = null progress = 0 logs = [] draw() @@ -392,6 +410,7 @@ export function render() { draw() } catch (e) { installing = false + installError = String(e.message || e) logs.push(`❌ ${t('engine.installFailed')}: ${e}`) draw() } finally { diff --git a/src/style/pages.css b/src/style/pages.css index d866d1e..9e23bad 100644 --- a/src/style/pages.css +++ b/src/style/pages.css @@ -1797,6 +1797,9 @@ border-radius: 4px; transition: width 0.4s ease; } +.hermes-progress-bar.error { + background: linear-gradient(90deg, var(--error, #ef4444), color-mix(in srgb, var(--error, #ef4444) 80%, #fff)); +} /* === Hermes Setup — Log Panel === */ .hermes-log-panel {