@yemi33/minions 0.1.1739 → 0.1.1740
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 +6 -1
- package/dashboard.js +107 -63
- package/engine/copilot-models.json +1 -1
- package/engine/runtimes/claude.js +23 -1
- package/engine/runtimes/copilot.js +23 -1
- package/engine/spawn-agent.js +8 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1740 (2026-05-06)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
|
+
- doc-chat resume retry + 1h timeout + surfaced stderr (#2101)
|
|
6
7
|
- make Command Center chat sessions non-expiring (#2100)
|
|
7
8
|
|
|
9
|
+
### Fixes
|
|
10
|
+
- invalidate stale session IDs on runtime switch (#2102)
|
|
11
|
+
- drop 5s setTimeout that nuked sysprompt .tmp before Claude could read it (#2105)
|
|
12
|
+
|
|
8
13
|
## 0.1.1738 (2026-05-06)
|
|
9
14
|
|
|
10
15
|
### Features
|
package/dashboard.js
CHANGED
|
@@ -952,9 +952,10 @@ const CC_STREAM_REATTACH_GRACE_MS = 60000; // keep CC job alive briefly after di
|
|
|
952
952
|
const CC_STREAM_DONE_RETENTION_MS = 30000; // retain final payload briefly so reconnect can still receive it
|
|
953
953
|
const CC_LIVE_STREAM_MAX_AGE_MS = shared.ENGINE_DEFAULTS.ccLiveStreamMaxAgeMs;
|
|
954
954
|
// Doc-chat is interactive — long-doc edits with multi-step Read+Write tool use can run
|
|
955
|
-
//
|
|
956
|
-
// edits mid-stream
|
|
957
|
-
|
|
955
|
+
// well past 5 min on `canEdit:true` paths. Bumped to 1 hour (matching CC) so legitimate
|
|
956
|
+
// edits aren't killed mid-stream and the backend timeout never beats the user's reading
|
|
957
|
+
// time. The doc-chat handlers still abort on client disconnect.
|
|
958
|
+
const DOC_CHAT_TIMEOUT_MS = 60 * 60 * 1000;
|
|
958
959
|
function _releaseCCTab(tabId) { ccInFlightTabs.delete(tabId); ccInFlightAborts.delete(tabId); }
|
|
959
960
|
function _getCcLiveStream(tabId) {
|
|
960
961
|
return ccLiveStreams.get(tabId) || null;
|
|
@@ -2466,6 +2467,56 @@ function _formatDocChatContext({ document, title, filePath, selection, canEdit,
|
|
|
2466
2467
|
return context;
|
|
2467
2468
|
}
|
|
2468
2469
|
|
|
2470
|
+
// Build the doc-chat extraContext for a single ccCall pass — refreshed on retry
|
|
2471
|
+
// so a fresh-session retry includes the full document instead of relying on the
|
|
2472
|
+
// dead session's prior turn for context.
|
|
2473
|
+
function _buildDocChatPass({ docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession }) {
|
|
2474
|
+
const existing = freshSession ? null : resolveSession('doc', sessionKey);
|
|
2475
|
+
const docHash = require('crypto').createHash('md5').update(docSlice).digest('hex').slice(0, 8);
|
|
2476
|
+
const docUnchanged = existing?.sessionId && existing._docHash === docHash;
|
|
2477
|
+
const extraContext = _formatDocChatContext({
|
|
2478
|
+
document: docSlice, title, filePath, selection, canEdit, isJson, docUnchanged,
|
|
2479
|
+
});
|
|
2480
|
+
return { extraContext, docHash, hadSession: !!existing?.sessionId };
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
// One-shot recovery from a stuck resumed session: if the initial call rode an
|
|
2484
|
+
// existing session and came back empty / non-zero, invalidate the persisted
|
|
2485
|
+
// session and re-run via the supplied closure. ccCall already retries fresh
|
|
2486
|
+
// when the runtime can't extract a sessionId, but on adapter-still-alive
|
|
2487
|
+
// failures it preserves the session — and from doc-chat's perspective that's
|
|
2488
|
+
// the failure mode the user actually sees ("Failed to process request").
|
|
2489
|
+
async function _retryDocChatAfterResumeFailure({ result, initialPass, freshSession, sessionKey, runOnce }) {
|
|
2490
|
+
if (!initialPass.hadSession || freshSession || result.missingRuntime) return result;
|
|
2491
|
+
if (result.code === 0 && result.text) return result;
|
|
2492
|
+
console.log(`[doc-chat] Resumed session call failed (code=${result.code}, empty=${!result.text}) — invalidating session and retrying fresh for ${sessionKey || 'untitled'}`);
|
|
2493
|
+
if (sessionKey) {
|
|
2494
|
+
docSessions.delete(sessionKey);
|
|
2495
|
+
schedulePersistDocSessions();
|
|
2496
|
+
}
|
|
2497
|
+
return runOnce();
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// Build the {error} envelope returned to the dashboard when doc-chat ultimately
|
|
2501
|
+
// fails. Keeps the polite user-facing message but exposes the runtime's real
|
|
2502
|
+
// stderr / exit code / errorClass so the UI can render the cause and so future
|
|
2503
|
+
// failures are debuggable from logs.
|
|
2504
|
+
function _docChatFailureResponse(label, filePath, result) {
|
|
2505
|
+
const stderrTail = (result.stderr || '').slice(-2048);
|
|
2506
|
+
console.error(`[${label}] Failed: code=${result.code}, empty=${!result.text}, filePath=${filePath}, errorClass=${result.errorClass || 'null'}, stderr=${stderrTail.slice(0, 200)}`);
|
|
2507
|
+
return {
|
|
2508
|
+
answer: 'Failed to process request. Try again.',
|
|
2509
|
+
content: null,
|
|
2510
|
+
actions: [],
|
|
2511
|
+
error: {
|
|
2512
|
+
code: result.code ?? null,
|
|
2513
|
+
stderr: stderrTail,
|
|
2514
|
+
errorClass: result.errorClass || null,
|
|
2515
|
+
runtime: result.runtime || null,
|
|
2516
|
+
},
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2469
2520
|
// Doc-specific wrapper — adds document context, parses ---DOCUMENT---
|
|
2470
2521
|
async function ccDocCall({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, onAbortReady }) {
|
|
2471
2522
|
const sessionKey = filePath || title;
|
|
@@ -2479,34 +2530,30 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2479
2530
|
// Skip persistDocSessions() here — the post-call cleanup below handles persistence.
|
|
2480
2531
|
}
|
|
2481
2532
|
|
|
2482
|
-
// Skip re-sending full document on session resume if content unchanged
|
|
2483
|
-
const docHash = require('crypto').createHash('md5').update(docSlice).digest('hex').slice(0, 8);
|
|
2484
|
-
const existing = freshSession ? null : resolveSession('doc', sessionKey);
|
|
2485
|
-
const docUnchanged = existing?.sessionId && existing._docHash === docHash;
|
|
2486
|
-
|
|
2487
|
-
const docContext = _formatDocChatContext({
|
|
2488
|
-
document: docSlice,
|
|
2489
|
-
title,
|
|
2490
|
-
filePath,
|
|
2491
|
-
selection,
|
|
2492
|
-
canEdit,
|
|
2493
|
-
isJson,
|
|
2494
|
-
docUnchanged,
|
|
2495
|
-
});
|
|
2496
2533
|
const allowActions = _messageRequestsOrchestration(message);
|
|
2497
2534
|
|
|
2498
|
-
const
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2535
|
+
const runOnce = async () => {
|
|
2536
|
+
const { extraContext } = _buildDocChatPass({
|
|
2537
|
+
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
2538
|
+
});
|
|
2539
|
+
return ccCall(message, {
|
|
2540
|
+
store: 'doc', sessionKey,
|
|
2541
|
+
extraContext, label: 'doc-chat',
|
|
2542
|
+
timeout: DOC_CHAT_TIMEOUT_MS,
|
|
2543
|
+
allowedTools: canEdit ? 'Read,Write,Edit,Glob,Grep' : 'Read,Glob,Grep',
|
|
2544
|
+
maxTurns: canEdit ? 25 : 10,
|
|
2545
|
+
skipStatePreamble: true,
|
|
2546
|
+
systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
|
|
2547
|
+
...(model ? { model } : {}),
|
|
2548
|
+
onAbortReady,
|
|
2549
|
+
});
|
|
2550
|
+
};
|
|
2551
|
+
|
|
2552
|
+
const initialPass = _buildDocChatPass({
|
|
2553
|
+
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
2509
2554
|
});
|
|
2555
|
+
let result = await runOnce();
|
|
2556
|
+
result = await _retryDocChatAfterResumeFailure({ result, initialPass, freshSession, sessionKey, runOnce });
|
|
2510
2557
|
|
|
2511
2558
|
if (freshSession && sessionKey) {
|
|
2512
2559
|
// One-shot call — discard the session ccCall just stored so it cannot
|
|
@@ -2516,7 +2563,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2516
2563
|
} else if (result.code === 0 && result.sessionId) {
|
|
2517
2564
|
// Store doc hash for next call's unchanged check
|
|
2518
2565
|
const session = resolveSession('doc', sessionKey);
|
|
2519
|
-
if (session) session._docHash = docHash;
|
|
2566
|
+
if (session) session._docHash = initialPass.docHash;
|
|
2520
2567
|
}
|
|
2521
2568
|
|
|
2522
2569
|
if (result.missingRuntime) {
|
|
@@ -2524,8 +2571,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2524
2571
|
}
|
|
2525
2572
|
|
|
2526
2573
|
if (result.code !== 0 || !result.text) {
|
|
2527
|
-
|
|
2528
|
-
return { answer: 'Failed to process request. Try again.', content: null, actions: [] };
|
|
2574
|
+
return _docChatFailureResponse('doc-chat', filePath, result);
|
|
2529
2575
|
}
|
|
2530
2576
|
|
|
2531
2577
|
return _parseDocChatResultText(result.text, { allowActions });
|
|
@@ -2539,42 +2585,39 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
2539
2585
|
docSessions.delete(sessionKey);
|
|
2540
2586
|
}
|
|
2541
2587
|
|
|
2542
|
-
const docHash = require('crypto').createHash('md5').update(docSlice).digest('hex').slice(0, 8);
|
|
2543
|
-
const existing = freshSession ? null : resolveSession('doc', sessionKey);
|
|
2544
|
-
const docUnchanged = existing?.sessionId && existing._docHash === docHash;
|
|
2545
|
-
|
|
2546
|
-
const docContext = _formatDocChatContext({
|
|
2547
|
-
document: docSlice,
|
|
2548
|
-
title,
|
|
2549
|
-
filePath,
|
|
2550
|
-
selection,
|
|
2551
|
-
canEdit,
|
|
2552
|
-
isJson,
|
|
2553
|
-
docUnchanged,
|
|
2554
|
-
});
|
|
2555
2588
|
const allowActions = _messageRequestsOrchestration(message);
|
|
2556
2589
|
|
|
2557
|
-
const
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2590
|
+
const runOnce = async () => {
|
|
2591
|
+
const { extraContext } = _buildDocChatPass({
|
|
2592
|
+
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
2593
|
+
});
|
|
2594
|
+
return ccCallStreaming(message, {
|
|
2595
|
+
store: 'doc', sessionKey,
|
|
2596
|
+
extraContext, label: 'doc-chat',
|
|
2597
|
+
timeout: DOC_CHAT_TIMEOUT_MS,
|
|
2598
|
+
allowedTools: canEdit ? 'Read,Write,Edit,Glob,Grep' : 'Read,Glob,Grep',
|
|
2599
|
+
maxTurns: canEdit ? 25 : 10,
|
|
2600
|
+
skipStatePreamble: true,
|
|
2601
|
+
systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
|
|
2602
|
+
...(model ? { model } : {}),
|
|
2603
|
+
onAbortReady,
|
|
2604
|
+
onChunk: (text) => { if (onChunk) onChunk(_docChatDisplayText(text, { allowActions })); },
|
|
2605
|
+
onToolUse,
|
|
2606
|
+
});
|
|
2607
|
+
};
|
|
2608
|
+
|
|
2609
|
+
const initialPass = _buildDocChatPass({
|
|
2610
|
+
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
2570
2611
|
});
|
|
2612
|
+
let result = await runOnce();
|
|
2613
|
+
result = await _retryDocChatAfterResumeFailure({ result, initialPass, freshSession, sessionKey, runOnce });
|
|
2571
2614
|
|
|
2572
2615
|
if (freshSession && sessionKey) {
|
|
2573
2616
|
docSessions.delete(sessionKey);
|
|
2574
2617
|
schedulePersistDocSessions();
|
|
2575
2618
|
} else if (result.code === 0 && result.sessionId) {
|
|
2576
2619
|
const session = resolveSession('doc', sessionKey);
|
|
2577
|
-
if (session) session._docHash = docHash;
|
|
2620
|
+
if (session) session._docHash = initialPass.docHash;
|
|
2578
2621
|
}
|
|
2579
2622
|
|
|
2580
2623
|
if (result.missingRuntime) {
|
|
@@ -2582,8 +2625,7 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
2582
2625
|
}
|
|
2583
2626
|
|
|
2584
2627
|
if (result.code !== 0 || !result.text) {
|
|
2585
|
-
|
|
2586
|
-
return { answer: 'Failed to process request. Try again.', content: null, actions: [] };
|
|
2628
|
+
return _docChatFailureResponse('doc-chat-stream', filePath, result);
|
|
2587
2629
|
}
|
|
2588
2630
|
|
|
2589
2631
|
return _parseDocChatResultText(result.text, { allowActions });
|
|
@@ -4680,7 +4722,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4680
4722
|
}
|
|
4681
4723
|
}
|
|
4682
4724
|
|
|
4683
|
-
const { answer, content, actions, actionParseError } = await ccDocCall({
|
|
4725
|
+
const { answer, content, actions, actionParseError, error: ccError } = await ccDocCall({
|
|
4684
4726
|
message: body.message, document: currentContent, title: body.title,
|
|
4685
4727
|
filePath: body.filePath, selection: body.selection, canEdit, isJson,
|
|
4686
4728
|
model: body.model || undefined,
|
|
@@ -4689,11 +4731,12 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4689
4731
|
});
|
|
4690
4732
|
const actionResults = await executeDocChatActions(actions);
|
|
4691
4733
|
const baseReply = (extra = {}) => ({
|
|
4692
|
-
ok:
|
|
4734
|
+
ok: !ccError,
|
|
4693
4735
|
answer,
|
|
4694
4736
|
actions,
|
|
4695
4737
|
...(actionResults ? { actionResults } : {}),
|
|
4696
4738
|
...(actionParseError ? { actionParseError } : {}),
|
|
4739
|
+
...(ccError ? { error: ccError } : {}),
|
|
4697
4740
|
...extra,
|
|
4698
4741
|
});
|
|
4699
4742
|
|
|
@@ -4795,7 +4838,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4795
4838
|
|
|
4796
4839
|
try {
|
|
4797
4840
|
|
|
4798
|
-
const { answer, content, actions, actionParseError } = await ccDocCallStreaming({
|
|
4841
|
+
const { answer, content, actions, actionParseError, error: ccError } = await ccDocCallStreaming({
|
|
4799
4842
|
message: body.message, document: currentContent, title: body.title,
|
|
4800
4843
|
filePath: body.filePath, selection: body.selection, canEdit, isJson,
|
|
4801
4844
|
model: body.model || undefined,
|
|
@@ -4811,6 +4854,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4811
4854
|
actions,
|
|
4812
4855
|
...(actionResults ? { actionResults } : {}),
|
|
4813
4856
|
...(actionParseError ? { actionParseError } : {}),
|
|
4857
|
+
...(ccError ? { error: ccError } : {}),
|
|
4814
4858
|
...extra,
|
|
4815
4859
|
});
|
|
4816
4860
|
|
|
@@ -287,12 +287,33 @@ function getSkillWriteTargets({ homeDir = os.homedir(), project = null } = {}) {
|
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
// Stamped into every session.json this adapter writes so the pre-spawn resume
|
|
291
|
+
// path can detect "session was produced by a different runtime" — Claude
|
|
292
|
+
// rejects Copilot session IDs (and vice versa) with "No conversation found",
|
|
293
|
+
// which would otherwise burn a retry slot before the post-failure cleanup at
|
|
294
|
+
// engine.js:1195 fires. See W-mot9fwya000d09cb.
|
|
295
|
+
const RUNTIME_NAME = 'claude';
|
|
296
|
+
|
|
290
297
|
function getResumeSessionId({ agentId, branchName, agentsDir, maxAgeMs = 2 * 60 * 60 * 1000, logger = console } = {}) {
|
|
291
298
|
if (!agentId || agentId.startsWith('temp-') || !agentsDir) return null;
|
|
299
|
+
const sessionPath = path.join(agentsDir, agentId, 'session.json');
|
|
292
300
|
try {
|
|
293
|
-
const sessionPath = path.join(agentsDir, agentId, 'session.json');
|
|
294
301
|
const sessionFile = _safeJson(sessionPath);
|
|
295
302
|
if (!sessionFile?.sessionId || !sessionFile.savedAt) return null;
|
|
303
|
+
|
|
304
|
+
// Runtime-mismatch invalidation. Distinct from stale-by-age: the session is
|
|
305
|
+
// structurally unusable on this runtime, so drop it AND clear session.json
|
|
306
|
+
// so the next dispatch starts fresh instead of failing with --resume.
|
|
307
|
+
// Legacy sessions (no `runtime` field) are treated as compatible — opt-in
|
|
308
|
+
// check, no false invalidations on first deploy.
|
|
309
|
+
if (sessionFile.runtime && sessionFile.runtime !== RUNTIME_NAME) {
|
|
310
|
+
if (logger && typeof logger.info === 'function') {
|
|
311
|
+
logger.info(`Skipping resume for ${agentId}: runtime mismatch (session: ${sessionFile.runtime}, current: ${RUNTIME_NAME}) — clearing session.json`);
|
|
312
|
+
}
|
|
313
|
+
try { fs.unlinkSync(sessionPath); } catch {}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
296
317
|
const sessionAge = Date.now() - new Date(sessionFile.savedAt).getTime();
|
|
297
318
|
const sameBranch = branchName && sessionFile.branch && sessionFile.branch === branchName;
|
|
298
319
|
if (sessionAge < maxAgeMs && sameBranch) {
|
|
@@ -315,6 +336,7 @@ function saveSession({ agentId, dispatchId, branch, sessionId, agentsDir, now =
|
|
|
315
336
|
dispatchId,
|
|
316
337
|
savedAt: typeof now === 'function' ? now() : new Date().toISOString(),
|
|
317
338
|
branch: branch || null,
|
|
339
|
+
runtime: RUNTIME_NAME,
|
|
318
340
|
});
|
|
319
341
|
return true;
|
|
320
342
|
} catch (err) {
|
|
@@ -306,12 +306,33 @@ function getSkillWriteTargets({ homeDir = os.homedir(), project = null } = {}) {
|
|
|
306
306
|
};
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
+
// Stamped into every session.json this adapter writes so the pre-spawn resume
|
|
310
|
+
// path can detect "session was produced by a different runtime" — Copilot
|
|
311
|
+
// rejects Claude session IDs (and vice versa) with "No conversation found",
|
|
312
|
+
// which would otherwise burn a retry slot before the post-failure cleanup at
|
|
313
|
+
// engine.js:1195 fires. See W-mot9fwya000d09cb.
|
|
314
|
+
const RUNTIME_NAME = 'copilot';
|
|
315
|
+
|
|
309
316
|
function getResumeSessionId({ agentId, branchName, agentsDir, maxAgeMs = 2 * 60 * 60 * 1000, logger = console } = {}) {
|
|
310
317
|
if (!agentId || agentId.startsWith('temp-') || !agentsDir) return null;
|
|
318
|
+
const sessionPath = path.join(agentsDir, agentId, 'session.json');
|
|
311
319
|
try {
|
|
312
|
-
const sessionPath = path.join(agentsDir, agentId, 'session.json');
|
|
313
320
|
const sessionFile = _safeJson(sessionPath);
|
|
314
321
|
if (!sessionFile?.sessionId || !sessionFile.savedAt) return null;
|
|
322
|
+
|
|
323
|
+
// Runtime-mismatch invalidation. Distinct from stale-by-age: the session is
|
|
324
|
+
// structurally unusable on this runtime, so drop it AND clear session.json
|
|
325
|
+
// so the next dispatch starts fresh instead of failing with --resume.
|
|
326
|
+
// Legacy sessions (no `runtime` field) are treated as compatible — opt-in
|
|
327
|
+
// check, no false invalidations on first deploy.
|
|
328
|
+
if (sessionFile.runtime && sessionFile.runtime !== RUNTIME_NAME) {
|
|
329
|
+
if (logger && typeof logger.info === 'function') {
|
|
330
|
+
logger.info(`Skipping resume for ${agentId}: runtime mismatch (session: ${sessionFile.runtime}, current: ${RUNTIME_NAME}) — clearing session.json`);
|
|
331
|
+
}
|
|
332
|
+
try { fs.unlinkSync(sessionPath); } catch {}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
|
|
315
336
|
const sessionAge = Date.now() - new Date(sessionFile.savedAt).getTime();
|
|
316
337
|
const sameBranch = branchName && sessionFile.branch && sessionFile.branch === branchName;
|
|
317
338
|
if (sessionAge < maxAgeMs && sameBranch) {
|
|
@@ -334,6 +355,7 @@ function saveSession({ agentId, dispatchId, branch, sessionId, agentsDir, now =
|
|
|
334
355
|
dispatchId,
|
|
335
356
|
savedAt: typeof now === 'function' ? now() : new Date().toISOString(),
|
|
336
357
|
branch: branch || null,
|
|
358
|
+
runtime: RUNTIME_NAME,
|
|
337
359
|
});
|
|
338
360
|
return true;
|
|
339
361
|
} catch (err) {
|
package/engine/spawn-agent.js
CHANGED
|
@@ -355,11 +355,14 @@ function main() {
|
|
|
355
355
|
|
|
356
356
|
// Clean up sys tmp (only created for non-resume sessions on adapters that
|
|
357
357
|
// use --system-prompt-file).
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
//
|
|
358
|
+
//
|
|
359
|
+
// We deliberately DO NOT use a fixed-delay setTimeout here. Claude CLI reads
|
|
360
|
+
// `--system-prompt-file` lazily during init; on cold starts (MCP boot,
|
|
361
|
+
// `--add-dir` traversal, Windows process startup) the read can land well
|
|
362
|
+
// after any short timer fires, leaving Claude to bail with
|
|
363
|
+
// "System prompt file not found". The exit/SIGTERM handler below — plus the
|
|
364
|
+
// matching unlinks in engine/dispatch.js and engine/meeting.js on dispatch
|
|
365
|
+
// completion — are sufficient to keep tmp files from leaking.
|
|
363
366
|
function _cleanupSpawnTempFiles() {
|
|
364
367
|
if (wantsSystemPromptFile) {
|
|
365
368
|
try { fs.unlinkSync(sysTmpPath); } catch { /* may already be cleaned */ }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1740",
|
|
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"
|