dual-brain 4.7.1 โ†’ 4.8.1

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.
@@ -323,7 +323,7 @@ function timeAgo(ts) {
323
323
  return h + 'h ago';
324
324
  }
325
325
 
326
- function snippet(s, n = 15) {
326
+ function snippet(s, n = 35) {
327
327
  const clean = (s || '').replace(/\s+/g, ' ').trim();
328
328
  return clean.length > n ? clean.slice(0, n - 1) + 'โ€ฆ' : clean;
329
329
  }
@@ -468,8 +468,14 @@ async function showAuthMenu(rl, providers) {
468
468
 
469
469
  if (choice === 'j') {
470
470
  console.log('');
471
- spawnSync('claude', ['login'], { stdio: 'inherit' });
472
- providers.claude.authed = true;
471
+ const r = spawnSync('claude', ['login'], { stdio: 'inherit' });
472
+ const fresh = detectProviders();
473
+ providers.claude = fresh.claude;
474
+ if (providers.claude.authed) {
475
+ console.log(` ${green('Claude authenticated.')}`);
476
+ } else {
477
+ console.log(` ${yellow('Claude login did not complete.')} Try again or check your subscription.`);
478
+ }
473
479
  continue;
474
480
  }
475
481
  if (choice === 'k' && providers.codex.installed) {
@@ -479,7 +485,13 @@ async function showAuthMenu(rl, providers) {
479
485
  console.log(` Open: ${cyan('https://auth.openai.com/codex/device')}`);
480
486
  console.log('');
481
487
  spawnSync(codexPath.stdout.trim(), ['login', '--device-auth'], { stdio: 'inherit' });
482
- providers.codex.authed = true;
488
+ const fresh = detectProviders();
489
+ providers.codex = fresh.codex;
490
+ if (providers.codex.authed) {
491
+ console.log(` ${green('Codex authenticated.')}`);
492
+ } else {
493
+ console.log(` ${yellow('Codex login did not complete.')} Try again.`);
494
+ }
483
495
  }
484
496
  continue;
485
497
  }
@@ -572,7 +584,7 @@ async function showToolsMenu(rl) {
572
584
  console.log(` ${bold('[3]')} Decision ledger insights`);
573
585
  console.log(` ${bold('[4]')} Run test suite (40 tests)`);
574
586
  console.log(` ${bold('[5]')} Session report`);
575
- console.log(` ${bold('[u]')} Update dual-brain ${dim('(' + formatVersionStatus(updateInfo) + ')')}`);
587
+ console.log(` ${bold('[u]')} Update Dual Brain ${dim('(' + formatVersionStatus(updateInfo) + ')')}`);
576
588
  console.log(` ${bold('[q]')} Back to main menu`);
577
589
  console.log('');
578
590
 
@@ -617,14 +629,15 @@ function renderFirstRunMenu(providers) {
617
629
  const updateInfo = checkForUpdate();
618
630
 
619
631
  lines.push('');
620
- lines.push(` ๐Ÿง  ${bold(`Dual-Brain v${VERSION}`)}`);
632
+ lines.push(` ๐Ÿง  ${bold('Data Tools')} ${dim('โ€”')} ${bold('Dual Brain')} ${dim(`v${VERSION}`)}`);
621
633
  lines.push(` ${dim(formatVersionStatus(updateInfo))}`);
634
+ lines.push(` ${dim('Powered by replit-tools by Steve Moraco')}`);
622
635
  lines.push('');
623
636
 
624
637
  // Provider status
625
- const cStat = providers.claude.authed ? 'โœ…' : providers.claude.installed ? 'โš ๏ธ' : 'โŒ';
626
- const xStat = providers.codex.authed ? 'โœ…' : providers.codex.installed ? 'โš ๏ธ' : 'โŒ';
627
- lines.push(` ๐ŸŸ  Claude ${cStat} ๐ŸŸข Codex ${xStat}`);
638
+ const cStat = providers.claude.authed ? (noColor ? '[OK]' : 'โœ…') : providers.claude.installed ? (noColor ? '[!]' : 'โš ๏ธ') : (noColor ? '[X]' : 'โŒ');
639
+ const xStat = providers.codex.authed ? (noColor ? '[OK]' : 'โœ…') : providers.codex.installed ? (noColor ? '[!]' : 'โš ๏ธ') : (noColor ? '[X]' : 'โŒ');
640
+ lines.push(` ${noColor ? '' : '๐ŸŸ  '}Claude ${cStat} ${noColor ? '' : '๐ŸŸข '}Codex ${xStat}`);
628
641
 
629
642
  if (providers.claude.authed && providers.codex.authed) {
630
643
  lines.push(` ${green('Both providers ready โ€” full dual-brain mode')}`);
@@ -654,8 +667,10 @@ function renderFirstRunMenu(providers) {
654
667
  lines.push('');
655
668
  }
656
669
 
657
- // Replit-tools check
658
- if (IS_REPLIT && !existsSync(join(CWD, '.replit-tools'))) {
670
+ // Data Tools shortcut
671
+ if (IS_REPLIT && existsSync(join(CWD, '.replit-tools'))) {
672
+ lines.push(` ${bold('[t]')} Open Data Tools dashboard`);
673
+ } else if (IS_REPLIT) {
659
674
  lines.push(` ${bold('[t]')} Install replit-tools ${dim('(recommended for Replit)')}`);
660
675
  }
661
676
 
@@ -664,6 +679,8 @@ function renderFirstRunMenu(providers) {
664
679
  lines.push(` ${bold('[a]')} Auth management`);
665
680
  lines.push(` ${bold('[d]')} Dashboard & diagnostics`);
666
681
  lines.push(` ${bold('[s]')} Skip โ€” just shell`);
682
+ lines.push(` ${dim('Enter = new session ยท [?] help')}`);
683
+
667
684
  lines.push('');
668
685
 
669
686
  return lines;
@@ -678,13 +695,14 @@ function renderReturningMenu(providers, sessions) {
678
695
  const lines = [];
679
696
 
680
697
  lines.push('');
681
- lines.push(` ๐Ÿง  ${bold(`Dual-Brain v${VERSION}`)}`);
698
+ lines.push(` ๐Ÿง  ${bold('Data Tools')} ${dim('โ€”')} ${bold('Dual Brain')} ${dim(`v${VERSION}`)}`);
682
699
  lines.push(` ${dim(formatVersionStatus(updateInfo))}`);
700
+ lines.push(` ${dim('Powered by replit-tools by Steve Moraco')}`);
683
701
  lines.push('');
684
702
 
685
703
  // Provider status
686
- const cStat = providers.claude.authed ? 'โœ…' : 'โš ๏ธ';
687
- const xStat = providers.codex.authed ? 'โœ…' : providers.codex.installed ? 'โš ๏ธ' : 'โŒ';
704
+ const cStat = providers.claude.authed ? (noColor ? '[OK]' : 'โœ…') : (noColor ? '[!]' : 'โš ๏ธ');
705
+ const xStat = providers.codex.authed ? (noColor ? '[OK]' : 'โœ…') : providers.codex.installed ? (noColor ? '[!]' : 'โš ๏ธ') : (noColor ? '[X]' : 'โŒ');
688
706
  let modeStatus = pf.uiLabel;
689
707
  if (profile.name === 'auto') {
690
708
  if (balance.total === 0) {
@@ -748,14 +766,21 @@ function renderReturningMenu(providers, sessions) {
748
766
  lines.push('');
749
767
  lines.push(` ${dim('โ”€โ”€โ”€ Tools')}`);
750
768
  lines.push(` ${bold('[d]')} Dashboard & diagnostics`);
751
- lines.push(` ${bold('[u]')} Update dual-brain ${dim('(' + formatVersionStatus(updateInfo) + ')')}`);
769
+ lines.push(` ${bold('[u]')} Update Dual Brain ${dim('(' + formatVersionStatus(updateInfo) + ')')}`);
752
770
 
753
- if (IS_REPLIT && !existsSync(join(CWD, '.replit-tools'))) {
771
+ if (IS_REPLIT && existsSync(join(CWD, '.replit-tools'))) {
772
+ lines.push(` ${bold('[t]')} Open Data Tools dashboard`);
773
+ } else if (IS_REPLIT) {
754
774
  lines.push(` ${bold('[t]')} Install replit-tools`);
755
775
  }
756
776
 
757
777
  lines.push('');
758
778
  lines.push(` ${bold('[s]')} Exit to shell`);
779
+ if (sessions.length > 0) {
780
+ lines.push(` ${dim('Enter = continue last ยท [?] help')}`);
781
+ } else {
782
+ lines.push(` ${dim('Enter = new session ยท [?] help')}`);
783
+ }
759
784
  lines.push('');
760
785
 
761
786
  return lines;
@@ -835,7 +860,10 @@ function runSession(cmd, args, label) {
835
860
  markLaunched();
836
861
  const result = spawnSync(cmd, args, { stdio: 'inherit' });
837
862
  console.log('');
838
- console.log(' Returned to Dual-Brain.');
863
+ if (result.status !== 0 && result.status !== null) {
864
+ console.log(` ${yellow('Session exited with code ' + result.status + '.')} ${dim('(' + cmd + ' ' + args.join(' ') + ')')}`);
865
+ }
866
+ console.log(' Returned to Data Tools โ€” Dual Brain.');
839
867
  return result.status || 0;
840
868
  }
841
869
 
@@ -872,6 +900,15 @@ async function mainLoop() {
872
900
  } else {
873
901
  runSession('claude', ['-r', s.id, '--dangerously-skip-permissions'], `Resuming session ${s.id.slice(0, 8)}...`);
874
902
  }
903
+ } else if (!providers.claude.authed && !providers.claude.installed) {
904
+ console.log('');
905
+ console.log(` ${yellow('Claude is not installed.')} Install first:`);
906
+ console.log(` ${cyan('curl -fsSL https://claude.ai/install.sh | sh')}`);
907
+ console.log('');
908
+ } else if (!providers.claude.authed) {
909
+ console.log('');
910
+ console.log(` ${yellow('Claude is not authenticated.')} Press ${bold('[j]')} to sign in first.`);
911
+ console.log('');
875
912
  } else {
876
913
  runSession('claude', ['--dangerously-skip-permissions'], 'Starting new session...');
877
914
  }
@@ -890,7 +927,13 @@ async function mainLoop() {
890
927
  }
891
928
 
892
929
  if (choice === 'n') {
893
- runSession('claude', ['--dangerously-skip-permissions'], 'Starting new session...');
930
+ if (!providers.claude.authed) {
931
+ console.log('');
932
+ console.log(` ${yellow('Claude needs to be authenticated first.')} Press ${bold('[j]')} to sign in.`);
933
+ console.log('');
934
+ } else {
935
+ runSession('claude', ['--dangerously-skip-permissions'], 'Starting new session...');
936
+ }
894
937
  continue;
895
938
  }
896
939
 
@@ -916,9 +959,46 @@ async function mainLoop() {
916
959
 
917
960
  if (choice === 'u') {
918
961
  console.log('');
919
- console.log(' Updating dual-brain...');
962
+ console.log(' Updating Dual Brain...');
920
963
  console.log('');
921
- spawnSync('npx', ['-y', 'dual-brain', 'update'], { stdio: 'inherit', cwd: CWD });
964
+ const upd = spawnSync('npx', ['-y', 'dual-brain', 'update'], { stdio: 'inherit', cwd: CWD });
965
+ if (upd.status !== 0) {
966
+ console.log('');
967
+ console.log(` ${yellow('Update failed (exit ' + upd.status + ').')} Try manually: ${cyan('npx -y dual-brain@latest')}`);
968
+ console.log('');
969
+ }
970
+ continue;
971
+ }
972
+
973
+ if (choice === 't') {
974
+ const dtPath = join(CWD, '.replit-tools');
975
+ if (existsSync(dtPath)) {
976
+ const scriptPath = join(dtPath, 'scripts', 'setup-claude-code.sh');
977
+ if (existsSync(scriptPath)) {
978
+ console.log('');
979
+ console.log(' Opening Data Tools dashboard...');
980
+ console.log('');
981
+ spawnSync('bash', [scriptPath], { stdio: 'inherit', cwd: CWD });
982
+ } else {
983
+ console.log('');
984
+ console.log(` Data Tools present but dashboard script missing.`);
985
+ console.log(` Try: ${cyan('source .replit-tools/scripts/setup-claude-code.sh')}`);
986
+ console.log('');
987
+ }
988
+ } else if (IS_REPLIT) {
989
+ console.log('');
990
+ console.log(' Installing replit-tools (Data Tools)...');
991
+ console.log('');
992
+ spawnSync('npx', ['-y', 'data-tools'], { stdio: 'inherit', cwd: CWD });
993
+ console.log('');
994
+ console.log(' Done. Press Enter to continue...');
995
+ const askOnce = () => new Promise(resolve => rl.question('', resolve));
996
+ await askOnce();
997
+ } else {
998
+ console.log('');
999
+ console.log(` Data Tools is designed for Replit environments.`);
1000
+ console.log('');
1001
+ }
922
1002
  continue;
923
1003
  }
924
1004
 
@@ -948,14 +1028,18 @@ async function mainLoop() {
948
1028
  continue;
949
1029
  }
950
1030
 
951
- if (choice === 't' && IS_REPLIT) {
1031
+ if (choice === '?') {
952
1032
  console.log('');
953
- console.log(' Installing replit-tools...');
1033
+ console.log(` ${bold('What is Dual Brain?')}`);
954
1034
  console.log('');
955
- spawnSync('npx', ['-y', 'data-tools'], { stdio: 'inherit', cwd: CWD });
1035
+ console.log(' Dual Brain orchestrates your Claude + Codex subscriptions together.');
1036
+ console.log(' It routes tasks to the right model: search (fast), execute (edits),');
1037
+ console.log(' think (architecture). Both providers work in parallel when possible.');
956
1038
  console.log('');
957
- console.log(' โœ… replit-tools installed.');
1039
+ console.log(' Modes: Auto adapts to your workflow. Cost-saver minimizes GPT usage.');
1040
+ console.log(' Quality-first uses dual-brain review on all medium+ risk changes.');
958
1041
  console.log('');
1042
+ console.log(` ${dim('Press Enter to return...')}`);
959
1043
  await ask();
960
1044
  continue;
961
1045
  }
@@ -27,11 +27,10 @@ const CONFIG_FILE = join(__dirname, '..', 'orchestrator.json');
27
27
  const EXECUTE_WORDS = /\b(edit|write|fix|implement|modify|refactor|delete|commit|test|build|run|add|update|create)\b/i;
28
28
  const SEARCH_WORDS = /\b(explore|search|find|grep|locate|list\s+files|read[-\s]?only|lookup|scan)\b/i;
29
29
  const THINK_WORDS = /\b(plan|design|architect|review|audit|security|code[-\s]?review|threat[-\s]?model|complex[-\s]?debug)\b/i;
30
- const GPT_TIER_SANDBOX = {
31
- search: 'read-only',
32
- execute: 'danger-full-access',
33
- think: 'read-only',
34
- };
30
+ const IS_REPLIT = !!(process.env.REPL_ID || process.env.REPL_SLUG);
31
+ const GPT_TIER_SANDBOX = IS_REPLIT
32
+ ? { search: 'danger-full-access', execute: 'danger-full-access', think: 'danger-full-access' }
33
+ : { search: 'read-only', execute: 'danger-full-access', think: 'read-only' };
35
34
  const GPT_TIER_PROMPTS = {
36
35
  search: 'You are a READ-ONLY search agent. Do NOT edit files.',
37
36
  execute: 'You are an execution agent. Edit files directly.',
package/install.mjs CHANGED
@@ -44,7 +44,9 @@ if (flag('--version') || flag('-v')) {
44
44
 
45
45
  if (flag('--help') || flag('-h')) {
46
46
  console.log(`
47
- ๐Ÿง  dual-brain v${VERSION} โ€” Dual-provider orchestrator for Claude Code
47
+ ๐Ÿง  Data Tools โ€” Dual Brain v${VERSION}
48
+ Dual-provider orchestrator for Claude Code
49
+ Powered by replit-tools by Steve Moraco
48
50
 
49
51
  Usage: npx -y dual-brain [command] [options]
50
52
 
@@ -846,7 +848,7 @@ function printReport(env, mode, actions, isDryRun) {
846
848
  const lines = [];
847
849
 
848
850
  lines.push(br('โ•”', 'โ•—'));
849
- lines.push(ln(`๐Ÿง  Dual-Brain v${VERSION}`));
851
+ lines.push(ln(`๐Ÿง  Data Tools โ€” Dual Brain v${VERSION}`));
850
852
  lines.push(sep());
851
853
 
852
854
  const cAuth = env.claude.authed ? 'โœ…' : env.claude.installed ? 'โš ๏ธ' : 'โŒ';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "4.7.1",
3
+ "version": "4.8.1",
4
4
  "description": "Dual-provider orchestration for Claude Code โ€” tiered routing, budget balancing, and GPT dual-brain review across Claude + OpenAI subscriptions",
5
5
  "type": "module",
6
6
  "bin": {