@@ -351,6 +351,31 @@ export function PromptInput(props: PromptInputProps) {
351351 // Tracks text we populated from a staged notification so we can distinguish
352352 // it from text the user actually typed when a replacement notification arrives.
353353 let lastStagedText = '' ;
354+
355+ function executeAutoFire ( staged : NonNullable < typeof props . stagedNotification > ) {
356+ if ( autoFireInterval !== undefined ) {
357+ clearInterval ( autoFireInterval ) ;
358+ autoFireInterval = undefined ;
359+ }
360+ const taskId = props . taskId ;
361+ const agentId = props . agentId ;
362+ void ( async ( ) => {
363+ try {
364+ await sendPrompt ( taskId , agentId , staged . text ) ;
365+ await invoke ( IPC . MCP_CoordinatorNotificationAck , {
366+ coordinatorTaskId : taskId ,
367+ batchId : staged . batchId ,
368+ } ) ;
369+ clearStagedNotification ( taskId ) ;
370+ lastStagedText = '' ;
371+ setText ( '' ) ;
372+ logWarn ( 'autofire' , 'auto-fire succeeded' , { taskId } ) ;
373+ } catch ( e ) {
374+ logWarn ( 'autofire' , 'auto-fire failed' , { taskId, err : String ( e ) } ) ;
375+ console . error ( '[coordinator] Auto-fire failed:' , e ) ;
376+ }
377+ } ) ( ) ;
378+ }
354379 let autoFirePromptMissCount = 0 ;
355380
356381 createEffect ( ( ) => {
@@ -469,28 +494,8 @@ export function PromptInput(props: PromptInputProps) {
469494 hasPrompt : true ,
470495 } ) ;
471496 autoFirePromptMissCount = 0 ;
472-
473497 logWarn ( 'autofire' , 'firing notification into coordinator PTY' , { taskId : props . taskId } ) ;
474- clearInterval ( autoFireInterval ) ;
475- autoFireInterval = undefined ;
476- const taskId = props . taskId ;
477- const agentId = props . agentId ;
478- void ( async ( ) => {
479- try {
480- await sendPrompt ( taskId , agentId , staged . text ) ;
481- await invoke ( IPC . MCP_CoordinatorNotificationAck , {
482- coordinatorTaskId : taskId ,
483- batchId : staged . batchId ,
484- } ) ;
485- clearStagedNotification ( taskId ) ;
486- lastStagedText = '' ;
487- setText ( '' ) ;
488- logWarn ( 'autofire' , 'auto-fire succeeded' , { taskId } ) ;
489- } catch ( e ) {
490- logWarn ( 'autofire' , 'auto-fire failed' , { taskId, err : String ( e ) } ) ;
491- console . error ( '[coordinator] Auto-fire failed:' , e ) ;
492- }
493- } ) ( ) ;
498+ executeAutoFire ( staged ) ;
494499 } , 1_000 ) ;
495500 } ) ;
496501
@@ -501,6 +506,25 @@ export function PromptInput(props: PromptInputProps) {
501506 }
502507 } ) ;
503508
509+ // When the user releases control, immediately attempt to fire any pending
510+ // staged notification rather than waiting up to 1s for the next interval tick.
511+ createEffect (
512+ on (
513+ // eslint-disable-next-line solid/reactivity
514+ [ ( ) => props . controlledBy , ( ) => props . stagedNotification ] as const ,
515+ ( [ cb , staged ] , prev ) => {
516+ const prevCb = prev ?. [ 0 ] ;
517+ if ( cb === 'coordinator' && prevCb === 'human' && staged && ! staged . userEdited ) {
518+ const tail = stripAnsi ( untrack ( ( ) => getAgentOutputTail ( props . agentId ) ) ) ;
519+ if ( / [ ❯ › ] / . test ( tail . slice ( - 500 ) ) ) {
520+ logWarn ( 'autofire' , 'immediate fire on control release' , { taskId : props . taskId } ) ;
521+ executeAutoFire ( staged ) ;
522+ }
523+ }
524+ } ,
525+ ) ,
526+ ) ;
527+
504528 // --- Countdown display for auto-fire ---
505529 const [ nowMs , setNowMs ] = createSignal ( Date . now ( ) ) ;
506530 createEffect ( ( ) => {
0 commit comments