mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-29 04:10:00 +08:00
fix(gateway): release 0.16.5
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -7,6 +7,18 @@
|
||||
|
||||
## [未发布]
|
||||
|
||||
## [0.16.5] - 2026-05-22
|
||||
|
||||
### 修复 (Fixes)
|
||||
|
||||
- **兼容已有 OpenClaw 安装** — Windows 桌面端自动发现范围扩展到 npm 全局目录、standalone 目录、常见 OpenClaw / Node 安装目录、`where openclaw` 结果,并支持 `openclaw.exe` / `openclaw.js` 入口,避免 Gateway 已运行但重启时报 “openclaw CLI 未安装”
|
||||
- **已有安装导入引导** — Dashboard 启动 / 重启 Gateway 遇到 CLI 未绑定时,会打开已有 OpenClaw 安装绑定弹窗,不再只显示失败提示
|
||||
- **Web 模式候选路径补齐** — Web 后端 CLI 发现同步补充 `openclaw.exe` 候选,保持桌面端与 Web 端行为一致
|
||||
|
||||
### 测试与验证 (Testing)
|
||||
|
||||
- **回归验证** — 已通过 `npm run build`、`node --test tests\*.test.js`、`cargo fmt --check`、`cargo check`、`cargo clippy --all-targets -- -D warnings`、`git diff --check`
|
||||
|
||||
## [0.16.4] - 2026-05-22
|
||||
|
||||
### 修复 (Fixes)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"description": "支持 OpenClaw 和 Hermes Agent 双引擎的多 AI Agent 可视化管理面板,基于 Tauri v2 的跨平台桌面应用。内置晴辰助手支持工具调用,晴辰云 AI 接口一键接入。支持仪表盘监控、多模型配置、Hermes Agent 对话、消息渠道管理、内置 QQ 机器人、实时 AI 聊天、记忆管理、Agent 管理、网关配置、内网穿透等功能。支持 11 种语言。",
|
||||
"url": "https://claw.qt.cool/",
|
||||
"downloadUrl": "https://github.com/qingchencloud/clawpanel/releases/latest",
|
||||
"softwareVersion": "0.16.4",
|
||||
"softwareVersion": "0.16.5",
|
||||
"author": {
|
||||
"@type": "Organization",
|
||||
"name": "晴辰云 QingchenCloud",
|
||||
@@ -1225,7 +1225,7 @@
|
||||
<div class="orb orb-2" style="top:auto;bottom:-100px"></div>
|
||||
<div class="container-sm" style="position:relative;z-index:10">
|
||||
<div class="section-header">
|
||||
<div class="reveal download-version"><span class="pulse"></span> <span id="dl-badge" data-i18n="dl.badge">v0.16.4 最新版</span></div>
|
||||
<div class="reveal download-version"><span class="pulse"></span> <span id="dl-badge" data-i18n="dl.badge">v0.16.5 最新版</span></div>
|
||||
<h2 class="reveal section-title" data-i18n="dl.title"><span class="gradient-text">下载安装</span></h2>
|
||||
<p class="reveal section-desc" data-i18n="dl.desc">选择你的操作系统,一键下载安装</p>
|
||||
</div>
|
||||
@@ -1235,11 +1235,11 @@
|
||||
<h3>macOS</h3>
|
||||
<p class="dl-desc" data-i18n="dl.mac.d">支持 Apple Silicon 和 Intel 芯片</p>
|
||||
<div class="dl-links">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_aarch64.dmg" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_aarch64.dmg" target="_blank" rel="noopener">
|
||||
Apple Silicon (M1/M2/M3/M4)
|
||||
<span class="dl-format">.dmg</span>
|
||||
</a>
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_x64.dmg" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_x64.dmg" target="_blank" rel="noopener">
|
||||
<span data-i18n="dl.mac.intel">Intel 芯片</span>
|
||||
<span class="dl-format">.dmg</span>
|
||||
</a>
|
||||
@@ -1257,15 +1257,15 @@
|
||||
<h3>Windows</h3>
|
||||
<p class="dl-desc" data-i18n="dl.win.d">支持 Windows 10 及以上版本</p>
|
||||
<div class="dl-links">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_x64-setup.exe" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_x64-setup.exe" target="_blank" rel="noopener">
|
||||
<span data-i18n="dl.win.exe">安装程序</span>
|
||||
<span class="dl-format">.exe</span>
|
||||
</a>
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_x64-setup-full.exe" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_x64-setup-full.exe" target="_blank" rel="noopener">
|
||||
<span data-i18n="dl.win.full">完整包(含 WebView2)</span>
|
||||
<span class="dl-format">.exe</span>
|
||||
</a>
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_x64_en-US.msi" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_x64_en-US.msi" target="_blank" rel="noopener">
|
||||
<span data-i18n="dl.win.msi">MSI 安装包</span>
|
||||
<span class="dl-format">.msi</span>
|
||||
</a>
|
||||
@@ -1276,11 +1276,11 @@
|
||||
<h3>Linux</h3>
|
||||
<p class="dl-desc" data-i18n="dl.linux.d">支持主流 Linux 发行版</p>
|
||||
<div class="dl-links">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_amd64.AppImage" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_amd64.AppImage" target="_blank" rel="noopener">
|
||||
<span data-i18n="dl.linux.ai">通用版</span>
|
||||
<span class="dl-format">.AppImage</span>
|
||||
</a>
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.4_amd64.deb" target="_blank" rel="noopener">
|
||||
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.16.5_amd64.deb" target="_blank" rel="noopener">
|
||||
Debian / Ubuntu
|
||||
<span class="dl-format">.deb</span>
|
||||
</a>
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "clawpanel",
|
||||
"version": "0.16.4",
|
||||
"version": "0.16.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "clawpanel",
|
||||
"version": "0.16.4",
|
||||
"version": "0.16.5",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clawpanel",
|
||||
"version": "0.16.4",
|
||||
"version": "0.16.5",
|
||||
"private": true,
|
||||
"description": "ClawPanel - OpenClaw 可视化管理面板,基于 Tauri v2 的跨平台桌面应用",
|
||||
"type": "module",
|
||||
|
||||
@@ -585,6 +585,7 @@ function collectPreferredCliCandidates() {
|
||||
if (!trimmed) continue
|
||||
if (isWindows) {
|
||||
addCliCandidate(candidates, seen, path.join(trimmed, 'openclaw.cmd'))
|
||||
addCliCandidate(candidates, seen, path.join(trimmed, 'openclaw.exe'))
|
||||
addCliCandidate(candidates, seen, path.join(trimmed, 'openclaw'))
|
||||
} else {
|
||||
addCliCandidate(candidates, seen, path.join(trimmed, 'openclaw'))
|
||||
|
||||
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -366,7 +366,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clawpanel"
|
||||
version = "0.16.4"
|
||||
version = "0.16.5"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clawpanel"
|
||||
version = "0.16.4"
|
||||
version = "0.16.5"
|
||||
edition = "2021"
|
||||
description = "ClawPanel - OpenClaw 可视化管理面板"
|
||||
authors = ["qingchencloud"]
|
||||
|
||||
@@ -2496,12 +2496,37 @@ fn scan_all_installations(
|
||||
try_add(prefix_path.join("openclaw"));
|
||||
}
|
||||
if let Ok(localappdata) = std::env::var("LOCALAPPDATA") {
|
||||
let localappdata_path = std::path::PathBuf::from(&localappdata);
|
||||
try_add(
|
||||
std::path::PathBuf::from(&localappdata)
|
||||
localappdata_path
|
||||
.join("Programs")
|
||||
.join("OpenClaw")
|
||||
.join("openclaw.exe"),
|
||||
);
|
||||
try_add(localappdata_path.join("OpenClaw").join("openclaw.cmd"));
|
||||
try_add(localappdata_path.join("OpenClaw").join("openclaw.exe"));
|
||||
try_add(
|
||||
localappdata_path
|
||||
.join("Programs")
|
||||
.join("nodejs")
|
||||
.join("openclaw.cmd"),
|
||||
);
|
||||
try_add(
|
||||
localappdata_path
|
||||
.join("Programs")
|
||||
.join("nodejs")
|
||||
.join("openclaw.exe"),
|
||||
);
|
||||
try_add(
|
||||
localappdata_path
|
||||
.join("Programs")
|
||||
.join("nodejs")
|
||||
.join("node_modules")
|
||||
.join("@qingchencloud")
|
||||
.join("openclaw-zh")
|
||||
.join("bin")
|
||||
.join("openclaw.js"),
|
||||
);
|
||||
}
|
||||
if let Ok(program_files) = std::env::var("ProgramFiles") {
|
||||
try_add(
|
||||
@@ -2607,6 +2632,15 @@ fn scan_all_installations(
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
try_add(base.join("openclaw.cmd"));
|
||||
try_add(base.join("openclaw.exe"));
|
||||
try_add(base.join("openclaw"));
|
||||
try_add(
|
||||
base.join("node_modules")
|
||||
.join("@qingchencloud")
|
||||
.join("openclaw-zh")
|
||||
.join("bin")
|
||||
.join("openclaw.js"),
|
||||
);
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
|
||||
@@ -1,6 +1,142 @@
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn push_unique_candidate(
|
||||
candidates: &mut Vec<std::path::PathBuf>,
|
||||
seen: &mut std::collections::HashSet<String>,
|
||||
path: std::path::PathBuf,
|
||||
) {
|
||||
let key = path.to_string_lossy().replace('/', "\\").to_lowercase();
|
||||
if seen.insert(key) {
|
||||
candidates.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn push_windows_cli_files(
|
||||
candidates: &mut Vec<std::path::PathBuf>,
|
||||
seen: &mut std::collections::HashSet<String>,
|
||||
base: std::path::PathBuf,
|
||||
) {
|
||||
push_unique_candidate(candidates, seen, base.join("openclaw.cmd"));
|
||||
push_unique_candidate(candidates, seen, base.join("openclaw.exe"));
|
||||
push_unique_candidate(candidates, seen, base.join("openclaw"));
|
||||
push_unique_candidate(
|
||||
candidates,
|
||||
seen,
|
||||
base.join("node_modules")
|
||||
.join("@qingchencloud")
|
||||
.join("openclaw-zh")
|
||||
.join("bin")
|
||||
.join("openclaw.js"),
|
||||
);
|
||||
push_unique_candidate(
|
||||
candidates,
|
||||
seen,
|
||||
base.join("node_modules")
|
||||
.join("openclaw")
|
||||
.join("bin")
|
||||
.join("openclaw.js"),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn common_windows_cli_candidates() -> Vec<std::path::PathBuf> {
|
||||
let mut candidates = Vec::new();
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
|
||||
// 先按 enhanced PATH 顺序找,保持与用户命令行优先级一致。
|
||||
for dir in crate::commands::enhanced_path().split(';') {
|
||||
let dir = dir.trim();
|
||||
if dir.is_empty() {
|
||||
continue;
|
||||
}
|
||||
push_windows_cli_files(&mut candidates, &mut seen, std::path::PathBuf::from(dir));
|
||||
}
|
||||
|
||||
if let Ok(appdata) = std::env::var("APPDATA") {
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(appdata).join("npm"),
|
||||
);
|
||||
}
|
||||
if let Some(prefix) = crate::commands::windows_npm_global_prefix() {
|
||||
push_windows_cli_files(&mut candidates, &mut seen, std::path::PathBuf::from(prefix));
|
||||
}
|
||||
for sa_dir in crate::commands::config::all_standalone_dirs() {
|
||||
push_windows_cli_files(&mut candidates, &mut seen, sa_dir);
|
||||
}
|
||||
if let Ok(localappdata) = std::env::var("LOCALAPPDATA") {
|
||||
let localappdata = std::path::PathBuf::from(localappdata);
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
localappdata.join("Programs").join("OpenClaw"),
|
||||
);
|
||||
push_windows_cli_files(&mut candidates, &mut seen, localappdata.join("OpenClaw"));
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
localappdata.join("Programs").join("nodejs"),
|
||||
);
|
||||
}
|
||||
if let Ok(program_files) = std::env::var("ProgramFiles") {
|
||||
let program_files = std::path::PathBuf::from(program_files);
|
||||
push_windows_cli_files(&mut candidates, &mut seen, program_files.join("nodejs"));
|
||||
push_windows_cli_files(&mut candidates, &mut seen, program_files.join("OpenClaw"));
|
||||
}
|
||||
if let Ok(program_files_x86) = std::env::var("ProgramFiles(x86)") {
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(program_files_x86).join("nodejs"),
|
||||
);
|
||||
}
|
||||
if let Ok(profile) = std::env::var("USERPROFILE") {
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(profile).join(".openclaw-bin"),
|
||||
);
|
||||
}
|
||||
for drive in ["C", "D", "E", "F", "G"] {
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(format!(r"{drive}:\OpenClaw")),
|
||||
);
|
||||
push_windows_cli_files(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(format!(r"{drive}:\AI\OpenClaw")),
|
||||
);
|
||||
}
|
||||
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
let mut where_cmd = std::process::Command::new("where");
|
||||
where_cmd.arg("openclaw");
|
||||
where_cmd.env("PATH", crate::commands::enhanced_path());
|
||||
where_cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
if let Ok(output) = where_cmd.output() {
|
||||
if output.status.success() {
|
||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||
let trimmed = line.trim();
|
||||
if !trimmed.is_empty() {
|
||||
push_unique_candidate(
|
||||
&mut candidates,
|
||||
&mut seen,
|
||||
std::path::PathBuf::from(trimmed),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
candidates
|
||||
}
|
||||
|
||||
pub fn is_rejected_cli_path(cli_path: &str) -> bool {
|
||||
let lower = cli_path.replace('\\', "/").to_lowercase();
|
||||
lower.contains("/.cherrystudio/") || lower.contains("cherry-studio")
|
||||
@@ -41,7 +177,7 @@ fn configured_cli_candidates() -> Vec<std::path::PathBuf> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Windows: 在 PATH 中查找 openclaw.cmd 的完整路径
|
||||
/// Windows: 在 PATH 和常见安装目录中查找 openclaw CLI 的完整路径
|
||||
/// 避免通过 `cmd /c openclaw` 调用时 npm .cmd shim 中的引号导致
|
||||
/// "\"node\"" is not recognized 错误
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -55,14 +191,9 @@ fn find_openclaw_cmd() -> Option<std::path::PathBuf> {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
let path = crate::commands::enhanced_path();
|
||||
for dir in path.split(';') {
|
||||
let candidate = std::path::Path::new(dir).join("openclaw.cmd");
|
||||
if candidate.exists() && !is_rejected_cli_path(&candidate.to_string_lossy()) {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
None
|
||||
common_windows_cli_candidates()
|
||||
.into_iter()
|
||||
.find(|candidate| candidate.exists() && !is_rejected_cli_path(&candidate.to_string_lossy()))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@@ -95,14 +226,7 @@ pub fn resolve_openclaw_cli_path() -> Option<String> {
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let path = crate::commands::enhanced_path();
|
||||
for dir in path.split(';') {
|
||||
let candidate = std::path::Path::new(dir).join("openclaw.cmd");
|
||||
if candidate.exists() && !is_rejected_cli_path(&candidate.to_string_lossy()) {
|
||||
return Some(candidate.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
None
|
||||
find_openclaw_cmd().map(|p| p.to_string_lossy().to_string())
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
@@ -161,7 +285,15 @@ pub fn openclaw_command() -> std::process::Command {
|
||||
// 优先:找到 openclaw.cmd 完整路径,用 cmd /c "完整路径" 避免引号问题
|
||||
if let Some(cmd_path) = find_openclaw_cmd() {
|
||||
let mut cmd = std::process::Command::new("cmd");
|
||||
cmd.arg("/c").arg(cmd_path);
|
||||
if cmd_path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("js"))
|
||||
{
|
||||
cmd.arg("/c").arg("node").arg(cmd_path);
|
||||
} else {
|
||||
cmd.arg("/c").arg(cmd_path);
|
||||
}
|
||||
cmd.env("PATH", &enhanced);
|
||||
apply_openclaw_dir_env(&mut cmd);
|
||||
crate::commands::apply_proxy_env(&mut cmd);
|
||||
@@ -197,7 +329,15 @@ pub fn openclaw_command_async() -> tokio::process::Command {
|
||||
// 优先:找到 openclaw.cmd 完整路径
|
||||
if let Some(cmd_path) = find_openclaw_cmd() {
|
||||
let mut cmd = tokio::process::Command::new("cmd");
|
||||
cmd.arg("/c").arg(cmd_path);
|
||||
if cmd_path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("js"))
|
||||
{
|
||||
cmd.arg("/c").arg("node").arg(cmd_path);
|
||||
} else {
|
||||
cmd.arg("/c").arg(cmd_path);
|
||||
}
|
||||
cmd.env("PATH", &enhanced);
|
||||
apply_openclaw_dir_env_tokio(&mut cmd);
|
||||
crate::commands::apply_proxy_env_tokio(&mut cmd);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json",
|
||||
"productName": "ClawPanel",
|
||||
"version": "0.16.4",
|
||||
"version": "0.16.5",
|
||||
"identifier": "ai.openclaw.clawpanel",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
|
||||
@@ -119,6 +119,22 @@ function dedupeOpenclawInstallations(list = []) {
|
||||
return [...map.values()]
|
||||
}
|
||||
|
||||
function isCliMissingError(err) {
|
||||
const message = String(err?.message || err || '')
|
||||
return message.includes('openclaw CLI 未安装') || message.includes('CLI 未安装')
|
||||
}
|
||||
|
||||
async function handleGatewayStartError(page, err, fallbackText) {
|
||||
if (isForeignGatewayError(err)) {
|
||||
await openGatewayConflict(page, err)
|
||||
return
|
||||
}
|
||||
toast(humanizeError(err, fallbackText), isCliMissingError(err) ? 'warning' : 'error')
|
||||
if (isCliMissingError(err)) {
|
||||
await showInstallationCleanup({ onRefresh: () => loadDashboardData(page, true) })
|
||||
}
|
||||
}
|
||||
|
||||
let _dashboardInitialized = false
|
||||
let _dashboardVersionCache = null
|
||||
let _dashboardStatusSummaryCache = null
|
||||
@@ -760,8 +776,7 @@ function bindActions(page) {
|
||||
toast(t('dashboard.gwStartSent'), 'success')
|
||||
setTimeout(() => loadDashboardData(page), 2000)
|
||||
} catch (err) {
|
||||
if (isForeignGatewayError(err)) await openGatewayConflict(page, err)
|
||||
else toast(t('dashboard.startFail') + ': ' + err, 'error')
|
||||
await handleGatewayStartError(page, err, t('dashboard.startFail'))
|
||||
}
|
||||
finally { actionBtn.disabled = false; actionBtn.textContent = t('dashboard.startBtn') }
|
||||
}
|
||||
@@ -784,8 +799,7 @@ function bindActions(page) {
|
||||
toast(t('dashboard.gwRestartSent'), 'success')
|
||||
setTimeout(() => loadDashboardData(page), 3000)
|
||||
} catch (err) {
|
||||
if (isForeignGatewayError(err)) await openGatewayConflict(page, err)
|
||||
else toast(t('dashboard.restartFail') + ': ' + err, 'error')
|
||||
await handleGatewayStartError(page, err, t('dashboard.restartFail'))
|
||||
}
|
||||
finally { actionBtn.disabled = false; actionBtn.textContent = t('dashboard.restartBtn') }
|
||||
}
|
||||
@@ -798,8 +812,7 @@ function bindActions(page) {
|
||||
try {
|
||||
await api.restartService('ai.openclaw.gateway')
|
||||
} catch (e) {
|
||||
if (isForeignGatewayError(e)) await openGatewayConflict(page, e)
|
||||
else toast(humanizeError(e, t('dashboard.restartFail')), 'error')
|
||||
await handleGatewayStartError(page, e, t('dashboard.restartFail'))
|
||||
btnRestart.disabled = false
|
||||
btnRestart.classList.remove('btn-loading')
|
||||
btnRestart.textContent = t('dashboard.restartGw')
|
||||
|
||||
Reference in New Issue
Block a user