dual-brain 0.3.20 → 0.3.21

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.
Files changed (2) hide show
  1. package/bin/dual-brain.mjs +8 -76
  2. package/package.json +1 -1
@@ -2719,81 +2719,8 @@ async function mainScreen(rl, ask) {
2719
2719
  const termW = process.stdout.columns || 80;
2720
2720
  const W = Math.min(termW - 2, 78); // usable content width
2721
2721
 
2722
- // ── Continuation card (interrupted work) ─────────────────────────────────
2723
- if (interrupted) {
2724
- if (_spinnerTimeout) clearTimeout(_spinnerTimeout);
2725
- if (dashSpinner) { try { dashSpinner.stop(); } catch {} dashSpinner = null; }
2726
- const DIM = '\x1b[2m', RST = '\x1b[0m', YLW = '\x1b[33m';
2727
- process.stdout.write(`\n ${YLW}Continue:${RST} ${interrupted.sessionName}\n`);
2728
- if (interrupted.lastState) {
2729
- process.stdout.write(` ${DIM}Last: ${interrupted.lastState} · ${interrupted.ageLabel}${RST}\n`);
2730
- } else {
2731
- process.stdout.write(` ${DIM}${interrupted.reason} · ${interrupted.ageLabel}${RST}\n`);
2732
- }
2733
- process.stdout.write(` \x1b[36mEnter\x1b[0m resume \x1b[36mn\x1b[0m new \x1b[36ms\x1b[0m skip\n\n`);
2734
-
2735
- // Wait for a keypress to decide what to do with the card
2736
- const readline2 = await import('node:readline');
2737
- readline2.emitKeypressEvents(process.stdin, rl);
2738
-
2739
- const cardChoice = await new Promise((resolve) => {
2740
- const wasRaw2 = process.stdin.isRaw;
2741
- const canRaw2 = process.stdin.isTTY && typeof process.stdin.setRawMode === 'function';
2742
- if (canRaw2) process.stdin.setRawMode(true);
2743
-
2744
- const cleanup2 = () => {
2745
- process.stdin.removeListener('keypress', onCardKey);
2746
- if (canRaw2) {
2747
- try { process.stdin.setRawMode(wasRaw2 || false); } catch {}
2748
- }
2749
- };
2750
-
2751
- const onCardKey = (str, key) => {
2752
- if (!key) return;
2753
- const name = key.name || '';
2754
- const seq = key.sequence || str || '';
2755
-
2756
- if (key.ctrl && (name === 'c' || name === 'd')) {
2757
- cleanup2();
2758
- process.stdout.write('\n');
2759
- resolve('q');
2760
- return;
2761
- }
2762
-
2763
- if (name === 'return' || name === 'enter' || seq === '\r' || seq === '\n') {
2764
- cleanup2();
2765
- process.stdout.write('\n');
2766
- resolve('resume');
2767
- return;
2768
- }
2769
-
2770
- if (!str || str.length === 0) return;
2771
- const lower = str.toLowerCase();
2772
- if (lower === 'n' || lower === 's' || lower === 'q') {
2773
- cleanup2();
2774
- process.stdout.write('\n');
2775
- resolve(lower);
2776
- return;
2777
- }
2778
- };
2779
-
2780
- process.stdin.on('keypress', onCardKey);
2781
- });
2782
-
2783
- if (cardChoice === 'q') return { next: 'exit' };
2784
-
2785
- if (cardChoice === 'resume') {
2786
- const { spawnSync } = await import('node:child_process');
2787
- process.stdout.write(` Launching: claude --resume ${interrupted.sessionId}\n\n`);
2788
- spawnSync('claude', _claudeResumeArgs(interrupted.sessionId, cwd), { stdio: 'inherit' });
2789
- saveTerminalState(cwd, getTerminalId(), interrupted.sessionId, 'claude');
2790
- return { next: 'main' };
2791
- }
2792
-
2793
- if (cardChoice === 'n') return { next: 'new-session' };
2794
-
2795
- // 's' → fall through to normal dashboard
2796
- }
2722
+ // Interrupted work is rendered as a dashboard signal below. New shells should
2723
+ // always land in the full menu instead of blocking on a pre-dashboard prompt.
2797
2724
 
2798
2725
  // ── Environment awareness (powers Box 1 dots + Box 3) ────────────────────
2799
2726
  let envReport = null;
@@ -3195,7 +3122,12 @@ async function mainScreen(rl, ask) {
3195
3122
  }
3196
3123
 
3197
3124
  // Resume / continuation hint
3198
- if (isReturning) {
3125
+ if (interrupted) {
3126
+ const labelTrunc = (interrupted.sessionName || 'last session').slice(0, 40);
3127
+ const agePart = interrupted.ageLabel ? ` ${DIM}${interrupted.ageLabel}${RST}` : '';
3128
+ const statePart = interrupted.lastState ? ` ${DIM}→ ${interrupted.lastState.slice(0, 48)}${RST}` : '';
3129
+ signalLines.push(`${CYAN}↩${RST} Resume: ${BOLD}${labelTrunc}${RST}${agePart}${statePart}`);
3130
+ } else if (isReturning) {
3199
3131
  const labelTrunc = (resumeState.label || 'last session').slice(0, 40);
3200
3132
  const agePart = resumeState.ageLabel ? ` ${DIM}${resumeState.ageLabel}${RST}` : '';
3201
3133
  const nextPart = resumeState.nextAction ? ` ${DIM}→ ${resumeState.nextAction}${RST}` : '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.3.20",
3
+ "version": "0.3.21",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {