@geekbeer/minion 2.44.0 → 2.48.1
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/core/config.js +7 -0
- package/core/lib/capability-checker.js +105 -0
- package/core/lib/end-of-day.js +113 -0
- package/core/lib/reflection-scheduler.js +157 -0
- package/core/lib/step-poller.js +4 -0
- package/core/routes/daily-logs.js +122 -0
- package/core/routes/health.js +2 -0
- package/core/routes/memory.js +112 -0
- package/core/routes/skills.js +2 -1
- package/core/routes/variables.js +131 -0
- package/core/stores/daily-log-store.js +182 -0
- package/core/stores/memory-store.js +256 -0
- package/core/stores/variable-store.js +152 -0
- package/docs/api-reference.md +128 -0
- package/linux/minion-cli.sh +6 -0
- package/linux/routes/chat.js +54 -14
- package/linux/routes/config.js +11 -1
- package/linux/routine-runner.js +7 -0
- package/linux/server.js +19 -5
- package/linux/workflow-runner.js +7 -0
- package/package.json +1 -1
- package/win/lib/process-manager.js +85 -8
- package/win/routes/chat.js +53 -10
- package/win/routes/config.js +12 -1
- package/win/routine-runner.js +4 -0
- package/win/server.js +16 -4
- package/win/workflow-runner.js +4 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const { execSync } = require('child_process')
|
|
11
|
+
const fs = require('fs')
|
|
11
12
|
const path = require('path')
|
|
12
13
|
const os = require('os')
|
|
13
14
|
|
|
@@ -18,7 +19,6 @@ const os = require('os')
|
|
|
18
19
|
*/
|
|
19
20
|
function detectProcessManager() {
|
|
20
21
|
// Check for user-process mode (PID file or start-agent.ps1 exists)
|
|
21
|
-
const fs = require('fs')
|
|
22
22
|
const dataDir = path.join(os.homedir(), '.minion')
|
|
23
23
|
const startScript = path.join(dataDir, 'start-agent.ps1')
|
|
24
24
|
if (fs.existsSync(startScript)) {
|
|
@@ -40,6 +40,56 @@ function detectProcessManager() {
|
|
|
40
40
|
return 'user-process'
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Generate a temporary PowerShell script that:
|
|
45
|
+
* 1. Stops the running agent process (releasing file locks)
|
|
46
|
+
* 2. Runs npm install -g
|
|
47
|
+
* 3. Restarts the agent
|
|
48
|
+
*
|
|
49
|
+
* This is necessary because node-pty's conpty.node DLL is locked by the
|
|
50
|
+
* running process, causing EBUSY errors if npm tries to overwrite it in-place.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} npmInstallCmd - The npm install command to run
|
|
53
|
+
* @param {string} stopCmd - Command/script block to stop the agent
|
|
54
|
+
* @param {string} startCmd - Command/script block to start the agent
|
|
55
|
+
* @returns {string} - Shell command that writes and launches the update script
|
|
56
|
+
*/
|
|
57
|
+
function buildUpdateScript(npmInstallCmd, stopCmd, startCmd) {
|
|
58
|
+
const dataDir = path.join(os.homedir(), '.minion')
|
|
59
|
+
const scriptPath = path.join(dataDir, 'update-agent.ps1')
|
|
60
|
+
const logPath = path.join(dataDir, 'update-agent.log')
|
|
61
|
+
|
|
62
|
+
// PowerShell script content: stop → install → start, with logging
|
|
63
|
+
const ps1 = [
|
|
64
|
+
`$ErrorActionPreference = 'Stop'`,
|
|
65
|
+
`$logFile = '${logPath.replace(/\\/g, '\\\\')}'`,
|
|
66
|
+
`function Log($msg) { "$(Get-Date -Format o) $msg" | Out-File -Append $logFile }`,
|
|
67
|
+
`Log 'Update started'`,
|
|
68
|
+
`try {`,
|
|
69
|
+
` Log 'Stopping agent...'`,
|
|
70
|
+
` ${stopCmd}`,
|
|
71
|
+
` Start-Sleep -Seconds 3`,
|
|
72
|
+
` Log 'Installing package...'`,
|
|
73
|
+
` $out = & cmd /c "${npmInstallCmd} 2>&1"`,
|
|
74
|
+
` Log "npm output: $out"`,
|
|
75
|
+
` if ($LASTEXITCODE -ne 0) { throw "npm install failed (exit code $LASTEXITCODE)" }`,
|
|
76
|
+
` Log 'Starting agent...'`,
|
|
77
|
+
` ${startCmd}`,
|
|
78
|
+
` Log 'Update completed successfully'`,
|
|
79
|
+
`} catch {`,
|
|
80
|
+
` Log "Update failed: $_"`,
|
|
81
|
+
` Log 'Attempting to restart agent anyway...'`,
|
|
82
|
+
` ${startCmd}`,
|
|
83
|
+
`}`,
|
|
84
|
+
].join('\n')
|
|
85
|
+
|
|
86
|
+
// Write the script to disk and launch it detached
|
|
87
|
+
try { fs.mkdirSync(dataDir, { recursive: true }) } catch { /* exists */ }
|
|
88
|
+
fs.writeFileSync(scriptPath, ps1, 'utf-8')
|
|
89
|
+
|
|
90
|
+
return `powershell -ExecutionPolicy Bypass -Command "Start-Process powershell -ArgumentList '-ExecutionPolicy Bypass -WindowStyle Hidden -File \\"${scriptPath}\\"' -WindowStyle Hidden"`
|
|
91
|
+
}
|
|
92
|
+
|
|
43
93
|
/**
|
|
44
94
|
* Build allowed commands for the detected process manager.
|
|
45
95
|
* @param {string} procMgr - Process manager type
|
|
@@ -53,19 +103,30 @@ function buildAllowedCommands(procMgr) {
|
|
|
53
103
|
const pidFile = path.join(dataDir, 'minion-agent.pid')
|
|
54
104
|
const startScript = path.join(dataDir, 'start-agent.ps1')
|
|
55
105
|
|
|
106
|
+
const stopBlock = `$pid = Get-Content '${pidFile}' -ErrorAction SilentlyContinue; if ($pid) { Get-CimInstance Win32_Process -Filter \\"ParentProcessId = $pid\\" -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }; Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue }`
|
|
107
|
+
const startBlock = `Start-Process powershell -ArgumentList '-ExecutionPolicy Bypass -WindowStyle Hidden -File \\"${startScript}\\"' -WindowStyle Hidden`
|
|
108
|
+
|
|
56
109
|
commands['restart-agent'] = {
|
|
57
110
|
description: 'Restart the minion agent process',
|
|
58
|
-
command: `powershell -Command "$
|
|
111
|
+
command: `powershell -Command "${stopBlock}; Start-Sleep -Seconds 2; ${startBlock}"`,
|
|
59
112
|
deferred: true,
|
|
60
113
|
}
|
|
61
114
|
commands['update-agent'] = {
|
|
62
115
|
description: 'Update @geekbeer/minion to latest version and restart',
|
|
63
|
-
command:
|
|
116
|
+
command: buildUpdateScript(
|
|
117
|
+
'npm install -g @geekbeer/minion@latest',
|
|
118
|
+
stopBlock,
|
|
119
|
+
startBlock,
|
|
120
|
+
),
|
|
64
121
|
deferred: true,
|
|
65
122
|
}
|
|
66
123
|
commands['update-agent-dev'] = {
|
|
67
124
|
description: 'Update @geekbeer/minion from Verdaccio (dev) and restart',
|
|
68
|
-
command:
|
|
125
|
+
command: buildUpdateScript(
|
|
126
|
+
'npm install -g @geekbeer/minion@latest --registry http://verdaccio:4873',
|
|
127
|
+
stopBlock,
|
|
128
|
+
startBlock,
|
|
129
|
+
),
|
|
69
130
|
deferred: true,
|
|
70
131
|
}
|
|
71
132
|
commands['status-services'] = {
|
|
@@ -80,12 +141,20 @@ function buildAllowedCommands(procMgr) {
|
|
|
80
141
|
}
|
|
81
142
|
commands['update-agent'] = {
|
|
82
143
|
description: 'Update @geekbeer/minion to latest version and restart',
|
|
83
|
-
command:
|
|
144
|
+
command: buildUpdateScript(
|
|
145
|
+
'npm install -g @geekbeer/minion@latest',
|
|
146
|
+
'nssm stop minion-agent',
|
|
147
|
+
'nssm start minion-agent',
|
|
148
|
+
),
|
|
84
149
|
deferred: true,
|
|
85
150
|
}
|
|
86
151
|
commands['update-agent-dev'] = {
|
|
87
152
|
description: 'Update @geekbeer/minion from Verdaccio (dev) and restart',
|
|
88
|
-
command:
|
|
153
|
+
command: buildUpdateScript(
|
|
154
|
+
'npm install -g @geekbeer/minion@latest --registry http://verdaccio:4873',
|
|
155
|
+
'nssm stop minion-agent',
|
|
156
|
+
'nssm start minion-agent',
|
|
157
|
+
),
|
|
89
158
|
deferred: true,
|
|
90
159
|
}
|
|
91
160
|
commands['restart-display'] = {
|
|
@@ -104,12 +173,20 @@ function buildAllowedCommands(procMgr) {
|
|
|
104
173
|
}
|
|
105
174
|
commands['update-agent'] = {
|
|
106
175
|
description: 'Update @geekbeer/minion to latest version and restart',
|
|
107
|
-
command:
|
|
176
|
+
command: buildUpdateScript(
|
|
177
|
+
'npm install -g @geekbeer/minion@latest',
|
|
178
|
+
'net stop minion-agent',
|
|
179
|
+
'net start minion-agent',
|
|
180
|
+
),
|
|
108
181
|
deferred: true,
|
|
109
182
|
}
|
|
110
183
|
commands['update-agent-dev'] = {
|
|
111
184
|
description: 'Update @geekbeer/minion from Verdaccio (dev) and restart',
|
|
112
|
-
command:
|
|
185
|
+
command: buildUpdateScript(
|
|
186
|
+
'npm install -g @geekbeer/minion@latest --registry http://verdaccio:4873',
|
|
187
|
+
'net stop minion-agent',
|
|
188
|
+
'net start minion-agent',
|
|
189
|
+
),
|
|
113
190
|
deferred: true,
|
|
114
191
|
}
|
|
115
192
|
commands['status-services'] = {
|
package/win/routes/chat.js
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* Same as linux/routes/chat.js but with Windows-compatible PATH and shell construction.
|
|
5
5
|
*
|
|
6
6
|
* Endpoints:
|
|
7
|
-
* POST /api/chat
|
|
8
|
-
* GET /api/chat/session
|
|
9
|
-
* POST /api/chat/clear
|
|
10
|
-
* POST /api/chat/abort
|
|
11
|
-
* POST /api/chat/reset
|
|
7
|
+
* POST /api/chat - Send message, get SSE stream
|
|
8
|
+
* GET /api/chat/session - Get active session (messages + session_id)
|
|
9
|
+
* POST /api/chat/clear - Clear session and start fresh
|
|
10
|
+
* POST /api/chat/abort - Kill the active LLM CLI process
|
|
11
|
+
* POST /api/chat/reset - Summarize conversation and start fresh session
|
|
12
|
+
* POST /api/chat/end-of-day - Generate daily log + extract memories from conversation
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
const { spawn } = require('child_process')
|
|
@@ -17,7 +18,10 @@ const path = require('path')
|
|
|
17
18
|
const { verifyToken } = require('../../core/lib/auth')
|
|
18
19
|
const { config } = require('../../core/config')
|
|
19
20
|
const chatStore = require('../../core/stores/chat-store')
|
|
21
|
+
const memoryStore = require('../../core/stores/memory-store')
|
|
22
|
+
const dailyLogStore = require('../../core/stores/daily-log-store')
|
|
20
23
|
const { buildExtendedPath } = require('../../core/lib/platform')
|
|
24
|
+
const { runEndOfDay } = require('../../core/lib/end-of-day')
|
|
21
25
|
|
|
22
26
|
let activeChatChild = null
|
|
23
27
|
|
|
@@ -34,7 +38,7 @@ async function chatRoutes(fastify) {
|
|
|
34
38
|
return { success: false, error: 'message is required' }
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const prompt =
|
|
41
|
+
const prompt = await buildContextPrefix(message, context, session_id)
|
|
38
42
|
const currentSessionId = session_id || null
|
|
39
43
|
|
|
40
44
|
if (currentSessionId) {
|
|
@@ -142,10 +146,45 @@ async function chatRoutes(fastify) {
|
|
|
142
146
|
console.log(`[Chat] session reset with summary (${summary?.length || 0} chars)`)
|
|
143
147
|
return { success: true, summary }
|
|
144
148
|
})
|
|
149
|
+
|
|
150
|
+
// POST /api/chat/end-of-day - Generate daily log + extract memories
|
|
151
|
+
fastify.post('/api/chat/end-of-day', async (request, reply) => {
|
|
152
|
+
if (!verifyToken(request)) {
|
|
153
|
+
reply.code(401)
|
|
154
|
+
return { success: false, error: 'Unauthorized' }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const { clear_session = false } = request.body || {}
|
|
158
|
+
|
|
159
|
+
const result = await runEndOfDay({
|
|
160
|
+
runQuickLlmCall,
|
|
161
|
+
clearSession: clear_session,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
return { success: true, ...result }
|
|
165
|
+
})
|
|
145
166
|
}
|
|
146
167
|
|
|
147
|
-
function buildContextPrefix(message, context) {
|
|
168
|
+
async function buildContextPrefix(message, context, sessionId) {
|
|
148
169
|
const parts = []
|
|
170
|
+
|
|
171
|
+
// Inject memory + daily logs on new sessions only (not on --resume)
|
|
172
|
+
if (!sessionId) {
|
|
173
|
+
try {
|
|
174
|
+
const memorySnippet = await memoryStore.getContextSnippet(2000)
|
|
175
|
+
const dailyLogSnippet = await dailyLogStore.getContextSnippet(3, 1500)
|
|
176
|
+
|
|
177
|
+
if (memorySnippet) {
|
|
178
|
+
parts.push('[ミニオンメモリ(長期記憶)]', memorySnippet, '')
|
|
179
|
+
}
|
|
180
|
+
if (dailyLogSnippet) {
|
|
181
|
+
parts.push('[最近のデイリーログ]', dailyLogSnippet, '')
|
|
182
|
+
}
|
|
183
|
+
} catch (err) {
|
|
184
|
+
console.error('[Chat] Failed to load memory/daily-log context:', err.message)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
149
188
|
if (context) {
|
|
150
189
|
switch (context.type) {
|
|
151
190
|
case 'skill':
|
|
@@ -218,7 +257,8 @@ function streamLlmResponse(res, prompt, sessionId) {
|
|
|
218
257
|
|
|
219
258
|
const args = ['-p', '--verbose', '--model', 'sonnet', '--output-format', 'stream-json']
|
|
220
259
|
if (sessionId) args.push('--resume', sessionId)
|
|
221
|
-
|
|
260
|
+
// Prompt is passed via stdin (not as CLI argument) to avoid
|
|
261
|
+
// shell argument parsing issues with spaces/special characters.
|
|
222
262
|
|
|
223
263
|
console.log(`[Chat] spawning: ${binary} ${sessionId ? `--resume ${sessionId}` : '(new session)'}`)
|
|
224
264
|
|
|
@@ -236,6 +276,8 @@ function streamLlmResponse(res, prompt, sessionId) {
|
|
|
236
276
|
})
|
|
237
277
|
|
|
238
278
|
activeChatChild = child
|
|
279
|
+
// Write prompt to stdin and close — claude -p reads from stdin when no positional arg
|
|
280
|
+
child.stdin.write(prompt)
|
|
239
281
|
child.stdin.end()
|
|
240
282
|
|
|
241
283
|
console.log(`[Chat] child PID: ${child.pid}`)
|
|
@@ -401,7 +443,7 @@ function runQuickLlmCall(prompt) {
|
|
|
401
443
|
const binary = fs.existsSync(binaryPath) ? binaryPath : binaryName
|
|
402
444
|
const extendedPath = buildExtendedPath(config.HOME_DIR)
|
|
403
445
|
|
|
404
|
-
const args = ['-p', '--model', 'haiku', '--max-turns', '1', '--output-format', 'json'
|
|
446
|
+
const args = ['-p', '--model', 'haiku', '--max-turns', '1', '--output-format', 'json']
|
|
405
447
|
|
|
406
448
|
const child = spawn(binary, args, {
|
|
407
449
|
cwd: config.HOME_DIR,
|
|
@@ -416,6 +458,7 @@ function runQuickLlmCall(prompt) {
|
|
|
416
458
|
},
|
|
417
459
|
})
|
|
418
460
|
|
|
461
|
+
child.stdin.write(prompt)
|
|
419
462
|
child.stdin.end()
|
|
420
463
|
|
|
421
464
|
let stdout = ''
|
|
@@ -441,4 +484,4 @@ function runQuickLlmCall(prompt) {
|
|
|
441
484
|
})
|
|
442
485
|
}
|
|
443
486
|
|
|
444
|
-
module.exports = { chatRoutes }
|
|
487
|
+
module.exports = { chatRoutes, runQuickLlmCall }
|
package/win/routes/config.js
CHANGED
|
@@ -13,7 +13,12 @@ const { clearLlmCache } = require('../../core/lib/llm-checker')
|
|
|
13
13
|
const { config, updateConfig } = require('../../core/config')
|
|
14
14
|
const { resolveEnvFilePath } = require('../../core/lib/platform')
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const reflectionScheduler = require('../../core/lib/reflection-scheduler')
|
|
17
|
+
|
|
18
|
+
const ALLOWED_ENV_KEYS = ['LLM_COMMAND', 'REFLECTION_TIME', 'TIMEZONE']
|
|
19
|
+
|
|
20
|
+
/** Keys that trigger a reflection scheduler reschedule when changed */
|
|
21
|
+
const REFLECTION_KEYS = ['REFLECTION_TIME', 'TIMEZONE']
|
|
17
22
|
|
|
18
23
|
const BACKUP_PATHS = [
|
|
19
24
|
'~/.claude',
|
|
@@ -217,6 +222,12 @@ function configRoutes(fastify, _opts, done) {
|
|
|
217
222
|
updateConfig(key, value)
|
|
218
223
|
|
|
219
224
|
clearLlmCache()
|
|
225
|
+
|
|
226
|
+
// Reschedule reflection if relevant key changed
|
|
227
|
+
if (REFLECTION_KEYS.includes(key)) {
|
|
228
|
+
reflectionScheduler.reschedule()
|
|
229
|
+
}
|
|
230
|
+
|
|
220
231
|
return { success: true, restart_required: false }
|
|
221
232
|
} catch (err) {
|
|
222
233
|
console.error(`[Config] Failed to update ${key} in ${envPath}:`, err.message)
|
package/win/routine-runner.js
CHANGED
|
@@ -17,6 +17,7 @@ const executionStore = require('../core/stores/execution-store')
|
|
|
17
17
|
const routineStore = require('../core/stores/routine-store')
|
|
18
18
|
const logManager = require('../core/lib/log-manager')
|
|
19
19
|
const { MARKER_DIR, buildExtendedPath } = require('../core/lib/platform')
|
|
20
|
+
const variableStore = require('../core/stores/variable-store')
|
|
20
21
|
const { activeSessions } = require('./workflow-runner')
|
|
21
22
|
|
|
22
23
|
const activeJobs = new Map()
|
|
@@ -105,8 +106,11 @@ async function executeRoutineSession(routine, executionId, skillNames) {
|
|
|
105
106
|
const escapedPrompt = prompt.replace(/'/g, "''")
|
|
106
107
|
const llmCommand = config.LLM_COMMAND.replace(/\{prompt\}/g, escapedPrompt)
|
|
107
108
|
|
|
109
|
+
// Inject minion variables/secrets (routines don't receive HQ vars)
|
|
110
|
+
const injectedEnv = variableStore.buildEnv()
|
|
108
111
|
const env = {
|
|
109
112
|
...process.env,
|
|
113
|
+
...injectedEnv,
|
|
110
114
|
HOME: homeDir,
|
|
111
115
|
USERPROFILE: homeDir,
|
|
112
116
|
PATH: extendedPath,
|
package/win/server.js
CHANGED
|
@@ -16,6 +16,7 @@ const fastify = require('fastify')({ logger: true })
|
|
|
16
16
|
const { config, validate, isHqConfigured } = require('../core/config')
|
|
17
17
|
const { sendHeartbeat } = require('../core/api')
|
|
18
18
|
const { version } = require('../package.json')
|
|
19
|
+
const { getCapabilities } = require('../core/lib/capability-checker')
|
|
19
20
|
const workflowStore = require('../core/stores/workflow-store')
|
|
20
21
|
const routineStore = require('../core/stores/routine-store')
|
|
21
22
|
|
|
@@ -30,12 +31,13 @@ const routineRunner = require('./routine-runner')
|
|
|
30
31
|
// Pull-model daemons (from core/)
|
|
31
32
|
const stepPoller = require('../core/lib/step-poller')
|
|
32
33
|
const revisionWatcher = require('../core/lib/revision-watcher')
|
|
34
|
+
const reflectionScheduler = require('../core/lib/reflection-scheduler')
|
|
33
35
|
const { commandRoutes, getProcessManager, getAllowedCommands } = require('./routes/commands')
|
|
34
36
|
const { terminalRoutes, cleanupSessions } = require('./routes/terminal')
|
|
35
37
|
const { startTerminalServer, stopTerminalServer } = require('./terminal-server')
|
|
36
38
|
const { fileRoutes } = require('./routes/files')
|
|
37
39
|
const { directiveRoutes } = require('./routes/directives')
|
|
38
|
-
const { chatRoutes } = require('./routes/chat')
|
|
40
|
+
const { chatRoutes, runQuickLlmCall } = require('./routes/chat')
|
|
39
41
|
const { configRoutes } = require('./routes/config')
|
|
40
42
|
|
|
41
43
|
// Compatible route modules (reused from Linux)
|
|
@@ -45,6 +47,9 @@ const { skillRoutes } = require('../core/routes/skills')
|
|
|
45
47
|
const { workflowRoutes } = require('../core/routes/workflows')
|
|
46
48
|
const { routineRoutes } = require('../core/routes/routines')
|
|
47
49
|
const { authRoutes } = require('../core/routes/auth')
|
|
50
|
+
const { variableRoutes } = require('../core/routes/variables')
|
|
51
|
+
const { memoryRoutes } = require('../core/routes/memory')
|
|
52
|
+
const { dailyLogRoutes } = require('../core/routes/daily-logs')
|
|
48
53
|
|
|
49
54
|
// Validate configuration
|
|
50
55
|
validate()
|
|
@@ -69,7 +74,7 @@ async function shutdown(signal) {
|
|
|
69
74
|
if (isHqConfigured()) {
|
|
70
75
|
try {
|
|
71
76
|
await Promise.race([
|
|
72
|
-
sendHeartbeat({ status: 'offline', version }),
|
|
77
|
+
sendHeartbeat({ status: 'offline', version, capabilities: getCapabilities() }),
|
|
73
78
|
new Promise(resolve => setTimeout(resolve, 3000)),
|
|
74
79
|
])
|
|
75
80
|
} catch {
|
|
@@ -79,6 +84,7 @@ async function shutdown(signal) {
|
|
|
79
84
|
|
|
80
85
|
stepPoller.stop()
|
|
81
86
|
revisionWatcher.stop()
|
|
87
|
+
reflectionScheduler.stop()
|
|
82
88
|
workflowRunner.stopAll()
|
|
83
89
|
routineRunner.stopAll()
|
|
84
90
|
stopTerminalServer()
|
|
@@ -192,6 +198,9 @@ async function registerRoutes(app) {
|
|
|
192
198
|
await app.register(workflowRoutes, { workflowRunner })
|
|
193
199
|
await app.register(routineRoutes, { routineRunner })
|
|
194
200
|
await app.register(authRoutes)
|
|
201
|
+
await app.register(variableRoutes)
|
|
202
|
+
await app.register(memoryRoutes)
|
|
203
|
+
await app.register(dailyLogRoutes)
|
|
195
204
|
|
|
196
205
|
// Windows-specific routes
|
|
197
206
|
await app.register(commandRoutes)
|
|
@@ -249,20 +258,23 @@ async function start() {
|
|
|
249
258
|
console.error('[Server] Failed to load cached routines:', err.message)
|
|
250
259
|
}
|
|
251
260
|
|
|
261
|
+
// Start reflection scheduler (self-reflection time)
|
|
262
|
+
reflectionScheduler.start(runQuickLlmCall)
|
|
263
|
+
|
|
252
264
|
if (isHqConfigured()) {
|
|
253
265
|
console.log(`[Server] HQ URL: ${config.HQ_URL}`)
|
|
254
266
|
|
|
255
267
|
// Send initial online heartbeat
|
|
256
268
|
const { getStatus } = require('../core/routes/health')
|
|
257
269
|
const { currentTask } = getStatus()
|
|
258
|
-
sendHeartbeat({ status: 'online', current_task: currentTask, version }).catch(err => {
|
|
270
|
+
sendHeartbeat({ status: 'online', current_task: currentTask, version, capabilities: getCapabilities() }).catch(err => {
|
|
259
271
|
console.error('[Heartbeat] Initial heartbeat failed:', err.message)
|
|
260
272
|
})
|
|
261
273
|
|
|
262
274
|
// Start periodic heartbeat
|
|
263
275
|
heartbeatTimer = setInterval(() => {
|
|
264
276
|
const { currentStatus, currentTask } = getStatus()
|
|
265
|
-
sendHeartbeat({ status: currentStatus, current_task: currentTask, version }).catch(err => {
|
|
277
|
+
sendHeartbeat({ status: currentStatus, current_task: currentTask, version, capabilities: getCapabilities() }).catch(err => {
|
|
266
278
|
console.error('[Heartbeat] Periodic heartbeat failed:', err.message)
|
|
267
279
|
})
|
|
268
280
|
}, HEARTBEAT_INTERVAL_MS)
|
package/win/workflow-runner.js
CHANGED
|
@@ -24,6 +24,7 @@ const executionStore = require('../core/stores/execution-store')
|
|
|
24
24
|
const workflowStore = require('../core/stores/workflow-store')
|
|
25
25
|
const logManager = require('../core/lib/log-manager')
|
|
26
26
|
const { buildExtendedPath } = require('../core/lib/platform')
|
|
27
|
+
const variableStore = require('../core/stores/variable-store')
|
|
27
28
|
|
|
28
29
|
// Active cron jobs keyed by workflow ID
|
|
29
30
|
const activeJobs = new Map()
|
|
@@ -112,9 +113,11 @@ async function executeWorkflowSession(workflow, executionId, skillNames, options
|
|
|
112
113
|
const escapedPrompt = prompt.replace(/'/g, "''")
|
|
113
114
|
const llmCommand = config.LLM_COMMAND.replace(/\{prompt\}/g, escapedPrompt)
|
|
114
115
|
|
|
115
|
-
// Build environment
|
|
116
|
+
// Build environment: base + minion variables/secrets + extra vars from HQ
|
|
117
|
+
const injectedEnv = variableStore.buildEnv(options.extraEnv || {})
|
|
116
118
|
const env = {
|
|
117
119
|
...process.env,
|
|
120
|
+
...injectedEnv,
|
|
118
121
|
HOME: homeDir,
|
|
119
122
|
USERPROFILE: homeDir,
|
|
120
123
|
PATH: extendedPath,
|