@@ -286,10 +286,21 @@ export async function handleSessionCommands(params: {
286286 }
287287
288288 if ( command === 'open' ) {
289+ const shouldRelaunch = req . flags ?. relaunch === true ;
289290 if ( sessionStore . has ( sessionName ) ) {
290291 const session = sessionStore . get ( sessionName ) ;
291- const appName = req . positionals ?. [ 0 ] ;
292+ const requestedAppName = req . positionals ?. [ 0 ] ;
293+ const appName = requestedAppName ?? ( shouldRelaunch ? session ?. appName : undefined ) ;
292294 if ( ! session || ! appName ) {
295+ if ( shouldRelaunch ) {
296+ return {
297+ ok : false ,
298+ error : {
299+ code : 'INVALID_ARGS' ,
300+ message : 'open --relaunch requires an app name or an active session app.' ,
301+ } ,
302+ } ;
303+ }
293304 return {
294305 ok : false ,
295306 error : {
@@ -307,7 +318,13 @@ export async function handleSessionCommands(params: {
307318 appBundleId = undefined ;
308319 }
309320 }
310- await dispatch ( session . device , 'open' , req . positionals ?? [ ] , req . flags ?. out , {
321+ const openPositionals = requestedAppName ? ( req . positionals ?? [ ] ) : [ appName ] ;
322+ if ( shouldRelaunch ) {
323+ await dispatch ( session . device , 'close' , [ appName ] , req . flags ?. out , {
324+ ...contextFromFlags ( logPath , req . flags , appBundleId ?? session . appBundleId , session . trace ?. outPath ) ,
325+ } ) ;
326+ }
327+ await dispatch ( session . device , 'open' , openPositionals , req . flags ?. out , {
311328 ...contextFromFlags ( logPath , req . flags , appBundleId ) ,
312329 } ) ;
313330 const nextSession : SessionState = {
@@ -319,13 +336,23 @@ export async function handleSessionCommands(params: {
319336 } ;
320337 sessionStore . recordAction ( nextSession , {
321338 command,
322- positionals : req . positionals ?? [ ] ,
339+ positionals : openPositionals ,
323340 flags : req . flags ?? { } ,
324341 result : { session : sessionName , appName, appBundleId } ,
325342 } ) ;
326343 sessionStore . set ( sessionName , nextSession ) ;
327344 return { ok : true , data : { session : sessionName , appName, appBundleId } } ;
328345 }
346+ const appName = req . positionals ?. [ 0 ] ;
347+ if ( shouldRelaunch && ! appName ) {
348+ return {
349+ ok : false ,
350+ error : {
351+ code : 'INVALID_ARGS' ,
352+ message : 'open --relaunch requires an app argument.' ,
353+ } ,
354+ } ;
355+ }
329356 const device = await resolveTargetDevice ( req . flags ?? { } ) ;
330357 const inUse = sessionStore . toArray ( ) . find ( ( s ) => s . device . id === device . id ) ;
331358 if ( inUse ) {
@@ -339,15 +366,21 @@ export async function handleSessionCommands(params: {
339366 } ;
340367 }
341368 let appBundleId : string | undefined ;
342- const appName = req . positionals ?. [ 0 ] ;
343369 if ( device . platform === 'ios' ) {
344370 try {
345- const { resolveIosApp } = await import ( '../../platforms/ios/index.ts' ) ;
346- appBundleId = await resolveIosApp ( device , req . positionals ?. [ 0 ] ?? '' ) ;
371+ if ( appName ) {
372+ const { resolveIosApp } = await import ( '../../platforms/ios/index.ts' ) ;
373+ appBundleId = await resolveIosApp ( device , appName ) ;
374+ }
347375 } catch {
348376 appBundleId = undefined ;
349377 }
350378 }
379+ if ( shouldRelaunch && appName ) {
380+ await dispatch ( device , 'close' , [ appName ] , req . flags ?. out , {
381+ ...contextFromFlags ( logPath , req . flags , appBundleId ) ,
382+ } ) ;
383+ }
351384 await dispatch ( device , 'open' , req . positionals ?? [ ] , req . flags ?. out , {
352385 ...contextFromFlags ( logPath , req . flags , appBundleId ) ,
353386 } ) ;
@@ -822,6 +855,19 @@ function parseReplayScriptLine(line: string): SessionAction | null {
822855 return action ;
823856 }
824857
858+ if ( command === 'open' ) {
859+ action . positionals = [ ] ;
860+ for ( let index = 0 ; index < args . length ; index += 1 ) {
861+ const token = args [ index ] ;
862+ if ( token === '--relaunch' ) {
863+ action . flags . relaunch = true ;
864+ continue ;
865+ }
866+ action . positionals . push ( token ) ;
867+ }
868+ return action ;
869+ }
870+
825871 if ( command === 'click' ) {
826872 if ( args . length === 0 ) return action ;
827873 const target = args [ 0 ] ;
@@ -948,6 +994,15 @@ function formatReplayActionLine(action: SessionAction): string {
948994 }
949995 return parts . join ( ' ' ) ;
950996 }
997+ if ( action . command === 'open' ) {
998+ for ( const positional of action . positionals ?? [ ] ) {
999+ parts . push ( formatReplayArg ( positional ) ) ;
1000+ }
1001+ if ( action . flags ?. relaunch ) {
1002+ parts . push ( '--relaunch' ) ;
1003+ }
1004+ return parts . join ( ' ' ) ;
1005+ }
9511006 for ( const positional of action . positionals ?? [ ] ) {
9521007 parts . push ( formatReplayArg ( positional ) ) ;
9531008 }
0 commit comments