@geekbeer/minion 2.16.5 → 2.23.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/.env.example +2 -2
- package/README.md +1 -1
- package/api.js +1 -1
- package/config.js +17 -3
- package/docs/api-reference.md +1 -1
- package/docs/task-guides.md +7 -7
- package/lib/llm-checker.js +49 -6
- package/minion-cli.sh +42 -11
- package/package.json +1 -1
- package/roles/pm.md +1 -1
- package/routes/auth.js +9 -409
- package/routes/chat.js +77 -16
- package/routes/config.js +252 -0
- package/routes/health.js +2 -1
- package/routes/index.js +7 -1
- package/routes/skills.js +22 -6
- package/routine-runner.js +6 -2
- package/rules/core.md +2 -2
- package/skills/execution-report/SKILL.md +1 -1
- package/workflow-runner.js +14 -5
package/.env.example
CHANGED
|
@@ -15,8 +15,8 @@ API_TOKEN=
|
|
|
15
15
|
# Minion ID (optional) - The minion's UUID assigned by HQ
|
|
16
16
|
MINION_ID=
|
|
17
17
|
|
|
18
|
-
# Agent port (optional, default:
|
|
19
|
-
AGENT_PORT=
|
|
18
|
+
# Agent port (optional, default: 8080)
|
|
19
|
+
AGENT_PORT=8080
|
|
20
20
|
|
|
21
21
|
# Heartbeat interval in seconds (optional, default: 30)
|
|
22
22
|
HEARTBEAT_INTERVAL=30
|
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ await reportIssue({
|
|
|
57
57
|
| `HQ_URL` | Minion HQ server URL | - |
|
|
58
58
|
| `API_TOKEN` | Authentication token | - |
|
|
59
59
|
| `MINION_ID` | Minion UUID | - |
|
|
60
|
-
| `AGENT_PORT` | Agent API listen port | `
|
|
60
|
+
| `AGENT_PORT` | Agent API listen port | `8080` |
|
|
61
61
|
| `HEARTBEAT_INTERVAL` | Heartbeat interval (ms) | `30000` |
|
|
62
62
|
|
|
63
63
|
## License
|
package/api.js
CHANGED
|
@@ -53,7 +53,7 @@ async function reportExecution(data) {
|
|
|
53
53
|
/**
|
|
54
54
|
* Report a single workflow step completion to HQ.
|
|
55
55
|
* Called by the post-execution hook after a dispatched skill finishes.
|
|
56
|
-
* @param {object} data - { workflow_execution_id, step_index, status }
|
|
56
|
+
* @param {object} data - { workflow_execution_id, step_index, status, output_summary? }
|
|
57
57
|
*/
|
|
58
58
|
async function reportStepComplete(data) {
|
|
59
59
|
return request('/step-complete', {
|
package/config.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* (no HQ communication).
|
|
11
11
|
*
|
|
12
12
|
* Other optional environment variables:
|
|
13
|
-
* - AGENT_PORT: Port for the local agent server (default:
|
|
13
|
+
* - AGENT_PORT: Port for the local agent server (default: 8080)
|
|
14
14
|
* - MINION_USER: System user running the agent (used to resolve home directory)
|
|
15
15
|
*/
|
|
16
16
|
|
|
@@ -44,10 +44,17 @@ const config = {
|
|
|
44
44
|
MINION_ID: process.env.MINION_ID || '',
|
|
45
45
|
|
|
46
46
|
// Server settings
|
|
47
|
-
AGENT_PORT: parseInt(process.env.AGENT_PORT, 10) ||
|
|
47
|
+
AGENT_PORT: parseInt(process.env.AGENT_PORT, 10) || 8080,
|
|
48
48
|
|
|
49
49
|
// Resolved home directory (safe for supervisord environments)
|
|
50
50
|
HOME_DIR: resolveHomeDir(),
|
|
51
|
+
|
|
52
|
+
// LLM command template (user-configured)
|
|
53
|
+
// Use {prompt} as placeholder for the prompt text.
|
|
54
|
+
// Examples:
|
|
55
|
+
// LLM_COMMAND="claude -p '{prompt}'"
|
|
56
|
+
// LLM_COMMAND="gemini-cli --prompt '{prompt}'"
|
|
57
|
+
LLM_COMMAND: process.env.LLM_COMMAND || '',
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
/**
|
|
@@ -68,4 +75,11 @@ function validate() {
|
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Check if LLM command is configured
|
|
80
|
+
*/
|
|
81
|
+
function isLlmConfigured() {
|
|
82
|
+
return !!config.LLM_COMMAND
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { config, validate, isHqConfigured, isLlmConfigured }
|
package/docs/api-reference.md
CHANGED
package/docs/task-guides.md
CHANGED
|
@@ -87,11 +87,11 @@ curl -s -X POST "$HQ_URL/api/minion/workflows" \
|
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
# HQからワークフローを取得 (不足スキルも自動fetch)
|
|
90
|
-
curl -s -X POST "http://localhost:
|
|
90
|
+
curl -s -X POST "http://localhost:8080/api/workflows/fetch/<name>" \
|
|
91
91
|
-H "Authorization: Bearer $API_TOKEN"
|
|
92
92
|
|
|
93
93
|
# ローカルワークフローをHQにpush (スキルも自動push)
|
|
94
|
-
curl -s -X POST "http://localhost:
|
|
94
|
+
curl -s -X POST "http://localhost:8080/api/workflows/push/<name>" \
|
|
95
95
|
-H "Authorization: Bearer $API_TOKEN"
|
|
96
96
|
```
|
|
97
97
|
|
|
@@ -128,18 +128,18 @@ curl -s -X PUT "$HQ_URL/api/minion/me/project/<project-id>/context" \
|
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
130
|
# 最近の実行一覧
|
|
131
|
-
curl -s "http://localhost:
|
|
131
|
+
curl -s "http://localhost:8080/api/executions?limit=10" \
|
|
132
132
|
-H "Authorization: Bearer $API_TOKEN"
|
|
133
133
|
|
|
134
134
|
# 特定の実行ログ
|
|
135
|
-
curl -s "http://localhost:
|
|
135
|
+
curl -s "http://localhost:8080/api/executions/<id>/log" \
|
|
136
136
|
-H "Authorization: Bearer $API_TOKEN"
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
### 実行結果の報告
|
|
140
140
|
|
|
141
141
|
```bash
|
|
142
|
-
curl -s -X POST "http://localhost:
|
|
142
|
+
curl -s -X POST "http://localhost:8080/api/executions/<id>/outcome" \
|
|
143
143
|
-H "Content-Type: application/json" \
|
|
144
144
|
-d '{
|
|
145
145
|
"outcome": "success",
|
|
@@ -199,11 +199,11 @@ minion-cli skill fetch <name>
|
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
# ローカルワークフロー一覧 (next_run を確認)
|
|
202
|
-
curl -s "http://localhost:
|
|
202
|
+
curl -s "http://localhost:8080/api/workflows" \
|
|
203
203
|
-H "Authorization: Bearer $API_TOKEN"
|
|
204
204
|
|
|
205
205
|
# 手動トリガー
|
|
206
|
-
curl -s -X POST "http://localhost:
|
|
206
|
+
curl -s -X POST "http://localhost:8080/api/workflows/trigger" \
|
|
207
207
|
-H "Authorization: Bearer $API_TOKEN" \
|
|
208
208
|
-H "Content-Type: application/json" \
|
|
209
209
|
-d '{ "workflow_id": "<workflow-uuid>" }'
|
package/lib/llm-checker.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* LLM Service authentication checker
|
|
3
3
|
*
|
|
4
4
|
* Detects whether supported LLM CLIs are authenticated and ready to use.
|
|
5
|
-
*
|
|
5
|
+
* Also checks whether LLM_COMMAND is configured for workflow/routine execution.
|
|
6
6
|
* Results are cached in memory for 60 seconds to avoid excessive filesystem checks.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const fs = require('fs')
|
|
10
10
|
const path = require('path')
|
|
11
|
+
const { execSync } = require('child_process')
|
|
11
12
|
const { config } = require('../config')
|
|
12
13
|
|
|
13
14
|
const CACHE_TTL_MS = 60000
|
|
@@ -15,11 +16,28 @@ const CACHE_TTL_MS = 60000
|
|
|
15
16
|
let cachedResult = null
|
|
16
17
|
let cachedAt = 0
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Build extended PATH that includes common Claude CLI installation locations
|
|
21
|
+
*/
|
|
22
|
+
function getExtendedPath() {
|
|
23
|
+
const additionalPaths = [
|
|
24
|
+
path.join(config.HOME_DIR, '.local', 'bin'),
|
|
25
|
+
path.join(config.HOME_DIR, 'bin'),
|
|
26
|
+
path.join(config.HOME_DIR, '.npm-global', 'bin'),
|
|
27
|
+
path.join(config.HOME_DIR, '.claude', 'bin'),
|
|
28
|
+
'/usr/local/bin',
|
|
29
|
+
]
|
|
30
|
+
return [...additionalPaths, process.env.PATH || '/usr/bin:/bin'].join(':')
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
/**
|
|
19
34
|
* Check Claude Code authentication.
|
|
20
|
-
*
|
|
35
|
+
* First checks known credential file locations (fast path),
|
|
36
|
+
* then falls back to `claude auth whoami` CLI command for newer CLI versions
|
|
37
|
+
* that may store credentials differently.
|
|
21
38
|
*/
|
|
22
39
|
function isClaudeAuthenticated() {
|
|
40
|
+
// Fast path: check known credential file locations
|
|
23
41
|
const candidates = [
|
|
24
42
|
path.join(config.HOME_DIR, '.claude', '.credentials.json'),
|
|
25
43
|
path.join(config.HOME_DIR, '.claude', 'credentials.json'),
|
|
@@ -35,7 +53,24 @@ function isClaudeAuthenticated() {
|
|
|
35
53
|
// Invalid JSON or read error — not authenticated
|
|
36
54
|
}
|
|
37
55
|
}
|
|
38
|
-
|
|
56
|
+
|
|
57
|
+
// Fallback: check via claude CLI command (handles newer credential storage)
|
|
58
|
+
try {
|
|
59
|
+
const claudePath = path.join(config.HOME_DIR, '.local', 'bin', 'claude')
|
|
60
|
+
const claudeBin = fs.existsSync(claudePath) ? claudePath : 'claude'
|
|
61
|
+
execSync(`${claudeBin} auth whoami`, {
|
|
62
|
+
encoding: 'utf-8',
|
|
63
|
+
timeout: 5000,
|
|
64
|
+
stdio: 'pipe',
|
|
65
|
+
env: {
|
|
66
|
+
HOME: config.HOME_DIR,
|
|
67
|
+
PATH: getExtendedPath(),
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
return true
|
|
71
|
+
} catch {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
39
74
|
}
|
|
40
75
|
|
|
41
76
|
/**
|
|
@@ -89,10 +124,18 @@ const SERVICE_DEFINITIONS = [
|
|
|
89
124
|
{ name: 'codex', display_name: 'Codex', check: isCodexAuthenticated },
|
|
90
125
|
]
|
|
91
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Check if LLM_COMMAND is configured for workflow/routine execution.
|
|
129
|
+
*/
|
|
130
|
+
function isLlmCommandConfigured() {
|
|
131
|
+
return !!config.LLM_COMMAND
|
|
132
|
+
}
|
|
133
|
+
|
|
92
134
|
/**
|
|
93
135
|
* Get authenticated LLM services (cached for 60s).
|
|
94
|
-
* Returns all services with their authentication status
|
|
95
|
-
*
|
|
136
|
+
* Returns all services with their authentication status,
|
|
137
|
+
* plus whether LLM_COMMAND is configured.
|
|
138
|
+
* @returns {{ services: { name: string, display_name: string, authenticated: boolean }[], llm_command_configured: boolean }}
|
|
96
139
|
*/
|
|
97
140
|
function getLlmServices() {
|
|
98
141
|
const now = Date.now()
|
|
@@ -117,4 +160,4 @@ function clearLlmCache() {
|
|
|
117
160
|
cachedAt = 0
|
|
118
161
|
}
|
|
119
162
|
|
|
120
|
-
module.exports = { getLlmServices, clearLlmCache }
|
|
163
|
+
module.exports = { getLlmServices, clearLlmCache, isLlmCommandConfigured }
|
package/minion-cli.sh
CHANGED
|
@@ -86,7 +86,7 @@ svc_control() {
|
|
|
86
86
|
esac
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
AGENT_URL="${MINION_AGENT_URL:-http://localhost:
|
|
89
|
+
AGENT_URL="${MINION_AGENT_URL:-http://localhost:8080}"
|
|
90
90
|
|
|
91
91
|
# Auto-load .env so that API_TOKEN etc. are available in interactive shells
|
|
92
92
|
ENV_FILE="/opt/minion-agent/.env"
|
|
@@ -279,11 +279,12 @@ do_setup() {
|
|
|
279
279
|
ENV_CONTENT+="MINION_ID=${MINION_ID}\n"
|
|
280
280
|
fi
|
|
281
281
|
|
|
282
|
-
ENV_CONTENT+="AGENT_PORT=
|
|
282
|
+
ENV_CONTENT+="AGENT_PORT=8080\n"
|
|
283
283
|
ENV_CONTENT+="HEARTBEAT_INTERVAL=30\n"
|
|
284
284
|
ENV_CONTENT+="MINION_USER=${TARGET_USER}\n"
|
|
285
285
|
|
|
286
286
|
echo -e "$ENV_CONTENT" | $SUDO tee /opt/minion-agent/.env > /dev/null
|
|
287
|
+
$SUDO chown "${TARGET_USER}:${TARGET_USER}" /opt/minion-agent/.env
|
|
287
288
|
echo " -> /opt/minion-agent/.env generated"
|
|
288
289
|
|
|
289
290
|
# Step 5: Configure sudoers for agent user
|
|
@@ -581,7 +582,7 @@ SUPEOF
|
|
|
581
582
|
local SUCCESS=false
|
|
582
583
|
|
|
583
584
|
for i in $(seq 1 $RETRIES); do
|
|
584
|
-
if curl -sf http://localhost:
|
|
585
|
+
if curl -sf http://localhost:8080/api/health > /dev/null 2>&1; then
|
|
585
586
|
SUCCESS=true
|
|
586
587
|
break
|
|
587
588
|
fi
|
|
@@ -649,10 +650,12 @@ SUPEOF
|
|
|
649
650
|
exit 1
|
|
650
651
|
fi
|
|
651
652
|
|
|
652
|
-
# Install cloudflared if not present
|
|
653
|
+
# Install cloudflared if not present (architecture-aware)
|
|
653
654
|
if ! command -v cloudflared &>/dev/null; then
|
|
654
655
|
echo " Installing cloudflared..."
|
|
655
|
-
|
|
656
|
+
local CF_ARCH
|
|
657
|
+
CF_ARCH=$(dpkg --print-architecture 2>/dev/null || echo "amd64")
|
|
658
|
+
curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${CF_ARCH}.deb" \
|
|
656
659
|
-o /tmp/cloudflared.deb
|
|
657
660
|
$SUDO dpkg -i /tmp/cloudflared.deb
|
|
658
661
|
rm -f /tmp/cloudflared.deb
|
|
@@ -688,10 +691,36 @@ SUPEOF
|
|
|
688
691
|
echo "$CONFIG_YML" | $SUDO tee /etc/cloudflared/config.yml > /dev/null
|
|
689
692
|
echo " -> /etc/cloudflared/config.yml saved"
|
|
690
693
|
|
|
691
|
-
# Install and start cloudflared service
|
|
692
|
-
$
|
|
693
|
-
|
|
694
|
-
|
|
694
|
+
# Install and start cloudflared service (process-manager aware)
|
|
695
|
+
case "$PROC_MGR" in
|
|
696
|
+
systemd)
|
|
697
|
+
$SUDO cloudflared service install 2>/dev/null || true
|
|
698
|
+
$SUDO systemctl enable cloudflared 2>/dev/null || true
|
|
699
|
+
$SUDO systemctl start cloudflared 2>/dev/null || true
|
|
700
|
+
;;
|
|
701
|
+
supervisord)
|
|
702
|
+
# Create supervisord config for cloudflared
|
|
703
|
+
$SUDO tee /etc/supervisor/conf.d/cloudflared.conf > /dev/null <<CFEOF
|
|
704
|
+
[program:cloudflared]
|
|
705
|
+
command=/usr/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run
|
|
706
|
+
autorestart=true
|
|
707
|
+
priority=150
|
|
708
|
+
startsecs=5
|
|
709
|
+
stdout_logfile=/var/log/supervisor/cloudflared.log
|
|
710
|
+
stderr_logfile=/var/log/supervisor/cloudflared.log
|
|
711
|
+
CFEOF
|
|
712
|
+
# Reload supervisord if running
|
|
713
|
+
if $SUDO supervisorctl status &>/dev/null; then
|
|
714
|
+
$SUDO supervisorctl reread
|
|
715
|
+
$SUDO supervisorctl update
|
|
716
|
+
fi
|
|
717
|
+
;;
|
|
718
|
+
*)
|
|
719
|
+
echo " WARNING: No supported process manager for cloudflared"
|
|
720
|
+
echo " You may need to start cloudflared manually:"
|
|
721
|
+
echo " cloudflared tunnel --config /etc/cloudflared/config.yml run"
|
|
722
|
+
;;
|
|
723
|
+
esac
|
|
695
724
|
echo " -> cloudflared tunnel configured and started"
|
|
696
725
|
fi
|
|
697
726
|
fi
|
|
@@ -701,10 +730,12 @@ SUPEOF
|
|
|
701
730
|
echo ""
|
|
702
731
|
echo "Notifying HQ of setup completion..."
|
|
703
732
|
local NOTIFY_RESPONSE
|
|
733
|
+
local HOSTNAME_VAL
|
|
734
|
+
HOSTNAME_VAL=$(hostname 2>/dev/null || echo "")
|
|
704
735
|
NOTIFY_RESPONSE=$(curl -sfL -X POST "${HQ_URL}/api/minion/setup-complete" \
|
|
705
736
|
-H "Content-Type: application/json" \
|
|
706
737
|
-H "Authorization: Bearer ${API_TOKEN}" \
|
|
707
|
-
-d "{}" 2>&1) || true
|
|
738
|
+
-d "{\"internal_ip_address\":\"${HOSTNAME_VAL}\"}" 2>&1) || true
|
|
708
739
|
|
|
709
740
|
if echo "$NOTIFY_RESPONSE" | grep -q '"success":true' 2>/dev/null; then
|
|
710
741
|
echo " -> HQ notified successfully"
|
|
@@ -854,6 +885,6 @@ case "${1:-}" in
|
|
|
854
885
|
echo "Status values: online, offline, busy"
|
|
855
886
|
echo ""
|
|
856
887
|
echo "Environment:"
|
|
857
|
-
echo " MINION_AGENT_URL Agent URL (default: http://localhost:
|
|
888
|
+
echo " MINION_AGENT_URL Agent URL (default: http://localhost:8080)"
|
|
858
889
|
;;
|
|
859
890
|
esac
|
package/package.json
CHANGED
package/roles/pm.md
CHANGED