dual-brain 0.3.35 → 0.3.36

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 +89 -4
  2. package/package.json +1 -1
@@ -6,6 +6,7 @@ import { join, dirname, basename, extname } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { execSync, spawnSync as _spawnSyncTop } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
9
+ import { randomUUID } from 'node:crypto';
9
10
 
10
11
  import {
11
12
  ensureProfile, loadProfile, saveProfile, runOnboarding,
@@ -68,6 +69,22 @@ function _codexResumeArgs(sessionId, cwd) {
68
69
  ];
69
70
  }
70
71
 
72
+ function _codexNewArgs(cwd) {
73
+ const workspace = cwd || process.cwd();
74
+ if (getEffectiveBypassPermissions(workspace)) {
75
+ return ['--dangerously-bypass-approvals-and-sandbox'];
76
+ }
77
+ const settings = loadSessionSettings(workspace);
78
+ const approvalMode = getEffectiveAutomode(loadProfile(workspace), workspace) ? 'never' : 'on-request';
79
+ return [
80
+ ..._codexModelEffortArgs(
81
+ _modelMatchesProvider(settings.headModel, 'codex') ? settings.headModel : null,
82
+ settings.effort,
83
+ ),
84
+ ..._codexApprovalArgs(workspace, approvalMode),
85
+ ];
86
+ }
87
+
71
88
  function _isReplitWorkspace(cwd) {
72
89
  const workspace = cwd || process.cwd();
73
90
  return !!(
@@ -4795,11 +4812,79 @@ async function mainScreen(rl, ask) {
4795
4812
 
4796
4813
  async function newSessionScreen(rl, ask) {
4797
4814
  const cwd = process.cwd();
4798
- const input = (await ask('\n What do you want to do? ')).trim();
4799
- if (!input) { return { next: 'main' }; }
4815
+ const profile = loadProfile(cwd);
4816
+ const settings = loadSessionSettings(cwd);
4817
+ settings.automode = true;
4818
+ settings.bypassPermissions = false;
4819
+
4820
+ let provider = _modelMatchesProvider(settings.headModel, 'claude') ? 'claude' : 'codex';
4821
+ if (!_modelMatchesProvider(settings.headModel, provider)) {
4822
+ const policy = _headPolicyFor(provider, profile, settings);
4823
+ settings.headModel = policy.model;
4824
+ settings.effort = policy.effort;
4825
+ }
4826
+ saveSessionSettings(cwd, settings);
4827
+
4828
+ const renderStart = () => {
4829
+ const policy = _headPolicyFor(provider, profile, settings);
4830
+ if (!_modelMatchesProvider(settings.headModel, provider)) {
4831
+ settings.headModel = policy.model;
4832
+ settings.effort = policy.effort;
4833
+ saveSessionSettings(cwd, settings);
4834
+ }
4835
+ process.stdout.write('\n');
4836
+ process.stdout.write(' New HEAD Conversation\n\n');
4837
+ process.stdout.write(' Recommended Balanced Session\n');
4838
+ process.stdout.write(` Provider: ${provider === 'codex' ? 'GPT/Codex' : 'Claude'}\n`);
4839
+ process.stdout.write(` Model: ${settings.headModel || policy.model} (${settings.effort || policy.effort || 'default'})\n`);
4840
+ process.stdout.write(' Mode: Smart Auto\n');
4841
+ process.stdout.write(` Permissions: ${provider === 'codex' ? 'never ask + Replit sandbox boundary' : 'auto'}\n\n`);
4842
+ process.stdout.write(' Enter start recommended p start with pasted prompt b back\n\n');
4843
+ };
4844
+
4845
+ renderStart();
4846
+ let choice = (await ask(' Choice: ')).trim().toLowerCase();
4847
+ let initialPrompt = '';
4848
+ if (choice === 'b' || choice === 'q') return { next: 'main' };
4849
+ if (choice === 'p' || choice === 'prompt') {
4850
+ initialPrompt = (await ask(' Initial prompt: ')).trim();
4851
+ }
4800
4852
 
4801
- // All work routes through pipeline — detect → decide → dispatch with mandatory gates.
4802
- await cmdGo([input], { cwd });
4853
+ const policy = _headPolicyFor(provider, profile, settings);
4854
+ if (!_modelMatchesProvider(settings.headModel, provider)) settings.headModel = policy.model;
4855
+ if (!settings.effort) settings.effort = policy.effort;
4856
+ settings.automode = true;
4857
+ settings.bypassPermissions = false;
4858
+ saveSessionSettings(cwd, settings);
4859
+
4860
+ const session = {
4861
+ id: randomUUID(),
4862
+ tool: provider,
4863
+ smartName: 'New HEAD Conversation',
4864
+ firstPrompt: initialPrompt || 'New dual-brain HEAD conversation',
4865
+ };
4866
+ const launchArgs = provider === 'codex'
4867
+ ? _codexNewArgs(cwd)
4868
+ : ['--session-id', session.id, ..._claudeNewArgs(cwd)];
4869
+ if (initialPrompt) launchArgs.push(initialPrompt);
4870
+
4871
+ process.stdout.write('\n');
4872
+ process.stdout.write(' Starting HEAD in Smart Auto...\n');
4873
+ process.stdout.write(` Provider: ${provider === 'codex' ? 'GPT/Codex' : 'Claude'}\n`);
4874
+ process.stdout.write(` Model: ${settings.headModel || 'default'}${settings.effort ? ` (${settings.effort})` : ''}\n`);
4875
+ process.stdout.write(` Launch: ${provider} ${launchArgs.join(' ')}\n\n`);
4876
+
4877
+ writeActiveConversation(cwd, session, provider, {
4878
+ model: settings.headModel || null,
4879
+ effort: settings.effort || null,
4880
+ automode: true,
4881
+ bypassPermissions: false,
4882
+ });
4883
+ try {
4884
+ await launchSupervisedHead(provider, launchArgs, cwd, session);
4885
+ } finally {
4886
+ clearActiveConversation(cwd, session.id);
4887
+ }
4803
4888
 
4804
4889
  return { next: 'main' };
4805
4890
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.3.35",
3
+ "version": "0.3.36",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {