diff --git a/apps/server/src/provider/CodexInstallation.test.ts b/apps/server/src/provider/CodexInstallation.test.ts index ab266b7a8c01d..daf1dac2654de 100644 --- a/apps/server/src/provider/CodexInstallation.test.ts +++ b/apps/server/src/provider/CodexInstallation.test.ts @@ -359,6 +359,33 @@ it.effect("requires an update before running an older activated managed installa }).pipe(Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeCrypto.layer))), ); +it.effect("updates an older supported managed installation to the pinned release on startup", () => + Effect.gen(function* () { + const first = yield* makeHarness(); + yield* first.installation.start; + yield* terminalState(first.installation); + const executable = yield* first.installation.resolve(); + const oldDirectory = `${first.installation.managedDirectory}/0.156.0`; + yield* first.fs.rename(executable.managedVersionDirectory!, oldDirectory); + for (const name of ["codex-package.json", ".install-complete.json"]) { + const file = `${oldDirectory}/${name}`; + yield* first.fs.writeFileString( + file, + (yield* first.fs.readFileString(file)).replaceAll("0.156.1", "0.156.0"), + ); + } + yield* first.fs.writeFileString( + `${first.installation.managedDirectory}/active.json`, + '{"version":"0.156.0"}', + ); + const restarted = yield* makeHarness({ baseDir: first.baseDir }); + expect((yield* restarted.installation.state).operationId).not.toBeNull(); + expect((yield* terminalState(restarted.installation)).phase).toBe("succeeded"); + expect((yield* restarted.installation.resolve()).version).toBe("0.156.1"); + expect(restarted.downloads()).toBe(1); + }).pipe(Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeCrypto.layer))), +); + it.effect("rejects corrupted downloads without publishing a runtime", () => Effect.gen(function* () { const { installation, fs } = yield* makeHarness({ diff --git a/apps/server/src/provider/CodexInstallation.ts b/apps/server/src/provider/CodexInstallation.ts index 83e9e4e15864d..8fdcfbebb328e 100644 --- a/apps/server/src/provider/CodexInstallation.ts +++ b/apps/server/src/provider/CodexInstallation.ts @@ -5,6 +5,7 @@ import { type ServerProviderCompatibilityAdvisory, } from "@t3tools/contracts"; import { cliArchiveTarCommand } from "@t3tools/shared/cliRelease"; +import { compareSemverVersions } from "@t3tools/shared/semver"; import * as HostProcess from "@t3tools/shared/HostProcess"; import { resolveCommandPath, resolveSpawnCommand } from "@t3tools/shared/shell"; import * as Clock from "effect/Clock"; @@ -58,46 +59,46 @@ export interface CodexReleaseAsset { } const RELEASES: Readonly> = { "darwin-arm64": { - version: "0.156.1", + version: "0.166.0", target: "aarch64-apple-darwin", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-aarch64-apple-darwin.tar.gz", - sha256: "fea42f9625091f011e38f059da974d52e57ba31831648bb1c7f0b1a385fde547", - archiveBytes: 127394863, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-aarch64-apple-darwin.tar.gz", + sha256: "55a440cb579f970abe7c79ab181e54b0ea4c419be99f333bbd868eebac9c21f0", + archiveBytes: 165951869, }, "darwin-x64": { - version: "0.156.1", + version: "0.166.0", target: "x86_64-apple-darwin", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-x86_64-apple-darwin.tar.gz", - sha256: "618dbcd55419fa041871f777a14b107ceb3fe2d339ef81e21e6ab5374420dc71", - archiveBytes: 138670455, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-x86_64-apple-darwin.tar.gz", + sha256: "1cb65690230be5982c654ba2655e3a3b594dce9c55b780e78bfdfeff829d7ad9", + archiveBytes: 180076524, }, "linux-arm64": { - version: "0.156.1", + version: "0.166.0", target: "aarch64-unknown-linux-musl", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-aarch64-unknown-linux-musl.tar.gz", - sha256: "fdd47ed6aade0360796fd3f6f95a45096f327c15e19e8c7339f9dc5633041786", - archiveBytes: 136933361, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-aarch64-unknown-linux-musl.tar.gz", + sha256: "7821b77dda2e6283fb1f63f3165177a271da8833e857cf673c6ca1c9db3bfcc6", + archiveBytes: 187370368, }, "linux-x64": { - version: "0.156.1", + version: "0.166.0", target: "x86_64-unknown-linux-musl", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-x86_64-unknown-linux-musl.tar.gz", - sha256: "8b711520beddf385467b8da4d2c93736637c6ba1e46811cf0d8606b7c490b6f6", - archiveBytes: 145976992, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-x86_64-unknown-linux-musl.tar.gz", + sha256: "1d44b28bc4ac9937d7d3532264baa68a507ce364956a0d4ebb856f331cdee254", + archiveBytes: 199694962, }, "win32-arm64": { - version: "0.156.1", + version: "0.166.0", target: "aarch64-pc-windows-msvc", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-aarch64-pc-windows-msvc.tar.gz", - sha256: "85994caecdc7609c49fd585c1cdb5677fa9d0acbf789650cff23a13afc9505db", - archiveBytes: 142037952, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-aarch64-pc-windows-msvc.tar.gz", + sha256: "9383152a72f97bb5dd148493c8214e4fed38d805aa2c3297cb3739f7f130becf", + archiveBytes: 187024318, }, "win32-x64": { - version: "0.156.1", + version: "0.166.0", target: "x86_64-pc-windows-msvc", - url: "https://github.com/openai/codex/releases/download/rust-v0.156.1/codex-package-x86_64-pc-windows-msvc.tar.gz", - sha256: "a2e017db9807e6a2269a26fea0e1d9546469cef4d472a33016bc9f3ad7d3b733", - archiveBytes: 153839991, + url: "https://github.com/openai/codex/releases/download/rust-v0.166.0/codex-package-x86_64-pc-windows-msvc.tar.gz", + sha256: "d559bb88e74d471265857b93b7f19bc250dae527673b9191b33534478093f6bc", + archiveBytes: 202589789, }, }; const resolveCodexReleaseAsset = (platform: NodeJS.Platform, arch: string) => @@ -655,14 +656,12 @@ export const makeCodexInstallation = Effect.fn("makeCodexInstallation")(function } const operationId = yield* random.uuidV4(); const next: ProviderInstallState = { - driver: DRIVER, + ...current, operationId, phase: "downloading", downloadedBytes: 0, totalBytes: asset.archiveBytes, version: asset.version, - installedVersion: current.installedVersion, - canRemove: current.canRemove, message: "Downloading Codex.", }; yield* SubscriptionRef.set(state, next); @@ -807,6 +806,9 @@ export const makeCodexInstallation = Effect.fn("makeCodexInstallation")(function source: "managed", }) satisfies ProviderInstallState, ); + // A supported older runtime still resolves, so a raised pin needs its own update. + if (asset && compareSemverVersions(installed.version, asset.version) < 0) + yield* start.pipe(Effect.ignore); }).pipe( Effect.catch(() => SubscriptionRef.update(