9b4a25799f
Replace fixed ackText with a rule-based AckProvider that picks response templates by message type and intent (translate, summary, rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync, zero I/O, auto-falls back to config.ackText on any error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
186 lines
5.8 KiB
Bash
186 lines
5.8 KiB
Bash
#!/usr/bin/env bash
|
||
# 安装 m.tkmind.cn + plaza.tkmind.cn 生产 LaunchAgent(登录自启 + 崩溃自动重启)
|
||
#
|
||
# 架构:
|
||
# cloudflared → g2 :8090 (Caddy) → Portal :8081
|
||
# cloudflared → plaza :3001 (Next.js) → Portal :8081
|
||
#
|
||
# 用法:pnpm setup:prod-services
|
||
set -euo pipefail
|
||
|
||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||
LOG_DIR="${HOME}/Library/Logs"
|
||
PORTAL_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.memind-portal.plist"
|
||
PLAZA_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.plaza.plist"
|
||
G2_LB_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.g2-lb.plist"
|
||
CF_PLIST="${HOME}/Library/LaunchAgents/com.cloudflare.cloudflared.plist"
|
||
PORTAL_RUN="${ROOT}/scripts/run-memind-portal-prod.sh"
|
||
PLAZA_RUN="${ROOT}/scripts/run-plaza-prod.sh"
|
||
CADDYFILE="${ROOT}/scripts/g2-lb.Caddyfile"
|
||
UID_NUM="$(id -u)"
|
||
GUI="gui/${UID_NUM}"
|
||
PATH_ENV="/opt/homebrew/bin:/opt/homebrew/opt/node@22/bin:/usr/local/bin:/usr/bin:/bin"
|
||
|
||
chmod +x "${PORTAL_RUN}" "${PLAZA_RUN}" "${ROOT}/scripts/install-g2-lb.sh"
|
||
|
||
mkdir -p "${LOG_DIR}"
|
||
|
||
cat >"${PORTAL_PLIST}" <<EOF
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>Label</key>
|
||
<string>cn.tkmind.memind-portal</string>
|
||
<key>ProgramArguments</key>
|
||
<array>
|
||
<string>${PORTAL_RUN}</string>
|
||
</array>
|
||
<key>WorkingDirectory</key>
|
||
<string>${ROOT}</string>
|
||
<key>EnvironmentVariables</key>
|
||
<dict>
|
||
<key>PATH</key>
|
||
<string>${PATH_ENV}</string>
|
||
</dict>
|
||
<key>RunAtLoad</key>
|
||
<true/>
|
||
<key>KeepAlive</key>
|
||
<true/>
|
||
<key>ThrottleInterval</key>
|
||
<integer>10</integer>
|
||
<key>StandardOutPath</key>
|
||
<string>${LOG_DIR}/memind-portal.log</string>
|
||
<key>StandardErrorPath</key>
|
||
<string>${LOG_DIR}/memind-portal.log</string>
|
||
</dict>
|
||
</plist>
|
||
EOF
|
||
|
||
cat >"${PLAZA_PLIST}" <<EOF
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>Label</key>
|
||
<string>cn.tkmind.plaza</string>
|
||
<key>ProgramArguments</key>
|
||
<array>
|
||
<string>${PLAZA_RUN}</string>
|
||
</array>
|
||
<key>WorkingDirectory</key>
|
||
<string>${ROOT}</string>
|
||
<key>EnvironmentVariables</key>
|
||
<dict>
|
||
<key>PATH</key>
|
||
<string>${PATH_ENV}</string>
|
||
</dict>
|
||
<key>RunAtLoad</key>
|
||
<true/>
|
||
<key>KeepAlive</key>
|
||
<true/>
|
||
<key>ThrottleInterval</key>
|
||
<integer>15</integer>
|
||
<key>StandardOutPath</key>
|
||
<string>${LOG_DIR}/plaza-prod.log</string>
|
||
<key>StandardErrorPath</key>
|
||
<string>${LOG_DIR}/plaza-prod.log</string>
|
||
</dict>
|
||
</plist>
|
||
EOF
|
||
|
||
if [[ ! -f "${G2_LB_PLIST}" ]]; then
|
||
cat >"${G2_LB_PLIST}" <<EOF
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>Label</key>
|
||
<string>cn.tkmind.g2-lb</string>
|
||
<key>ProgramArguments</key>
|
||
<array>
|
||
<string>/opt/homebrew/bin/caddy</string>
|
||
<string>run</string>
|
||
<string>--config</string>
|
||
<string>${CADDYFILE}</string>
|
||
</array>
|
||
<key>RunAtLoad</key>
|
||
<true/>
|
||
<key>KeepAlive</key>
|
||
<true/>
|
||
<key>ThrottleInterval</key>
|
||
<integer>10</integer>
|
||
<key>StandardOutPath</key>
|
||
<string>${LOG_DIR}/g2-lb.log</string>
|
||
<key>StandardErrorPath</key>
|
||
<string>${LOG_DIR}/g2-lb.log</string>
|
||
</dict>
|
||
</plist>
|
||
EOF
|
||
fi
|
||
|
||
install_agent() {
|
||
local label="$1"
|
||
local plist="$2"
|
||
if launchctl print "${GUI}/${label}" >/dev/null 2>&1; then
|
||
launchctl bootout "${GUI}/${label}" 2>/dev/null || true
|
||
sleep 1
|
||
fi
|
||
launchctl bootstrap "${GUI}" "${plist}"
|
||
launchctl enable "${GUI}/${label}"
|
||
launchctl kickstart -k "${GUI}/${label}"
|
||
}
|
||
|
||
echo "==> 释放端口 8081 / 3001(避免与手动进程冲突)…"
|
||
for port in 8081 3001; do
|
||
lsof -ti "TCP:${port}" -sTCP:LISTEN 2>/dev/null | xargs kill -9 2>/dev/null || true
|
||
done
|
||
sleep 1
|
||
|
||
echo "==> 安装 LaunchAgent…"
|
||
install_agent "cn.tkmind.memind-portal" "${PORTAL_PLIST}"
|
||
sleep 2
|
||
install_agent "cn.tkmind.plaza" "${PLAZA_PLIST}"
|
||
install_agent "cn.tkmind.g2-lb" "${G2_LB_PLIST}"
|
||
|
||
if [[ -f "${CF_PLIST}" ]]; then
|
||
install_agent "com.cloudflare.cloudflared" "${CF_PLIST}"
|
||
else
|
||
echo "⚠ 未找到 ${CF_PLIST},请确认 cloudflared LaunchAgent 已配置" >&2
|
||
fi
|
||
|
||
echo "==> 等待服务就绪…"
|
||
for _ in $(seq 1 60); do
|
||
portal_ok=0
|
||
plaza_ok=0
|
||
g2_ok=0
|
||
curl -sf "http://127.0.0.1:8081/api/status" >/dev/null 2>&1 && portal_ok=1
|
||
curl -sf "http://127.0.0.1:3001/plaza" >/dev/null 2>&1 && plaza_ok=1
|
||
curl -sf "http://127.0.0.1:8090/api/status" >/dev/null 2>&1 && g2_ok=1
|
||
if [[ "${portal_ok}" -eq 1 && "${plaza_ok}" -eq 1 && "${g2_ok}" -eq 1 ]]; then
|
||
break
|
||
fi
|
||
sleep 2
|
||
done
|
||
|
||
echo ""
|
||
echo "=== 生产服务状态 ==="
|
||
launchctl list | grep -E "cn.tkmind\.(memind-portal|plaza|g2-lb)|com.cloudflare.cloudflared" || true
|
||
curl -s -o /dev/null -w "Portal :8081 → %{http_code}\n" "http://127.0.0.1:8081/api/status" || true
|
||
curl -s -o /dev/null -w "g2 LB :8090 → %{http_code}\n" "http://127.0.0.1:8090/api/status" || true
|
||
curl -s -o /dev/null -w "Plaza :3001 → %{http_code}\n" "http://127.0.0.1:3001/plaza" || true
|
||
curl -s -o /dev/null -w "外网 m → %{http_code}\n" "https://m.tkmind.cn/api/status" || true
|
||
curl -s -o /dev/null -w "外网 plaza → %{http_code}\n" "https://plaza.tkmind.cn/plaza" || true
|
||
|
||
echo ""
|
||
echo "✅ 生产 LaunchAgent 已安装(登录自启 + KeepAlive)"
|
||
echo " Portal cn.tkmind.memind-portal → ~/Library/Logs/memind-portal.log"
|
||
echo " Plaza cn.tkmind.plaza → ~/Library/Logs/plaza-prod.log"
|
||
echo " g2 LB cn.tkmind.g2-lb → ~/Library/Logs/g2-lb.log"
|
||
echo " 隧道 com.cloudflare.cloudflared"
|
||
echo ""
|
||
echo "管理命令:"
|
||
echo " launchctl kickstart -k ${GUI}/cn.tkmind.memind-portal"
|
||
echo " launchctl kickstart -k ${GUI}/cn.tkmind.plaza"
|
||
echo " tail -f ~/Library/Logs/memind-portal.log ~/Library/Logs/plaza-prod.log"
|