@geekbeer/minion 3.40.1 → 3.40.2
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/routes/skills.js +6 -5
- package/docs/api-reference.md +2 -2
- package/linux/routes/directives.js +1 -4
- package/linux/routine-runner.js +40 -7
- package/linux/workflow-runner.js +1 -1
- package/package.json +1 -1
- package/roles/engineer.md +0 -1
- package/win/routes/directives.js +1 -1
- package/win/routine-runner.js +38 -4
package/core/routes/skills.js
CHANGED
|
@@ -49,7 +49,7 @@ function parseFrontmatter(content) {
|
|
|
49
49
|
* written to every enabled plugin's directory so switching Primary doesn't
|
|
50
50
|
* break skill availability.
|
|
51
51
|
*
|
|
52
|
-
* @param {string} name - Skill slug (e.g. "
|
|
52
|
+
* @param {string} name - Skill slug (e.g. "daily-check")
|
|
53
53
|
* @param {object} opts
|
|
54
54
|
* @param {string} opts.content - Skill body (markdown without frontmatter)
|
|
55
55
|
* @param {string} [opts.description] - Skill description for frontmatter
|
|
@@ -103,7 +103,7 @@ async function writeSkillToLocal(name, { content, description, display_name, typ
|
|
|
103
103
|
* Read a local skill and push it to HQ.
|
|
104
104
|
* Reusable by workflow push to auto-sync pipeline skills.
|
|
105
105
|
*
|
|
106
|
-
* @param {string} name - Skill slug (e.g. "
|
|
106
|
+
* @param {string} name - Skill slug (e.g. "daily-check")
|
|
107
107
|
* @param {object} [opts]
|
|
108
108
|
* @param {string} [opts.workspaceId] - Target workspace ID (overrides WORKSPACE_ID env var)
|
|
109
109
|
* @returns {Promise<object>} HQ response
|
|
@@ -391,8 +391,9 @@ async function skillRoutes(fastify, opts) {
|
|
|
391
391
|
log_file: logFile,
|
|
392
392
|
})
|
|
393
393
|
|
|
394
|
-
//
|
|
395
|
-
//
|
|
394
|
+
// For dispatched steps, the post-execution hook reads the outcome record
|
|
395
|
+
// (set by workflow-runner from the CLI exit code via the local outcome API)
|
|
396
|
+
// and forwards the summary to HQ so reviewers can see the step's report.
|
|
396
397
|
const isDispatchedStep = execution_id && step_index != null
|
|
397
398
|
const runOptions = {}
|
|
398
399
|
if (role) runOptions.role = role
|
|
@@ -437,7 +438,7 @@ async function skillRoutes(fastify, opts) {
|
|
|
437
438
|
// Post-execution hook: report step completion to HQ
|
|
438
439
|
if (isDispatchedStep) {
|
|
439
440
|
try {
|
|
440
|
-
// Read
|
|
441
|
+
// Read the outcome record saved by workflow-runner
|
|
441
442
|
let outputSummary = null
|
|
442
443
|
try {
|
|
443
444
|
const execRecord = await executionStore.getById(effectiveExecutionId)
|
package/docs/api-reference.md
CHANGED
|
@@ -867,7 +867,7 @@ push するとパイプライン内のスキル名が `skill_version_id` に解
|
|
|
867
867
|
```json
|
|
868
868
|
{
|
|
869
869
|
"name": "my-workflow",
|
|
870
|
-
"pipeline_skill_names": ["skill-1", "skill-2"
|
|
870
|
+
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
871
871
|
"pipeline": [
|
|
872
872
|
{
|
|
873
873
|
"skill_version_id": "uuid",
|
|
@@ -1748,7 +1748,7 @@ Response:
|
|
|
1748
1748
|
{
|
|
1749
1749
|
"id": "uuid",
|
|
1750
1750
|
"name": "routine-name",
|
|
1751
|
-
"pipeline_skill_names": ["skill-1"
|
|
1751
|
+
"pipeline_skill_names": ["skill-1"],
|
|
1752
1752
|
"content": "...",
|
|
1753
1753
|
"is_active": true,
|
|
1754
1754
|
"cron_expression": "0 9 * * 1-5",
|
|
@@ -112,15 +112,12 @@ async function directiveRoutes(fastify) {
|
|
|
112
112
|
|
|
113
113
|
try {
|
|
114
114
|
// Execute as a single-skill workflow
|
|
115
|
-
// skipExecutionReport: the orchestration template has its own
|
|
116
|
-
// completion report (section 5), so /execution-report is redundant
|
|
117
|
-
// and would use the wrong (local) execution ID.
|
|
118
115
|
const result = await workflowRunner.runWorkflow({
|
|
119
116
|
id: effectiveExecutionId,
|
|
120
117
|
name: workflowName,
|
|
121
118
|
pipeline_skill_names: [skill_name],
|
|
122
119
|
workspace_id: workspaceId,
|
|
123
|
-
}
|
|
120
|
+
})
|
|
124
121
|
|
|
125
122
|
console.log(`[Directive] Execution completed: ${skill_name} (success: ${result.execution_id ? 'yes' : 'no'})`)
|
|
126
123
|
} catch (err) {
|
package/linux/routine-runner.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Key design:
|
|
7
7
|
* - All skills in a routine run in ONE CLI session (context preserved)
|
|
8
|
-
* -
|
|
9
|
-
* - Marker file written before session start for skill-to-execution mapping
|
|
8
|
+
* - Outcome is reported to the local API by the runner itself based on CLI exit code
|
|
10
9
|
* - Same tmux execution model as workflow-runner
|
|
11
10
|
*/
|
|
12
11
|
|
|
@@ -66,7 +65,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
|
|
|
66
65
|
const homeDir = config.HOME_DIR
|
|
67
66
|
const sessionName = generateSessionName(routine.id, executionId)
|
|
68
67
|
|
|
69
|
-
// Build prompt: run each skill in sequence
|
|
68
|
+
// Build prompt: run each skill in sequence
|
|
70
69
|
const primary = getActivePrimary()
|
|
71
70
|
const formatSkill = primary && typeof primary.formatSkillInvocation === 'function'
|
|
72
71
|
? primary.formatSkillInvocation.bind(primary)
|
|
@@ -78,8 +77,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
|
|
|
78
77
|
? `## Context\n\n${routine.context}\n\n---\n\n`
|
|
79
78
|
: ''
|
|
80
79
|
|
|
81
|
-
const
|
|
82
|
-
const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}. After completing all skills, run ${reportSkill} to report the results.`
|
|
80
|
+
const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}.`
|
|
83
81
|
|
|
84
82
|
// Exit code file to capture CLI result
|
|
85
83
|
const exitCodeFile = `/tmp/tmux-exit-${sessionName}`
|
|
@@ -88,7 +86,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
|
|
|
88
86
|
const logFile = logManager.getLogPath(executionId)
|
|
89
87
|
|
|
90
88
|
console.log(`[RoutineRunner] Executing routine: ${routine.name}`)
|
|
91
|
-
console.log(`[RoutineRunner] Skills: ${skillNames.join(' → ')}
|
|
89
|
+
console.log(`[RoutineRunner] Skills: ${skillNames.join(' → ')}`)
|
|
92
90
|
console.log(`[RoutineRunner] tmux session: ${sessionName}`)
|
|
93
91
|
console.log(`[RoutineRunner] Log file: ${logFile}`)
|
|
94
92
|
|
|
@@ -281,6 +279,7 @@ async function runRoutine(routine) {
|
|
|
281
279
|
const result = await executeRoutineSession(routine, executionId, pipelineSkillNames)
|
|
282
280
|
|
|
283
281
|
const completedAt = new Date().toISOString()
|
|
282
|
+
const outcome = result.success ? 'success' : 'failure'
|
|
284
283
|
|
|
285
284
|
// Save: routine completed
|
|
286
285
|
await executionStore.save({
|
|
@@ -290,7 +289,7 @@ async function runRoutine(routine) {
|
|
|
290
289
|
routine_name: routine.name,
|
|
291
290
|
workspace_id: routine.workspace_id || '',
|
|
292
291
|
status: result.success ? 'completed' : 'failed',
|
|
293
|
-
outcome
|
|
292
|
+
outcome,
|
|
294
293
|
started_at: startedAt,
|
|
295
294
|
completed_at: completedAt,
|
|
296
295
|
parent_execution_id: null,
|
|
@@ -298,6 +297,40 @@ async function runRoutine(routine) {
|
|
|
298
297
|
log_file: logFile,
|
|
299
298
|
})
|
|
300
299
|
|
|
300
|
+
// Extract summary from execution log file (captured via tmux pipe-pane)
|
|
301
|
+
let summary = result.success
|
|
302
|
+
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
303
|
+
: `Routine failed: ${result.error || 'unknown error'}`
|
|
304
|
+
try {
|
|
305
|
+
const logData = await logManager.readLog(executionId, { tail: 200 })
|
|
306
|
+
if (logData && logData.content && logData.content.trim().length > 0) {
|
|
307
|
+
const MAX_SUMMARY_LENGTH = 10000
|
|
308
|
+
const content = logData.content.trim()
|
|
309
|
+
summary = content.length > MAX_SUMMARY_LENGTH
|
|
310
|
+
? content.slice(-MAX_SUMMARY_LENGTH)
|
|
311
|
+
: content
|
|
312
|
+
}
|
|
313
|
+
} catch (err) {
|
|
314
|
+
console.error(`[RoutineRunner] Failed to read log for summary: ${err.message}`)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Report outcome via local API
|
|
318
|
+
try {
|
|
319
|
+
const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
|
|
320
|
+
method: 'POST',
|
|
321
|
+
headers: { 'Content-Type': 'application/json' },
|
|
322
|
+
body: JSON.stringify({
|
|
323
|
+
outcome,
|
|
324
|
+
summary,
|
|
325
|
+
}),
|
|
326
|
+
})
|
|
327
|
+
if (!resp.ok) {
|
|
328
|
+
console.error(`[RoutineRunner] Failed to report outcome: ${resp.status}`)
|
|
329
|
+
}
|
|
330
|
+
} catch (err) {
|
|
331
|
+
console.error(`[RoutineRunner] Failed to report outcome: ${err.message}`)
|
|
332
|
+
}
|
|
333
|
+
|
|
301
334
|
// Update last_run in local store
|
|
302
335
|
await routineStore.updateLastRun(routine.id)
|
|
303
336
|
|
package/linux/workflow-runner.js
CHANGED
|
@@ -383,7 +383,7 @@ async function runWorkflow(workflow, options = {}) {
|
|
|
383
383
|
console.error(`[WorkflowRunner] Failed to read log for summary: ${err.message}`)
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
// Report outcome via local API
|
|
386
|
+
// Report outcome via local API
|
|
387
387
|
try {
|
|
388
388
|
const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
|
|
389
389
|
method: 'POST',
|
package/package.json
CHANGED
package/roles/engineer.md
CHANGED
package/win/routes/directives.js
CHANGED
|
@@ -94,7 +94,7 @@ async function directiveRoutes(fastify) {
|
|
|
94
94
|
name: workflowName,
|
|
95
95
|
pipeline_skill_names: [skill_name],
|
|
96
96
|
workspace_id: workspaceId,
|
|
97
|
-
}
|
|
97
|
+
})
|
|
98
98
|
|
|
99
99
|
console.log(`[Directive] Execution completed: ${skill_name} (success: ${result.execution_id ? 'yes' : 'no'})`)
|
|
100
100
|
} catch (err) {
|
package/win/routine-runner.js
CHANGED
|
@@ -58,13 +58,12 @@ async function executeRoutineSession(routine, executionId, skillNames) {
|
|
|
58
58
|
const contextPrefix = routine.context
|
|
59
59
|
? `## Context\n\n${routine.context}\n\n---\n\n`
|
|
60
60
|
: ''
|
|
61
|
-
const
|
|
62
|
-
const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}. After completing all skills, run ${reportSkill} to report the results.`
|
|
61
|
+
const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}.`
|
|
63
62
|
|
|
64
63
|
const logFile = logManager.getLogPath(executionId)
|
|
65
64
|
|
|
66
65
|
console.log(`[RoutineRunner] Executing routine: ${routine.name}`)
|
|
67
|
-
console.log(`[RoutineRunner] Skills: ${skillNames.join(' -> ')}
|
|
66
|
+
console.log(`[RoutineRunner] Skills: ${skillNames.join(' -> ')}`)
|
|
68
67
|
console.log(`[RoutineRunner] Session: ${sessionName}`)
|
|
69
68
|
console.log(`[RoutineRunner] Log file: ${logFile}`)
|
|
70
69
|
|
|
@@ -220,6 +219,7 @@ async function runRoutine(routine) {
|
|
|
220
219
|
|
|
221
220
|
const result = await executeRoutineSession(routine, executionId, pipelineSkillNames)
|
|
222
221
|
const completedAt = new Date().toISOString()
|
|
222
|
+
const outcome = result.success ? 'success' : 'failure'
|
|
223
223
|
|
|
224
224
|
await executionStore.save({
|
|
225
225
|
id: executionId,
|
|
@@ -228,7 +228,7 @@ async function runRoutine(routine) {
|
|
|
228
228
|
routine_name: routine.name,
|
|
229
229
|
workspace_id: routine.workspace_id || '',
|
|
230
230
|
status: result.success ? 'completed' : 'failed',
|
|
231
|
-
outcome
|
|
231
|
+
outcome,
|
|
232
232
|
started_at: startedAt,
|
|
233
233
|
completed_at: completedAt,
|
|
234
234
|
parent_execution_id: null,
|
|
@@ -236,6 +236,40 @@ async function runRoutine(routine) {
|
|
|
236
236
|
log_file: logFile,
|
|
237
237
|
})
|
|
238
238
|
|
|
239
|
+
// Extract summary from execution log file (captured via pty logStream)
|
|
240
|
+
let summary = result.success
|
|
241
|
+
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
242
|
+
: `Routine failed: ${result.error || 'unknown error'}`
|
|
243
|
+
try {
|
|
244
|
+
const logData = await logManager.readLog(executionId, { tail: 200 })
|
|
245
|
+
if (logData && logData.content && logData.content.trim().length > 0) {
|
|
246
|
+
const MAX_SUMMARY_LENGTH = 10000
|
|
247
|
+
const content = logData.content.trim()
|
|
248
|
+
summary = content.length > MAX_SUMMARY_LENGTH
|
|
249
|
+
? content.slice(-MAX_SUMMARY_LENGTH)
|
|
250
|
+
: content
|
|
251
|
+
}
|
|
252
|
+
} catch (err) {
|
|
253
|
+
console.error(`[RoutineRunner] Failed to read log for summary: ${err.message}`)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Report outcome via local API
|
|
257
|
+
try {
|
|
258
|
+
const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
|
|
259
|
+
method: 'POST',
|
|
260
|
+
headers: { 'Content-Type': 'application/json' },
|
|
261
|
+
body: JSON.stringify({
|
|
262
|
+
outcome,
|
|
263
|
+
summary,
|
|
264
|
+
}),
|
|
265
|
+
})
|
|
266
|
+
if (!resp.ok) {
|
|
267
|
+
console.error(`[RoutineRunner] Failed to report outcome: ${resp.status}`)
|
|
268
|
+
}
|
|
269
|
+
} catch (err) {
|
|
270
|
+
console.error(`[RoutineRunner] Failed to report outcome: ${err.message}`)
|
|
271
|
+
}
|
|
272
|
+
|
|
239
273
|
await routineStore.updateLastRun(routine.id)
|
|
240
274
|
|
|
241
275
|
runningExecutions.delete(executionId)
|