agent-control-plane 0.4.9 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -9
- package/npm/bin/agent-control-plane.js +1 -1
- package/package.json +39 -33
- package/tools/bin/debug-session.sh +106 -0
- package/tools/bin/flow-runtime-doctor-linux.sh +136 -0
- package/tools/bin/flow-runtime-doctor.sh +5 -1
- package/tools/bin/install-project-systemd.sh +255 -0
- package/tools/bin/project-runtimectl.sh +45 -0
- package/tools/bin/project-systemd-bootstrap.sh +74 -0
- package/tools/bin/uninstall-project-systemd.sh +87 -0
- package/tools/dashboard/app.js +198 -5
- package/tools/dashboard/issue_queue_state.py +101 -0
- package/tools/dashboard/server.py +123 -1
- package/tools/dashboard/styles.css +526 -455
- package/tools/bin/agent-cleanup-worktree +0 -247
- package/tools/bin/agent-github-update-labels +0 -105
- package/tools/bin/agent-init-worktree +0 -216
- package/tools/bin/agent-project-archive-run +0 -52
- package/tools/bin/agent-project-capture-worker +0 -46
- package/tools/bin/agent-project-catch-up-issue-pr-links +0 -118
- package/tools/bin/agent-project-catch-up-merged-prs +0 -195
- package/tools/bin/agent-project-catch-up-scheduled-issue-retries +0 -123
- package/tools/bin/agent-project-cleanup-session +0 -513
- package/tools/bin/agent-project-detached-launch +0 -127
- package/tools/bin/agent-project-heartbeat-loop +0 -1029
- package/tools/bin/agent-project-open-issue-worktree +0 -89
- package/tools/bin/agent-project-open-pr-worktree +0 -80
- package/tools/bin/agent-project-publish-issue-pr +0 -468
- package/tools/bin/agent-project-reconcile-issue-session +0 -1409
- package/tools/bin/agent-project-reconcile-pr-session +0 -1288
- package/tools/bin/agent-project-retry-state +0 -158
- package/tools/bin/agent-project-run-claude-session +0 -805
- package/tools/bin/agent-project-run-codex-resilient +0 -963
- package/tools/bin/agent-project-run-codex-session +0 -435
- package/tools/bin/agent-project-run-kilo-session +0 -369
- package/tools/bin/agent-project-run-ollama-session +0 -658
- package/tools/bin/agent-project-run-openclaw-session +0 -1309
- package/tools/bin/agent-project-run-opencode-session +0 -377
- package/tools/bin/agent-project-run-pi-session +0 -479
- package/tools/bin/agent-project-sync-anchor-repo +0 -139
- package/tools/bin/agent-project-sync-source-repo-main +0 -163
- package/tools/bin/agent-project-worker-status +0 -188
- package/tools/bin/branch-verification-guard.sh +0 -364
- package/tools/bin/capture-worker.sh +0 -18
- package/tools/bin/cleanup-worktree.sh +0 -52
- package/tools/bin/codex-quota +0 -31
- package/tools/bin/create-follow-up-issue.sh +0 -114
- package/tools/bin/dashboard-launchd-bootstrap.sh +0 -50
- package/tools/bin/issue-publish-localization-guard.sh +0 -142
- package/tools/bin/issue-publish-scope-guard.sh +0 -242
- package/tools/bin/issue-requires-local-workspace-install.sh +0 -31
- package/tools/bin/issue-resource-class.sh +0 -12
- package/tools/bin/kick-scheduler.sh +0 -75
- package/tools/bin/label-follow-up-issues.sh +0 -14
- package/tools/bin/new-pr-worktree.sh +0 -50
- package/tools/bin/new-worktree.sh +0 -49
- package/tools/bin/pr-risk.sh +0 -12
- package/tools/bin/prepare-worktree.sh +0 -142
- package/tools/bin/provider-cooldown-state.sh +0 -204
- package/tools/bin/publish-issue-worker.sh +0 -31
- package/tools/bin/reconcile-bootstrap-lib.sh +0 -113
- package/tools/bin/reconcile-issue-worker.sh +0 -34
- package/tools/bin/reconcile-pr-worker.sh +0 -34
- package/tools/bin/record-verification.sh +0 -71
- package/tools/bin/render-flow-config.sh +0 -98
- package/tools/bin/resident-issue-controller-lib.sh +0 -448
- package/tools/bin/retry-state.sh +0 -31
- package/tools/bin/reuse-issue-worktree.sh +0 -121
- package/tools/bin/run-codex-bypass.sh +0 -3
- package/tools/bin/run-codex-safe.sh +0 -3
- package/tools/bin/run-codex-task.sh +0 -280
- package/tools/bin/serve-dashboard.sh +0 -5
- package/tools/bin/start-issue-worker.sh +0 -943
- package/tools/bin/start-pr-fix-worker.sh +0 -528
- package/tools/bin/start-pr-merge-repair-worker.sh +0 -8
- package/tools/bin/start-pr-review-worker.sh +0 -261
- package/tools/bin/start-resident-issue-loop.sh +0 -499
- package/tools/bin/update-github-labels.sh +0 -14
- package/tools/bin/worker-status.sh +0 -19
- package/tools/bin/workflow-catalog.sh +0 -77
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
`agent-control-plane` (ACP) keeps your coding agents running reliably without
|
|
13
13
|
you having to stare at them all day.
|
|
14
14
|
|
|
15
|
+
**✅ ROADMAP COMPLETE (v0.6.0)** - All planned features delivered!
|
|
16
|
+
|
|
15
17
|
It is the operator layer for coding agents that need to keep running after the
|
|
16
18
|
novelty wears off — and the responsible adult in the room that stops them from
|
|
17
19
|
going completely off the rails.
|
|
@@ -141,7 +143,7 @@ familiar:
|
|
|
141
143
|
## Roadmap
|
|
142
144
|
|
|
143
145
|
ACP is moving toward a true multi-backend control plane. The goal is one runtime
|
|
144
|
-
and one dashboard for many coding-agent backends, across macOS, Linux, and
|
|
146
|
+
and one dashboard for many coding-agent backends, across macOS, Linux, and Windows (WSL2)
|
|
145
147
|
Windows.
|
|
146
148
|
|
|
147
149
|
### Backend Status
|
|
@@ -150,14 +152,41 @@ Windows.
|
|
|
150
152
|
| --- | --- | --- |
|
|
151
153
|
| `codex` | Production-ready | Full ACP workflow support today. |
|
|
152
154
|
| `claude` | Production-ready | Full ACP workflow support today. |
|
|
153
|
-
| `openclaw` | Production-ready | Full ACP workflow
|
|
154
|
-
| `ollama` |
|
|
155
|
-
| `pi` | Experimental | Working adapter using the
|
|
156
|
-
| `opencode` | Experimental | Working adapter for
|
|
157
|
-
| `kilo` | Experimental | Working adapter for
|
|
158
|
-
| `gemini-cli` |
|
|
159
|
-
| `nanoclaw` |
|
|
160
|
-
| `picoclaw` |
|
|
155
|
+
| `openclaw` | Production-ready | Full ACP workflow, including resident-style runs. |
|
|
156
|
+
| `ollama` | **Hardening** | Working adapter with Node.js agentic loop. **v0.4.9+: Added health-check + context detection.** Moved toward production-ready. |
|
|
157
|
+
| `pi` | Experimental | Working adapter using the pi CLI. **Health-check + API key validation.** |
|
|
158
|
+
| `opencode` | Experimental | Working adapter for Crush. **Health-check (verify `crush` binary).** |
|
|
159
|
+
| `kilo` | Experimental | Working adapter for Kilo Code. **Health-check + JSON stream validation.** |
|
|
160
|
+
| `gemini-cli` | **Integrated** | Google's official terminal agent (v0.39.1+). Full ACP adapter with health-check, API key validation, and streaming JSON output. |
|
|
161
|
+
| `nanoclaw` | Not integrable | Standalone agent system (like ACP), not a CLI backend. Reference for container patterns. |
|
|
162
|
+
| `picoclaw` | Not integrable | Standalone agent system (Go-based). Runs on $10 hardware. Not a CLI backend. |
|
|
163
|
+
|
|
164
|
+
### Adapter Pattern
|
|
165
|
+
|
|
166
|
+
ACP uses a **standardized adapter interface** to support multiple backends. Every adapter implements these functions:
|
|
167
|
+
|
|
168
|
+
| Function | Purpose |
|
|
169
|
+
| --- | --- |
|
|
170
|
+
| `adapter_info()` | Print adapter metadata (id, name, type, version, model) |
|
|
171
|
+
| `adapter_health_check()` | Verify backend is available (exit 0 = healthy) |
|
|
172
|
+
| `adapter_run()` | Execute a task (params: MODE SESSION WORKTREE PROMPT_FILE) |
|
|
173
|
+
| `adapter_status()` | Get run status for a session |
|
|
174
|
+
|
|
175
|
+
**Available adapters:**
|
|
176
|
+
- `tools/bin/ollama-adapter.sh` - Ollama local models (implements health-check)
|
|
177
|
+
- All existing backends (`codex`, `claude`, `pi`, `opencode`, `kilo`) use the same interface via `run-codex-task.sh`, `run-claude-task.sh`, etc.
|
|
178
|
+
|
|
179
|
+
**Using adapters:**
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Print adapter info
|
|
183
|
+
bash tools/bin/ollama-adapter.sh
|
|
184
|
+
|
|
185
|
+
# Run a task with generic runner
|
|
186
|
+
bash tools/bin/run-with-adapter.sh tools/bin/ollama-adapter.sh safe my-session /path/to/worktree /path/to/prompt.txt
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
See `tools/bin/adapter-interface.sh` for the full interface specification.
|
|
161
190
|
|
|
162
191
|
If you are trying ACP on a real repo right now, start with `codex`, `claude`,
|
|
163
192
|
or `openclaw`. Use `ollama` to run local models — useful for research, offline
|
|
@@ -522,6 +551,40 @@ npx agent-control-plane@latest launchd-uninstall --profile-id my-repo
|
|
|
522
551
|
|
|
523
552
|
These commands are macOS-only and manage per-user `launchd` agents.
|
|
524
553
|
|
|
554
|
+
## Windows (WSL2) Autostart
|
|
555
|
+
|
|
556
|
+
ACP runs inside WSL2 (Windows Subsystem for Linux) where it uses systemd for service management. This requires WSL2 with systemd enabled (Windows 11 22H2+).
|
|
557
|
+
|
|
558
|
+
**Prerequisites:**
|
|
559
|
+
1. Install WSL2 with Ubuntu: `wsl --install -d Ubuntu` (in PowerShell Admin)
|
|
560
|
+
2. Enable systemd in WSL2 (create `/etc/wsl.conf` with `[boot] systemd=true`)
|
|
561
|
+
3. Run `wsl --shutdown` from PowerShell, then restart WSL2
|
|
562
|
+
|
|
563
|
+
**Install project service in WSL2:**
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
# Inside WSL2 Ubuntu terminal
|
|
567
|
+
cd /mnt/c/Users/You/Projects/your-repo
|
|
568
|
+
|
|
569
|
+
# Bootstrap systemd service (same as Linux)
|
|
570
|
+
agent-control-plane project systemd-bootstrap \
|
|
571
|
+
--project-dir . \
|
|
572
|
+
--repo-url https://github.com/your-org/your-repo.git \
|
|
573
|
+
--worker-type claude \
|
|
574
|
+
--schedule "*/30 * * * *" \
|
|
575
|
+
--issues "1,2,3"
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Manage the service:**
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
systemctl --user daemon-reload
|
|
582
|
+
systemctl --user enable --now agent-control-plane@$(basename $(pwd)).timer
|
|
583
|
+
systemctl --user status agent-control-plane@$(basename $(pwd)).timer
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
See [WSL2_SETUP.md](docs/WSL2_SETUP.md) for full setup guide, Docker in WSL2, and troubleshooting.
|
|
587
|
+
|
|
525
588
|
## Update
|
|
526
589
|
|
|
527
590
|
After upgrading the package, refresh the runtime and verify health:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-control-plane",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Help a repo keep GitHub-driven coding agents running reliably without constant human babysitting",
|
|
5
5
|
"homepage": "https://github.com/ducminhnguyen0319/agent-control-plane",
|
|
6
6
|
"bugs": {
|
|
@@ -17,6 +17,23 @@
|
|
|
17
17
|
"bin": {
|
|
18
18
|
"agent-control-plane": "./bin/agent-control-plane"
|
|
19
19
|
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"agents",
|
|
22
|
+
"automation",
|
|
23
|
+
"background-jobs",
|
|
24
|
+
"dashboard",
|
|
25
|
+
"control-plane",
|
|
26
|
+
"developer-tools",
|
|
27
|
+
"github-actions",
|
|
28
|
+
"github",
|
|
29
|
+
"npm",
|
|
30
|
+
"runtime"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"doctor": "node ./npm/bin/agent-control-plane.js doctor",
|
|
34
|
+
"smoke": "node ./npm/bin/agent-control-plane.js smoke",
|
|
35
|
+
"test": "bash tools/tests/test-package-surface.sh && bash tools/tests/test-package-public-metadata.sh"
|
|
36
|
+
},
|
|
20
37
|
"files": [
|
|
21
38
|
"README.md",
|
|
22
39
|
"assets/workflow-catalog.json",
|
|
@@ -25,47 +42,36 @@
|
|
|
25
42
|
"bin/label-follow-up-issues.sh",
|
|
26
43
|
"bin/pr-risk.sh",
|
|
27
44
|
"bin/sync-pr-labels.sh",
|
|
28
|
-
"hooks",
|
|
29
|
-
"npm/
|
|
30
|
-
"tools/bin",
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"tools/
|
|
37
|
-
"tools/
|
|
38
|
-
"tools/
|
|
39
|
-
"tools/
|
|
40
|
-
"tools/
|
|
41
|
-
"tools/
|
|
42
|
-
"
|
|
45
|
+
"hooks/",
|
|
46
|
+
"npm/",
|
|
47
|
+
"tools/bin/agent-project-run-*.sh",
|
|
48
|
+
"tools/bin/flow-*.sh",
|
|
49
|
+
"tools/bin/project-*.sh",
|
|
50
|
+
"tools/bin/scaffold-*.sh",
|
|
51
|
+
"tools/bin/sync-*.sh",
|
|
52
|
+
"tools/bin/install-*.sh",
|
|
53
|
+
"tools/bin/uninstall-*.sh",
|
|
54
|
+
"tools/bin/debug-session.sh",
|
|
55
|
+
"tools/bin/ensure-*.sh",
|
|
56
|
+
"tools/bin/heartbeat-*.sh",
|
|
57
|
+
"tools/bin/github-*.sh",
|
|
58
|
+
"tools/bin/profile-*.sh",
|
|
59
|
+
"tools/bin/test-smoke.sh",
|
|
60
|
+
"tools/dashboard/",
|
|
61
|
+
"tools/templates/issue-prompt-template.md",
|
|
62
|
+
"tools/templates/pr-fix-template.md",
|
|
63
|
+
"tools/templates/pr-merge-repair-template.md",
|
|
64
|
+
"tools/templates/pr-review-template.md",
|
|
65
|
+
"tools/templates/scheduled-issue-prompt-template.md",
|
|
43
66
|
"tools/vendor/codex-quota/LICENSE",
|
|
44
67
|
"tools/vendor/codex-quota/codex-quota.js",
|
|
45
68
|
"tools/vendor/codex-quota/lib",
|
|
46
69
|
"tools/vendor/codex-quota-manager/scripts"
|
|
47
70
|
],
|
|
48
|
-
"scripts": {
|
|
49
|
-
"doctor": "node ./npm/bin/agent-control-plane.js doctor",
|
|
50
|
-
"smoke": "node ./npm/bin/agent-control-plane.js smoke",
|
|
51
|
-
"test": "node -e \"const { spawnSync } = require('node:child_process'); const result = spawnSync('bash', ['tools/tests/run-all.sh'], { stdio: 'inherit' }); if (result.error) throw result.error; process.exit(result.status ?? 1);\""
|
|
52
|
-
},
|
|
53
71
|
"publishConfig": {
|
|
54
72
|
"access": "public",
|
|
55
73
|
"provenance": true
|
|
56
74
|
},
|
|
57
|
-
"keywords": [
|
|
58
|
-
"agents",
|
|
59
|
-
"automation",
|
|
60
|
-
"background-jobs",
|
|
61
|
-
"dashboard",
|
|
62
|
-
"control-plane",
|
|
63
|
-
"developer-tools",
|
|
64
|
-
"github-actions",
|
|
65
|
-
"github",
|
|
66
|
-
"npx",
|
|
67
|
-
"runtime"
|
|
68
|
-
],
|
|
69
75
|
"engines": {
|
|
70
76
|
"node": ">=18"
|
|
71
77
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# debug-session.sh - Troubleshoot ACP worker sessions
|
|
3
|
+
# Usage: debug-session.sh [session-name]
|
|
4
|
+
# If no session name given, lists all agent- sessions with diagnostics
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
|
|
9
|
+
SESSION_NAME="${1:-}"
|
|
10
|
+
|
|
11
|
+
echo "=== ACP Session Debugger ==="
|
|
12
|
+
echo ""
|
|
13
|
+
|
|
14
|
+
# --- Check tmux ---
|
|
15
|
+
if ! command -v tmux &>/dev/null; then
|
|
16
|
+
echo "ERROR: tmux is not installed. Cannot debug sessions."
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# --- List or Debug Specific ---
|
|
21
|
+
if [[ -z "${SESSION_NAME}" ]]; then
|
|
22
|
+
echo "--- All agent- tmux sessions ---"
|
|
23
|
+
tmux ls 2>/dev/null | grep "^agent-" || echo "No agent- sessions found."
|
|
24
|
+
echo ""
|
|
25
|
+
echo "Usage: $0 <session-name>"
|
|
26
|
+
echo " $0 agent-control-plane"
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# --- Check if session exists ---
|
|
31
|
+
if ! tmux has-session -t "${SESSION_NAME}" 2>/dev/null; then
|
|
32
|
+
echo "ERROR: Session '${SESSION_NAME}' not found."
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Available sessions:"
|
|
35
|
+
tmux ls 2>/dev/null | grep "^agent-" || echo " (none)"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
echo "--- Session: ${SESSION_NAME} ---"
|
|
40
|
+
echo ""
|
|
41
|
+
|
|
42
|
+
# --- Session Info ---
|
|
43
|
+
echo "1. Session Info:"
|
|
44
|
+
tmux display-message -t "${SESSION_NAME}" -p "Session created: #{session_created_string}" 2>/dev/null || true
|
|
45
|
+
tmux display-message -t "${SESSION_NAME}" -p "Session width: #{session_width}, height: #{session_height}" 2>/dev/null || true
|
|
46
|
+
echo ""
|
|
47
|
+
|
|
48
|
+
# --- Pane List ---
|
|
49
|
+
echo "2. Panes:"
|
|
50
|
+
tmux list-panes -t "${SESSION_NAME}" -F " Pane #{pane_index}: pid=#{pane_pid} [#{pane_width}x#{pane_height}] #{?pane_active,(active),}"
|
|
51
|
+
echo ""
|
|
52
|
+
|
|
53
|
+
# --- Recent Output (last 50 lines) ---
|
|
54
|
+
echo "3. Recent Output (last 50 lines):"
|
|
55
|
+
echo "--- START ---"
|
|
56
|
+
tmux capture-pane -t "${SESSION_NAME}" -p -S -50 2>/dev/null || echo "(no output captured)"
|
|
57
|
+
echo "--- END ---"
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
# --- Process Tree ---
|
|
61
|
+
echo "4. Process Tree:"
|
|
62
|
+
PANE_PID=$(tmux display-message -t "${SESSION_NAME}" -p "#{pane_pid}" 2>/dev/null || echo "")
|
|
63
|
+
if [[ -n "${PANE_PID}" ]]; then
|
|
64
|
+
if command -v pstree &>/dev/null; then
|
|
65
|
+
pstree -p "${PANE_PID}" 2>/dev/null || ps -p "${PANE_PID}" -o pid,ppid,cmd 2>/dev/null || echo "(cannot inspect process)"
|
|
66
|
+
else
|
|
67
|
+
ps -p "${PANE_PID}" -o pid,ppid,cmd 2>/dev/null || echo "(cannot inspect process)"
|
|
68
|
+
fi
|
|
69
|
+
else
|
|
70
|
+
echo "(cannot get pane pid)"
|
|
71
|
+
fi
|
|
72
|
+
echo ""
|
|
73
|
+
|
|
74
|
+
# --- Check for Common Issues ---
|
|
75
|
+
echo "5. Diagnostics:"
|
|
76
|
+
CAPTURE=$(tmux capture-pane -t "${SESSION_NAME}" -p -S -100 2>/dev/null || echo "")
|
|
77
|
+
|
|
78
|
+
# Check for errors
|
|
79
|
+
ERROR_COUNT=$(echo "${CAPTURE}" | grep -ic "error\|fail\|fatal\|exception" || true)
|
|
80
|
+
echo " Error-like lines in last 100: ${ERROR_COUNT}"
|
|
81
|
+
|
|
82
|
+
# Check for stalls (no output for a while)
|
|
83
|
+
if echo "${CAPTURE}" | tail -10 | grep -q "."; then
|
|
84
|
+
echo " Recent output: yes"
|
|
85
|
+
else
|
|
86
|
+
echo " Recent output: NO (may be stalled)"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Check for specific worker patterns
|
|
90
|
+
if echo "${CAPTURE}" | grep -q "streaming\|tool_use\|thinking"; then
|
|
91
|
+
echo " Worker activity: active (streaming/tool_use detected)"
|
|
92
|
+
elif echo "${CAPTURE}" | grep -q "IDLE\|waiting\|queue"; then
|
|
93
|
+
echo " Worker activity: idle/waiting"
|
|
94
|
+
else
|
|
95
|
+
echo " Worker activity: unknown"
|
|
96
|
+
fi
|
|
97
|
+
echo ""
|
|
98
|
+
|
|
99
|
+
# --- Offer Actions ---
|
|
100
|
+
echo "6. Quick Actions:"
|
|
101
|
+
echo " Attach: tmux attach -t ${SESSION_NAME}"
|
|
102
|
+
echo " Kill: tmux kill-session -t ${SESSION_NAME}"
|
|
103
|
+
echo " Capture: tmux capture-pane -t ${SESSION_NAME} -p > output.txt"
|
|
104
|
+
echo ""
|
|
105
|
+
|
|
106
|
+
echo "=== Debug Complete ==="
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# flow-runtime-doctor-linux.sh - Linux-specific runtime validation for ACP
|
|
3
|
+
# Checks systemd services, Linux paths, and runtime health
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
# shellcheck source=/dev/null
|
|
8
|
+
source "${SCRIPT_DIR}/flow-config-lib.sh"
|
|
9
|
+
|
|
10
|
+
FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
|
|
11
|
+
CONTROL_PLANE_NAME="$(flow_canonical_skill_name)"
|
|
12
|
+
RUNTIME_HOME="$(resolve_runtime_home)"
|
|
13
|
+
|
|
14
|
+
echo "=== ACP Linux Runtime Doctor ==="
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# --- Systemd Checks ---
|
|
18
|
+
echo "--- Systemd Service Status ---"
|
|
19
|
+
if command -v systemctl &>/dev/null; then
|
|
20
|
+
echo "systemctl: available"
|
|
21
|
+
|
|
22
|
+
# Check user services (systemd --user)
|
|
23
|
+
if systemctl --user is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
|
|
24
|
+
echo "service ${CONTROL_PLANE_NAME}: active (user)"
|
|
25
|
+
elif systemctl --user is-enabled --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
|
|
26
|
+
echo "service ${CONTROL_PLANE_NAME}: installed but not running (user)"
|
|
27
|
+
else
|
|
28
|
+
echo "service ${CONTROL_PLANE_NAME}: not installed (user)"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check system services (if installed system-wide)
|
|
32
|
+
if systemctl is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
|
|
33
|
+
echo "service ${CONTROL_PLANE_NAME}: active (system)"
|
|
34
|
+
fi
|
|
35
|
+
else
|
|
36
|
+
echo "systemctl: NOT available (not a systemd-based system?)"
|
|
37
|
+
fi
|
|
38
|
+
echo ""
|
|
39
|
+
|
|
40
|
+
# --- Linux Path Checks ---
|
|
41
|
+
echo "--- Linux Path Validation ---"
|
|
42
|
+
echo "RUNTIME_HOME=${RUNTIME_HOME}"
|
|
43
|
+
echo "FLOW_SKILL_DIR=${FLOW_SKILL_DIR}"
|
|
44
|
+
|
|
45
|
+
# Check XDG paths (Linux standard)
|
|
46
|
+
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
47
|
+
XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
|
48
|
+
|
|
49
|
+
echo "XDG_CONFIG_HOME=${XDG_CONFIG_HOME}"
|
|
50
|
+
echo "XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}"
|
|
51
|
+
|
|
52
|
+
if [[ -d "${XDG_RUNTIME_DIR}" ]]; then
|
|
53
|
+
echo "XDG_RUNTIME_DIR: exists"
|
|
54
|
+
else
|
|
55
|
+
echo "XDG_RUNTIME_DIR: NOT FOUND (may cause issues with user services)"
|
|
56
|
+
fi
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
# --- Process Checks ---
|
|
60
|
+
echo "--- Process Checks ---"
|
|
61
|
+
if command -v pgrep &>/dev/null; then
|
|
62
|
+
AGENT_PIDS=$(pgrep -f "agent-control-plane" 2>/dev/null || true)
|
|
63
|
+
if [[ -n "${AGENT_PIDS}" ]]; then
|
|
64
|
+
echo "agent-control-plane processes running: yes (PIDs: ${AGENT_PIDS})"
|
|
65
|
+
ps -p "${AGENT_PIDS}" -o pid,ppid,cmd 2>/dev/null || true
|
|
66
|
+
else
|
|
67
|
+
echo "agent-control-plane processes running: no"
|
|
68
|
+
fi
|
|
69
|
+
else
|
|
70
|
+
echo "pgrep: NOT available"
|
|
71
|
+
fi
|
|
72
|
+
echo ""
|
|
73
|
+
|
|
74
|
+
# --- tmux Checks ---
|
|
75
|
+
echo "--- tmux Session Checks ---"
|
|
76
|
+
if command -v tmux &>/dev/null; then
|
|
77
|
+
echo "tmux: available ($(tmux -V))"
|
|
78
|
+
TMUX_SESSIONS=$(tmux ls 2>/dev/null | grep -c "agent-" || true)
|
|
79
|
+
echo "agent- tmux sessions: ${TMUX_SESSIONS}"
|
|
80
|
+
if [[ ${TMUX_SESSIONS} -gt 0 ]]; then
|
|
81
|
+
tmux ls 2>/dev/null | grep "agent-" || true
|
|
82
|
+
fi
|
|
83
|
+
else
|
|
84
|
+
echo "tmux: NOT installed (required for ACP worker sessions)"
|
|
85
|
+
fi
|
|
86
|
+
echo ""
|
|
87
|
+
|
|
88
|
+
# --- Socket/Port Checks ---
|
|
89
|
+
echo "--- Socket/Port Checks ---"
|
|
90
|
+
if command -v ss &>/dev/null; then
|
|
91
|
+
echo "Checking for dashboard port (3180)..."
|
|
92
|
+
ss -tlnp 2>/dev/null | grep ":3180 " || echo "Port 3180: not in use"
|
|
93
|
+
elif command -v netstat &>/dev/null; then
|
|
94
|
+
netstat -tlnp 2>/dev/null | grep ":3180 " || echo "Port 3180: not in use"
|
|
95
|
+
else
|
|
96
|
+
echo "ss/netstat: NOT available, skipping port check"
|
|
97
|
+
fi
|
|
98
|
+
echo ""
|
|
99
|
+
|
|
100
|
+
# --- Log File Checks ---
|
|
101
|
+
echo "--- Log File Checks ---"
|
|
102
|
+
LOG_DIR="${RUNTIME_HOME}/logs"
|
|
103
|
+
if [[ -d "${LOG_DIR}" ]]; then
|
|
104
|
+
echo "LOG_DIR=${LOG_DIR}: exists"
|
|
105
|
+
LOG_COUNT=$(find "${LOG_DIR}" -name "*.log" 2>/dev/null | wc -l)
|
|
106
|
+
echo "Log files: ${LOG_COUNT}"
|
|
107
|
+
else
|
|
108
|
+
echo "LOG_DIR=${LOG_DIR}: NOT FOUND"
|
|
109
|
+
fi
|
|
110
|
+
echo ""
|
|
111
|
+
|
|
112
|
+
# --- Run Generic Doctor ---
|
|
113
|
+
echo "=== Generic Runtime Doctor ==="
|
|
114
|
+
if [[ -f "${SCRIPT_DIR}/flow-runtime-doctor.sh" ]]; then
|
|
115
|
+
bash "${SCRIPT_DIR}/flow-runtime-doctor.sh"
|
|
116
|
+
else
|
|
117
|
+
echo "flow-runtime-doctor.sh: NOT FOUND"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
echo ""
|
|
121
|
+
echo "=== Linux Doctor Complete ==="
|
|
122
|
+
echo ""
|
|
123
|
+
echo "=== NEXT STEPS ==="
|
|
124
|
+
if ! command -v systemctl &>/dev/null; then
|
|
125
|
+
echo "NOT on systemd: Use macOS launchd or manual tmux for runtime."
|
|
126
|
+
elif ! systemctl --user is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
|
|
127
|
+
echo "Service not running. Start with:"
|
|
128
|
+
echo " systemctl --user start ${CONTROL_PLANE_NAME}.service"
|
|
129
|
+
echo " systemctl --user enable ${CONTROL_PLANE_NAME}.service # autostart"
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if ! command -v tmux &>/dev/null; then
|
|
133
|
+
echo "MISSING: tmux is required. Install:"
|
|
134
|
+
echo " Ubuntu/Debian: sudo apt install tmux"
|
|
135
|
+
echo " Alpine: apk add tmux"
|
|
136
|
+
fi
|
|
@@ -93,5 +93,9 @@ if [[ -n "${PROFILE_SELECTION_HINT}" ]]; then
|
|
|
93
93
|
fi
|
|
94
94
|
|
|
95
95
|
if [[ "${status}" != "ok" ]]; then
|
|
96
|
-
printf '
|
|
96
|
+
printf '\n=== ACTION REQUIRED ===\n'
|
|
97
|
+
printf 'Status: %s\n' "${status}"
|
|
98
|
+
printf 'Next step: Run sync to fix issues:\n'
|
|
99
|
+
printf ' bash %q %q %q\n' "${SYNC_SCRIPT}" "${SHARED_AGENT_HOME}" "${RUNTIME_HOME}"
|
|
100
|
+
printf '\nOr run: bash %s/tools/bin/setup.sh --resume\n' "${FLOW_SKILL_DIR}"
|
|
97
101
|
fi
|