@geekbeer/minion 1.0.3 → 1.0.5
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/api.js +0 -16
- package/config.js +1 -5
- package/package.json +2 -3
- package/server.js +17 -31
- package/heartbeat.js +0 -91
package/api.js
CHANGED
|
@@ -37,21 +37,6 @@ async function request(endpoint, options = {}) {
|
|
|
37
37
|
return data
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
/**
|
|
41
|
-
* Send heartbeat with status update
|
|
42
|
-
* @param {string} status - 'online' | 'offline' | 'busy'
|
|
43
|
-
* @param {string|null} currentTask - Current task description
|
|
44
|
-
*/
|
|
45
|
-
async function sendHeartbeat(status, currentTask = null) {
|
|
46
|
-
return request('/heartbeat', {
|
|
47
|
-
method: 'POST',
|
|
48
|
-
body: JSON.stringify({
|
|
49
|
-
status,
|
|
50
|
-
current_task: currentTask,
|
|
51
|
-
}),
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
40
|
/**
|
|
56
41
|
* Send a log entry
|
|
57
42
|
* @param {string} message - Log message
|
|
@@ -71,6 +56,5 @@ async function log(message, level = 'info', metadata = null) {
|
|
|
71
56
|
|
|
72
57
|
module.exports = {
|
|
73
58
|
request,
|
|
74
|
-
sendHeartbeat,
|
|
75
59
|
log,
|
|
76
60
|
}
|
package/config.js
CHANGED
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
* - MINION_ID: The minion's UUID (assigned by HQ)
|
|
8
8
|
*
|
|
9
9
|
* If HQ_URL and API_TOKEN are not set, the agent runs in standalone mode
|
|
10
|
-
* (no
|
|
10
|
+
* (no HQ communication).
|
|
11
11
|
*
|
|
12
12
|
* Other optional environment variables:
|
|
13
13
|
* - AGENT_PORT: Port for the local agent server (default: 3001)
|
|
14
|
-
* - HEARTBEAT_INTERVAL: Interval between heartbeats in seconds (default: 30)
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
const config = {
|
|
@@ -22,9 +21,6 @@ const config = {
|
|
|
22
21
|
|
|
23
22
|
// Server settings
|
|
24
23
|
AGENT_PORT: parseInt(process.env.AGENT_PORT, 10) || 3001,
|
|
25
|
-
|
|
26
|
-
// Heartbeat interval in seconds
|
|
27
|
-
HEARTBEAT_INTERVAL: parseInt(process.env.HEARTBEAT_INTERVAL, 10) || 30,
|
|
28
24
|
}
|
|
29
25
|
|
|
30
26
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekbeer/minion",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "AI Agent runtime for Minion - manages
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "AI Agent runtime for Minion - manages status and skill deployment on VPS",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"minion-cli": "./minion-cli.sh"
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"server.js",
|
|
11
11
|
"config.js",
|
|
12
|
-
"heartbeat.js",
|
|
13
12
|
"api.js",
|
|
14
13
|
"minion-cli.sh",
|
|
15
14
|
".env.example"
|
package/server.js
CHANGED
|
@@ -12,9 +12,12 @@ const execAsync = promisify(exec)
|
|
|
12
12
|
|
|
13
13
|
const fastify = require('fastify')({ logger: true })
|
|
14
14
|
const { config, validate, isHqConfigured } = require('./config')
|
|
15
|
-
const heartbeat = require('./heartbeat')
|
|
16
15
|
const api = require('./api')
|
|
17
16
|
|
|
17
|
+
// In-memory status (read by health check via GET /api/status)
|
|
18
|
+
let currentStatus = 'online'
|
|
19
|
+
let currentTask = null
|
|
20
|
+
|
|
18
21
|
// Detect process manager (matching minion-cli.sh logic)
|
|
19
22
|
function detectProcessManager() {
|
|
20
23
|
try {
|
|
@@ -124,8 +127,8 @@ fastify.get('/api/health', async () => {
|
|
|
124
127
|
// Get current status
|
|
125
128
|
fastify.get('/api/status', async () => {
|
|
126
129
|
return {
|
|
127
|
-
status:
|
|
128
|
-
current_task:
|
|
130
|
+
status: currentStatus,
|
|
131
|
+
current_task: currentTask,
|
|
129
132
|
uptime: process.uptime(),
|
|
130
133
|
timestamp: new Date().toISOString(),
|
|
131
134
|
}
|
|
@@ -135,23 +138,19 @@ fastify.get('/api/status', async () => {
|
|
|
135
138
|
fastify.post('/api/status', async (request, reply) => {
|
|
136
139
|
const { status, current_task } = request.body || {}
|
|
137
140
|
|
|
138
|
-
|
|
139
|
-
if (status) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (current_task !== undefined) {
|
|
144
|
-
heartbeat.setTask(current_task)
|
|
141
|
+
if (status) {
|
|
142
|
+
if (!['online', 'offline', 'busy'].includes(status)) {
|
|
143
|
+
reply.code(400)
|
|
144
|
+
return { success: false, error: `Invalid status: ${status}` }
|
|
145
145
|
}
|
|
146
|
+
currentStatus = status
|
|
147
|
+
}
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return { success: true }
|
|
151
|
-
} catch (error) {
|
|
152
|
-
reply.code(400)
|
|
153
|
-
return { success: false, error: error.message }
|
|
149
|
+
if (current_task !== undefined) {
|
|
150
|
+
currentTask = current_task || null
|
|
154
151
|
}
|
|
152
|
+
|
|
153
|
+
return { success: true }
|
|
155
154
|
})
|
|
156
155
|
|
|
157
156
|
// Send log entry
|
|
@@ -455,17 +454,7 @@ ${content}`
|
|
|
455
454
|
async function shutdown(signal) {
|
|
456
455
|
console.log(`[Server] Received ${signal}, shutting down...`)
|
|
457
456
|
|
|
458
|
-
|
|
459
|
-
if (isHqConfigured()) {
|
|
460
|
-
heartbeat.setStatus('offline')
|
|
461
|
-
try {
|
|
462
|
-
await heartbeat.sendHeartbeat()
|
|
463
|
-
console.log('[Server] Status set to offline')
|
|
464
|
-
} catch (error) {
|
|
465
|
-
console.error(`[Server] Failed to update status: ${error.message}`)
|
|
466
|
-
}
|
|
467
|
-
heartbeat.stop()
|
|
468
|
-
}
|
|
457
|
+
currentStatus = 'offline'
|
|
469
458
|
|
|
470
459
|
// Close server
|
|
471
460
|
await fastify.close()
|
|
@@ -544,9 +533,6 @@ async function start() {
|
|
|
544
533
|
if (isHqConfigured()) {
|
|
545
534
|
console.log(`[Server] HQ URL: ${config.HQ_URL}`)
|
|
546
535
|
|
|
547
|
-
// Start heartbeat
|
|
548
|
-
heartbeat.start()
|
|
549
|
-
|
|
550
536
|
// Sync VNC password from HQ (non-blocking, run in background)
|
|
551
537
|
syncVncPassword().catch(err => {
|
|
552
538
|
console.error('[VNC] Background sync failed:', err.message)
|
package/heartbeat.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Heartbeat Manager for Minion Agent
|
|
3
|
-
* Sends periodic heartbeats to the API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { config } = require('./config')
|
|
7
|
-
const api = require('./api')
|
|
8
|
-
|
|
9
|
-
// Current state
|
|
10
|
-
let currentStatus = 'online'
|
|
11
|
-
let currentTask = null
|
|
12
|
-
let intervalId = null
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Start the heartbeat loop
|
|
16
|
-
*/
|
|
17
|
-
function start() {
|
|
18
|
-
console.log(`[Heartbeat] Starting with interval: ${config.HEARTBEAT_INTERVAL}s`)
|
|
19
|
-
|
|
20
|
-
// Send initial heartbeat
|
|
21
|
-
sendHeartbeat()
|
|
22
|
-
|
|
23
|
-
// Schedule periodic heartbeats
|
|
24
|
-
intervalId = setInterval(sendHeartbeat, config.HEARTBEAT_INTERVAL * 1000)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Stop the heartbeat loop
|
|
29
|
-
*/
|
|
30
|
-
function stop() {
|
|
31
|
-
if (intervalId) {
|
|
32
|
-
clearInterval(intervalId)
|
|
33
|
-
intervalId = null
|
|
34
|
-
console.log('[Heartbeat] Stopped')
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Send a heartbeat to the API
|
|
40
|
-
*/
|
|
41
|
-
async function sendHeartbeat() {
|
|
42
|
-
try {
|
|
43
|
-
await api.sendHeartbeat(currentStatus, currentTask)
|
|
44
|
-
console.log(`[Heartbeat] Sent: status=${currentStatus}, task=${currentTask || 'none'}`)
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.error(`[Heartbeat] Failed: ${error.message}`)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Set the current status
|
|
52
|
-
* @param {'online'|'offline'|'busy'} status
|
|
53
|
-
*/
|
|
54
|
-
function setStatus(status) {
|
|
55
|
-
if (!['online', 'offline', 'busy'].includes(status)) {
|
|
56
|
-
throw new Error(`Invalid status: ${status}`)
|
|
57
|
-
}
|
|
58
|
-
currentStatus = status
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Set the current task
|
|
63
|
-
* @param {string|null} task
|
|
64
|
-
*/
|
|
65
|
-
function setTask(task) {
|
|
66
|
-
currentTask = task || null
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Get the current status
|
|
71
|
-
*/
|
|
72
|
-
function getStatus() {
|
|
73
|
-
return currentStatus
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Get the current task
|
|
78
|
-
*/
|
|
79
|
-
function getTask() {
|
|
80
|
-
return currentTask
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
module.exports = {
|
|
84
|
-
start,
|
|
85
|
-
stop,
|
|
86
|
-
sendHeartbeat,
|
|
87
|
-
setStatus,
|
|
88
|
-
setTask,
|
|
89
|
-
getStatus,
|
|
90
|
-
getTask,
|
|
91
|
-
}
|