Files
karuo-ai/01_卡资(金)/金仓_存储备份/Cursor持久对话/install.sh
2026-07-19 00:21:46 +08:00

217 lines
7.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# 可持续对话 · 一键安装(本地 MCP无卡密
# 用法:
# bash install.sh # 装全局 + 当前目录项目
# bash install.sh --global-only # 仅 ~/.cursor/mcp.json
# bash install.sh --project /path/to/repo
# bash install.sh --all-karuo # 卡若常用多根工作区一并装
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_DIR="$SCRIPT_DIR/package"
INSTALL_DIR="${PCHAT_INSTALL_DIR:-$HOME/.persistent-chat-local}"
GLOBAL_MCP="$HOME/.cursor/mcp.json"
PORT="${PCHAT_HTTP_PORT:-13458}"
GLOBAL_ONLY=0
ALL_KARUO=0
PROJECTS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--global-only) GLOBAL_ONLY=1; shift ;;
--all-karuo) ALL_KARUO=1; shift ;;
--project) PROJECTS+=("$2"); shift 2 ;;
*) echo "未知参数: $1"; exit 1 ;;
esac
done
if [[ "$GLOBAL_ONLY" -eq 0 && "$ALL_KARUO" -eq 0 && ${#PROJECTS[@]} -eq 0 ]]; then
PROJECTS+=("$(pwd)")
fi
if [[ "$ALL_KARUO" -eq 1 ]]; then
PROJECTS=(
"/Users/karuo/Documents/个人/卡若AI"
"/Users/karuo/Documents/开发/3、自营项目/卡若ai网站"
"/Users/karuo/Documents/开发/8、小工具/Docker项目/OpenClaw"
"/Users/karuo/Documents/开发/8、小工具/Docker项目/OpenClaw/openclaw"
"/Users/karuo/Documents/开发/7.项目调研/claude-code-sourcemap"
"/Users/karuo/Documents/开发/7.项目调研/tryvoice-oss"
)
fi
# --- 找 node ---
find_node() {
for c in \
"$(command -v node 2>/dev/null || true)" \
"/usr/local/opt/node@22/bin/node" \
"/opt/homebrew/opt/node@22/bin/node" \
"/usr/local/bin/node" \
"/opt/homebrew/bin/node"; do
[[ -n "$c" && -x "$c" ]] && echo "$c" && return 0
done
return 1
}
NODE_BIN="$(find_node)" || { echo "❌ 未找到 node。请先安装: brew install node@22"; exit 1; }
echo "✅ node: $NODE_BIN ($("$NODE_BIN" -v))"
# --- 部署 runtime ---
mkdir -p "$INSTALL_DIR/logs" "$INSTALL_DIR/sessions" "$INSTALL_DIR/replies"
cp "$PKG_DIR/server.js" "$INSTALL_DIR/server.js"
cp "$PKG_DIR/hub.js" "$INSTALL_DIR/hub.js"
cp "$PKG_DIR/ensure-hub.sh" "$INSTALL_DIR/ensure-hub.sh"
cp "$PKG_DIR/panel.html" "$INSTALL_DIR/panel.html"
cp "$PKG_DIR/mongo_sync.py" "$INSTALL_DIR/mongo_sync.py"
chmod +x "$INSTALL_DIR/server.js" "$INSTALL_DIR/hub.js" "$INSTALL_DIR/ensure-hub.sh" "$INSTALL_DIR/mongo_sync.py"
echo "✅ 已部署到 $INSTALL_DIR"
# --- 写全局 mcp.json合并已有 ---
mkdir -p "$(dirname "$GLOBAL_MCP")"
TMP_MCP="$(mktemp)"
sed "s|__NODE_PATH__|$NODE_BIN|g; s|__INSTALL_DIR__|$INSTALL_DIR|g" "$PKG_DIR/templates/mcp.json" > "$TMP_MCP"
python3 <<PY
import json, os
global_mcp = os.path.expanduser("$GLOBAL_MCP")
with open("$TMP_MCP") as f:
block = json.load(f)
existing = {"mcpServers": {}}
if os.path.isfile(global_mcp):
with open(global_mcp) as f:
existing = json.load(f)
existing.setdefault("mcpServers", {})
existing["mcpServers"]["persistent-chat"] = block["mcpServers"]["persistent-chat"]
with open(global_mcp, "w") as f:
json.dump(existing, f, ensure_ascii=False, indent=2)
print("✅ 全局 MCP:", global_mcp)
PY
rm -f "$TMP_MCP"
# --- Codex config.toml通用 · 与 Cursor 共用 Hub ---
CODEX_CFG="$HOME/.codex/config.toml"
if [[ -f "$CODEX_CFG" ]] || [[ "${INSTALL_CODEX:-1}" == "1" ]]; then
python3 <<PY
import os, re
install = os.path.expanduser("$INSTALL_DIR")
node = "$NODE_BIN"
ws = "${PROJECTS[0]:-/Users/karuo/Documents/个人/卡若AI}"
cfg = os.path.expanduser("$CODEX_CFG")
block = f'''[mcp_servers.persistent-chat]
command = "bash"
args = ["{install}/ensure-hub.sh", "--workspace={ws}"]
[mcp_servers.persistent-chat.env]
PCHAT_HTTP_PORT = "13458"
PCHAT_NODE = "{node}"
[mcp_servers.persistent-chat.tools.wait_for_user_input]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.init_conversation]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.merge_conversation]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.select_conversation]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.verify_binding]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.verify_karuo_ai_gate]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.verify_mcp_status]
approval_mode = "auto"
[mcp_servers.persistent-chat.tools.apply_binding_choice]
approval_mode = "auto"
'''
if os.path.isfile(cfg):
with open(cfg) as f: text = f.read()
if '[mcp_servers.persistent-chat]' in text:
text = re.sub(
r'\[mcp_servers\.persistent-chat\][\s\S]*?(?=\n\[|\Z)',
block.strip() + '\n\n',
text,
count=1,
)
else:
text = text.rstrip() + '\n\n' + block
else:
os.makedirs(os.path.dirname(cfg), exist_ok=True)
text = block
with open(cfg, 'w') as f: f.write(text)
print("✅ Codex MCP:", cfg)
PY
fi
# --- 项目级:只装规则,不写 MCPMCP 仅全局一条,避免 Settings 出现两个) ---
install_project() {
local root="$1"
[[ -d "$root" ]] || { echo "⚠️ 跳过(目录不存在): $root"; return 0; }
mkdir -p "$root/.cursor/rules"
cp "$PKG_DIR/templates/persistent-chat.mdc" "$root/.cursor/rules/persistent-chat.mdc"
# 移除项目级 persistent-chat若曾装过
if [[ -f "$root/.cursor/mcp.json" ]]; then
python3 -c "
import json, sys
p = sys.argv[1]
try:
with open(p) as f: d = json.load(f)
s = d.get('mcpServers') or {}
if 'persistent-chat' in s:
del s['persistent-chat']
d['mcpServers'] = s
with open(p,'w') as f: json.dump(d,f,ensure_ascii=False,indent=2); f.write('\n')
print(' 🧹 已移除项目级 MCP:', p)
except Exception: pass
" "$root/.cursor/mcp.json" 2>/dev/null || true
fi
echo "✅ 规则: $root"
}
if [[ "$GLOBAL_ONLY" -eq 0 ]]; then
for p in "${PROJECTS[@]}"; do
install_project "$p"
done
fi
# --- 启动 Hub全局唯一 HTTP ---
if ! curl -sf -m 2 "http://127.0.0.1:${PORT}/api/health" >/dev/null 2>&1; then
nohup "$NODE_BIN" "$INSTALL_DIR/hub.js" >> "$INSTALL_DIR/logs/hub.log" 2>&1 &
sleep 0.5
fi
if curl -sf -m 2 "http://127.0.0.1:${PORT}/api/health" >/dev/null 2>&1; then
echo "✅ Hub 面板 http://127.0.0.1:${PORT}/"
else
echo "⚠️ Hub 未启动,请手动: node $INSTALL_DIR/hub.js"
fi
# --- Mongo 同步(可选) ---
if python3 "$INSTALL_DIR/mongo_sync.py" 2>/dev/null; then
echo "✅ MongoDB 会话已同步"
else
echo "⚠️ MongoDB 同步跳过Mongo 未开或 pymongo 未装,不影响 MCP 主功能)"
fi
# --- 验收 ---
echo ""
bash "$SCRIPT_DIR/verify.sh" || true
echo ""
bash "$SCRIPT_DIR/脚本/清理重复MCP.sh" 2>/dev/null || true
bash "$SCRIPT_DIR/check-mcp.sh" 2>/dev/null || bash "$SCRIPT_DIR/verify.sh" || true
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🎉 安装完成(通用 · Cursor + Codex + VS Code 共用 Hub"
echo " Cursor: ~/.cursor/mcp.json · Codex: ~/.codex/config.toml"
echo " 1. Cmd+Q 完全退出 Cursor 再打开"
echo " 2. Settings → Tools & MCP → 只保留 1 个 persistent-chat绿点"
echo " 3. 浏览器 http://127.0.0.1:${PORT}/ 回复 Agent"
echo " 4. Agent 模式直接说任务"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"