@yemi33/minions 0.1.1928 → 0.1.1929

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.
@@ -98,6 +98,19 @@ function _hashMcpServers(mcpServers) {
98
98
  return crypto.createHash('sha256').update(json).digest('hex');
99
99
  }
100
100
 
101
+ // Bug B (issue #2479): `model` and `effort` were stored on the Worker but
102
+ // never forwarded to ACP `session/new`, so any `ccModel` override was silently
103
+ // dropped on the pool path. Build the params object here and only include
104
+ // fields that are defined — sending `model: undefined` would force the daemon
105
+ // onto its built-in default instead of letting it pick whatever the user has
106
+ // configured globally.
107
+ function _buildSessionNewParams({ cwd, mcpServers, model, effort }) {
108
+ const params = { cwd, mcpServers: mcpServers || [] };
109
+ if (model !== undefined && model !== null && model !== '') params.model = model;
110
+ if (effort !== undefined && effort !== null && effort !== '') params.effort = effort;
111
+ return params;
112
+ }
113
+
101
114
  class Worker {
102
115
  constructor({ tabId, model, effort, mcpServers, mcpServersHash, systemPromptHash, cwd }) {
103
116
  this.tabId = tabId;
@@ -170,7 +183,9 @@ class Worker {
170
183
  earlyExitPromise,
171
184
  ]);
172
185
  const result = await Promise.race([
173
- this._call('session/new', { cwd: this.cwd, mcpServers: this.mcpServers }),
186
+ this._call('session/new', _buildSessionNewParams({
187
+ cwd: this.cwd, mcpServers: this.mcpServers, model: this.model, effort: this.effort,
188
+ })),
174
189
  earlyExitPromise,
175
190
  ]);
176
191
  this.sessionId = result && result.sessionId;
@@ -344,7 +359,7 @@ class Worker {
344
359
  this._notify('session/cancel', { sessionId: this.inflight.sessionId });
345
360
  }
346
361
 
347
- async newSession({ mcpServers, systemPromptHash }) {
362
+ async newSession({ mcpServers, systemPromptHash, model, effort }) {
348
363
  // Cancel any inflight before swapping the underlying session.
349
364
  if (this.inflight) {
350
365
  this.cancel();
@@ -360,10 +375,15 @@ class Worker {
360
375
  wait();
361
376
  });
362
377
  }
363
- const result = await this._call('session/new', {
364
- cwd: this.cwd,
365
- mcpServers: mcpServers || [],
366
- });
378
+ // Bug B (issue #2479): if the caller is rotating the session because the
379
+ // system prompt changed, they may also be passing a fresh model/effort —
380
+ // update bookkeeping BEFORE session/new so the new fields land on the
381
+ // daemon. Falls through to whatever we already had when callers omit them.
382
+ if (model !== undefined) this.model = model;
383
+ if (effort !== undefined) this.effort = effort;
384
+ const result = await this._call('session/new', _buildSessionNewParams({
385
+ cwd: this.cwd, mcpServers: mcpServers || [], model: this.model, effort: this.effort,
386
+ }));
367
387
  this.sessionId = result && result.sessionId;
368
388
  this.systemPromptHash = systemPromptHash;
369
389
  this.firstSystemPromptSent = false;
@@ -425,9 +445,9 @@ async function getSession({ tabId, model, effort, mcpServers, systemPromptHash,
425
445
  } else if (worker.systemPromptHash !== systemPromptHash) {
426
446
  // System prompt changed → keep the warm process, drop the session
427
447
  // and create a fresh one. Saves the ~2.1 s initialize handshake.
428
- await worker.newSession({ mcpServers, systemPromptHash });
429
- worker.model = model;
430
- worker.effort = effort;
448
+ // Pass model/effort so the NEW session picks up any override the
449
+ // caller has rotated in (Bug B / issue #2479).
450
+ await worker.newSession({ mcpServers, systemPromptHash, model, effort });
431
451
  worker.lastUsedAt = _internals.now();
432
452
  } else {
433
453
  // Warm reuse — only update bookkeeping. model/effort changes on a
@@ -507,6 +527,7 @@ module.exports = {
507
527
  _internals,
508
528
  _tabs,
509
529
  _reapIdleTabs,
530
+ _buildSessionNewParams,
510
531
  IDLE_REAPER_MS,
511
532
  REAPER_INTERVAL_MS,
512
533
  };
@@ -0,0 +1,5 @@
1
+ {
2
+ "runtime": "copilot",
3
+ "models": null,
4
+ "cachedAt": "2026-05-14T02:50:03.274Z"
5
+ }
@@ -2,27 +2,51 @@
2
2
  * engine/features.js — Feature flag registry. Recipe in CLAUDE.md → "Feature Flags".
3
3
  */
4
4
 
5
- // Entry shape: id → { description, default: bool, addedIn?: version, expires?: ISO-date }
5
+ // Entry shape: id → { description, default: bool, addedIn?: version, expires?: ISO-date, requiredCcRuntime?: string }
6
6
  //
7
- // INTENTIONAL EMPTY REGISTRY — DO NOT DELETE.
7
+ // Optional fields:
8
+ // `requiredCcRuntime` (e.g. 'copilot') signals that the flag only takes
9
+ // effect when `resolveCcCli(engine)` matches. The dashboard uses this to
10
+ // render the toggle as disabled with a tooltip when the configured CC
11
+ // runtime is incompatible. Engine code still has to gate explicitly via
12
+ // `isFeatureOn` + a runtime check — `requiredCcRuntime` is a UX hint only.
13
+ //
14
+ // REGISTRY GROWTH POLICY — DO NOT DELETE THE FRAMEWORK.
8
15
  //
9
- // The `FEATURES = {}` literal below is intentional scaffolding, not dead code.
10
16
  // The surrounding framework (isFeatureOn, listFeatures, hasFeature, env-var
11
17
  // override resolver, expiration timestamps) is load-bearing: dashboard.js
12
18
  // boot wires it into /api/features (list), /api/features/toggle, and the
13
19
  // `window.MINIONS_FEATURES` client bootstrap. Deleting the registry — even
14
- // while empty — would break dashboard startup and the experimental-flags UI.
20
+ // if it became empty — would break dashboard startup and the experimental-flags UI.
15
21
  //
16
22
  // New flags belong here. Register them in this object instead of removing
17
- // the empty literal. The first real entry will replace the example below;
18
- // until then the empty object is the correct, expected shape.
23
+ // entries. Keep at least one entry so the framework remains demonstrably wired.
19
24
  //
20
25
  // Decision logged in the 2026-05-13 daily architecture & bug review meeting
21
26
  // (knowledge/architecture/2026-05-13-ripley-meeting-conclusion-daily-architecture-bug-review-2.md,
22
- // PR-C, Option B — keep framework, document the empty registry).
27
+ // PR-C, Option B — keep framework, document the registry).
23
28
  const FEATURES = {
24
- // Example:
25
- // 'ux-sidebar-v2': { description: '…', default: false, addedIn: '0.1.1738', expires: '2026-06-01' },
29
+ // ccUseWorkerPool — sub-tasks B/C/D of W-mp2w003600196c51 (CC perf).
30
+ // Routes Command Center / doc-chat through engine/cc-worker-pool.js
31
+ // (persistent `copilot --acp` per CC tab) instead of spawning a fresh CLI
32
+ // per turn. Saves ~14 s of cold-start cost. Copilot-only — the pool drives
33
+ // ACP which Claude does not implement.
34
+ //
35
+ // Resolution: `shared.resolveCcUseWorkerPool(engine)` (engine/shared.js)
36
+ // is the canonical predicate every dashboard.js call site uses. Explicit
37
+ // `engine.ccUseWorkerPool` true/false in config wins; otherwise the helper
38
+ // defaults ON for `copilot` and OFF for `claude`. PR #2492 flipped the
39
+ // default ON for copilot; see that PR for the cold-spawn measurements.
40
+ //
41
+ // `requiredCcRuntime: 'copilot'` here is a UX hint — the Settings panel
42
+ // greys out the toggle when the resolved CC runtime mismatches so users
43
+ // see the constraint instead of toggling a no-op.
44
+ 'ccUseWorkerPool': {
45
+ description: 'Route Command Center / doc-chat through a persistent `copilot --acp` worker per tab instead of spawning a fresh CLI per turn (~14s cold-start savings). Copilot-only — has no effect when the CC runtime is Claude.',
46
+ default: false,
47
+ addedIn: '0.1.1916',
48
+ requiredCcRuntime: 'copilot',
49
+ },
26
50
  };
27
51
 
28
52
  const ENV_TRUTHY = new Set(['1', 'true', 'on', 'yes']);
@@ -64,6 +88,7 @@ function listFeatures(config, registry = FEATURES) {
64
88
  addedIn: meta.addedIn || null,
65
89
  expires: meta.expires || null,
66
90
  expired: expiresAt < now,
91
+ requiredCcRuntime: meta.requiredCcRuntime || null,
67
92
  };
68
93
  });
69
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1928",
3
+ "version": "0.1.1929",
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"