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.
- package/bin/dual-brain.mjs +8 -74
- package/package.json +1 -1
package/bin/dual-brain.mjs
CHANGED
|
@@ -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
|
-
//
|
|
2723
|
-
|
|
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 (
|
|
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