Add agent command execution (terminal panel)
- DB: new agent_commands table (id, agent_id, command, status, output, exit_code, timestamps)
- Server: 4 new routes
POST /api/agents/:id/commands queue a command (dashboard → agent)
GET /api/agents/:id/commands history (last 50) for dashboard
GET /api/agents/commands/pending agent dequeues + marks running (Bearer auth)
POST /api/agents/commands/:id/result agent posts output/exit_code (Bearer auth)
Output capped at 128 KB; Bearer token enforced on agent-facing routes
- Agents (Linux/macOS/Windows): each polls /commands/pending each cycle,
executes via bash/PowerShell with 60s timeout, posts result back
- UI: ">_" button on each AgentCard opens CommandTerminal panel
Input line, Run button, history list (status icon + command + time)
Click any entry with output to expand/collapse its output
Auto-refreshes every 4 s while open
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
13b3e3612b
commit
ce4bea5e29
15 files changed
+543
-15
No files matched your search
@@ -255,6 +255,51 @@ report_metrics() {
|
||||
fi
|
||||
}
|
||||
|
||||
poll_commands() {
|
||||
local resp http_code
|
||||
resp=$(curl -sf -m 10 \
|
||||
-H "Authorization: Bearer ${AGENT_TOKEN}" \
|
||||
-w '\n__HTTP_CODE__%{http_code}' \
|
||||
"${SKYWATCH_URL}/api/agents/commands/pending" 2>/dev/null) || return 0
|
||||
|
||||
http_code=$(echo "$resp" | grep -o '__HTTP_CODE__[0-9]*' | tail -1 | grep -o '[0-9]*')
|
||||
resp=$(echo "$resp" | sed '/__HTTP_CODE__/d')
|
||||
|
||||
[ "$http_code" = "204" ] && return 0
|
||||
[ "$http_code" != "200" ] && return 0
|
||||
|
||||
local cmd_id cmd_str
|
||||
cmd_id=$(echo "$resp" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
|
||||
cmd_str=$(echo "$resp" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('command',''))" 2>/dev/null \
|
||||
|| echo "$resp" | sed -n 's/.*"command":"\([^"]*\)".*/\1/p')
|
||||
|
||||
[ -z "$cmd_id" ] || [ -z "$cmd_str" ] && return 0
|
||||
|
||||
log "Running command #${cmd_id}: ${cmd_str}"
|
||||
|
||||
local tmp_out exit_code
|
||||
tmp_out=$(mktemp)
|
||||
gtimeout 60 bash -c "$cmd_str" > "$tmp_out" 2>&1 || timeout 60 bash -c "$cmd_str" > "$tmp_out" 2>&1
|
||||
exit_code=$?
|
||||
|
||||
local tmp_json
|
||||
tmp_json=$(mktemp)
|
||||
python3 - "$tmp_out" "$exit_code" > "$tmp_json" 2>/dev/null << 'PYEOF'
|
||||
import sys, json
|
||||
with open(sys.argv[1]) as f:
|
||||
output = f.read(131072)
|
||||
print(json.dumps({"output": output, "exit_code": int(sys.argv[2])}))
|
||||
PYEOF
|
||||
|
||||
curl -sf -m 15 -X POST \
|
||||
-H "Authorization: Bearer ${AGENT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "@${tmp_json}" \
|
||||
"${SKYWATCH_URL}/api/agents/commands/${cmd_id}/result" >/dev/null 2>&1 || true
|
||||
|
||||
rm -f "$tmp_out" "$tmp_json"
|
||||
}
|
||||
|
||||
main() {
|
||||
load_config
|
||||
|
||||
@@ -278,6 +323,7 @@ main() {
|
||||
|
||||
while true; do
|
||||
report_metrics
|
||||
poll_commands
|
||||
local sleep_time=$(( interval - 1 ))
|
||||
[ "$sleep_time" -lt 1 ] && sleep_time=1
|
||||
sleep "$sleep_time"
|
||||
|
||||
Reference in new issue
Block a user