@@ -23,6 +23,7 @@ import {
2323} from "./compaction.js" ;
2424import { onTurnBoundary } from "./reactor-events.js" ;
2525import { isOperatorOriginated } from "./message-provenance.js" ;
26+ import { errorMessage } from "./error-message.js" ;
2627import { type } from "arktype" ;
2728import {
2829 applyManageTasks ,
@@ -656,79 +657,89 @@ class ChatDirectorImpl extends DefaultDirector {
656657 // is the exception: its sole call site runs mid-turn (tool.done, never the
657658 // turn boundary), so it always degrades to plain inference on a
658659 // coordinator throw and takes no rethrow parameter.
659- private coordinatorIsActive ( rethrowCoordinatorError : boolean ) : boolean {
660+ //
661+ // The four rethrow-capable consults below share one guard: on a coordinator
662+ // throw, either rethrow (noting it so the turn drops queued notifications)
663+ // or log under the consult's label and resolve the consult's fallback.
664+ private withCoordinatorGuard < T > (
665+ label : string ,
666+ fallback : T ,
667+ rethrowCoordinatorError : boolean ,
668+ consult : ( ) => T ,
669+ ) : T {
660670 try {
661- return this . workflowCoordinator ?. isActive ( ) === true ;
671+ return consult ( ) ;
662672 } catch ( err ) {
663673 if ( rethrowCoordinatorError ) {
664674 this . coordinatorRethrowNoted = true ;
665675 throw err ;
666676 }
667- logger . warn `workflow-coordinator-isActive-threw error=${ err instanceof Error ? err . message : String ( err ) } ` ;
668- return false ;
677+ logger . warn `${ label } error=${ errorMessage ( err ) } ` ;
678+ return fallback ;
669679 }
670680 }
671681
682+ private coordinatorIsActive ( rethrowCoordinatorError : boolean ) : boolean {
683+ return this . withCoordinatorGuard (
684+ "workflow-coordinator-isActive-threw" ,
685+ false ,
686+ rethrowCoordinatorError ,
687+ ( ) => this . workflowCoordinator ?. isActive ( ) === true ,
688+ ) ;
689+ }
690+
672691 private coordinatorDirective (
673692 rethrowCoordinatorError : boolean ,
674693 ) : string | null {
675- try {
676- const directive = this . workflowCoordinator ?. directive ( ) ?? null ;
677- if ( directive === null ) return null ;
678- if ( typeof directive !== "string" ) {
679- logger . warn `workflow-coordinator-directive-not-string` ;
680- return null ;
681- }
682- if ( directive . length === 0 ) return null ;
683- if ( directive . length > MAX_WORKFLOW_DIRECTIVE_CHARS ) {
684- logger . warn `workflow-coordinator-directive-truncated chars=${ String ( directive . length ) } max=${ String ( MAX_WORKFLOW_DIRECTIVE_CHARS ) } ` ;
685- return `${ directive . slice ( 0 , MAX_WORKFLOW_DIRECTIVE_CHARS ) } \n…[truncated]` ;
686- }
687- return directive ;
688- } catch ( err ) {
689- if ( rethrowCoordinatorError ) {
690- this . coordinatorRethrowNoted = true ;
691- throw err ;
692- }
693- logger . warn `workflow-coordinator-directive-threw error=${ err instanceof Error ? err . message : String ( err ) } ` ;
694- return null ;
695- }
694+ return this . withCoordinatorGuard < string | null > (
695+ "workflow-coordinator-directive-threw" ,
696+ null ,
697+ rethrowCoordinatorError ,
698+ ( ) => {
699+ const directive = this . workflowCoordinator ?. directive ( ) ?? null ;
700+ if ( directive === null ) return null ;
701+ if ( typeof directive !== "string" ) {
702+ logger . warn `workflow-coordinator-directive-not-string` ;
703+ return null ;
704+ }
705+ if ( directive . length === 0 ) return null ;
706+ if ( directive . length > MAX_WORKFLOW_DIRECTIVE_CHARS ) {
707+ logger . warn `workflow-coordinator-directive-truncated chars=${ String ( directive . length ) } max=${ String ( MAX_WORKFLOW_DIRECTIVE_CHARS ) } ` ;
708+ return `${ directive . slice ( 0 , MAX_WORKFLOW_DIRECTIVE_CHARS ) } \n…[truncated]` ;
709+ }
710+ return directive ;
711+ } ,
712+ ) ;
696713 }
697714
698715 private coordinatorCurrentStepIsGate (
699716 rethrowCoordinatorError : boolean ,
700717 ) : boolean {
701- try {
702- return this . workflowCoordinator ?. currentStepIsGate ( ) === true ;
703- } catch ( err ) {
704- if ( rethrowCoordinatorError ) {
705- this . coordinatorRethrowNoted = true ;
706- throw err ;
707- }
708- logger . warn `workflow-coordinator-gate-threw error=${ err instanceof Error ? err . message : String ( err ) } ` ;
709- return false ;
710- }
718+ return this . withCoordinatorGuard (
719+ "workflow-coordinator-gate-threw" ,
720+ false ,
721+ rethrowCoordinatorError ,
722+ ( ) => this . workflowCoordinator ?. currentStepIsGate ( ) === true ,
723+ ) ;
711724 }
712725
713726 private coordinatorCurrentStepId (
714727 rethrowCoordinatorError : boolean ,
715728 ) : string | null {
716- try {
717- const stepId = this . workflowCoordinator ?. currentStepId ( ) ?? null ;
718- if ( stepId === null ) return null ;
719- if ( typeof stepId !== "string" || stepId . length === 0 ) {
720- logger . warn `workflow-coordinator-step-id-not-string` ;
721- return null ;
722- }
723- return stepId ;
724- } catch ( err ) {
725- if ( rethrowCoordinatorError ) {
726- this . coordinatorRethrowNoted = true ;
727- throw err ;
728- }
729- logger . warn `workflow-coordinator-step-id-threw error=${ err instanceof Error ? err . message : String ( err ) } ` ;
730- return null ;
731- }
729+ return this . withCoordinatorGuard < string | null > (
730+ "workflow-coordinator-step-id-threw" ,
731+ null ,
732+ rethrowCoordinatorError ,
733+ ( ) => {
734+ const stepId = this . workflowCoordinator ?. currentStepId ( ) ?? null ;
735+ if ( stepId === null ) return null ;
736+ if ( typeof stepId !== "string" || stepId . length === 0 ) {
737+ logger . warn `workflow-coordinator-step-id-not-string` ;
738+ return null ;
739+ }
740+ return stepId ;
741+ } ,
742+ ) ;
732743 }
733744
734745 private coordinatorHandleToolDone (
@@ -743,7 +754,7 @@ class ChatDirectorImpl extends DefaultDirector {
743754 } catch ( err ) {
744755 // Mid-turn only (tool.done): a throwing coordinator degrades to plain
745756 // inference rather than failing the turn.
746- logger . warn `workflow-coordinator-handleToolDone-threw error=${ err instanceof Error ? err . message : String ( err ) } ` ;
757+ logger . warn `workflow-coordinator-handleToolDone-threw error=${ errorMessage ( err ) } ` ;
747758 return false ;
748759 }
749760 }
0 commit comments