@@ -72,15 +72,64 @@ export async function handleWaiting(ctx: RunnerContext, callbacks: WaitCallbacks
7272 // Handle Scenario 6: Auto-advance (interactive:false + autoMode + no chainedPrompts)
7373 // This can happen when queue is exhausted after autonomous loop
7474 if ( ! ctx . mode . paused && ! behavior . shouldWait && ! behavior . runAutonomousLoop ) {
75- debug ( '[Runner] Auto-advancing to next step (Scenario 6)' ) ;
76- if ( session ) {
77- await session . complete ( ) ;
75+ const action = await processPostStepDirectives ( {
76+ ctx,
77+ step,
78+ stepOutput : { output : machineCtx . currentOutput ?. output ?? '' } ,
79+ stepIndex : machineCtx . currentStepIndex ,
80+ uniqueAgentId : stepUniqueAgentId ,
81+ } ) ;
82+
83+ debug ( '[Runner:scenario6] Post-step action: %s' , action . type ) ;
84+
85+ switch ( action . type ) {
86+ case 'stop' :
87+ ctx . machine . send ( { type : 'STOP' } ) ;
88+ return ;
89+
90+ case 'checkpoint' :
91+ return ;
92+
93+ case 'pause' : {
94+ debug ( '[Runner:scenario6] Directive: pause' ) ;
95+ ctx . emitter . logMessage ( stepUniqueAgentId , `Paused${ action . reason ? `: ${ action . reason } ` : '' } ` ) ;
96+ ctx . mode . pause ( ) ;
97+ machineCtx . paused = true ;
98+ ctx . emitter . updateAgentStatus ( stepUniqueAgentId , 'awaiting' ) ;
99+ // Enable input box for user to resume
100+ const pauseQueueState = session
101+ ? session . getQueueState ( )
102+ : { promptQueue : [ ...ctx . indexManager . promptQueue ] , promptQueueIndex : ctx . indexManager . promptQueueIndex } ;
103+ ctx . emitter . setInputState ( {
104+ active : true ,
105+ queuedPrompts : pauseQueueState . promptQueue . map ( p => ( { name : p . name , label : p . label , content : p . content } ) ) ,
106+ currentIndex : pauseQueueState . promptQueueIndex ,
107+ monitoringId : machineCtx . currentMonitoringId ,
108+ } ) ;
109+ return ;
110+ }
111+
112+ case 'loop' :
113+ debug ( '[Runner:scenario6] Loop to step %d' , action . targetIndex ) ;
114+ ctx . emitter . updateAgentStatus ( stepUniqueAgentId , 'completed' ) ;
115+ await ctx . indexManager . stepCompleted ( machineCtx . currentStepIndex ) ;
116+ ctx . indexManager . resetQueue ( ) ;
117+ machineCtx . currentStepIndex = action . targetIndex ;
118+ ctx . machine . send ( { type : 'INPUT_RECEIVED' , input : '' } ) ;
119+ return ;
120+
121+ case 'advance' :
122+ default :
123+ debug ( '[Runner] Auto-advancing to next step (Scenario 6)' ) ;
124+ if ( session ) {
125+ await session . complete ( ) ;
126+ }
127+ ctx . emitter . updateAgentStatus ( stepUniqueAgentId , 'completed' ) ;
128+ ctx . indexManager . resetQueue ( ) ;
129+ await ctx . indexManager . stepCompleted ( machineCtx . currentStepIndex ) ;
130+ ctx . machine . send ( { type : 'INPUT_RECEIVED' , input : '' } ) ;
131+ return ;
78132 }
79- ctx . emitter . updateAgentStatus ( stepUniqueAgentId , 'completed' ) ;
80- ctx . indexManager . resetQueue ( ) ;
81- await ctx . indexManager . stepCompleted ( machineCtx . currentStepIndex ) ;
82- ctx . machine . send ( { type : 'INPUT_RECEIVED' , input : '' } ) ;
83- return ;
84133 }
85134
86135 // Get provider from WorkflowMode (single source of truth)
@@ -242,6 +291,27 @@ async function runAutonomousPromptLoop(ctx: RunnerContext): Promise<void> {
242291 const uniqueAgentId = getUniqueAgentId ( step , stepIndex ) ;
243292 const session = ctx . getCurrentSession ( ) ;
244293
294+ // Check for pause directive BEFORE sending next prompt (regardless of queue state)
295+ const pauseResult = await evaluateOnAdvance ( ctx . cwd ) ;
296+ if ( pauseResult . type === 'pause' ) {
297+ debug ( '[Runner:autonomous] Directive: pause (before next prompt)' ) ;
298+ ctx . emitter . logMessage ( uniqueAgentId , `Paused${ pauseResult . reason ? `: ${ pauseResult . reason } ` : '' } ` ) ;
299+ ctx . mode . pause ( ) ;
300+ machineCtx . paused = true ;
301+ ctx . emitter . updateAgentStatus ( uniqueAgentId , 'awaiting' ) ;
302+ // Enable input box for user to resume
303+ const queueState = session
304+ ? session . getQueueState ( )
305+ : { promptQueue : [ ...ctx . indexManager . promptQueue ] , promptQueueIndex : ctx . indexManager . promptQueueIndex } ;
306+ ctx . emitter . setInputState ( {
307+ active : true ,
308+ queuedPrompts : queueState . promptQueue . map ( p => ( { name : p . name , label : p . label , content : p . content } ) ) ,
309+ currentIndex : queueState . promptQueueIndex ,
310+ monitoringId : machineCtx . currentMonitoringId ,
311+ } ) ;
312+ return ;
313+ }
314+
245315 // Check if queue is exhausted
246316 const isExhausted = session
247317 ? session . isQueueExhausted
@@ -268,6 +338,25 @@ async function runAutonomousPromptLoop(ctx: RunnerContext): Promise<void> {
268338 // Checkpoint was handled by afterRun, just stay in current state
269339 return ;
270340
341+ case 'pause' : {
342+ debug ( '[Runner:autonomous] Directive: pause' ) ;
343+ ctx . emitter . logMessage ( uniqueAgentId , `Paused${ action . reason ? `: ${ action . reason } ` : '' } ` ) ;
344+ ctx . mode . pause ( ) ;
345+ machineCtx . paused = true ;
346+ ctx . emitter . updateAgentStatus ( uniqueAgentId , 'awaiting' ) ;
347+ // Enable input box for user to resume
348+ const pauseQueueState = session
349+ ? session . getQueueState ( )
350+ : { promptQueue : [ ...ctx . indexManager . promptQueue ] , promptQueueIndex : ctx . indexManager . promptQueueIndex } ;
351+ ctx . emitter . setInputState ( {
352+ active : true ,
353+ queuedPrompts : pauseQueueState . promptQueue . map ( p => ( { name : p . name , label : p . label , content : p . content } ) ) ,
354+ currentIndex : pauseQueueState . promptQueueIndex ,
355+ monitoringId : machineCtx . currentMonitoringId ,
356+ } ) ;
357+ return ;
358+ }
359+
271360 case 'loop' :
272361 // Loop directive processed - rewind to target step
273362 debug ( '[Runner:autonomous] Loop to step %d' , action . targetIndex ) ;
@@ -311,6 +400,25 @@ async function runAutonomousPromptLoop(ctx: RunnerContext): Promise<void> {
311400 case 'checkpoint' :
312401 return ;
313402
403+ case 'pause' : {
404+ debug ( '[Runner:autonomous] Directive: pause (no prompts)' ) ;
405+ ctx . emitter . logMessage ( uniqueAgentId , `Paused${ action . reason ? `: ${ action . reason } ` : '' } ` ) ;
406+ ctx . mode . pause ( ) ;
407+ machineCtx . paused = true ;
408+ ctx . emitter . updateAgentStatus ( uniqueAgentId , 'awaiting' ) ;
409+ // Enable input box for user to resume
410+ const pauseQueueState = session
411+ ? session . getQueueState ( )
412+ : { promptQueue : [ ...ctx . indexManager . promptQueue ] , promptQueueIndex : ctx . indexManager . promptQueueIndex } ;
413+ ctx . emitter . setInputState ( {
414+ active : true ,
415+ queuedPrompts : pauseQueueState . promptQueue . map ( p => ( { name : p . name , label : p . label , content : p . content } ) ) ,
416+ currentIndex : pauseQueueState . promptQueueIndex ,
417+ monitoringId : machineCtx . currentMonitoringId ,
418+ } ) ;
419+ return ;
420+ }
421+
314422 case 'loop' :
315423 debug ( '[Runner:autonomous] Loop to step %d' , action . targetIndex ) ;
316424 ctx . emitter . updateAgentStatus ( uniqueAgentId , 'completed' ) ;
0 commit comments