diff --git a/README.md b/README.md index f8fb5ab6..736fbd3b 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ go build -o cyberstrike-ai cmd/server/main.go **CyberStrikeAI one-click upgrade (recommended):** 1. (First time) enable the script: `chmod +x upgrade.sh` -2. Upgrade with: `./upgrade.sh` (optional flags: `--tag vX.Y.Z`, `--no-venv`, `--preserve-custom`, `--yes`) +2. Upgrade with: `./upgrade.sh` (optional flags: `--tag vX.Y.Z`, `--no-venv`, `--yes`). Local `tools/`, `roles/`, and `skills/` are always preserved. 3. The script will back up your `config.yaml` and `data/`, upgrade the code from GitHub Release, update `config.yaml`'s `version`, then restart the server. Recommended one-liner: diff --git a/README_CN.md b/README_CN.md index 46376535..2e7bb04f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -209,7 +209,7 @@ go build -o cyberstrike-ai cmd/server/main.go ### CyberStrikeAI 版本更新(无兼容性问题) 1. (首次使用)启用脚本:`chmod +x upgrade.sh` -2. 一键升级:`./upgrade.sh`(可选参数:`--tag vX.Y.Z`、`--no-venv`、`--preserve-custom`、`--yes`) +2. 一键升级:`./upgrade.sh`(可选参数:`--tag vX.Y.Z`、`--no-venv`、`--yes`)。本地的 `tools/`、`roles/`、`skills/` 会始终保留不被覆盖。 3. 脚本会备份你的 `config.yaml` 和 `data/`,从 GitHub Release 升级代码,更新 `config.yaml` 的 `version` 字段后重启服务。 推荐的一键指令: diff --git a/upgrade.sh b/upgrade.sh index b015bf74..1e00f295 100644 --- a/upgrade.sh +++ b/upgrade.sh @@ -8,11 +8,8 @@ set -euo pipefail # - data/ # - venv/ (disabled with --no-venv) # - tools/ (user extensions; never overwritten by upgrade) -# -# Optional preserves (may overwrite upstream updates): # - roles/ # - skills/ -# Enable with --preserve-custom ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT_DIR" @@ -28,7 +25,6 @@ BACKUP_BASE_DIR="$ROOT_DIR/.upgrade-backup" GITHUB_REPO="Ed1s0nZ/CyberStrikeAI" TAG="" -PRESERVE_CUSTOM=0 PRESERVE_VENV=1 STOP_SERVICE=1 FORCE_STOP=0 @@ -37,14 +33,12 @@ YES=0 usage() { cat < Specify GitHub Release tag (e.g. v1.3.28). If omitted, the script uses the latest release. - --preserve-custom Preserve roles/skills (may overwrite upstream files). - tools/ is always preserved. Use with caution. --no-venv Do not preserve venv/ (Python deps will be re-installed). --no-stop Do not try to stop the running service. --force-stop If no process matching current directory is found, also stop @@ -52,7 +46,7 @@ Options: --yes Do not ask for confirmation. Description: - The script backs up config.yaml/data/tools/ (and optionally venv/roles/skills) to + The script backs up config.yaml/data/tools/roles/skills/ (and optionally venv/) to .upgrade-backup/ EOF } @@ -177,11 +171,7 @@ confirm_or_exit() { info " - Preserve venv/: no (will remove old venv and re-install deps)" fi info " - Preserve tools/: yes (always)" - if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then - info " - Preserve roles/skills: yes (may overwrite upstream updates)" - else - info " - Preserve roles/skills: no (will use upstream versions)" - fi + info " - Preserve roles/skills: yes (always)" info " - Stop service: ${STOP_SERVICE}" echo "" read -r -p "Continue? (y/N) " ans @@ -299,11 +289,8 @@ sync_code() { # User tool extensions: never replace or delete during upgrade. rsync_excludes+=( "--exclude=tools/" ) - - if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then - rsync_excludes+=( "--exclude=roles/" ) - rsync_excludes+=( "--exclude=skills/" ) - fi + rsync_excludes+=( "--exclude=roles/" ) + rsync_excludes+=( "--exclude=skills/" ) # Ensure this upgrade script itself is not deleted. rsync_excludes+=( "--exclude=upgrade.sh" ) @@ -324,10 +311,6 @@ main() { TAG="${2:-}" shift 2 ;; - --preserve-custom) - PRESERVE_CUSTOM=1 - shift 1 - ;; --no-venv) PRESERVE_VENV=0 shift 1 @@ -384,8 +367,10 @@ main() { if [[ -d "$ROOT_DIR/tools" ]]; then backup_dir_tgz "tools" "$ROOT_DIR/tools" fi - if [[ "$PRESERVE_CUSTOM" -eq 1 ]]; then + if [[ -d "$ROOT_DIR/roles" ]]; then backup_dir_tgz "roles" "$ROOT_DIR/roles" + fi + if [[ -d "$ROOT_DIR/skills" ]]; then backup_dir_tgz "skills" "$ROOT_DIR/skills" fi diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index c99a5f10..546aa261 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -726,8 +726,8 @@ function renderDashboardAlertBanner(stats) { try { sessionStorage.setItem(DASH_SESSION_ALERT_LAST_REASONS, reasonPartJoined); } catch (_) {} } -// External MCP 健康度:从 /api/external-mcp/stats 解析出 running / total / down, -// 决定是否在「能力总览」第 6 行显示,并把 down 数返回给 alert banner 驱动告警。 +// External MCP 健康度:从 /api/external-mcp/stats 解析(后端字段为 total/enabled/disabled/connected), +// 决定是否在「能力总览」第 6 行显示,并把「已启用但未连接」的数量返回给 alert banner。 function renderExternalMcpHealth(stats) { var row = document.getElementById('dashboard-resource-external-mcp-row'); var textEl = document.getElementById('dashboard-resource-external-mcp-text'); @@ -738,22 +738,29 @@ function renderExternalMcpHealth(stats) { row.hidden = true; return 0; } - // 兼容多种返回字段:{ total, running, stopped/error };常见命名都尝试一下 var total = Number(stats.total ?? stats.Total ?? 0) || 0; - var running = Number(stats.running ?? stats.Running ?? 0) || 0; + var enabled = Number(stats.enabled ?? stats.Enabled ?? 0) || 0; + // 后端用 connected 表示已连接数;兼容旧字段 running + var connected = Number(stats.connected ?? stats.Connected ?? + stats.running ?? stats.Running ?? 0) || 0; if (total === 0) { row.hidden = true; return 0; } - var down = Math.max(0, total - running); + // 未配置任何「已启用」的外部 MCP 时不展示健康行,也不告警(与 MCP 管理页口径一致) + if (enabled === 0) { + row.hidden = true; + return 0; + } + var down = Math.max(0, enabled - connected); row.hidden = false; - textEl.textContent = formatNumber(running) + ' / ' + formatNumber(total); + textEl.textContent = formatNumber(connected) + ' / ' + formatNumber(enabled); if (healthEl) { healthEl.classList.remove('is-ok', 'is-warning', 'is-danger'); if (down === 0) { healthEl.classList.add('is-ok'); healthEl.textContent = dt('dashboard.mcpAllRunning', null, '全部运行'); - } else if (down < total) { + } else if (down < enabled) { healthEl.classList.add('is-warning'); healthEl.textContent = dt('dashboard.mcpPartialDown', { count: down }, down + ' 个未运行');