@@ -141,6 +141,65 @@ async function waitForPath(filePath: string, timeoutMs = 60_000): Promise<void>
141141 throw new Error ( `timed out waiting for ${ filePath } ` ) ;
142142}
143143
144+ function extractAssistantTexts ( messages : unknown [ ] ) : string [ ] {
145+ const texts : string [ ] = [ ] ;
146+ for ( const entry of messages ) {
147+ if ( ! entry || typeof entry !== "object" ) {
148+ continue ;
149+ }
150+ if ( ( entry as { role ?: unknown } ) . role !== "assistant" ) {
151+ continue ;
152+ }
153+ const text = extractFirstTextBlock ( entry ) ;
154+ if ( typeof text === "string" && text . trim ( ) . length > 0 ) {
155+ texts . push ( text ) ;
156+ }
157+ }
158+ return texts ;
159+ }
160+
161+ function formatAssistantTextPreview ( texts : string [ ] , maxChars = 800 ) : string {
162+ const combined = texts . join ( "\n\n" ) . trim ( ) ;
163+ if ( ! combined ) {
164+ return "<none>" ;
165+ }
166+ return combined . length > maxChars ? `${ combined . slice ( 0 , maxChars ) } ...` : combined ;
167+ }
168+
169+ async function waitForAssistantText ( params : {
170+ client : GatewayClient ;
171+ contains : string ;
172+ sessionKey : string ;
173+ timeoutMs ?: number ;
174+ } ) : Promise < string > {
175+ const timeoutMs = params . timeoutMs ?? 60_000 ;
176+ const startedAt = Date . now ( ) ;
177+ while ( Date . now ( ) - startedAt < timeoutMs ) {
178+ const history : { messages ?: unknown [ ] } = await params . client . request ( "chat.history" , {
179+ sessionKey : params . sessionKey ,
180+ limit : 24 ,
181+ } ) ;
182+ const assistantTexts = extractAssistantTexts ( history . messages ?? [ ] ) ;
183+ const matched = assistantTexts . find ( ( text ) => text . includes ( params . contains ) ) ;
184+ if ( matched ) {
185+ return matched ;
186+ }
187+ await new Promise ( ( resolve ) => {
188+ setTimeout ( resolve , 500 ) ;
189+ } ) ;
190+ }
191+
192+ const finalHistory : { messages ?: unknown [ ] } = await params . client . request ( "chat.history" , {
193+ sessionKey : params . sessionKey ,
194+ limit : 24 ,
195+ } ) ;
196+ throw new Error (
197+ `timed out waiting for assistant text containing ${ params . contains } : ${ formatAssistantTextPreview (
198+ extractAssistantTexts ( finalHistory . messages ?? [ ] ) ,
199+ ) } `,
200+ ) ;
201+ }
202+
144203async function approveTrajectoryExport ( client : GatewayClient ) : Promise < string > {
145204 const approvals = ( await client . request (
146205 "exec.approval.list" ,
@@ -282,7 +341,12 @@ describeLive("gateway live trajectory export", () => {
282341 const finalText =
283342 typeof exportResponse ?. message === "object"
284343 ? extractFirstTextBlock ( exportResponse . message )
285- : undefined ;
344+ : await waitForAssistantText ( {
345+ client,
346+ sessionKey,
347+ contains : "Trajectory exports can include" ,
348+ timeoutMs : 60_000 ,
349+ } ) ;
286350 expect ( finalText ) . toContain ( "Trajectory exports can include" ) ;
287351 expect ( finalText ) . toContain ( "through exec approval" ) ;
288352 const approvalId = await approveTrajectoryExport ( client ) ;
0 commit comments