dual-brain 0.3.32 → 0.3.33

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 +21 -0
  2. package/package.json +1 -1
@@ -1564,6 +1564,7 @@ async function cmdRuntimeSwitch(args = []) {
1564
1564
  const activeForSwitch = readActiveConversation(cwd);
1565
1565
  if (activeForSwitch?.sessionId === sess.id) {
1566
1566
  console.log('Active supervisor detected: HEAD will restart with these settings.');
1567
+ signalActiveConversation(cwd, sess.id);
1567
1568
  } else if (!args.includes('--apply')) {
1568
1569
  console.log('No active supervisor detected: saved for the next dual-brain resume/switch, not live yet.');
1569
1570
  }
@@ -2851,6 +2852,18 @@ function updateActiveConversation(cwd, sessionId, updates = {}) {
2851
2852
  } catch {}
2852
2853
  }
2853
2854
 
2855
+ function signalActiveConversation(cwd, sessionId) {
2856
+ try {
2857
+ const lease = JSON.parse(readFileSync(activeConversationPath(cwd), 'utf8'));
2858
+ if (sessionId && lease.sessionId !== sessionId) return false;
2859
+ if (!pidAlive(lease.ownerPid)) return false;
2860
+ process.kill(lease.ownerPid, 'SIGUSR1');
2861
+ return true;
2862
+ } catch {
2863
+ return false;
2864
+ }
2865
+ }
2866
+
2854
2867
  function writeHandoffConversationLease(cwd, session, fromTool, targetTool, taskBrief = '') {
2855
2868
  const dir = join(cwd, '.dualbrain');
2856
2869
  const terminalId = getTerminalId();
@@ -2957,6 +2970,12 @@ async function launchSupervisedHead(tool, launchArgs, cwd, session) {
2957
2970
  }, 2500);
2958
2971
  };
2959
2972
 
2973
+ const onSignalSwitch = () => {
2974
+ const pending = readPendingRuntimeSwitch(cwd);
2975
+ if (pendingSwitchMatchesSession(pending, session)) stopChildForSwitch();
2976
+ };
2977
+ process.on('SIGUSR1', onSignalSwitch);
2978
+
2960
2979
  const watcher = setInterval(() => {
2961
2980
  const pending = readPendingRuntimeSwitch(cwd);
2962
2981
  if (pendingSwitchMatchesSession(pending, session)) stopChildForSwitch();
@@ -2964,6 +2983,7 @@ async function launchSupervisedHead(tool, launchArgs, cwd, session) {
2964
2983
 
2965
2984
  child.on('exit', async (code, signal) => {
2966
2985
  clearInterval(watcher);
2986
+ process.off('SIGUSR1', onSignalSwitch);
2967
2987
  if (forceTimer) clearTimeout(forceTimer);
2968
2988
  saveTerminalState(cwd, getTerminalId(), session?.id, session?.tool || tool);
2969
2989
 
@@ -2979,6 +2999,7 @@ async function launchSupervisedHead(tool, launchArgs, cwd, session) {
2979
2999
 
2980
3000
  child.on('error', (err) => {
2981
3001
  clearInterval(watcher);
3002
+ process.off('SIGUSR1', onSignalSwitch);
2982
3003
  if (forceTimer) clearTimeout(forceTimer);
2983
3004
  process.stderr.write(`\n Could not launch ${tool}: ${err.message}\n`);
2984
3005
  clearActiveConversation(cwd, session?.id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.3.32",
3
+ "version": "0.3.33",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {