From 6931f69cf49a278e5cfa0d47248fab718a0e12b1 Mon Sep 17 00:00:00 2001 From: Michel-Liao Date: Wed, 2 Sep 2026 21:31:48 -0400 Subject: [PATCH] fix(codex): allow slow provider probes to finish --- apps/server/src/provider/Layers/CodexProvider.ts | 6 ++++-- .../src/provider/Layers/ProviderRegistry.test.ts | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/server/src/provider/Layers/CodexProvider.ts b/apps/server/src/provider/Layers/CodexProvider.ts index a0e2b744c2a7..551da63c97ea 100644 --- a/apps/server/src/provider/Layers/CodexProvider.ts +++ b/apps/server/src/provider/Layers/CodexProvider.ts @@ -33,7 +33,6 @@ import { import { resolveSpawnCommand } from "@t3tools/shared/shell"; import { codexAppServerArgs, resolveCodexLaunchArgs } from "./codexLaunchArgs.ts"; import { - AUTH_PROBE_TIMEOUT_MS, buildServerProvider, COMPACT_SLASH_COMMAND, type ServerProviderDraft, @@ -62,6 +61,9 @@ type CodexRateLimitsProbe = | { readonly failure: string }; const CODEX_APP_SERVER_PROBE_FORCE_KILL_AFTER = "2 seconds" as const; +// Codex's probe includes the app-server handshake, account, models, and skills. On Windows the +// command shim and concurrent startup probes can legitimately take longer than the shared 10s. +const CODEX_AUTH_PROBE_TIMEOUT_MS = 20_000; const CODEX_PRESENTATION = { displayName: "Codex", @@ -608,7 +610,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu environment: resolvedEnvironment, }).pipe( Effect.scoped, - Effect.timeoutOption(Duration.millis(AUTH_PROBE_TIMEOUT_MS)), + Effect.timeoutOption(Duration.millis(CODEX_AUTH_PROBE_TIMEOUT_MS)), Effect.result, ); diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts index 988c89e1e679..fc7c15471a0f 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts @@ -530,6 +530,20 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te }), ); + it.effect("allows a slow Codex app-server probe to finish", () => + Effect.gen(function* () { + const statusFiber = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.sleep("15 seconds").pipe(Effect.as(makeCodexProbeSnapshot())), + ).pipe(Effect.forkChild); + + yield* Effect.yieldNow; + yield* TestClock.adjust("15 seconds"); + + const status = yield* Fiber.join(statusFiber); + assert.strictEqual(status.status, "ready"); + }), + ); + it.effect("closes the app-server probe scope when provider status times out", () => Effect.gen(function* () { const killCalls = yield* Ref.make(0); @@ -539,7 +553,7 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te ); yield* Effect.yieldNow; - yield* TestClock.adjust("11 seconds"); + yield* TestClock.adjust("21 seconds"); yield* Effect.yieldNow; const status = yield* Fiber.join(statusFiber);