@yemi33/minions 0.1.577 → 0.1.578
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/CHANGELOG.md +5 -0
- package/engine/llm.js +52 -84
- package/engine.js +6 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/engine/llm.js
CHANGED
|
@@ -68,54 +68,62 @@ function _buildCliArgs({ model, maxTurns, allowedTools, effort, sessionId, sysPr
|
|
|
68
68
|
return args;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Spawn a claude CLI process. Returns { proc, cleanupFiles } or null if binary not cached.
|
|
73
|
+
* When direct=true, spawns claude CLI directly (fewer syscalls). Otherwise uses spawn-agent.js.
|
|
74
|
+
*/
|
|
75
|
+
function _spawnProcess(promptText, sysPromptText, { direct, label, model, maxTurns, allowedTools, effort, sessionId }) {
|
|
76
|
+
const fs = require('fs');
|
|
77
|
+
const id = uid();
|
|
78
|
+
const tmpDir = path.join(ENGINE_DIR, 'tmp');
|
|
79
|
+
if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
|
|
80
|
+
|
|
81
|
+
const cleanupFiles = [];
|
|
82
|
+
const resolved = direct ? _resolveClaudeBin() : null;
|
|
83
|
+
|
|
84
|
+
if (resolved) {
|
|
85
|
+
let sysTmpPath = null;
|
|
86
|
+
if (!sessionId && sysPromptText) {
|
|
87
|
+
sysTmpPath = path.join(tmpDir, `direct-sys-${id}.md`);
|
|
88
|
+
fs.writeFileSync(sysTmpPath, sysPromptText);
|
|
89
|
+
cleanupFiles.push(sysTmpPath);
|
|
90
|
+
}
|
|
91
|
+
const cliArgs = _buildCliArgs({ model, maxTurns, allowedTools, effort, sessionId, sysPromptFile: sysTmpPath });
|
|
92
|
+
const proc = resolved.native
|
|
93
|
+
? runFile(resolved.bin, cliArgs, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() })
|
|
94
|
+
: runFile(process.execPath, [resolved.bin, ...cliArgs], { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
95
|
+
try { proc.stdin.write(promptText); proc.stdin.end(); } catch { /* broken pipe */ }
|
|
96
|
+
return { proc, cleanupFiles };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Indirect: use spawn-agent.js
|
|
100
|
+
const promptPath = path.join(tmpDir, `${label}-prompt-${id}.md`);
|
|
101
|
+
const sysPath = path.join(tmpDir, `${label}-sys-${id}.md`);
|
|
102
|
+
safeWrite(promptPath, promptText);
|
|
103
|
+
safeWrite(sysPath, sysPromptText || '');
|
|
104
|
+
cleanupFiles.push(promptPath, sysPath);
|
|
105
|
+
|
|
106
|
+
const spawnScript = path.join(ENGINE_DIR, 'spawn-agent.js');
|
|
107
|
+
const args = [
|
|
108
|
+
spawnScript, promptPath, sysPath,
|
|
109
|
+
'--output-format', 'stream-json', '--max-turns', String(maxTurns), '--model', model,
|
|
110
|
+
'--verbose',
|
|
111
|
+
];
|
|
112
|
+
if (allowedTools) args.push('--allowedTools', allowedTools);
|
|
113
|
+
if (effort) args.push('--effort', effort);
|
|
114
|
+
args.push('--permission-mode', 'bypassPermissions');
|
|
115
|
+
if (sessionId) args.push('--resume', sessionId);
|
|
116
|
+
|
|
117
|
+
const proc = runFile(process.execPath, args, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
118
|
+
return { proc, cleanupFiles };
|
|
119
|
+
}
|
|
120
|
+
|
|
71
121
|
// ── Core LLM Call ───────────────────────────────────────────────────────────
|
|
72
122
|
|
|
73
123
|
function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', model = 'sonnet', maxTurns = 1, allowedTools = '', sessionId = null, effort = null, direct = false } = {}) {
|
|
74
124
|
return new Promise((resolve) => {
|
|
75
125
|
const _startMs = Date.now();
|
|
76
|
-
const
|
|
77
|
-
const id = uid();
|
|
78
|
-
const tmpDir = path.join(ENGINE_DIR, 'tmp');
|
|
79
|
-
if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
|
|
80
|
-
|
|
81
|
-
let proc;
|
|
82
|
-
const cleanupFiles = [];
|
|
83
|
-
const resolved = direct ? _resolveClaudeBin() : null;
|
|
84
|
-
|
|
85
|
-
if (resolved) {
|
|
86
|
-
// Direct spawn: skip spawn-agent.js — fewer file syscalls, no extra process
|
|
87
|
-
let sysTmpPath = null;
|
|
88
|
-
if (!sessionId && sysPromptText) {
|
|
89
|
-
sysTmpPath = path.join(tmpDir, `direct-sys-${id}.md`);
|
|
90
|
-
fs.writeFileSync(sysTmpPath, sysPromptText);
|
|
91
|
-
cleanupFiles.push(sysTmpPath);
|
|
92
|
-
}
|
|
93
|
-
const cliArgs = _buildCliArgs({ model, maxTurns, allowedTools, effort, sessionId, sysPromptFile: sysTmpPath });
|
|
94
|
-
proc = resolved.native
|
|
95
|
-
? runFile(resolved.bin, cliArgs, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() })
|
|
96
|
-
: runFile(process.execPath, [resolved.bin, ...cliArgs], { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
97
|
-
try { proc.stdin.write(promptText); proc.stdin.end(); } catch { /* broken pipe */ }
|
|
98
|
-
} else {
|
|
99
|
-
// Indirect: use spawn-agent.js (for agent dispatches or if binary not cached)
|
|
100
|
-
const promptPath = path.join(tmpDir, `${label}-prompt-${id}.md`);
|
|
101
|
-
const sysPath = path.join(tmpDir, `${label}-sys-${id}.md`);
|
|
102
|
-
safeWrite(promptPath, promptText);
|
|
103
|
-
safeWrite(sysPath, sysPromptText || '');
|
|
104
|
-
cleanupFiles.push(promptPath, sysPath);
|
|
105
|
-
|
|
106
|
-
const spawnScript = path.join(ENGINE_DIR, 'spawn-agent.js');
|
|
107
|
-
const args = [
|
|
108
|
-
spawnScript, promptPath, sysPath,
|
|
109
|
-
'--output-format', 'stream-json', '--max-turns', String(maxTurns), '--model', model,
|
|
110
|
-
'--verbose',
|
|
111
|
-
];
|
|
112
|
-
if (allowedTools) args.push('--allowedTools', allowedTools);
|
|
113
|
-
if (effort) args.push('--effort', effort);
|
|
114
|
-
args.push('--permission-mode', 'bypassPermissions');
|
|
115
|
-
if (sessionId) args.push('--resume', sessionId);
|
|
116
|
-
|
|
117
|
-
proc = runFile(process.execPath, args, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
118
|
-
}
|
|
126
|
+
const { proc, cleanupFiles } = _spawnProcess(promptText, sysPromptText, { direct, label, model, maxTurns, allowedTools, effort, sessionId });
|
|
119
127
|
|
|
120
128
|
let stdout = '';
|
|
121
129
|
let stderr = '';
|
|
@@ -167,47 +175,7 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
|
|
|
167
175
|
let _abort = null;
|
|
168
176
|
const promise = new Promise((resolve) => {
|
|
169
177
|
const _startMs = Date.now();
|
|
170
|
-
const
|
|
171
|
-
const id = uid();
|
|
172
|
-
const tmpDir = path.join(ENGINE_DIR, 'tmp');
|
|
173
|
-
if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
|
|
174
|
-
|
|
175
|
-
let proc;
|
|
176
|
-
const cleanupFiles = [];
|
|
177
|
-
const resolved = direct ? _resolveClaudeBin() : null;
|
|
178
|
-
|
|
179
|
-
if (resolved) {
|
|
180
|
-
let sysTmpPath = null;
|
|
181
|
-
if (!sessionId && sysPromptText) {
|
|
182
|
-
sysTmpPath = path.join(tmpDir, `direct-sys-${id}.md`);
|
|
183
|
-
fs.writeFileSync(sysTmpPath, sysPromptText);
|
|
184
|
-
cleanupFiles.push(sysTmpPath);
|
|
185
|
-
}
|
|
186
|
-
const cliArgs = _buildCliArgs({ model, maxTurns, allowedTools, effort, sessionId, sysPromptFile: sysTmpPath });
|
|
187
|
-
proc = resolved.native
|
|
188
|
-
? runFile(resolved.bin, cliArgs, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() })
|
|
189
|
-
: runFile(process.execPath, [resolved.bin, ...cliArgs], { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
190
|
-
try { proc.stdin.write(promptText); proc.stdin.end(); } catch { /* broken pipe */ }
|
|
191
|
-
} else {
|
|
192
|
-
const promptPath = path.join(tmpDir, `${label}-prompt-${id}.md`);
|
|
193
|
-
const sysPath = path.join(tmpDir, `${label}-sys-${id}.md`);
|
|
194
|
-
safeWrite(promptPath, promptText);
|
|
195
|
-
safeWrite(sysPath, sysPromptText || '');
|
|
196
|
-
cleanupFiles.push(promptPath, sysPath);
|
|
197
|
-
|
|
198
|
-
const spawnScript = path.join(ENGINE_DIR, 'spawn-agent.js');
|
|
199
|
-
const args = [
|
|
200
|
-
spawnScript, promptPath, sysPath,
|
|
201
|
-
'--output-format', 'stream-json', '--max-turns', String(maxTurns), '--model', model,
|
|
202
|
-
'--verbose',
|
|
203
|
-
];
|
|
204
|
-
if (allowedTools) args.push('--allowedTools', allowedTools);
|
|
205
|
-
if (effort) args.push('--effort', effort);
|
|
206
|
-
args.push('--permission-mode', 'bypassPermissions');
|
|
207
|
-
if (sessionId) args.push('--resume', sessionId);
|
|
208
|
-
|
|
209
|
-
proc = runFile(process.execPath, args, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
|
|
210
|
-
}
|
|
178
|
+
const { proc, cleanupFiles } = _spawnProcess(promptText, sysPromptText, { direct, label, model, maxTurns, allowedTools, effort, sessionId });
|
|
211
179
|
|
|
212
180
|
_abort = () => { shared.killImmediate(proc); };
|
|
213
181
|
|
package/engine.js
CHANGED
|
@@ -292,6 +292,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
292
292
|
safeWrite(promptPath, fullTaskPrompt);
|
|
293
293
|
const sysPromptPath = path.join(tmpDir, `sysprompt-${safeId}.md`);
|
|
294
294
|
safeWrite(sysPromptPath, systemPrompt);
|
|
295
|
+
const _cleanupPromptFiles = () => { safeUnlink(promptPath); safeUnlink(sysPromptPath); };
|
|
295
296
|
|
|
296
297
|
if (branchName) {
|
|
297
298
|
const wtSuffix = id ? id.split('-').pop() : shared.uid();
|
|
@@ -440,11 +441,11 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
440
441
|
execAsync(`git fetch origin "${depBranch}"`, { ..._gitOpts, cwd: rootDir }).then(() => depBranch)
|
|
441
442
|
)
|
|
442
443
|
);
|
|
443
|
-
for (
|
|
444
|
-
if (
|
|
445
|
-
const failedBranch = fetchable.
|
|
444
|
+
for (let i = 0; i < fetchResults.length; i++) {
|
|
445
|
+
if (fetchResults[i].status === 'rejected') {
|
|
446
|
+
const failedBranch = fetchable[i].branch;
|
|
446
447
|
_failedRefCache.add(failedBranch);
|
|
447
|
-
log('warn', `Failed to fetch dependency ${failedBranch}: ${
|
|
448
|
+
log('warn', `Failed to fetch dependency ${failedBranch}: ${fetchResults[i].reason?.message}`);
|
|
448
449
|
depMergeFailed = true;
|
|
449
450
|
}
|
|
450
451
|
}
|
|
@@ -462,6 +463,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
462
463
|
}
|
|
463
464
|
}
|
|
464
465
|
if (depMergeFailed) {
|
|
466
|
+
_cleanupPromptFiles();
|
|
465
467
|
completeDispatch(id, DISPATCH_RESULT.ERROR, `Dependency merge failed — will retry next tick`);
|
|
466
468
|
return;
|
|
467
469
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.578",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|