11import { proxyActivities , setHandler , defineSignal , condition , workflowInfo } from '@temporalio/workflow' ;
22import Handlebars from 'handlebars' ;
3- import type {
4- WorkflowResult ,
5- Blackboard ,
6- WorkflowState ,
7- TransitionRule ,
8- JudgeConfig ,
3+ import type {
4+ WorkflowResult ,
5+ Blackboard ,
6+ WorkflowState ,
7+ TransitionRule ,
8+ JudgeConfig ,
99} from '../types.js' ;
1010import * as activities from '../activities/index.js' ;
1111
@@ -242,15 +242,17 @@ async function executeState(
242242 } ) ;
243243
244244 lastOutput = result ;
245- await emit ( 'WorkflowIterationCompleted' , {
246- iteration_number : iteration ,
247- output : result . output
248- } ) ;
249245
250246 if ( result . status !== 'completed' ) {
247+ // Throw here — the catch block below emits WorkflowIterationFailed
251248 throw new Error ( `Agent execution failed: ${ result . error } ` ) ;
252249 }
253250
251+ await emit ( 'WorkflowIterationCompleted' , {
252+ iteration_number : iteration ,
253+ output : result . output ?? '' ,
254+ } ) ;
255+
254256 if ( judges . length === 0 ) {
255257 // No judges configured — treat first successful execution as valid.
256258 break ;
@@ -393,11 +395,11 @@ async function executeState(
393395 max_attempts : state . container_run_retry ?. max_attempts ?? 1 ,
394396 } ) ;
395397
396- if ( crResult . exit_code === 0 ) {
397- await emit ( 'ContainerRunCompleted' , {
398- state_name : stateName ,
399- exit_code : crResult . exit_code ,
400- duration_ms : crResult . duration_ms ,
398+ if ( crResult . exit_code === 0 ) {
399+ await emit ( 'ContainerRunCompleted' , {
400+ state_name : stateName ,
401+ exit_code : crResult . exit_code ,
402+ duration_ms : crResult . duration_ms ,
401403 attempts : crResult . attempts ,
402404 } ) ;
403405 } else {
@@ -410,20 +412,20 @@ async function executeState(
410412 } ) ;
411413 }
412414
413- return {
414- status : crResult . exit_code === 0 ? 'success' : 'failed' ,
415- output : {
416- exit_code : crResult . exit_code ,
417- stdout : crResult . stdout ,
418- stderr : crResult . stderr ,
419- duration_ms : crResult . duration_ms ,
420- attempts : crResult . attempts ,
421- } ,
422- exit_code : crResult . exit_code ,
423- stdout : crResult . stdout ,
424- stderr : crResult . stderr ,
425- duration_ms : crResult . duration_ms ,
426- attempts : crResult . attempts ,
415+ return {
416+ status : crResult . exit_code === 0 ? 'success' : 'failed' ,
417+ output : {
418+ exit_code : crResult . exit_code ,
419+ stdout : crResult . stdout ,
420+ stderr : crResult . stderr ,
421+ duration_ms : crResult . duration_ms ,
422+ attempts : crResult . attempts ,
423+ } ,
424+ exit_code : crResult . exit_code ,
425+ stdout : crResult . stdout ,
426+ stderr : crResult . stderr ,
427+ duration_ms : crResult . duration_ms ,
428+ attempts : crResult . attempts ,
427429 } ;
428430 }
429431
@@ -447,60 +449,60 @@ async function executeState(
447449 completion : state . parallel_container_completion ?? 'all_succeed' ,
448450 } ) ;
449451
450- const pcrResult = await executeParallelContainerRunActivity ( {
451- execution_id : executionId ,
452- state_name : stateName ,
453- steps : renderedSteps ,
454- completion : state . parallel_container_completion ?? 'all_succeed' ,
455- } ) ;
456-
457- const byStep = Object . fromEntries (
458- pcrResult . results . map ( ( r ) => [ r . name , {
459- exit_code : r . exit_code ,
460- stdout : r . stdout ,
461- stderr : r . stderr ,
462- duration_ms : r . duration_ms ,
463- } ] )
464- ) ;
465-
466- if ( pcrResult . overall_success ) {
467- await emit ( 'ContainerRunCompleted' , {
468- state_name : stateName ,
469- overall_success : pcrResult . overall_success ,
470- completion : pcrResult . completion ,
471- succeeded : pcrResult . succeeded ,
472- failed : pcrResult . failed ,
473- step_results : pcrResult . results . map ( ( r ) => ( {
474- name : r . name ,
475- exit_code : r . exit_code ,
476- duration_ms : r . duration_ms ,
477- } ) ) ,
478- } ) ;
479- } else {
480- await emit ( 'ContainerRunFailed' , {
481- state_name : stateName ,
482- overall_success : pcrResult . overall_success ,
483- completion : pcrResult . completion ,
484- succeeded : pcrResult . succeeded ,
485- failed : pcrResult . failed ,
486- step_results : pcrResult . results . map ( ( r ) => ( {
487- name : r . name ,
488- exit_code : r . exit_code ,
489- stderr : r . stderr ,
490- } ) ) ,
491- } ) ;
492- }
493-
494- return {
495- status : pcrResult . overall_success ? 'success' : 'failed' ,
496- overall_success : pcrResult . overall_success ,
497- completion : pcrResult . completion ,
498- succeeded : pcrResult . succeeded ,
499- failed : pcrResult . failed ,
500- output : byStep ,
501- results : pcrResult . results ,
502- } ;
503- }
452+ const pcrResult = await executeParallelContainerRunActivity ( {
453+ execution_id : executionId ,
454+ state_name : stateName ,
455+ steps : renderedSteps ,
456+ completion : state . parallel_container_completion ?? 'all_succeed' ,
457+ } ) ;
458+
459+ const byStep = Object . fromEntries (
460+ pcrResult . results . map ( ( r ) => [ r . name , {
461+ exit_code : r . exit_code ,
462+ stdout : r . stdout ,
463+ stderr : r . stderr ,
464+ duration_ms : r . duration_ms ,
465+ } ] )
466+ ) ;
467+
468+ if ( pcrResult . overall_success ) {
469+ await emit ( 'ContainerRunCompleted' , {
470+ state_name : stateName ,
471+ overall_success : pcrResult . overall_success ,
472+ completion : pcrResult . completion ,
473+ succeeded : pcrResult . succeeded ,
474+ failed : pcrResult . failed ,
475+ step_results : pcrResult . results . map ( ( r ) => ( {
476+ name : r . name ,
477+ exit_code : r . exit_code ,
478+ duration_ms : r . duration_ms ,
479+ } ) ) ,
480+ } ) ;
481+ } else {
482+ await emit ( 'ContainerRunFailed' , {
483+ state_name : stateName ,
484+ overall_success : pcrResult . overall_success ,
485+ completion : pcrResult . completion ,
486+ succeeded : pcrResult . succeeded ,
487+ failed : pcrResult . failed ,
488+ step_results : pcrResult . results . map ( ( r ) => ( {
489+ name : r . name ,
490+ exit_code : r . exit_code ,
491+ stderr : r . stderr ,
492+ } ) ) ,
493+ } ) ;
494+ }
495+
496+ return {
497+ status : pcrResult . overall_success ? 'success' : 'failed' ,
498+ overall_success : pcrResult . overall_success ,
499+ completion : pcrResult . completion ,
500+ succeeded : pcrResult . succeeded ,
501+ failed : pcrResult . failed ,
502+ output : byStep ,
503+ results : pcrResult . results ,
504+ } ;
505+ }
504506
505507 default :
506508 throw new Error ( `Unknown state kind: ${ state . kind } ` ) ;
@@ -520,34 +522,34 @@ async function evaluateTransitions(
520522 return null ;
521523}
522524
523- async function evaluateCondition ( t : TransitionRule , output : any , bb : Blackboard ) : Promise < boolean > {
524- const resolvedExitCode =
525- typeof output ?. exit_code === 'number'
526- ? output . exit_code
527- : typeof output ?. output ?. exit_code === 'number'
528- ? output . output . exit_code
529- : undefined ;
530-
531- const resolvedStatus = output ?. status ;
532-
533- switch ( t . condition ) {
534- case 'always' : return true ;
535- case 'on_success' :
536- return resolvedStatus === 'completed' ||
537- resolvedStatus === 'success' ||
538- resolvedExitCode === 0 ||
539- output ?. overall_success === true ;
540- case 'on_failure' :
541- return resolvedStatus === 'failed' ||
542- resolvedStatus === 'error' ||
543- ( typeof resolvedExitCode === 'number' && resolvedExitCode !== 0 ) ||
544- output ?. overall_success === false ;
545- case 'exit_code_zero' :
546- return resolvedExitCode === 0 ;
547- case 'exit_code_non_zero' :
548- return typeof resolvedExitCode === 'number' && resolvedExitCode !== 0 ;
549- case 'exit_code' :
550- return typeof resolvedExitCode === 'number' && resolvedExitCode === t . exit_code ;
525+ async function evaluateCondition ( t : TransitionRule , output : any , bb : Blackboard ) : Promise < boolean > {
526+ const resolvedExitCode =
527+ typeof output ?. exit_code === 'number'
528+ ? output . exit_code
529+ : typeof output ?. output ?. exit_code === 'number'
530+ ? output . output . exit_code
531+ : undefined ;
532+
533+ const resolvedStatus = output ?. status ;
534+
535+ switch ( t . condition ) {
536+ case 'always' : return true ;
537+ case 'on_success' :
538+ return resolvedStatus === 'completed' ||
539+ resolvedStatus === 'success' ||
540+ resolvedExitCode === 0 ||
541+ output ?. overall_success === true ;
542+ case 'on_failure' :
543+ return resolvedStatus === 'failed' ||
544+ resolvedStatus === 'error' ||
545+ ( typeof resolvedExitCode === 'number' && resolvedExitCode !== 0 ) ||
546+ output ?. overall_success === false ;
547+ case 'exit_code_zero' :
548+ return resolvedExitCode === 0 ;
549+ case 'exit_code_non_zero' :
550+ return typeof resolvedExitCode === 'number' && resolvedExitCode !== 0 ;
551+ case 'exit_code' :
552+ return typeof resolvedExitCode === 'number' && resolvedExitCode === t . exit_code ;
551553 case 'score_above' : return ( output ?. score || output ?. final_score || 0 ) > ( t . threshold || 0 ) ;
552554 case 'score_below' : return ( output ?. score || output ?. final_score || 0 ) < ( t . threshold || 1 ) ;
553555 case 'score_between' :
@@ -577,10 +579,10 @@ async function evaluateCondition(t: TransitionRule, output: any, bb: Blackboard)
577579 try {
578580 const tmpl = `{{#if ${ t . expression } }}true{{else}}false{{/if}}` ;
579581 return renderTemplate ( tmpl , { ...bb , state_output : output } ) . trim ( ) === 'true' ;
580- } catch {
581- // If custom handlebar evaluation throws, we assume false to prevent FSM crash
582- return false ;
583- }
582+ } catch {
583+ // If custom handlebar evaluation throws, we assume false to prevent FSM crash
584+ return false ;
585+ }
584586 default : return false ;
585587 }
586588}
0 commit comments