dual-brain 0.3.19 → 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 -74
  2. package/package.json +1 -1
@@ -2719,79 +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
- const DIM = '\x1b[2m', RST = '\x1b[0m', YLW = '\x1b[33m';
2725
- process.stdout.write(`\n ${YLW}Continue:${RST} ${interrupted.sessionName}\n`);
2726
- if (interrupted.lastState) {
2727
- process.stdout.write(` ${DIM}Last: ${interrupted.lastState} · ${interrupted.ageLabel}${RST}\n`);
2728
- } else {
2729
- process.stdout.write(` ${DIM}${interrupted.reason} · ${interrupted.ageLabel}${RST}\n`);
2730
- }
2731
- process.stdout.write(` \x1b[36mEnter\x1b[0m resume \x1b[36mn\x1b[0m new \x1b[36ms\x1b[0m skip\n\n`);
2732
-
2733
- // Wait for a keypress to decide what to do with the card
2734
- const readline2 = await import('node:readline');
2735
- readline2.emitKeypressEvents(process.stdin, rl);
2736
-
2737
- const cardChoice = await new Promise((resolve) => {
2738
- const wasRaw2 = process.stdin.isRaw;
2739
- const canRaw2 = process.stdin.isTTY && typeof process.stdin.setRawMode === 'function';
2740
- if (canRaw2) process.stdin.setRawMode(true);
2741
-
2742
- const cleanup2 = () => {
2743
- process.stdin.removeListener('keypress', onCardKey);
2744
- if (canRaw2) {
2745
- try { process.stdin.setRawMode(wasRaw2 || false); } catch {}
2746
- }
2747
- };
2748
-
2749
- const onCardKey = (str, key) => {
2750
- if (!key) return;
2751
- const name = key.name || '';
2752
- const seq = key.sequence || str || '';
2753
-
2754
- if (key.ctrl && (name === 'c' || name === 'd')) {
2755
- cleanup2();
2756
- process.stdout.write('\n');
2757
- resolve('q');
2758
- return;
2759
- }
2760
-
2761
- if (name === 'return' || name === 'enter' || seq === '\r' || seq === '\n') {
2762
- cleanup2();
2763
- process.stdout.write('\n');
2764
- resolve('resume');
2765
- return;
2766
- }
2767
-
2768
- if (!str || str.length === 0) return;
2769
- const lower = str.toLowerCase();
2770
- if (lower === 'n' || lower === 's' || lower === 'q') {
2771
- cleanup2();
2772
- process.stdout.write('\n');
2773
- resolve(lower);
2774
- return;
2775
- }
2776
- };
2777
-
2778
- process.stdin.on('keypress', onCardKey);
2779
- });
2780
-
2781
- if (cardChoice === 'q') return { next: 'exit' };
2782
-
2783
- if (cardChoice === 'resume') {
2784
- const { spawnSync } = await import('node:child_process');
2785
- process.stdout.write(` Launching: claude --resume ${interrupted.sessionId}\n\n`);
2786
- spawnSync('claude', _claudeResumeArgs(interrupted.sessionId, cwd), { stdio: 'inherit' });
2787
- saveTerminalState(cwd, getTerminalId(), interrupted.sessionId, 'claude');
2788
- return { next: 'main' };
2789
- }
2790
-
2791
- if (cardChoice === 'n') return { next: 'new-session' };
2792
-
2793
- // 's' → fall through to normal dashboard
2794
- }
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.
2795
2724
 
2796
2725
  // ── Environment awareness (powers Box 1 dots + Box 3) ────────────────────
2797
2726
  let envReport = null;
@@ -3193,7 +3122,12 @@ async function mainScreen(rl, ask) {
3193
3122
  }
3194
3123
 
3195
3124
  // Resume / continuation hint
3196
- 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) {
3197
3131
  const labelTrunc = (resumeState.label || 'last session').slice(0, 40);
3198
3132
  const agePart = resumeState.ageLabel ? ` ${DIM}${resumeState.ageLabel}${RST}` : '';
3199
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.19",
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": {