@@ -116,6 +116,58 @@ export async function createWindow(opts: {
116116 }
117117}
118118
119+ /**
120+ * Set a user option on a tmux window for ownership tracking
121+ */
122+ export async function setWindowOption ( target : string , option : string , value : string ) : Promise < void > {
123+ try {
124+ const proc = spawn ( [ "tmux" , "set-option" , "-w" , "-t" , target , option , value ] , { stderr : "pipe" } ) ;
125+ const exitCode = await proc . exited ;
126+ if ( exitCode !== 0 ) {
127+ throw new Error ( `tmux set-option failed with exit code ${ exitCode } ` ) ;
128+ }
129+ } catch ( error ) {
130+ throw new Error (
131+ `Failed to set tmux window option: ${ error instanceof Error ? error . message : String ( error ) } `
132+ ) ;
133+ }
134+ }
135+
136+ /**
137+ * Find and kill all tmux windows tagged with a specific job ID
138+ */
139+ export async function killTaggedWindows ( jobId : string ) : Promise < number > {
140+ try {
141+ const proc = spawn (
142+ [ "tmux" , "list-windows" , "-a" , "-F" , "#{session_name}:#{window_index} #{@mc_job_id}" ] ,
143+ { stderr : "pipe" } ,
144+ ) ;
145+ const output = await new Response ( proc . stdout ) . text ( ) ;
146+ const exitCode = await proc . exited ;
147+ if ( exitCode !== 0 ) {
148+ return 0 ;
149+ }
150+
151+ let killed = 0 ;
152+ for ( const line of output . trim ( ) . split ( '\n' ) ) {
153+ if ( ! line . trim ( ) ) continue ;
154+ const [ target , taggedId ] = line . split ( ' ' , 2 ) ;
155+ if ( taggedId === jobId && target ) {
156+ try {
157+ const killProc = spawn ( [ "tmux" , "kill-window" , "-t" , target ] , { stderr : "pipe" } ) ;
158+ await killProc . exited ;
159+ killed ++ ;
160+ } catch {
161+ // Best-effort: window may already be gone
162+ }
163+ }
164+ }
165+ return killed ;
166+ } catch {
167+ return 0 ;
168+ }
169+ }
170+
119171/**
120172 * Check if a tmux session exists
121173 */
0 commit comments