Skip to content

Commit 8c802aa

Browse files
committed
fix(codex): stabilize app-server release tests
1 parent de16f57 commit 8c802aa

2 files changed

Lines changed: 52 additions & 66 deletions

File tree

extensions/codex/src/app-server/attempt-startup.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ describe("startCodexAttemptThread", () => {
177177
vi.restoreAllMocks();
178178
vi.unstubAllEnvs();
179179
for (const root of tempRoots) {
180-
await fs.rm(root, { recursive: true, force: true });
180+
await fs.rm(root, { recursive: true, force: true, maxRetries: 3, retryDelay: 20 });
181181
}
182182
tempRoots.clear();
183183
});
@@ -240,7 +240,7 @@ describe("startCodexAttemptThread", () => {
240240
});
241241

242242
it("clears the shared app-server when startup abandons an in-flight thread request", async () => {
243-
const { harness, run } = startThreadWithHarness(2_000);
243+
const { harness, run } = startThreadWithHarness(250);
244244
const runError = run.then(
245245
() => undefined,
246246
(error: unknown) => error,

extensions/codex/src/app-server/run-attempt.turn-watches.test.ts

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -459,75 +459,61 @@ describe("runCodexAppServerAttempt turn watches", () => {
459459
});
460460

461461
it("keeps a progressing active turn alive beyond the original attempt timeout", async () => {
462-
const harness = createStartedThreadHarness();
463-
const params = createParams(
464-
path.join(tempDir, "session.jsonl"),
465-
path.join(tempDir, "workspace"),
466-
);
467-
params.timeoutMs = 100;
468462
const onRunProgress = vi.fn();
469-
params.onRunProgress = onRunProgress;
470-
471-
const run = runCodexAppServerAttempt(params, {
472-
turnCompletionIdleTimeoutMs: 300,
473-
turnAssistantCompletionIdleTimeoutMs: 300,
474-
turnTerminalIdleTimeoutMs: 300,
463+
const onTimeout = vi.fn();
464+
const onAbort = vi.fn();
465+
const controller = createCodexAttemptTurnWatchController({
466+
threadId: "thread-1",
467+
signal: new AbortController().signal,
468+
getTurnId: () => "turn-1",
469+
isCompleted: () => false,
470+
isTerminalTurnNotificationQueued: () => false,
471+
getActiveAppServerTurnRequests: () => 0,
472+
getActiveTurnItemCount: () => 0,
473+
turnCompletionIdleTimeoutMs: 1_000,
474+
turnAssistantCompletionIdleTimeoutMs: 1_000,
475+
turnAttemptIdleTimeoutMs: 300,
476+
turnTerminalIdleTimeoutMs: 1_000,
477+
interruptTimeoutMs: 5_000,
478+
onInterruptTurn: vi.fn(),
479+
onTimeout,
480+
onMarkTimedOut: vi.fn(),
481+
onAbort,
482+
onCompleted: vi.fn(),
483+
onResolveCompletion: vi.fn(),
484+
onRecordEvent: vi.fn(),
485+
onAttemptProgress: onRunProgress,
486+
onProgressDiagnostic: vi.fn(),
475487
});
476-
await harness.waitForMethod("turn/start");
477-
await vi.waitFor(
478-
() =>
479-
expect(onRunProgress).toHaveBeenCalledWith(
480-
expect.objectContaining({ reason: "turn:start" }),
481-
),
482-
fastWait,
483-
);
484488

485-
await new Promise((resolve) => {
486-
setTimeout(resolve, 60);
487-
});
488-
await harness.notify({
489-
method: "rawResponseItem/completed",
490-
params: {
491-
threadId: "thread-1",
492-
turnId: "turn-1",
493-
item: {
494-
type: "message",
495-
id: "raw-progress-1",
496-
role: "assistant",
497-
content: [{ type: "output_text", text: "Still working." }],
498-
},
499-
},
500-
});
501-
await new Promise((resolve) => {
502-
setTimeout(resolve, 60);
503-
});
504-
await harness.notify({
505-
method: "rawResponseItem/completed",
506-
params: {
507-
threadId: "thread-1",
508-
turnId: "turn-1",
509-
item: {
510-
type: "message",
511-
id: "raw-progress-2",
512-
role: "assistant",
513-
content: [{ type: "output_text", text: "Almost done." }],
514-
},
515-
},
516-
});
489+
vi.useFakeTimers();
490+
try {
491+
controller.armAttemptIdleWatch();
492+
controller.touchActivity("turn:start", { attemptProgress: true });
517493

518-
expect(harness.request.mock.calls.some(([method]) => method === "turn/interrupt")).toBe(false);
519-
await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" });
494+
await vi.advanceTimersByTimeAsync(200);
495+
controller.noteNotificationReceived("response.custom_tool_call_input.delta", {
496+
attemptProgress: true,
497+
});
520498

521-
const result = await run;
522-
expect(result.aborted).toBe(false);
523-
expect(result.timedOut).toBe(false);
524-
expect(result.promptError).toBeNull();
525-
expect(harness.request.mock.calls.some(([method]) => method === "turn/interrupt")).toBe(false);
526-
const progressReasons = onRunProgress.mock.calls.map(([info]) => info.reason);
527-
expect(progressReasons).toContain("turn:start");
528-
expect(
529-
progressReasons.filter((reason) => reason === "notification:rawResponseItem/completed"),
530-
).toHaveLength(2);
499+
await vi.advanceTimersByTimeAsync(200);
500+
controller.noteNotificationReceived("response.custom_tool_call_input.delta", {
501+
attemptProgress: true,
502+
});
503+
504+
await vi.advanceTimersByTimeAsync(200);
505+
506+
expect(onTimeout).not.toHaveBeenCalled();
507+
expect(onAbort).not.toHaveBeenCalled();
508+
expect(onRunProgress.mock.calls.map(([reason]) => reason)).toEqual([
509+
"turn:start",
510+
"notification:response.custom_tool_call_input.delta",
511+
"notification:response.custom_tool_call_input.delta",
512+
]);
513+
} finally {
514+
controller.clearAllTimers();
515+
vi.useRealTimers();
516+
}
531517
});
532518

533519
it("does not count non-turn app-server requests as turn attempt progress", async () => {

0 commit comments

Comments
 (0)