dual-brain 0.1.13 → 0.1.15
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/bin/dual-brain.mjs +65 -2
- package/package.json +1 -1
package/bin/dual-brain.mjs
CHANGED
|
@@ -362,6 +362,18 @@ async function cmdGo(args) {
|
|
|
362
362
|
provider: plan?._decision?.provider ?? 'claude',
|
|
363
363
|
nextAction: null,
|
|
364
364
|
}, cwd);
|
|
365
|
+
// ── Next steps suggestions (dual-brain consensus path) ──────────────────
|
|
366
|
+
try {
|
|
367
|
+
const { suggestNextSteps, formatNextSteps } = await import('../src/nextstep.mjs');
|
|
368
|
+
const steps = await suggestNextSteps(
|
|
369
|
+
{ prompt, tier: plan?._decision?.tier ?? 'think', files, trigger: 'go' },
|
|
370
|
+
{ success: true, filesChanged: files, error: null, duration: null },
|
|
371
|
+
cwd
|
|
372
|
+
);
|
|
373
|
+
if (steps?.steps?.length > 0) {
|
|
374
|
+
console.log('\n' + formatNextSteps(steps.steps, 3));
|
|
375
|
+
}
|
|
376
|
+
} catch { /* non-fatal */ }
|
|
365
377
|
} else {
|
|
366
378
|
const statusLine = result.status === 'completed' ? 'Done' : `Failed (exit ${result.exitCode})`;
|
|
367
379
|
console.log(`\n${statusLine}${result.durationMs != null ? ` in ${(result.durationMs / 1000).toFixed(1)}s` : ''}`);
|
|
@@ -381,6 +393,28 @@ async function cmdGo(args) {
|
|
|
381
393
|
}, cwd);
|
|
382
394
|
if (result.status !== 'completed') process.exit(1);
|
|
383
395
|
await offerAutoCommit(cwd);
|
|
396
|
+
// ── Next steps suggestions ──────────────────────────────────────────────
|
|
397
|
+
try {
|
|
398
|
+
const { suggestNextSteps, formatNextSteps } = await import('../src/nextstep.mjs');
|
|
399
|
+
const steps = await suggestNextSteps(
|
|
400
|
+
{
|
|
401
|
+
prompt,
|
|
402
|
+
tier: plan?._decision?.tier ?? 'execute',
|
|
403
|
+
files: result.filesChanged || files,
|
|
404
|
+
trigger: 'go',
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
success: result.status === 'completed',
|
|
408
|
+
filesChanged: result.filesChanged || files,
|
|
409
|
+
error: result.error,
|
|
410
|
+
duration: result.durationMs,
|
|
411
|
+
},
|
|
412
|
+
cwd
|
|
413
|
+
);
|
|
414
|
+
if (steps?.steps?.length > 0) {
|
|
415
|
+
console.log('\n' + formatNextSteps(steps.steps, 3));
|
|
416
|
+
}
|
|
417
|
+
} catch { /* non-fatal — module may not exist yet */ }
|
|
384
418
|
}
|
|
385
419
|
}
|
|
386
420
|
|
|
@@ -465,8 +499,9 @@ async function cmdStatus(args = []) {
|
|
|
465
499
|
.filter(([k]) => k.startsWith(`${p.name}:`));
|
|
466
500
|
const sess = sessionStats[p.name] ?? { calls: 0, tokens: 0 };
|
|
467
501
|
|
|
502
|
+
const planStr = p.plan ? ` plan=${p.plan}` : '';
|
|
468
503
|
if (provStates.length === 0) {
|
|
469
|
-
console.log(` ${label}
|
|
504
|
+
console.log(` ${label}${planStr} status=healthy calls=${sess.calls} tokens=${sess.tokens}`);
|
|
470
505
|
} else {
|
|
471
506
|
for (const [k, st] of provStates) {
|
|
472
507
|
const modelClass = k.split(':').slice(1).join(':');
|
|
@@ -475,7 +510,7 @@ async function cmdStatus(args = []) {
|
|
|
475
510
|
const remaining = remainingCooldownMinutes(p.name, modelClass, cwd);
|
|
476
511
|
statusStr = remaining > 0 ? `hot (retry in ${remaining}m)` : 'hot (cooling)';
|
|
477
512
|
}
|
|
478
|
-
console.log(` ${label}
|
|
513
|
+
console.log(` ${label}${planStr} model=${modelClass} status=${statusStr} calls=${sess.calls} tokens=${sess.tokens}`);
|
|
479
514
|
}
|
|
480
515
|
}
|
|
481
516
|
}
|
|
@@ -1472,11 +1507,39 @@ async function mainScreen(rl, ask) {
|
|
|
1472
1507
|
statusRows.push(row(`\x1b[2m📦 data-tools v${dtVersion}\x1b[0m`));
|
|
1473
1508
|
}
|
|
1474
1509
|
|
|
1510
|
+
// ── Observer observations (top 2, high priority first) ───────────────────
|
|
1511
|
+
let quickObservations = [];
|
|
1512
|
+
try {
|
|
1513
|
+
const observerMod = await import('../src/observer.mjs');
|
|
1514
|
+
const quickState = await observerMod.getQuickState(cwd);
|
|
1515
|
+
if (quickState?.observations?.length > 0) {
|
|
1516
|
+
const PRIO = { high: 0, medium: 1, low: 2 };
|
|
1517
|
+
const sorted = [...quickState.observations].sort(
|
|
1518
|
+
(a, b) => (PRIO[a.priority] ?? 2) - (PRIO[b.priority] ?? 2)
|
|
1519
|
+
);
|
|
1520
|
+
quickObservations = sorted.slice(0, 2);
|
|
1521
|
+
for (const obs of quickObservations) {
|
|
1522
|
+
let prefix;
|
|
1523
|
+
if (obs.priority === 'high') prefix = '🔴';
|
|
1524
|
+
else if (obs.priority === 'medium') prefix = '🟡';
|
|
1525
|
+
else prefix = '\x1b[2m💡\x1b[0m';
|
|
1526
|
+
statusRows.push(row(`${prefix} ${obs.message}`));
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
} catch { /* non-fatal — module may not exist yet */ }
|
|
1530
|
+
|
|
1475
1531
|
// ── Action cards (git state + open PRs) ──────────────────────────────────
|
|
1476
1532
|
const repoState = detectRepoState(cwd);
|
|
1477
1533
|
const openPRs = await detectOpenPRs(cwd);
|
|
1478
1534
|
const actionRows = buildActionRows(repoState, row, openPRs);
|
|
1479
1535
|
|
|
1536
|
+
// ── High-priority observer action cards ───────────────────────────────────
|
|
1537
|
+
if (quickObservations.some(o => o.priority === 'high')) {
|
|
1538
|
+
const DIM = '\x1b[2m';
|
|
1539
|
+
const RESET = '\x1b[0m';
|
|
1540
|
+
actionRows.push(row(`${DIM}[r] Security review [t] Run tests [c] Commit${RESET}`));
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1480
1543
|
// ── Related sessions hint (only when no continuation card is showing) ─────
|
|
1481
1544
|
if (!interrupted && recentSessions.length > 0) {
|
|
1482
1545
|
try {
|
package/package.json
CHANGED