@yemi33/minions 0.1.734 → 0.1.735

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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.735 (2026-04-09)
4
+
5
+ ### Features
6
+ - configurable ccMaxTurns, native binary detection, relaxed CC exit check
7
+
3
8
  ## 0.1.734 (2026-04-09)
4
9
 
5
10
  ### Fixes
package/dashboard.js CHANGED
@@ -654,7 +654,8 @@ function updateSession(store, key, sessionId, existing) {
654
654
  * @param {number} opts.maxTurns - Max tool-use turns
655
655
  * @param {string} opts.allowedTools - Comma-separated tool list
656
656
  */
657
- async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns = 25, allowedTools = 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch', skipStatePreamble = false, model } = {}) {
657
+ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns, allowedTools = 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch', skipStatePreamble = false, model } = {}) {
658
+ if (!maxTurns) maxTurns = CONFIG.engine?.ccMaxTurns || shared.ENGINE_DEFAULTS.ccMaxTurns;
658
659
  if (!model) model = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
659
660
  const ccEffort = CONFIG.engine?.ccEffort || shared.ENGINE_DEFAULTS.ccEffort;
660
661
  const existing = resolveSession(store, sessionKey);
@@ -676,18 +677,16 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
676
677
  });
677
678
  llm.trackEngineUsage(label, result.usage);
678
679
 
679
- if (result.code === 0 && result.text) {
680
+ if (result.text) {
680
681
  updateSession(store, sessionKey, result.sessionId || sessionId, true);
681
682
  return result;
682
683
  }
683
684
 
684
- // Distinguish "session exists but call failed" (e.g. tool timeout, signal timeout)
685
+ // No text — distinguish "session exists but call failed" (e.g. tool timeout)
685
686
  // from "session is truly dead" (no sessionId returned, or stderr indicates invalid session).
686
- // If the session still exists, preserve it so the next "try again" can resume.
687
687
  const sessionStillValid = llm.isResumeSessionStillValid(result);
688
688
  if (sessionStillValid) {
689
689
  console.log(`[${label}] Resume call failed (code=${result.code}, empty=${!result.text}) but session is still valid — preserving session for retry`);
690
- // Update lastActiveAt so session doesn't expire while user retries
691
690
  updateSession(store, sessionKey, result.sessionId || sessionId, true);
692
691
  return result;
693
692
  }
@@ -711,7 +710,7 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
711
710
  });
712
711
  llm.trackEngineUsage(label, result.usage);
713
712
 
714
- if (result.code === 0 && result.text) {
713
+ if (result.text) {
715
714
  updateSession(store, sessionKey, result.sessionId, false);
716
715
  return result;
717
716
  }
@@ -725,7 +724,7 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
725
724
  });
726
725
  llm.trackEngineUsage(label, result.usage);
727
726
 
