mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-30 04:40:18 +08:00
fix(hermes): restore gateway message sending dependencies
Hermes Gateway 能启动但消息发送链路仍可能不可用:工具安装环境缺少运行时依赖, 同时自定义端点场景下 provider 字段可能被省略,导致消息路由继续落到错误 provider。 ## 补齐运行时依赖 - uv tool install 固定带上 HTTP 客户端依赖 - 补齐 OpenAI SDK 依赖 - 补齐 Gateway HTTP server 所需 aiohttp - 补齐 browser/dialog 等工具链会触发的 websocket 依赖 - 安装日志同步展示完整安装参数,便于用户排查环境问题 ## 明确 custom provider - 自定义 base_url 时显式写入 provider: custom - 如果 model 段已有 provider,则覆盖为 custom - 如果 model 段缺少 provider,则补写 provider: custom - 继续保留 OPENAI_API_KEY alias 自愈,确保辅助客户端和主流程读取同一份凭证 ## 范围 - 桌面 Tauri 安装与配置自愈逻辑 - Web dev API 安装与配置自愈逻辑
This commit is contained in:
@@ -441,27 +441,21 @@ fn sanitize_hermes_openrouter_custom_mismatch() -> Result<bool, String> {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if provider != "openrouter" {
|
||||
if !uses_custom_endpoint {
|
||||
return Ok(alias_changed);
|
||||
}
|
||||
if base.is_empty() || base == expected {
|
||||
return Ok(alias_changed);
|
||||
}
|
||||
|
||||
let env_raw = std::fs::read_to_string(home.join(".env")).unwrap_or_default();
|
||||
let has_openrouter_key = env_file_has_value(&env_raw, "OPENROUTER_API_KEY");
|
||||
let has_custom_key = env_file_has_value(&env_raw, "CUSTOM_API_KEY")
|
||||
|| env_file_has_value(&env_raw, "OPENAI_API_KEY");
|
||||
if has_openrouter_key && !has_custom_key {
|
||||
if provider == "custom" {
|
||||
return Ok(alias_changed);
|
||||
}
|
||||
|
||||
let mut out = Vec::new();
|
||||
let mut in_model = false;
|
||||
let mut provider_written = false;
|
||||
for line in raw.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with("model:") {
|
||||
in_model = true;
|
||||
provider_written = false;
|
||||
out.push(line.to_string());
|
||||
continue;
|
||||
}
|
||||
@@ -469,12 +463,21 @@ fn sanitize_hermes_openrouter_custom_mismatch() -> Result<bool, String> {
|
||||
let indented = line.starts_with(' ') || line.starts_with('\t');
|
||||
if !indented && !trimmed.is_empty() && !trimmed.starts_with('#') {
|
||||
in_model = false;
|
||||
if !provider_written {
|
||||
out.push(" provider: custom".to_string());
|
||||
provider_written = true;
|
||||
}
|
||||
} else if trimmed.starts_with("provider:") {
|
||||
out.push(" provider: custom".to_string());
|
||||
provider_written = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
out.push(line.to_string());
|
||||
}
|
||||
if in_model && !provider_written {
|
||||
out.push(" provider: custom".to_string());
|
||||
}
|
||||
let mut fixed = out.join("\n");
|
||||
if !fixed.ends_with('\n') {
|
||||
fixed.push('\n');
|
||||
@@ -1653,7 +1656,22 @@ async fn install_via_uv_tool(
|
||||
|
||||
let mut cmd = tokio::process::Command::new(uv_path);
|
||||
cmd.args([
|
||||
"tool", "install", "--force", &pkg, "--python", "3.11", "--with", "croniter",
|
||||
"tool",
|
||||
"install",
|
||||
"--force",
|
||||
&pkg,
|
||||
"--python",
|
||||
"3.11",
|
||||
"--with",
|
||||
"croniter",
|
||||
"--with",
|
||||
"httpx",
|
||||
"--with",
|
||||
"openai",
|
||||
"--with",
|
||||
"aiohttp",
|
||||
"--with",
|
||||
"websockets",
|
||||
]);
|
||||
|
||||
// 配置 PyPI 镜像(extras 的依赖仍从 PyPI 下载)
|
||||
@@ -1678,7 +1696,7 @@ async fn install_via_uv_tool(
|
||||
|
||||
let _ = app.emit(
|
||||
"hermes-install-log",
|
||||
"uv tool install hermes-agent --python 3.11",
|
||||
"uv tool install hermes-agent --python 3.11 --with croniter --with httpx --with openai --with aiohttp --with websockets",
|
||||
);
|
||||
|
||||
let child = cmd.spawn().map_err(|e| format!("启动安装进程失败: {e}"))?;
|
||||
@@ -1904,8 +1922,8 @@ pub async fn configure_hermes(
|
||||
_ => String::new(),
|
||||
};
|
||||
// Provider 字段用于稳定选择凭证来源。
|
||||
// `custom` 不写 provider 行,让 Hermes Agent 从 base_url 自动推断。
|
||||
let provider_line = if provider == "custom" || provider.is_empty() {
|
||||
// `custom` 也需要显式写入,避免自定义端点被默认路由接管。
|
||||
let provider_line = if provider.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(" provider: {provider}\n")
|
||||
@@ -2026,7 +2044,7 @@ fn merge_hermes_config_yaml(
|
||||
// base_url_line 已包含 " base_url: xxx\n" 格式
|
||||
result.push(base_url_line.trim_end().to_string());
|
||||
}
|
||||
// provider_line 仅在非空时写入(Hermes 不需要 provider 字段)
|
||||
// provider_line 仅在非空时写入,确保模型路由稳定。
|
||||
if !provider_line.is_empty() {
|
||||
result.push(provider_line.trim_end().to_string());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user