| 1 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 2 | import { assert, it } from "@effect/vitest"; |
| 3 | import { CodexSettings } from "@t3tools/contracts"; |
| 4 | import * as DateTime from "effect/DateTime"; |
| 5 | import * as Effect from "effect/Effect"; |
| 6 | import * as FileSystem from "effect/FileSystem"; |
| 7 | import * as Path from "effect/Path"; |
| 8 | import * as Schema from "effect/Schema"; |
| 9 | |
| 10 | import { checkCodexProviderStatus } from "./CodexProvider.ts"; |
| 11 | |
| 12 | /** |
| 13 | * Stand-in for Codex 0.162's app-server catalog behavior: |
| 14 | * - `model/list` answers from `CODEX_HOME/models_cache.json` while it is fresh. |
| 15 | * - A startup refresh runs before `initialize`, so it uses the originator set |
| 16 | * at spawn (the override env var, else the plain CLI's `codex_cli_rs`). |
| 17 | * - The backend grants Ultrafast only to entitled accounts on app originators. |
| 18 | */ |
| 19 | const FAKE_CODEX_APP_SERVER = String.raw`#!/usr/bin/env node |
| 20 | const fs = require("node:fs"); |
| 21 | const path = require("node:path"); |
| 22 | const readline = require("node:readline"); |
| 23 | const cachePath = path.join(process.env.CODEX_HOME, "models_cache.json"); |
| 24 | const originator = process.env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE ?? "codex_cli_rs"; |
| 25 | const ultrafast = process.env.FAKE_ULTRAFAST_ENTITLED === "1" && originator !== "codex_cli_rs"; |
| 26 | const model = (tiers) => ({ |
| 27 | id: "gpt-6.1-sol", model: "gpt-6.1-sol", displayName: "GPT-6.1 Sol", description: "", |
| 28 | hidden: false, isDefault: true, defaultReasoningEffort: "high", |
| 29 | supportedReasoningEfforts: [{ reasoningEffort: "high", description: "" }], |
| 30 | serviceTiers: tiers.map((id) => ({ id, name: id, description: "" })), |
| 31 | }); |
| 32 | setTimeout(() => { |
| 33 | const tiers = ultrafast ? ["priority", "ultrafast"] : ["priority"]; |
| 34 | fs.writeFileSync(cachePath, JSON.stringify({ fetched_at: new Date().toISOString(), models: [model(tiers)] })); |
| 35 | }, 300); |
| 36 | const write = (message) => process.stdout.write(JSON.stringify(message) + "\n"); |
| 37 | readline.createInterface({ input: process.stdin }).on("line", (line) => { |
| 38 | const { id, method } = JSON.parse(line); |
| 39 | if (id === undefined) return; |
| 40 | if (method === "initialize") { |
| 41 | write({ id, result: { userAgent: "codex/0.162.0", codexHome: process.env.CODEX_HOME, platformFamily: "unix", platformOs: "macos" } }); |
| 42 | } else if (method === "account/read") { |
| 43 | write({ id, result: { account: { type: "chatgpt", email: "test@example.com", planType: "promax" }, requiresOpenaiAuth: false } }); |
| 44 | } else if (method === "skills/list") { |
| 45 | write({ id, result: { data: [] } }); |
| 46 | } else if (method === "model/list") { |
| 47 | write({ id, result: { data: JSON.parse(fs.readFileSync(cachePath, "utf8")).models, nextCursor: null } }); |
| 48 | } else { |
| 49 | write({ id, error: { code: -32601, message: "unsupported" } }); |
| 50 | } |
| 51 | }); |
| 52 | `; |
| 53 | |
| 54 | const decodeCodexSettings = Schema.decodeSync(CodexSettings); |
| 55 | |
| 56 | const solServiceTiers = Effect.fn("solServiceTiers")(function* (ultrafastEntitled: boolean) { |
| 57 | const fs = yield* FileSystem.FileSystem; |
| 58 | const path = yield* Path.Path; |
| 59 | const dir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-codex-catalog-" }); |
| 60 | const binaryPath = path.join(dir, "codex"); |
| 61 | yield* fs.writeFileString(binaryPath, FAKE_CODEX_APP_SERVER); |
| 62 | yield* fs.chmod(binaryPath, 0o755); |
| 63 | // A fresh cache written by another client: the plain CLI's (no Ultrafast) |
| 64 | // when entitled, or a stale entitled catalog when the entitlement is gone. |
| 65 | yield* fs.writeFileString( |
| 66 | path.join(dir, "models_cache.json"), |
| 67 | JSON.stringify({ |
| 68 | fetched_at: DateTime.formatIso(DateTime.subtract(yield* DateTime.now, { minutes: 1 })), |
| 69 | models: [ |
| 70 | { |
| 71 | id: "gpt-6.1-sol", |
| 72 | model: "gpt-6.1-sol", |
| 73 | displayName: "GPT-6.1 Sol", |
| 74 | description: "", |
| 75 | hidden: false, |
| 76 | isDefault: true, |
| 77 | defaultReasoningEffort: "high", |
| 78 | supportedReasoningEfforts: [{ reasoningEffort: "high", description: "" }], |
| 79 | serviceTiers: (ultrafastEntitled ? ["priority"] : ["priority", "ultrafast"]).map( |
| 80 | (id) => ({ id, name: id, description: "" }), |
| 81 | ), |
| 82 | }, |
| 83 | ], |
| 84 | }), |
| 85 | ); |
| 86 | |
| 87 | const { CODEX_INTERNAL_ORIGINATOR_OVERRIDE: _ambient, ...environment } = process.env; |
| 88 | const provider = yield* checkCodexProviderStatus( |
| 89 | decodeCodexSettings({ binaryPath, homePath: dir }), |
| 90 | undefined, |
| 91 | { ...environment, FAKE_ULTRAFAST_ENTITLED: ultrafastEntitled ? "1" : "0" }, |
| 92 | ); |
| 93 | const serviceTier = provider.models |
| 94 | .find((model) => model.slug === "gpt-6.1-sol") |
| 95 | ?.capabilities?.optionDescriptors?.find((descriptor) => descriptor.id === "serviceTier"); |
| 96 | return serviceTier?.type === "select" ? serviceTier.options.map((option) => option.id) : []; |
| 97 | }); |
| 98 | |
| 99 | it.layer(NodeServices.layer, { excludeTestServices: true })("Codex catalog discovery", (it) => { |
| 100 | it.effect("keeps Ultrafast when another Codex client wrote the shared catalog cache", () => |
| 101 | Effect.gen(function* () { |
| 102 | assert.deepStrictEqual(yield* solServiceTiers(true), ["default", "priority", "ultrafast"]); |
| 103 | }).pipe(Effect.scoped), |
| 104 | ); |
| 105 | |
| 106 | it.effect("drops Ultrafast once the account is no longer entitled to it", () => |
| 107 | Effect.gen(function* () { |
| 108 | assert.deepStrictEqual(yield* solServiceTiers(false), ["default", "priority"]); |
| 109 | }).pipe(Effect.scoped), |
| 110 | ); |
| 111 | }); |