summaryrefslogtreecommitdiff
path: root/execute_commands.sh
blob: 8093ad8792d49f9adb2e187c871aa9c8ba629670 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/bin/bash
# 轮询 broker 命令队列,执行系统级命令(切换项目、重启等)
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    set -a; source "$SCRIPT_DIR/.env"; set +a
fi
export BROKER_URL API_SECRET

AUTH="Authorization: Bearer $API_SECRET"
CLAUDE_MD_SRC="$SCRIPT_DIR/CLAUDE.md"

# 拉取待执行命令
DATA=$(curl -sf -H "$AUTH" "$BROKER_URL/commands/pending" 2>/dev/null) || exit 0

echo "$DATA" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for cmd in d.get('commands', []):
    params = json.loads(cmd['params']) if isinstance(cmd['params'], str) else cmd['params']
    print(cmd['id'] + '\t' + cmd['target'] + '\t' + cmd['action'] + '\t' + json.dumps(params))
" 2>/dev/null | while IFS=$'\t' read -r CMD_ID TARGET ACTION PARAMS; do

    echo "$(date): Executing command $CMD_ID: $ACTION on $TARGET"

    # 只执行属于本机的命令(target 在 .sessions 里,或者 create_worker 的 host 匹配)
    if [ "$ACTION" = "create_worker" ]; then
        CMD_HOST=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('host',''))" 2>/dev/null)
        MY_HOST=$(hostname)
        if [ -n "$CMD_HOST" ] && [ "$CMD_HOST" != "$MY_HOST" ]; then
            echo "$(date): Skipping $CMD_ID - host $CMD_HOST != $MY_HOST"
            continue
        fi
    else
        if ! grep -q "^${TARGET}$(printf '\t')" "$SCRIPT_DIR/.sessions" 2>/dev/null; then
            echo "$(date): Skipping $CMD_ID - $TARGET not in local .sessions"
            continue
        fi
    fi

    # 检查 tmux session 存在
    # create_worker 不需要 session 已存在
    if [ "$ACTION" != "create_worker" ]; then
        if ! tmux has-session -t "$TARGET" 2>/dev/null; then
            curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
                -d "{\"result\": \"ERROR: tmux session $TARGET not found\"}" \
                "$BROKER_URL/commands/$CMD_ID/done" >/dev/null 2>&1
            continue
        fi
    fi

    case "$ACTION" in
        switch_project)
            DIR=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('directory',''))")
            if [ -z "$DIR" ]; then
                curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
                    -d '{"result": "ERROR: no directory specified"}' \
                    "$BROKER_URL/commands/$CMD_ID/done" >/dev/null 2>&1
                continue
            fi

            # 创建目录(如果不存在)
            mkdir -p "$DIR"

            # 复制 CLAUDE.md
            cp "$CLAUDE_MD_SRC" "$DIR/CLAUDE.md" 2>/dev/null || true

            # /exit 当前 claude
            tmux send-keys -t "$TARGET" "/exit" Enter
            sleep 5

            # cd 到新目录
            tmux send-keys -t "$TARGET" "cd $DIR" Enter
            sleep 1

            # 启动 claude --continue
            tmux send-keys -t "$TARGET" "claude --continue" Enter
            sleep 3

            RESULT="OK: $TARGET switched to $DIR"
            ;;

        restart)
            # /exit 当前 claude
            tmux send-keys -t "$TARGET" "/exit" Enter
            sleep 5

            # claude --continue(在同一目录)
            tmux send-keys -t "$TARGET" "claude --continue" Enter
            sleep 3

            RESULT="OK: $TARGET restarted"
            ;;

        create_worker)
            SESSION_NAME=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('session_name',''))")
            DIR=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('path',''))")
            SLACK_CH=$(echo "$PARAMS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('slack_channel',''))")
            if [ -z "$SESSION_NAME" ] || [ -z "$DIR" ]; then
                RESULT="ERROR: missing session_name or path"
            elif tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
                RESULT="OK: session $SESSION_NAME already exists"
            else
                # 用交互式脚本创建,自动处理弹窗
                RESULT=$(bash "$SCRIPT_DIR/create_worker.sh" "$SESSION_NAME" "$DIR" "$BROKER_URL" "$API_SECRET" "$SLACK_CH" 2>&1 | tail -1)
            fi
            ;;

        stop)
            tmux send-keys -t "$TARGET" "/exit" Enter
            sleep 3
            tmux kill-session -t "$TARGET" 2>/dev/null || true
            # 从 .sessions 移除
            grep -v "^${TARGET}$(printf '\t')" "$SCRIPT_DIR/.sessions" > "${SCRIPT_DIR}/.sessions.tmp" 2>/dev/null || true
            mv "${SCRIPT_DIR}/.sessions.tmp" "$SCRIPT_DIR/.sessions"
            RESULT="OK: $TARGET stopped and removed"
            ;;

        *)
            RESULT="ERROR: unknown action $ACTION"
            ;;
    esac

    # 汇报完成
    python3 -c "
import json, urllib.request
req = urllib.request.Request(
    '$BROKER_URL/commands/$CMD_ID/done',
    data=json.dumps({'result': '$RESULT'}).encode(),
    headers={'Authorization': 'Bearer $API_SECRET', 'Content-Type': 'application/json'},
    method='POST',
)
urllib.request.urlopen(req, timeout=10)
" 2>/dev/null || true

    echo "$(date): Command $CMD_ID done: $RESULT"
done