Skip to content

Commit 9a27af9

Browse files
committed
test(gateway): wait for trajectory export guidance
(cherry picked from commit 4675423)
1 parent 1d9b9ef commit 9a27af9

1 file changed

Lines changed: 65 additions & 1 deletion

File tree

src/gateway/gateway-trajectory-export.live.test.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
144203
async 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

Comments
 (0)