dual-brain 0.3.12 → 0.3.14

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.
@@ -649,6 +649,72 @@ async function showToolsMenu(rl) {
649
649
  }
650
650
  }
651
651
 
652
+ // ─── Submenu: Data Tools Status ───────────────────────────────────────────
653
+
654
+ async function showDataToolsStatus(rl, providers) {
655
+ const dtPath = join(CWD, '.replit-tools');
656
+ const configPath = join(dtPath, 'config.json');
657
+ const claudeArchive = join(dtPath, '.session-archive', 'claude', 'history.jsonl');
658
+ const codexArchive = join(dtPath, '.session-archive', 'codex', 'history.jsonl');
659
+ const claudeCreds = join(dtPath, '.claude-persistent', '.credentials.json');
660
+ const codexAuth = join(dtPath, '.codex-persistent', 'auth.json');
661
+ const sessionManager = join(dtPath, 'scripts', 'claude-session-manager.sh');
662
+
663
+ const fileStatus = (p) => existsSync(p) ? green('present') : yellow('missing');
664
+ const countLines = (p) => {
665
+ try {
666
+ return readFileSync(p, 'utf8').split('\n').filter(Boolean).length;
667
+ } catch {
668
+ return 0;
669
+ }
670
+ };
671
+
672
+ console.log('');
673
+ console.log(` ${bold('Data Tools Integration')}`);
674
+ console.log(' ' + '─'.repeat(44));
675
+ if (!existsSync(dtPath)) {
676
+ console.log(` ${yellow('replit-tools is not installed in this workspace.')}`);
677
+ console.log('');
678
+ console.log(` ${bold('[i]')} Install replit-tools`);
679
+ console.log(` ${bold('[q]')} Back to main menu`);
680
+ const choice = (await new Promise(resolve => rl.question(' Choice: ', resolve))).trim().toLowerCase();
681
+ if (choice === 'i') spawnSync('npx', ['-y', 'data-tools'], { stdio: 'inherit', cwd: CWD });
682
+ return;
683
+ }
684
+
685
+ console.log(` Root: ${dim(dtPath)}`);
686
+ console.log(` Config: ${fileStatus(configPath)}`);
687
+ console.log(` Claude auth: ${providers.claude.authed ? green('authenticated') : yellow('not authenticated')} ${dim('(' + fileStatus(claudeCreds) + ')')}`);
688
+ console.log(` Codex auth: ${providers.codex.authed ? green('authenticated') : yellow('not authenticated')} ${dim('(' + fileStatus(codexAuth) + ')')}`);
689
+ console.log(` Claude archive: ${countLines(claudeArchive)} entries`);
690
+ console.log(` Codex archive: ${countLines(codexArchive)} entries`);
691
+ console.log(` Session manager: ${fileStatus(sessionManager)}`);
692
+ console.log('');
693
+ console.log(` ${dim('The original Replit/Data Tools menu is still available with:')} ${cyan('claude-menu')}`);
694
+ console.log('');
695
+ console.log(` ${bold('[r]')} Refresh auth`);
696
+ console.log(` ${bold('[m]')} Open original session manager`);
697
+ console.log(` ${bold('[q]')} Back to main menu`);
698
+ console.log('');
699
+
700
+ const choice = (await new Promise(resolve => rl.question(' Choice: ', resolve))).trim().toLowerCase();
701
+ if (choice === 'r') {
702
+ const refreshScript = join(dtPath, 'scripts', 'claude-auth-refresh.sh');
703
+ if (existsSync(refreshScript)) {
704
+ spawnSync('bash', [refreshScript, '--force'], { stdio: 'inherit', cwd: CWD });
705
+ } else {
706
+ console.log(` ${yellow('Refresh script missing.')}`);
707
+ }
708
+ await new Promise(resolve => rl.question(' Press Enter to continue...', resolve));
709
+ }
710
+ if (choice === 'm') {
711
+ console.log('');
712
+ console.log(` ${dim('Opening the original Data Tools session manager. Use [s] there to return to shell.')}`);
713
+ console.log('');
714
+ spawnSync('bash', ['-lc', `source "${sessionManager}" && claude_prompt`], { stdio: 'inherit', cwd: CWD });
715
+ }
716
+ }
717
+
652
718
  // ─── Submenu: Vibe Workflow ───────────────────────────────────────────────
653
719
 
