Repository navigation
feat(models): add Daybreak aliases for cybersecurity work on eligible ChatGPT models - #327
Merged
Merged
Conversation
…odels with --daybreak
…single-model launch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
If your ChatGPT account has access to OpenAI's Daybreak cybersecurity programs, you can now use them through clodex on any model that offers them, not just the dedicated
gpt-daybreak-blue-latestmodel. Add--daybreakwhen you save an alias:Requests through
luna-bluethen run under Daybreak;gpt-6-lunaunder any other name is unchanged. clodex reads which programs each model offers your account from your ChatGPT model catalog, so you never pick a program yourself, and it refuses up front when a model doesn't offer Daybreak.This supersedes #325 by @mLupine, which added the same request field from a hand-written per-alias value. Its wire handling and fetch wrapper are reused here; thanks for the groundwork and the live observations that shaped this design.
Why catalog-driven
The Codex catalog (
chatgpt.com/backend-api/codex/models) returnsavailable_access_programs: { cyber: [...] }per model and per account. On our account it predicted all 33 explicit model × program results we sent live: a listed program was accepted; an unlisted one got 400 (naming the right one) or 403 (model has no Daybreak). Native Codex reads the same field and picks Daybreak Blue, then Red (codex-rs/protocol/src/openai_models/access_programs.rs,codex-rs/exec/src/daybreak.rs). Using it here removes the failure modes of a hand-written value: wrong program, ineligible model, silent typo.The change
available_access_programs.cyberis parsed on refresh intoCachedModel.cyberAccessPrograms(unknown programs dropped, "absent" kept distinct from "empty"), re-validated when read back from disk, and carried onto routes and server models.daybreak: trueinmodelAliases.normalizeModelAliasesrejects a non-boolean value, and treats duplicate spellings that disagree about Daybreak as conflicting.src/daybreak.tsresolveAliasDaybreak): Blue before Red, or a reason it can't be met (not anopenai-oauthroute, catalog has no Daybreak data, model doesn't offer it). Every alias resolver calls it: proxy mode (buildHttpProxyRoutes), the endpoint switch menu (resolveCatalogModelAliases), the explicit/print-mode endpoint launch (singleModelDaybreakAliases), and the endpoint server (createGatewayModelCatalog).clodex models --list. The explicit endpoint launch used to answer every unknown model id with its one model; Daybreak aliases now get their program or a refusal there, and other aliases keep the old fallback. One case is deliberately left alone: in a hand-edited config whose only valid row for a name is plain, a second malformed Daybreak row for the same name is reported and ignored, so the name stays plain in every mode.--daybreakvalidates through the same route builder the proxy uses. It refuses ineligible models, a stale catalog (pointing toclodex providers refresh-models), non-OAuth targets, and alias names the endpoint server answers as its own model ids (those win over aliases there).--alias/--unaliascombined with--jsonor--contextnow errors; it used to skip the alias change silently.Tests
Nine
tests/daybreak*.test.tsfiles (56 tests). They stage state through production producers wherever practical:daybreak-producers: catalog response → refresh →providers.json→ account selection →config.json→ all resolvers, including the general-listing fallback and per-account eligibility.daybreak-server-command: the realclodex server --endpointwith a realconfig.json, real router, provider factory, AI SDK and WebSocket transport (onlywsis fake). Both request orders, Anthropic and OpenAI routes, refusal text.daybreak-alias-routing: the real CONNECT + TLS MITM in proxy mode; the endpoint switch menu; the gateway in both request orders.daybreak-single-model-launch: the realrunClaudeCommandexplicit-endpoint launch, including saved names that normalization rejects (conflicting spellings, a non-boolean flag).daybreak-wire,daybreak-continuation: theresponse.createframe, with Responses-Lite on and off, on the first turn and onprevious_response_idcontinuation turns.daybreak-alias-command:main([...])dispatch, every refusal (ineligible model, stale catalog, a name that is a model id or masked discovery id), flag combinations.Mutation matrix, full-file runs (script and results available on request): 44 production mutations, one per hunk or guard, each reddens at least one test. Three adversarial reviewers added further mutations; the ones that survived are now caught by the tests above. Those covered the general-listing catalog fallback, per-account eligibility, continuation turns, the CLI's flag forwarding, the OpenAI-format server route, the guard scopes and masked ids.
pnpm typecheck && pnpm buildpass.pnpm testwas run on Node v24.14.1 with an isolatedCLODEX_HOMEand a deadHTTPS_PROXY, on a machine at load average 100–150. The only failures were timing tests in files this branch doesn't touch, and they pass on rerun (tests/http-proxy-server.test.ts65/65 alone, on both this branch andmain). CI is the clean run.Live evidence
ChatGPT account, 2026-10-13, built branch, temporary
CLODEX_HOMEholding copies of the real config:clodex providers refresh-modelsrecordeddaybreak_bluefor gpt-6-sol, gpt-6-luna, gpt-5.6-sol/terra/luna, gpt-5.5 and two hidden models, onlystandardfor gpt-6.1-sol and gpt-6-astra, and onlydaybreak_bluefor gpt-daybreak-blue-latest. No model offersdaybreak_red, so the Red path is unit-tested only.--daybreaksavedluna-blue(Daybreak Blue) and refusedgpt-6.1-solwith "Daybreak isn't available for gpt-6.1-sol on this ChatGPT account".luna-blueframes carriedaccess_programs: {"cyber":"daybreak_blue"}; the plain alias and canonical id carried none. Evidence: the payload-key hashes in the--ws-diagnosticshead decisions.clodex claude -- --model luna-blue -p …) answered; an inactive alias showedAPI Error: 400 Clodex model route 'sol-forced' is unavailable: Daybreak isn't available for gpt-6.1-sol on this ChatGPT account. ….What we could not verify
daybreak_red.Rollback: revert the PR. Saved aliases with
"daybreak": trueare then ignored by older clodex (the field is unknown there) and route as plain aliases.