728
- if (result.code === 0 && result.text) {
727
+ if (result.text) {
729
728
  updateSession(store, sessionKey, result.sessionId, false);
730
729
  }
731
730
  return result;
@@ -3277,7 +3276,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3277
3276
 
3278
3277
  const result = await ccCall(body.message, { store: 'cc' });
3279
3278
 
3280
- if (result.code !== 0 || !result.text) {
3279
+ // Non-zero exit with text = max_turns or partial success — still usable
3280
+ if (!result.text) {
3281
3281
  const debugInfo = result.code !== 0 ? `(exit code ${result.code})` : '(empty response)';
3282
3282
  const stderrTail = (result.stderr || '').trim().split('\n').filter(Boolean).slice(-5).join(' | ');
3283
3283
  console.error(`[CC] LLM failed after retries ${debugInfo}: ${stderrTail}`);
@@ -3330,8 +3330,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3330
3330
  const { callLLMStreaming, trackEngineUsage: trackUsage } = require('./engine/llm');
3331
3331
  const streamModel = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
3332
3332
  const streamEffort = CONFIG.engine?.ccEffort || shared.ENGINE_DEFAULTS.ccEffort;
3333
+ const ccMaxTurns = CONFIG.engine?.ccMaxTurns || shared.ENGINE_DEFAULTS.ccMaxTurns;
3333
3334
  const llmPromise = callLLMStreaming(prompt, CC_STATIC_SYSTEM_PROMPT, {
3334
- timeout: 900000, label: 'command-center', model: streamModel, maxTurns: 25,
3335
+ timeout: 900000, label: 'command-center', model: streamModel, maxTurns: ccMaxTurns,
3335
3336
  allowedTools: 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch',
3336
3337
  sessionId, effort: streamEffort, direct: true,
3337
3338
  onChunk: (text) => {
@@ -3345,8 +3346,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3345
3346
  const result = await llmPromise;
3346
3347
  trackUsage('command-center', result.usage);
3347
3348
 
3348
- // Handle failure — same error reporting as non-streaming
3349
- if (result.code !== 0 || !result.text) {
3349
+ // Handle failure — non-zero exit with text = max_turns or partial success, still usable
3350
+ if (!result.text) {
3350
3351
  const debugInfo = result.code !== 0 ? `(exit code ${result.code})` : '(empty response)';
3351
3352
  const stderrTail = (result.stderr || '').trim().split('\n').filter(Boolean).slice(-3).join(' | ');
3352
3353
  console.error(`[CC-stream] Failed: code=${result.code}, stderr=${(result.stderr || '').slice(0, 500)}, stdout_tail=${(result.raw || '').slice(-500)}`);
@@ -37,7 +37,7 @@ function findClaudeBinary() {
37
37
  for (const p of searchPaths) {
38
38
  try { if (fs.existsSync(p)) return p; } catch {}
39
39
  }
40
- // Fallback: which/where → resolve wrapper to cli.js
40
+ // Fallback: which/where → resolve wrapper to cli.js, or detect native binary
41
41
  try {
42
42
  const isWin = process.platform === 'win32';
43
43
  const cmd = isWin ? 'where claude 2>NUL' : 'which claude 2>/dev/null';
@@ -55,7 +55,11 @@ function findClaudeBinary() {
55
55
  const candidate = path.join(path.dirname(whichNative), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
56
56
  if (fs.existsSync(candidate)) return candidate;
57
57
  }
58
- } catch {}
58
+ } catch {
59
+ // Can't read as text — it's a compiled native binary
60
+ }
61
+ // Native installer binary on PATH — use directly
62
+ return whichNative;
59
63
  }
60
64
  } catch { /* optional */ }
61
65
  // Last resort: npm root -g
@@ -101,9 +105,11 @@ function runPreflight(opts = {}) {
101
105
  // 3. Claude Code CLI
102
106
  const claudeBin = findClaudeBinary();
103
107
  if (claudeBin) {
104
- results.push({ name: 'Claude Code CLI', ok: true, message: path.basename(path.dirname(path.dirname(claudeBin))) });
108
+ const isNative = !claudeBin.endsWith('cli.js');
109
+ const label = isNative ? 'native' : path.basename(path.dirname(path.dirname(claudeBin)));
110
+ results.push({ name: 'Claude Code CLI', ok: true, message: label });
105
111
  } else {
106
- results.push({ name: 'Claude Code CLI', ok: false, message: 'not found — install with: npm install -g @anthropic-ai/claude-code' });
112
+ results.push({ name: 'Claude Code CLI', ok: false, message: 'not found — install from https://claude.ai/download or: npm install -g @anthropic-ai/claude-code' });
107
113
  allOk = false;
108
114
  }
109
115
 
package/engine/shared.js CHANGED
@@ -549,6 +549,7 @@ const ENGINE_DEFAULTS = {
549
549
  buildFixGracePeriod: 600000, // 10min — wait for CI to run after build fix before re-dispatching
550
550
  ccModel: 'sonnet', // model for Command Center and doc-chat (sonnet, haiku, opus)
551
551
  ccEffort: null, // effort level for CC/doc-chat (null, 'low', 'medium', 'high')
552
+ ccMaxTurns: 50, // max tool-use turns for CC/doc-chat before CLI stops
552
553
  };
553
554
 
554
555
  // ─── Status & Type Constants ─────────────────────────────────────────────────
@@ -108,7 +108,7 @@ if (isResume) {
108
108
  }
109
109
 
110
110
  if (!claudeBin) {
111
- const msg = 'FATAL: Cannot find claude-code cli.js — install with: npm install -g @anthropic-ai/claude-code';
111
+ const msg = 'FATAL: Cannot find Claude Code CLI — install from https://claude.ai/download or: npm install -g @anthropic-ai/claude-code';
112
112
  fs.appendFileSync(debugPath, msg + '\n');
113
113
  console.error(msg);
114
114
  process.exit(78); // 78 = configuration error (distinct from runtime failures)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.734",
3
+ "version": "0.1.735",
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"
@@ -1,42 +0,0 @@
1
- {
2
- "id": "pr-review-fix-cycle",
3
- "title": "PR Review & Fix Cycle",
4
- "description": "Visualizes the default engine flow: review a PR, fix issues if rejected, re-review until approved and build passes.",
5
- "trigger": { "manual": true },
6
- "stages": [
7
- {
8
- "id": "review-pr",
9
- "type": "task",
10
- "taskType": "review",
11
- "title": "Review PR",
12
- "description": "Review the target PR for correctness, quality, and completeness. Provide actionable feedback if changes are needed."
13
- },
14
- {
15
- "id": "check-review-status",
16
- "type": "condition",
17
- "title": "Approved?",
18
- "check": "allBuildsGreen",
19
- "action": "stop",
20
- "onMet": "Merge",
21
- "onUnmet": "Fix",
22
- "dependsOn": ["review-pr"]
23
- },
24
- {
25
- "id": "fix-feedback",
26
- "type": "task",
27
- "taskType": "fix",
28
- "title": "Fix review feedback",
29
- "description": "Address all review comments and push fixes to the PR branch.",
30
- "dependsOn": ["check-review-status"]
31
- },
32
- {
33
- "id": "re-review",
34
- "type": "task",
35
- "taskType": "review",
36
- "title": "Re-review after fix",
37
- "description": "Re-review the PR after fixes have been applied. Verify all prior feedback was addressed.",
38
- "dependsOn": ["fix-feedback"]
39
- }
40
- ],
41
- "stopWhen": "allBuildsGreen"
42
- }