@geekbeer/minion 2.48.3 → 2.49.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/routes/skills.js +31 -21
- package/linux/workflow-runner.js +18 -3
- package/package.json +1 -1
- package/win/workflow-runner.js +17 -5
package/core/routes/skills.js
CHANGED
|
@@ -48,15 +48,15 @@ function parseFrontmatter(content) {
|
|
|
48
48
|
* @param {string} opts.content - Skill body (markdown without frontmatter)
|
|
49
49
|
* @param {string} [opts.description] - Skill description for frontmatter
|
|
50
50
|
* @param {string} [opts.display_name] - Display name for frontmatter
|
|
51
|
-
* @param {Array<{
|
|
52
|
-
* @returns {Promise<{path: string,
|
|
51
|
+
* @param {Array<{path: string, content?: string}>} [opts.files] - Skill files from HQ storage
|
|
52
|
+
* @returns {Promise<{path: string, files_count: number}>}
|
|
53
53
|
*/
|
|
54
|
-
async function writeSkillToLocal(name, { content, description, display_name, type,
|
|
54
|
+
async function writeSkillToLocal(name, { content, description, display_name, type, files = [] }) {
|
|
55
55
|
const skillDir = path.join(config.HOME_DIR, '.claude', 'skills', name)
|
|
56
|
-
const
|
|
56
|
+
const filesDir = path.join(skillDir, 'files')
|
|
57
57
|
|
|
58
58
|
await fs.mkdir(skillDir, { recursive: true })
|
|
59
|
-
await fs.mkdir(
|
|
59
|
+
await fs.mkdir(filesDir, { recursive: true })
|
|
60
60
|
|
|
61
61
|
// Build frontmatter with all available metadata
|
|
62
62
|
const frontmatterLines = [
|
|
@@ -72,15 +72,15 @@ async function writeSkillToLocal(name, { content, description, display_name, typ
|
|
|
72
72
|
'utf-8'
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
-
// Write
|
|
76
|
-
for (const
|
|
77
|
-
if (
|
|
78
|
-
const safeFilename = path.basename(
|
|
79
|
-
await fs.writeFile(path.join(
|
|
75
|
+
// Write skill files
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
if (file.path && file.content) {
|
|
78
|
+
const safeFilename = path.basename(file.path)
|
|
79
|
+
await fs.writeFile(path.join(filesDir, safeFilename), file.content, 'utf-8')
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
return { path: skillDir,
|
|
83
|
+
return { path: skillDir, files_count: files.length }
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -99,17 +99,27 @@ async function pushSkillToHQ(name) {
|
|
|
99
99
|
const rawContent = await fs.readFile(skillMdPath, 'utf-8')
|
|
100
100
|
const { metadata, body } = parseFrontmatter(rawContent)
|
|
101
101
|
|
|
102
|
-
// Read
|
|
103
|
-
const
|
|
104
|
-
const
|
|
102
|
+
// Read skill files
|
|
103
|
+
const filesDir = path.join(skillDir, 'files')
|
|
104
|
+
const files = []
|
|
105
105
|
try {
|
|
106
|
-
const
|
|
107
|
-
for (const filename of
|
|
108
|
-
const
|
|
109
|
-
|
|
106
|
+
const fileEntries = await fs.readdir(filesDir)
|
|
107
|
+
for (const filename of fileEntries) {
|
|
108
|
+
const fileContent = await fs.readFile(path.join(filesDir, filename), 'utf-8')
|
|
109
|
+
files.push({ path: filename, content: fileContent })
|
|
110
110
|
}
|
|
111
111
|
} catch {
|
|
112
|
-
// No references
|
|
112
|
+
// No files directory — try legacy references/ for backward compatibility
|
|
113
|
+
try {
|
|
114
|
+
const legacyDir = path.join(skillDir, 'references')
|
|
115
|
+
const legacyEntries = await fs.readdir(legacyDir)
|
|
116
|
+
for (const filename of legacyEntries) {
|
|
117
|
+
const fileContent = await fs.readFile(path.join(legacyDir, filename), 'utf-8')
|
|
118
|
+
files.push({ path: filename, content: fileContent })
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// No files at all
|
|
122
|
+
}
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
return api.request('/skills', {
|
|
@@ -120,7 +130,7 @@ async function pushSkillToHQ(name) {
|
|
|
120
130
|
description: metadata.description || '',
|
|
121
131
|
content: body,
|
|
122
132
|
type: metadata.type || 'workflow',
|
|
123
|
-
|
|
133
|
+
files,
|
|
124
134
|
}),
|
|
125
135
|
})
|
|
126
136
|
}
|
|
@@ -243,7 +253,7 @@ async function skillRoutes(fastify, opts) {
|
|
|
243
253
|
description: skill.description,
|
|
244
254
|
display_name: skill.display_name,
|
|
245
255
|
type: skill.type,
|
|
246
|
-
|
|
256
|
+
files: skill.files || [],
|
|
247
257
|
})
|
|
248
258
|
|
|
249
259
|
console.log(`[Skills] Skill fetched and deployed: ${name}`)
|
package/linux/workflow-runner.js
CHANGED
|
@@ -277,6 +277,23 @@ async function runWorkflow(workflow, options = {}) {
|
|
|
277
277
|
log_file: logFile,
|
|
278
278
|
})
|
|
279
279
|
|
|
280
|
+
// Extract summary from execution log file (captured via tmux pipe-pane)
|
|
281
|
+
let summary = result.success
|
|
282
|
+
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
283
|
+
: `Workflow failed: ${result.error || 'unknown error'}`
|
|
284
|
+
try {
|
|
285
|
+
const logData = await logManager.readLog(executionId, { tail: 200 })
|
|
286
|
+
if (logData && logData.content && logData.content.trim().length > 0) {
|
|
287
|
+
const MAX_SUMMARY_LENGTH = 10000
|
|
288
|
+
const content = logData.content.trim()
|
|
289
|
+
summary = content.length > MAX_SUMMARY_LENGTH
|
|
290
|
+
? content.slice(-MAX_SUMMARY_LENGTH)
|
|
291
|
+
: content
|
|
292
|
+
}
|
|
293
|
+
} catch (err) {
|
|
294
|
+
console.error(`[WorkflowRunner] Failed to read log for summary: ${err.message}`)
|
|
295
|
+
}
|
|
296
|
+
|
|
280
297
|
// Report outcome via local API (same data the execution-report skill used to send)
|
|
281
298
|
try {
|
|
282
299
|
const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
|
|
@@ -284,9 +301,7 @@ async function runWorkflow(workflow, options = {}) {
|
|
|
284
301
|
headers: { 'Content-Type': 'application/json' },
|
|
285
302
|
body: JSON.stringify({
|
|
286
303
|
outcome,
|
|
287
|
-
summary
|
|
288
|
-
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
289
|
-
: `Workflow failed: ${result.error || 'unknown error'}`,
|
|
304
|
+
summary,
|
|
290
305
|
}),
|
|
291
306
|
})
|
|
292
307
|
if (!resp.ok) {
|
package/package.json
CHANGED
package/win/workflow-runner.js
CHANGED
|
@@ -183,12 +183,19 @@ async function executeWorkflowSession(workflow, executionId, skillNames, options
|
|
|
183
183
|
// Close log stream
|
|
184
184
|
try { logStream.end() } catch { /* ignore */ }
|
|
185
185
|
|
|
186
|
+
// Capture output for summary
|
|
187
|
+
const MAX_SUMMARY_LENGTH = 10000
|
|
188
|
+
const output = outputBuffer.trim()
|
|
189
|
+
const capturedOutput = output.length > MAX_SUMMARY_LENGTH
|
|
190
|
+
? output.slice(-MAX_SUMMARY_LENGTH)
|
|
191
|
+
: output
|
|
192
|
+
|
|
186
193
|
if (exitCode === 0) {
|
|
187
194
|
console.log(`[WorkflowRunner] Workflow ${workflow.name} completed successfully`)
|
|
188
|
-
resolve({ success: true, sessionName })
|
|
195
|
+
resolve({ success: true, sessionName, output: capturedOutput })
|
|
189
196
|
} else {
|
|
190
197
|
console.error(`[WorkflowRunner] Workflow ${workflow.name} failed with exit code: ${exitCode}`)
|
|
191
|
-
resolve({ success: false, error: `Exit code: ${exitCode}`, sessionName })
|
|
198
|
+
resolve({ success: false, error: `Exit code: ${exitCode}`, sessionName, output: capturedOutput })
|
|
192
199
|
}
|
|
193
200
|
})
|
|
194
201
|
})
|
|
@@ -261,6 +268,13 @@ async function runWorkflow(workflow, options = {}) {
|
|
|
261
268
|
log_file: logFile,
|
|
262
269
|
})
|
|
263
270
|
|
|
271
|
+
// Use captured output as summary, falling back to generic message
|
|
272
|
+
const summary = (result.output && result.output.length > 0)
|
|
273
|
+
? result.output
|
|
274
|
+
: result.success
|
|
275
|
+
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
276
|
+
: `Workflow failed: ${result.error || 'unknown error'}`
|
|
277
|
+
|
|
264
278
|
// Report outcome via local API
|
|
265
279
|
try {
|
|
266
280
|
const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
|
|
@@ -268,9 +282,7 @@ async function runWorkflow(workflow, options = {}) {
|
|
|
268
282
|
headers: { 'Content-Type': 'application/json' },
|
|
269
283
|
body: JSON.stringify({
|
|
270
284
|
outcome,
|
|
271
|
-
summary
|
|
272
|
-
? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
|
|
273
|
-
: `Workflow failed: ${result.error || 'unknown error'}`,
|
|
285
|
+
summary,
|
|
274
286
|
}),
|
|
275
287
|
})
|
|
276
288
|
if (!resp.ok) {
|