@@ -4,10 +4,43 @@ import { jsonResponse } from "./http";
44interface RpcRequest {
55 command : string ;
66 args ?: string [ ] ;
7+ branch ?: string ;
78}
89
910type RpcResponse = { ok : true ; output : string } | { ok : false ; error : string }
1011
12+ /** Build env with TMUX set so workmux can resolve agent states outside tmux. */
13+ function tmuxEnv ( ) : Record < string , string | undefined > {
14+ if ( Bun . env . TMUX ) return Bun . env ;
15+ const tmpdir = Bun . env . TMUX_TMPDIR || "/tmp" ;
16+ const uid = process . getuid ?.( ) ?? 1000 ;
17+ return { ...Bun . env , TMUX : `${ tmpdir } /tmux-${ uid } /default,0,0` } ;
18+ }
19+
20+ /**
21+ * Resolve the tmux pane ID for a worktree window (wm-{branch}).
22+ * Returns the first pane ID, or null if the window doesn't exist.
23+ */
24+ async function resolvePaneId ( branch : string ) : Promise < string | null > {
25+ const proc = Bun . spawn (
26+ [ "tmux" , "list-panes" , "-a" , "-F" , "#{window_name}\t#{pane_id}" ] ,
27+ { stdout : "pipe" , stderr : "pipe" , env : tmuxEnv ( ) } ,
28+ ) ;
29+ const [ stdout , , exitCode ] = await Promise . all ( [
30+ new Response ( proc . stdout ) . text ( ) ,
31+ new Response ( proc . stderr ) . text ( ) ,
32+ proc . exited ,
33+ ] ) ;
34+ if ( exitCode !== 0 ) return null ;
35+
36+ const target = `wm-${ branch } ` ;
37+ for ( const line of stdout . trim ( ) . split ( "\n" ) ) {
38+ const [ windowName , paneId ] = line . split ( "\t" ) ;
39+ if ( windowName === target && paneId ) return paneId ;
40+ }
41+ return null ;
42+ }
43+
1144export async function handleWorkmuxRpc ( req : Request ) : Promise < Response > {
1245 const secret = await loadRpcSecret ( ) ;
1346 const authHeader = req . headers . get ( "Authorization" ) ;
@@ -23,15 +56,26 @@ export async function handleWorkmuxRpc(req: Request): Promise<Response> {
2356 return jsonResponse ( { ok : false , error : "Invalid JSON" } satisfies RpcResponse , 400 ) ;
2457 }
2558
26- const { command, args = [ ] } = raw ;
59+ const { command, args = [ ] , branch } = raw ;
2760 if ( ! command ) {
2861 return jsonResponse ( { ok : false , error : "Missing command" } satisfies RpcResponse , 400 ) ;
2962 }
3063
3164 try {
65+ // Build spawn environment. For set-window-status from a container,
66+ // resolve the tmux pane ID so the workmux binary can target the right window.
67+ const env = tmuxEnv ( ) ;
68+ if ( command === "set-window-status" && branch ) {
69+ const paneId = await resolvePaneId ( branch ) ;
70+ if ( paneId ) {
71+ env . TMUX_PANE = paneId ;
72+ }
73+ }
74+
3275 const proc = Bun . spawn ( [ "workmux" , command , ...args ] , {
3376 stdout : "pipe" ,
3477 stderr : "pipe" ,
78+ env,
3579 } ) ;
3680 const [ stdout , stderr , exitCode ] = await Promise . all ( [
3781 new Response ( proc . stdout ) . text ( ) ,
0 commit comments