654
720
  async function showVibeWorkflow(rl) {
@@ -748,9 +814,9 @@ function renderFirstRunMenu(providers) {
748
814
  lines.push('');
749
815
  }
750
816
 
751
- // Data Tools shortcut
817
+ // Data Tools integration status
752
818
  if (IS_REPLIT && existsSync(join(CWD, '.replit-tools'))) {
753
- lines.push(` ${bold('[t]')} Open Data Tools dashboard`);
819
+ lines.push(` ${bold('[t]')} Data Tools status`);
754
820
  } else if (IS_REPLIT) {
755
821
  lines.push(` ${bold('[t]')} Install replit-tools ${dim('(recommended for Replit)')}`);
756
822
  }
@@ -854,7 +920,7 @@ function renderReturningMenu(providers, sessions) {
854
920
  lines.push(` ${bold('[u]')} Update Dual Brain ${dim('(' + formatVersionStatus(updateInfo) + ')')}`);
855
921
 
856
922
  if (IS_REPLIT && existsSync(join(CWD, '.replit-tools'))) {
857
- lines.push(` ${bold('[t]')} Open Data Tools dashboard`);
923
+ lines.push(` ${bold('[t]')} Data Tools status`);
858
924
  } else if (IS_REPLIT) {
859
925
  lines.push(` ${bold('[t]')} Install replit-tools`);
860
926
  }
@@ -1100,18 +1166,7 @@ async function mainLoop() {
1100
1166
  if (choice === 't') {
1101
1167
  const dtPath = join(CWD, '.replit-tools');
1102
1168
  if (existsSync(dtPath)) {
1103
- const scriptPath = join(dtPath, 'scripts', 'setup-claude-code.sh');
1104
- if (existsSync(scriptPath)) {
1105
- console.log('');
1106
- console.log(' Opening Data Tools dashboard...');
1107
- console.log('');
1108
- spawnSync('bash', [scriptPath], { stdio: 'inherit', cwd: CWD });
1109
- } else {
1110
- console.log('');
1111
- console.log(` Data Tools present but dashboard script missing.`);
1112
- console.log(` Try: ${cyan('source .replit-tools/scripts/setup-claude-code.sh')}`);
1113
- console.log('');
1114
- }
1169
+ await showDataToolsStatus(rl, providers);
1115
1170
  } else if (IS_REPLIT) {
1116
1171
  console.log('');
1117
1172
  console.log(' Installing replit-tools (Data Tools)...');
package/install.mjs CHANGED
@@ -1042,10 +1042,17 @@ function installDefaultShellLauncher(workspace, actions) {
1042
1042
 
1043
1043
  const start = '# >>> dual-brain default launcher >>>';
1044
1044
  const end = '# <<< dual-brain default launcher <<<';
1045
+ const suppressStart = '# >>> dual-brain suppress data-tools prompt >>>';
1046
+ const suppressEnd = '# <<< dual-brain suppress data-tools prompt <<<';
1047
+ const suppressBlock = [
1048
+ suppressStart,
1049
+ '# Added by dual-brain install when dual-brain is the default shell menu.',
1050
+ 'export CLAUDE_NO_PROMPT=true',
1051
+ suppressEnd,
1052
+ ].join('\n');
1045
1053
  const block = [
1046
1054
  start,
1047
1055
  '# Added by dual-brain install. Set DUAL_BRAIN_SKIP=1 to bypass.',
1048
- 'export CLAUDE_NO_PROMPT=true',
1049
1056
  'if [ -t 1 ] && [ -z "${DUAL_BRAIN_LOADED}" ] && [ -z "${DUAL_BRAIN_SKIP}" ]; then',
1050
1057
  ' export DUAL_BRAIN_LOADED=1',
1051
1058
  ' command -v dual-brain >/dev/null 2>&1 && dual-brain',
@@ -1057,7 +1064,12 @@ function installDefaultShellLauncher(workspace, actions) {
1057
1064
  let src = readFileSync(bashrcPath, 'utf8');
1058
1065
  const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1059
1066
  const existing = new RegExp(`${esc(start)}[\\s\\S]*?${esc(end)}\\n?`, 'm');
1067
+ const existingSuppress = new RegExp(`${esc(suppressStart)}[\\s\\S]*?${esc(suppressEnd)}\\n?`, 'm');
1060
1068
  src = src.replace(existing, '');
1069
+ src = src.replace(existingSuppress, '');
1070
+ const sessionMarker = '# Session Manager (interactive menu)';
1071
+ if (src.includes(sessionMarker)) src = src.replace(sessionMarker, `${suppressBlock}\n\n${sessionMarker}`);
1072
+ else src = `${suppressBlock}\n\n${src.replace(/^\s*/, '')}`;
1061
1073
  const marker = '# Auto-show menu on shell start';
1062
1074
  if (src.includes(marker)) src = src.replace(marker, `${block}\n\n${marker}`);
1063
1075
  else src = `${src.replace(/\s*$/, '\n\n')}${block}\n`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {