@@ -32,6 +32,11 @@ import {
3232import { AgentPath } from './server/domain/values/AgentPath.js' ;
3333import { CommandRunner } from './server/infrastructure/CommandRunner.js' ;
3434import { CacheRegistry } from './server/infrastructure/CacheRegistry.js' ;
35+ import {
36+ DEFAULT_BD_FALLBACK_PATHS ,
37+ DEFAULT_GT_FALLBACK_PATHS ,
38+ resolveExecutable ,
39+ } from './server/infrastructure/ExecutableResolver.js' ;
3540import { BDGateway } from './server/gateways/BDGateway.js' ;
3641import { GTGateway } from './server/gateways/GTGateway.js' ;
3742import { GitHubGateway } from './server/gateways/GitHubGateway.js' ;
@@ -60,10 +65,20 @@ const PORT = process.env.GASTOWN_PORT || 7667;
6065const HOST = process . env . HOST || '127.0.0.1' ;
6166const HOME = process . env . HOME || os . homedir ( ) ;
6267const GT_ROOT = process . env . GT_ROOT || path . join ( HOME , 'gt' ) ;
68+ const GT_EXECUTABLE = resolveExecutable ( {
69+ command : 'gt' ,
70+ envVarName : 'GT_BIN' ,
71+ fallbackPaths : DEFAULT_GT_FALLBACK_PATHS ,
72+ } ) ;
73+ const BD_EXECUTABLE = resolveExecutable ( {
74+ command : 'bd' ,
75+ envVarName : 'BD_BIN' ,
76+ fallbackPaths : DEFAULT_BD_FALLBACK_PATHS ,
77+ } ) ;
6378
6479const commandRunner = new CommandRunner ( ) ;
65- const gtGateway = new GTGateway ( { runner : commandRunner , gtRoot : GT_ROOT } ) ;
66- const bdGateway = new BDGateway ( { runner : commandRunner , gtRoot : GT_ROOT } ) ;
80+ const gtGateway = new GTGateway ( { runner : commandRunner , gtRoot : GT_ROOT , executable : GT_EXECUTABLE } ) ;
81+ const bdGateway = new BDGateway ( { runner : commandRunner , gtRoot : GT_ROOT , executable : BD_EXECUTABLE } ) ;
6782const tmuxGateway = new TmuxGateway ( { runner : commandRunner } ) ;
6883const backendCache = new CacheRegistry ( ) ;
6984const convoyService = new ConvoyService ( {
@@ -467,11 +482,11 @@ async function getPolecatOutput(sessionName, lines = 50) {
467482
468483// Execute a Gas Town command
469484async function executeGT ( args , options = { } ) {
470- const cmd = `gt ${ args . join ( ' ' ) } ` ;
485+ const cmd = `${ GT_EXECUTABLE } ${ args . join ( ' ' ) } ` ;
471486 console . log ( `[GT] Executing: ${ cmd } ` ) ;
472487
473488 try {
474- const { stdout, stderr } = await execFileAsync ( 'gt' , args , {
489+ const { stdout, stderr } = await execFileAsync ( GT_EXECUTABLE , args , {
475490 cwd : options . cwd || GT_ROOT ,
476491 timeout : options . timeout || 30000 ,
477492 env : { ...process . env , ...options . env }
@@ -506,14 +521,14 @@ async function executeGT(args, options = {}) {
506521
507522// Execute a Beads command
508523async function executeBD ( args , options = { } ) {
509- const cmd = `bd ${ args . join ( ' ' ) } ` ;
524+ const cmd = `${ BD_EXECUTABLE } ${ args . join ( ' ' ) } ` ;
510525 console . log ( `[BD] Executing: ${ cmd } ` ) ;
511526
512527 // Set BEADS_DIR to ensure bd finds the database
513528 const beadsDir = path . join ( GT_ROOT , '.beads' ) ;
514529
515530 try {
516- const { stdout } = await execFileAsync ( 'bd' , args , {
531+ const { stdout } = await execFileAsync ( BD_EXECUTABLE , args , {
517532 cwd : options . cwd || GT_ROOT ,
518533 timeout : options . timeout || 30000 ,
519534 env : { ...process . env , BEADS_DIR : beadsDir }
@@ -1174,7 +1189,7 @@ app.get('/api/setup/status', async (req, res) => {
11741189
11751190 // Check gt
11761191 try {
1177- const gtResult = await execFileAsync ( 'gt' , [ 'version' ] , { timeout : 5000 } ) ;
1192+ const gtResult = await execFileAsync ( GT_EXECUTABLE , [ 'version' ] , { timeout : 5000 } ) ;
11781193 status . gt_installed = true ;
11791194 status . gt_version = String ( gtResult . stdout || '' ) . trim ( ) . split ( '\n' ) [ 0 ] ;
11801195 } catch {
@@ -1183,7 +1198,7 @@ app.get('/api/setup/status', async (req, res) => {
11831198
11841199 // Check bd
11851200 try {
1186- const bdResult = await execFileAsync ( 'bd' , [ 'version' ] , { timeout : 5000 } ) ;
1201+ const bdResult = await execFileAsync ( BD_EXECUTABLE , [ 'version' ] , { timeout : 5000 } ) ;
11871202 status . bd_installed = true ;
11881203 status . bd_version = String ( bdResult . stdout || '' ) . trim ( ) . split ( '\n' ) [ 0 ] ;
11891204 } catch {
@@ -1713,14 +1728,26 @@ registerGitHubRoutes(app, { gitHubService });
17131728
17141729// Start activity stream
17151730let activityProcess = null ;
1731+ let activityRestartTimer = null ;
1732+
1733+ function scheduleActivityRestart ( ) {
1734+ if ( clients . size === 0 ) return ;
1735+ if ( activityRestartTimer ) return ;
1736+ activityRestartTimer = setTimeout ( ( ) => {
1737+ activityRestartTimer = null ;
1738+ if ( clients . size > 0 ) {
1739+ startActivityStream ( ) ;
1740+ }
1741+ } , 5000 ) ;
1742+ }
17161743
17171744function startActivityStream ( ) {
17181745 if ( activityProcess ) return ;
17191746
17201747 console . log ( '[WS] Starting activity stream...' ) ;
17211748
17221749 // Use gt feed for comprehensive activity (beads + gt events + convoys)
1723- activityProcess = spawn ( 'gt' , [ 'feed' , '--plain' , '--follow' ] , {
1750+ activityProcess = spawn ( GT_EXECUTABLE , [ 'feed' , '--plain' , '--follow' ] , {
17241751 cwd : GT_ROOT
17251752 } ) ;
17261753
@@ -1738,13 +1765,16 @@ function startActivityStream() {
17381765 console . error ( `[BD Activity] stderr: ${ data } ` ) ;
17391766 } ) ;
17401767
1768+ activityProcess . on ( 'error' , ( error ) => {
1769+ console . error ( `[BD Activity] Process error: ${ error . message } ` ) ;
1770+ activityProcess = null ;
1771+ scheduleActivityRestart ( ) ;
1772+ } ) ;
1773+
17411774 activityProcess . on ( 'close' , ( code ) => {
17421775 console . log ( `[BD Activity] Process exited with code ${ code } ` ) ;
17431776 activityProcess = null ;
1744- // Restart after delay if clients connected
1745- if ( clients . size > 0 ) {
1746- setTimeout ( startActivityStream , 5000 ) ;
1747- }
1777+ scheduleActivityRestart ( ) ;
17481778 } ) ;
17491779}
17501780
@@ -1816,9 +1846,15 @@ wss.on('connection', (ws) => {
18161846 clients . delete ( ws ) ;
18171847
18181848 // Stop activity stream if no clients
1819- if ( clients . size === 0 && activityProcess ) {
1820- activityProcess . kill ( ) ;
1821- activityProcess = null ;
1849+ if ( clients . size === 0 ) {
1850+ if ( activityRestartTimer ) {
1851+ clearTimeout ( activityRestartTimer ) ;
1852+ activityRestartTimer = null ;
1853+ }
1854+ if ( activityProcess ) {
1855+ activityProcess . kill ( ) ;
1856+ activityProcess = null ;
1857+ }
18221858 }
18231859 } ) ;
18241860
0 commit comments