@yemi33/minions 0.1.1932 → 0.1.1933

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/dashboard.js CHANGED
@@ -6368,7 +6368,28 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6368
6368
  let accumulated = '';
6369
6369
  let sessionHandle = null;
6370
6370
  let resolveResult;
6371
+ // Per-turn phase timing — emitted as one structured [cc-timing] log line
6372
+ // so we can attribute Copilot CC slowness (e.g. 36s) to spawn vs first-byte
6373
+ // vs streaming vs trailing inference. Parallels engine.js's [spawn-timing].
6374
+ const _tStart = Date.now();
6375
+ let _tFirstByte = null;
6376
+ let _tFirstTool = null;
6377
+ let _chunkCount = 0;
6378
+ let _toolUseCount = 0;
6371
6379
  const promise = new Promise((resolve) => { resolveResult = resolve; });
6380
+ const _emitTimingLog = (lifecycle, sessionReady, streamEnd, outcome) => {
6381
+ try {
6382
+ const _diff = (a, b) => (a != null && b != null) ? (b - a) : null;
6383
+ const timings = {
6384
+ get_session: _diff(_tStart, sessionReady),
6385
+ first_byte: _diff(sessionReady, _tFirstByte),
6386
+ first_tool: _diff(sessionReady, _tFirstTool),
6387
+ stream: _diff(sessionReady, streamEnd),
6388
+ total: _diff(_tStart, streamEnd),
6389
+ };
6390
+ shared.log('info', `[cc-timing] tab=${resolvedTabId} lifecycle=${lifecycle || 'unknown'} outcome=${outcome} chunks=${_chunkCount} tools=${_toolUseCount} ${JSON.stringify(timings)}`);
6391
+ } catch { /* telemetry is best-effort */ }
6392
+ };
6372
6393
  promise.abort = () => {
6373
6394
  cancelled = true;
6374
6395
  try { sessionHandle && sessionHandle.cancel(); } catch { /* swallow */ }
@@ -6383,6 +6404,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6383
6404
  systemPromptHash: _ccPromptHash,
6384
6405
  });
6385
6406
  } catch (err) {
6407
+ _emitTimingLog(null, null, Date.now(), 'spawn-failed');
6386
6408
  return resolveResult({
6387
6409
  text: '',
6388
6410
  sessionId: null,
@@ -6392,19 +6414,26 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6392
6414
  stderr: String((err && err.message) || err || 'cc-worker-pool spawn failed'),
6393
6415
  });
6394
6416
  }
6417
+ const _tSessionReady = Date.now();
6418
+ const _lifecycle = sessionHandle.lifecycle || 'unknown';
6395
6419
  if (cancelled) {
6396
6420
  try { sessionHandle.cancel(); } catch { /* swallow */ }
6421
+ _emitTimingLog(_lifecycle, _tSessionReady, Date.now(), 'cancelled-pre-stream');
6397
6422
  return resolveResult({ text: accumulated, sessionId: sessionHandle.sessionId, code: 0, usage: {}, raw: accumulated, stderr: '' });
6398
6423
  }
6399
6424
  await sessionHandle.stream(prompt, {
6400
6425
  systemPromptText: systemPrompt,
6401
6426
  onChunk: (delta) => {
6427
+ if (_tFirstByte == null) _tFirstByte = Date.now();
6428
+ _chunkCount += 1;
6402
6429
  accumulated += delta;
6403
6430
  _touchCcLiveStream(liveState);
6404
6431
  liveState.text = accumulated;
6405
6432
  if (liveState.writer) liveState.writer({ type: 'chunk', text: accumulated });
6406
6433
  },
6407
6434
  onToolUse: (name, input) => {
6435
+ if (_tFirstTool == null) _tFirstTool = Date.now();
6436
+ _toolUseCount += 1;
6408
6437
  _touchCcLiveStream(liveState);
6409
6438
  const safeInput = input || {};
6410
6439
  if (Array.isArray(toolUses)) toolUses.push({ name, input: safeInput });
@@ -6412,9 +6441,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6412
6441
  if (liveState.writer) liveState.writer({ type: 'tool', name, input: _lightToolInput(safeInput) });
6413
6442
  },
6414
6443
  onDone: () => {
6444
+ _emitTimingLog(_lifecycle, _tSessionReady, Date.now(), 'done');
6415
6445
  resolveResult({ text: accumulated, sessionId: sessionHandle.sessionId, code: 0, usage: {}, raw: accumulated, stderr: '' });
6416
6446
  },
6417
6447
  onError: (err) => {
6448
+ _emitTimingLog(_lifecycle, _tSessionReady, Date.now(), cancelled ? 'cancelled' : 'error');
6418
6449
  resolveResult({
6419
6450
  text: accumulated,
6420
6451
  sessionId: sessionHandle.sessionId,
@@ -483,6 +483,12 @@ async function getSession({ tabId, model, effort, mcpServers, systemPromptHash,
483
483
  if (!tabId) throw new Error('cc-worker-pool.getSession: tabId is required');
484
484
  const mcpServersHash = _hashMcpServers(mcpServers);
485
485
  let worker = _tabs.get(tabId);
486
+ // Track which lifecycle path we took so the dashboard's [cc-timing] log can
487
+ // attribute warm-reuse vs new-session vs cold-spawn. One of:
488
+ // 'warm-reuse' — proc + session both reused (no spawn, no session/new)
489
+ // 'new-session' — proc reused, fresh session/new (sysprompt hash changed)
490
+ // 'cold-spawn' — fresh proc + initialize + session/new
491
+ let lifecycle = 'warm-reuse';
486
492
 
487
493
  if (worker) {
488
494
  if (worker.killed) {
@@ -501,6 +507,7 @@ async function getSession({ tabId, model, effort, mcpServers, systemPromptHash,
501
507
  // caller has rotated in (Bug B / issue #2479).
502
508
  await worker.newSession({ mcpServers, systemPromptHash, model, effort });
503
509
  worker.lastUsedAt = _internals.now();
510
+ lifecycle = 'new-session';
504
511
  } else {
505
512
  // Warm reuse — only update bookkeeping. model/effort changes on a
506
513
  // warm session are tracked here but not pushed via configOptions in
@@ -524,12 +531,14 @@ async function getSession({ tabId, model, effort, mcpServers, systemPromptHash,
524
531
  try { worker.close(); } catch { /* already torn down */ }
525
532
  throw err;
526
533
  }
534
+ lifecycle = 'cold-spawn';
527
535
  }
528
536
 
529
537
  _ensureReaper();
530
538
 
531
539
  return {
532
540
  sessionId: worker.sessionId,
541
+ lifecycle,
533
542
  stream: (promptText, opts) => worker.stream(promptText, opts),
534
543
  cancel: () => worker.cancel(),
535
544
  close: () => closeTab(tabId),
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-14T03:48:55.090Z"
4
+ "cachedAt": "2026-05-14T03:53:21.722Z"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1932",
3
+ "version": "0.1.1933",
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"