Files

234 lines
7.8 KiB
Bash
Raw Permalink Normal View History

2026-05-29 17:33:12 +08:00
#!/usr/bin/env bash
#
# sync-hermes-llm-to-tdai.sh — 读取系统 Hermes 模型配置,同步到 TDAI Gateway
#
# 前置条件:
# 1. memory-tencentdb-ctl.sh 存在
# 2. ~/.hermes/config.yaml 存在且包含模型配置
#
# 用法:
# bash sync-hermes-llm-to-tdai.sh [--restart] [--dry-run] [--hermes]
#
# 参数语义:
# --restart 仅当 CTL 脚本的 `status` 显示 Gateway 当前为 RUNNING 时,
# 才透传给 `memory-tencentdb-ctl.sh config llm` 执行重启;
# 若当前未运行,则本脚本只同步配置,不拉起新进程。
# --hermes 以 hermes 集成模式调用 CTL(影响 status 判定与配置落点)
# --standalone 以 standalone 模式调用 CTL
# --dry-run 透传给 CTL,预演写配置但不真正落盘
#
# 可选环境变量:
# HERMES_HOME hermes 主目录(默认 ~/.hermes
# MEMORY_TENCENTDB_ROOT TDAI 统一根目录(默认 ~/.memory-tencentdb
#
set -euo pipefail
SCRIPT_NAME="sync-hermes-llm-to-tdai"
USER_HOME="${HOME:-$(eval echo "~$(whoami)")}"
# ============================================================
# 路径
# ============================================================
HERMES_HOME="${HERMES_HOME:-$USER_HOME/.hermes}"
HERMES_CONFIG="$HERMES_HOME/config.yaml"
MEMORY_TENCENTDB_ROOT="${MEMORY_TENCENTDB_ROOT:-$USER_HOME/.memory-tencentdb}"
TDAI_INSTALL_DIR="${TDAI_INSTALL_DIR:-$MEMORY_TENCENTDB_ROOT/tdai-memory-openclaw-plugin}"
CTL_SCRIPT="$TDAI_INSTALL_DIR/scripts/memory-tencentdb-ctl.sh"
# ============================================================
# 通用 helpers
# ============================================================
log() { printf '[%s] %s\n' "$SCRIPT_NAME" "$*"; }
warn() { printf '[%s:warn] %s\n' "$SCRIPT_NAME" "$*" >&2; }
die() { printf '[%s:error] %s\n' "$SCRIPT_NAME" "$*" >&2; exit "${2:-1}"; }
should_restart_gateway() {
local ctl_mode_args=()
case "${SYNC_MODE:-standalone}" in
hermes) ctl_mode_args+=("--hermes") ;;
*) ctl_mode_args+=("--standalone") ;;
esac
local status_out
status_out="$(bash "$CTL_SCRIPT" "${ctl_mode_args[@]}" status 2>&1 || true)"
if printf '%s\n' "$status_out" | grep -Eq 'state[[:space:]]*:[[:space:]]*RUNNING'; then
log "通过 ctl status 检测到 Gateway 正在运行,允许执行 --restart"
return 0
fi
warn "ctl status 未显示 Gateway 处于 RUNNING;本次仅同步配置,不执行 --restart,也不会拉起新进程。"
return 1
}
# ============================================================
# Step 1: 检查 memory-tencentdb-ctl.sh 是否存在
# ============================================================
if [[ ! -f "$CTL_SCRIPT" ]]; then
# 也尝试旧路径
_LEGACY_CTL="$USER_HOME/tdai-memory-openclaw-plugin/scripts/memory-tencentdb-ctl.sh"
if [[ -f "$_LEGACY_CTL" ]]; then
CTL_SCRIPT="$_LEGACY_CTL"
warn "使用旧路径: $CTL_SCRIPT"
else
die "memory-tencentdb-ctl.sh 不存在,TDAI 未安装。退出。" 1
fi
fi
log "找到 ctl 脚本: $CTL_SCRIPT"
# ============================================================
# Step 2: 检查 hermes config.yaml
# ============================================================
if [[ ! -f "$HERMES_CONFIG" ]]; then
die "Hermes 配置文件不存在: $HERMES_CONFIG" 1
fi
log "读取 Hermes 配置: $HERMES_CONFIG"
# ============================================================
# Step 3: 从 hermes config.yaml 提取模型配置
# ============================================================
need_cmd() {
command -v "$1" >/dev/null 2>&1 || die "必需命令未找到: $1" 127
}
need_cmd python3
# 使用 python3 安全解析 YAML,提取 model 段的 default / base_url / api_key
read_hermes_model_config() {
python3 - "$HERMES_CONFIG" <<'PYEOF'
import sys, json
config_path = sys.argv[1]
# 尝试使用 PyYAML;如果不存在则手动逐行解析
try:
import yaml
with open(config_path, "r", encoding="utf-8") as f:
cfg = yaml.safe_load(f) or {}
model_section = cfg.get("model", {})
result = {
"model": model_section.get("default", ""),
"base_url": model_section.get("base_url", ""),
"api_key": model_section.get("api_key", ""),
}
print(json.dumps(result))
except ImportError:
# PyYAML 不可用,用简单逐行解析提取 model 段
import re
with open(config_path, "r", encoding="utf-8") as f:
lines = f.readlines()
in_model = False
result = {"model": "", "base_url": "", "api_key": ""}
for line in lines:
stripped = line.rstrip("\n")
# 检测 model: 顶层段
if re.match(r"^model:\s*$", stripped) or re.match(r"^model:\s*#", stripped):
in_model = True
continue
# 进入新的顶层段则退出
if in_model and re.match(r"^[A-Za-z_]", stripped):
break
if in_model:
m = re.match(r"^\s+default:\s*(.+)", stripped)
if m:
result["model"] = m.group(1).strip().strip("'\"")
m = re.match(r"^\s+base_url:\s*(.+)", stripped)
if m:
result["base_url"] = m.group(1).strip().strip("'\"")
m = re.match(r"^\s+api_key:\s*(.+)", stripped)
if m:
result["api_key"] = m.group(1).strip().strip("'\"")
print(json.dumps(result))
PYEOF
}
MODEL_JSON="$(read_hermes_model_config)"
HERMES_MODEL="$(printf '%s' "$MODEL_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["model"])')"
HERMES_BASE_URL="$(printf '%s' "$MODEL_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["base_url"])')"
HERMES_API_KEY="$(printf '%s' "$MODEL_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["api_key"])')"
# 校验必需字段
if [[ -z "$HERMES_MODEL" ]]; then
die "Hermes 配置中 model.default 为空" 1
fi
if [[ -z "$HERMES_BASE_URL" ]]; then
die "Hermes 配置中 model.base_url 为空" 1
fi
if [[ -z "$HERMES_API_KEY" ]]; then
die "Hermes 配置中 model.api_key 为空" 1
fi
log "Hermes 模型配置:"
log " model = $HERMES_MODEL"
log " base_url = $HERMES_BASE_URL"
log " api_key = <${#HERMES_API_KEY} chars>"
# ============================================================
# Step 4: 透传参数(--restart / --dry-run / --hermes
# ============================================================
CTL_EXTRA_ARGS=()
SYNC_MODE="standalone"
REQUEST_RESTART=0
for arg in "$@"; do
case "$arg" in
--restart)
REQUEST_RESTART=1
;;
--hermes)
SYNC_MODE="hermes"
CTL_EXTRA_ARGS+=("$arg")
;;
--standalone)
SYNC_MODE="standalone"
CTL_EXTRA_ARGS+=("$arg")
;;
--dry-run)
CTL_EXTRA_ARGS+=("$arg")
;;
*)
warn "忽略未知参数: $arg"
;;
esac
done
if [[ $REQUEST_RESTART -eq 1 ]]; then
# 新语义:--restart 只在 Gateway 当前已运行时才生效。
# 这里复用 CTL 的 status 输出作为唯一事实来源,避免本脚本
# 自己维护另一套“端口监听/健康检查”判定逻辑。
if should_restart_gateway; then
CTL_EXTRA_ARGS+=("--restart")
else
log "已按新逻辑跳过 --restart。"
fi
fi
# ============================================================
# Step 5: 调用 memory-tencentdb-ctl.sh config llm 同步配置
# ============================================================
log "调用 memory-tencentdb-ctl.sh config llm 同步配置到 TDAI ..."
bash "$CTL_SCRIPT" "${CTL_EXTRA_ARGS[@]+"${CTL_EXTRA_ARGS[@]}"}" \
config llm \
--api-key "$HERMES_API_KEY" \
--base-url "$HERMES_BASE_URL" \
--model "$HERMES_MODEL"
log "同步完成。"
log ""
log "如需立即重启 Gateway 使配置生效,请重新运行并追加 --restart"
log " bash $0 --restart"