@@ -690,12 +690,77 @@ function assertMatrixQaToolProgressMentionsInert(event: MatrixQaObservedEvent) {
690690 }
691691}
692692
693+ function hasMatrixQaToolProgressPreviewLine ( body : string | undefined ) {
694+ return Boolean (
695+ body ?. split ( / \r ? \n / ) . some ( ( line ) => / ^ \s * [ - * • ] \s + ` ? [ ^ ` \s ] [ ^ ` ] * ` ? \s * $ / u. test ( line ) ) ,
696+ ) ;
697+ }
698+
699+ function truncateMatrixQaToolProgressBody ( body : string | undefined ) {
700+ if ( ! body ) {
701+ return "<none>" ;
702+ }
703+ return body . length <= 240 ? body : `${ body . slice ( 0 , 237 ) } ...` ;
704+ }
705+
706+ function describeMatrixQaToolProgressCandidate ( event : MatrixQaObservedEvent ) {
707+ const relation = event . relatesTo ?. relType
708+ ? `${ event . relatesTo . relType } :${ event . relatesTo . eventId ?? "<none>" } `
709+ : "<none>" ;
710+ return [
711+ `${ event . eventId } kind=${ event . kind } ` ,
712+ `relation=${ relation } ` ,
713+ `body=${ JSON . stringify ( truncateMatrixQaToolProgressBody ( event . body ) ) } ` ,
714+ ] . join ( " " ) ;
715+ }
716+
717+ function buildMatrixQaToolProgressTimeoutMessage ( params : {
718+ cause : unknown ;
719+ events : MatrixQaObservedEvent [ ] ;
720+ expectedPreviewKind : MatrixQaObservedEvent [ "kind" ] ;
721+ previewEventId : string ;
722+ roomId : string ;
723+ startIndex : number ;
724+ sutUserId : string ;
725+ } ) {
726+ const candidates = params . events
727+ . slice ( params . startIndex )
728+ . filter ( ( event ) => {
729+ if (
730+ event . roomId !== params . roomId ||
731+ event . sender !== params . sutUserId ||
732+ event . type !== "m.room.message" ||
733+ event . kind !== params . expectedPreviewKind
734+ ) {
735+ return false ;
736+ }
737+ return (
738+ event . eventId === params . previewEventId ||
739+ event . relatesTo ?. eventId === params . previewEventId ||
740+ / \b W o r k i n g \b / i. test ( event . body ?? "" )
741+ ) ;
742+ } )
743+ . slice ( - 8 ) ;
744+ const candidateDetails =
745+ candidates . length === 0
746+ ? [ "observed preview candidates: <none>" ]
747+ : [ "observed preview candidates:" , ...candidates . map ( describeMatrixQaToolProgressCandidate ) ] ;
748+ return [
749+ params . cause instanceof Error
750+ ? params . cause . message
751+ : `Matrix tool progress wait failed: ${ String ( params . cause ) } ` ,
752+ `preview event: ${ params . previewEventId } ` ,
753+ ...candidateDetails ,
754+ ] . join ( "\n" ) ;
755+ }
756+
693757async function runMatrixToolProgressScenario (
694758 context : MatrixQaScenarioContext ,
695759 params : {
696760 expectedPreviewKind : MatrixQaObservedEvent [ "kind" ] ;
697761 finalText : string ;
698762 label : string ;
763+ allowGenericProgressLine ?: boolean ;
699764 mentionSafety ?: boolean ;
700765 progressPattern : RegExp ;
701766 triggerBodyBuilder : ( sutUserId : string , finalText : string ) => string ;
@@ -721,22 +786,39 @@ async function runMatrixToolProgressScenario(
721786 since : startSince ,
722787 timeoutMs : context . timeoutMs ,
723788 } ) ;
724- const progress = params . progressPattern . test ( preview . event . body ?? "" )
789+ const matchesExpectedProgress = ( body : string | undefined ) =>
790+ params . progressPattern . test ( body ?? "" ) ||
791+ ( params . allowGenericProgressLine === true && hasMatrixQaToolProgressPreviewLine ( body ) ) ;
792+ const progress = matchesExpectedProgress ( preview . event . body )
725793 ? preview
726- : await client . waitForRoomEvent ( {
727- observedEvents : context . observedEvents ,
728- predicate : ( event ) =>
729- event . roomId === context . roomId &&
730- event . sender === context . sutUserId &&
731- event . kind === params . expectedPreviewKind &&
732- event . relatesTo ?. relType === "m.replace" &&
733- event . relatesTo . eventId === preview . event . eventId &&
734- / \b W o r k i n g \b / i. test ( event . body ?? "" ) &&
735- params . progressPattern . test ( event . body ?? "" ) ,
736- roomId : context . roomId ,
737- since : preview . since ,
738- timeoutMs : context . timeoutMs ,
739- } ) ;
794+ : await client
795+ . waitForRoomEvent ( {
796+ observedEvents : context . observedEvents ,
797+ predicate : ( event ) =>
798+ event . roomId === context . roomId &&
799+ event . sender === context . sutUserId &&
800+ event . kind === params . expectedPreviewKind &&
801+ event . relatesTo ?. relType === "m.replace" &&
802+ event . relatesTo . eventId === preview . event . eventId &&
803+ / \b W o r k i n g \b / i. test ( event . body ?? "" ) &&
804+ matchesExpectedProgress ( event . body ) ,
805+ roomId : context . roomId ,
806+ since : preview . since ,
807+ timeoutMs : context . timeoutMs ,
808+ } )
809+ . catch ( ( err : unknown ) => {
810+ throw new Error (
811+ buildMatrixQaToolProgressTimeoutMessage ( {
812+ cause : err ,
813+ events : context . observedEvents ,
814+ expectedPreviewKind : params . expectedPreviewKind ,
815+ previewEventId : preview . event . eventId ,
816+ roomId : context . roomId ,
817+ startIndex : startObservedIndex ,
818+ sutUserId : context . sutUserId ,
819+ } ) ,
820+ ) ;
821+ } ) ;
740822
741823 if ( params . mentionSafety ) {
742824 assertMatrixQaToolProgressMentionsInert ( progress . event ) ;
@@ -804,6 +886,7 @@ export async function runToolProgressPreviewScenario(context: MatrixQaScenarioCo
804886 expectedPreviewKind : "notice" ,
805887 finalText : buildMatrixQaToken ( "MATRIX_QA_TOOL_PROGRESS" ) ,
806888 label : "tool progress preview" ,
889+ allowGenericProgressLine : true ,
807890 progressPattern : / \b t o o l : \s * r e a d \b / i,
808891 triggerBodyBuilder : buildMatrixToolProgressPrompt ,
809892 } ) ;
0 commit comments