Repository navigation
feat(codex): register gpt-6-astra preemptively as an account-gated native model #3368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5565b6e
a59244b
4305286
6441ede
73f3109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # 260904_gpt6_astra_prereg — preemptive gpt-6-astra registration | ||
|
|
||
| ## Evidence | ||
| - 2026-09-03/04 X + dev community: Responses API probe of `gpt-6-astra` returns 404 like internal | ||
| staging slugs (arbitrary slugs 400); OpenAI posted a launch teaser the same day (2.5M views). | ||
| - aside-jun X search on the signed-in profile confirmed the chatter and the OpenAI teaser post. | ||
| - Upstream codex-rs (main @ 7a7c18868, pulled 2026-09-04): no astra/gpt-6 reference yet. | ||
| - GPT-6 / GPT-5.7 / standalone naming is unconfirmed; only the API slug is evidenced. | ||
|
|
||
| ## Change (GPT native side only, per user) | ||
| - NATIVE_GPT6_ASTRA_MODEL = "gpt-6-astra": account-gated (roster-proven availability only), | ||
| capability metadata inherited from gpt-5.6-sol, GPT-5.6-era context clamp until measured, | ||
| NOT wire-normalized (the slug is the API id). | ||
| - Nothing surfaces anywhere until an entitled account's authenticated /models roster lists it — | ||
| the registration is invisible until OpenAI ships. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,23 @@ | ||
| /** ChatGPT/Codex wire id observed for the account-native Daybreak Blue surface. */ | ||
| export const NATIVE_DAYBREAK_BLUE_MODEL = "gpt-daybreak-blue-latest"; | ||
|
|
||
| /** | ||
| * Leaked Responses API identifier for the announced next-generation OpenAI model | ||
| * (2026-09-03: OpenAI teased the launch on X; community probes report `gpt-6-astra` returning | ||
| * the same 404 as other internal staging slugs where an arbitrary slug returns 400). | ||
| * Registered preemptively so an entitled account can route it the moment it ships, before any | ||
| * codex-rs catalog carries it. Unlike Daybreak it is NOT wire-normalized to a serving id — | ||
| * the leaked slug IS the wire id. | ||
| */ | ||
| export const NATIVE_GPT6_ASTRA_MODEL = "gpt-6-astra"; | ||
|
|
||
| /** Native ChatGPT/Codex ids whose availability is proven per authenticated account. */ | ||
| export const ACCOUNT_GATED_NATIVE_OPENAI_MODELS: ReadonlySet<string> = new Set([ | ||
| "gpt-5.6-sol", | ||
| "gpt-5.6-terra", | ||
| "gpt-5.6-luna", | ||
| NATIVE_DAYBREAK_BLUE_MODEL, | ||
| NATIVE_GPT6_ASTRA_MODEL, | ||
| ]); | ||
|
|
||
| /** | ||
|
|
@@ -23,6 +34,7 @@ export const ACCOUNT_GATED_NATIVE_OPENAI_MODELS: ReadonlySet<string> = new Set([ | |
| */ | ||
| const NATIVE_OPENAI_CAPABILITY_SOURCES: Readonly<Record<string, string>> = Object.freeze({ | ||
| [NATIVE_DAYBREAK_BLUE_MODEL]: "gpt-5.6-sol", | ||
| [NATIVE_GPT6_ASTRA_MODEL]: "gpt-5.6-sol", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an entitled account exposes Useful? React with 👍 / 👎.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed in 6441ede: presentation is now a per-alias map (nativeOpenAiAliasPresentation) used by both upstreamNativeEntryForSlug and the custom-row path; astra presents as GPT-6 Astra with a provisional description, and an alias without an identity no longer ships a borrowed one. Pin test covers display name and description. |
||
| }); | ||
|
|
||
| /** | ||
|
|
@@ -50,6 +62,27 @@ export function nativeOpenAiCapabilitySourceSlug(slug: string): string { | |
| return NATIVE_OPENAI_CAPABILITY_SOURCES[slug] ?? slug; | ||
| } | ||
|
|
||
| /** | ||
| * Presentation identity per capability alias. Capability metadata (context, ladder, modalities) | ||
| * is inherited from the source model; the NAME and description are the alias's own product | ||
| * identity — hardcoding one alias's label would present every other alias as the wrong product. | ||
| */ | ||
| export const NATIVE_OPENAI_ALIAS_PRESENTATION: Readonly<Record<string, { displayName: string; description: string }>> = Object.freeze({ | ||
| [NATIVE_DAYBREAK_BLUE_MODEL]: { | ||
| displayName: "Daybreak Blue", | ||
| description: "Frontier general-purpose model with safeguards for defensive cybersecurity work.", | ||
| }, | ||
| [NATIVE_GPT6_ASTRA_MODEL]: { | ||
| displayName: "GPT-6 Astra", | ||
| // Provisional until the official announcement names the product. | ||
| description: "Next-generation OpenAI model (preemptively registered from the leaked API identifier; presentation provisional).", | ||
| }, | ||
| }); | ||
|
|
||
| export function nativeOpenAiAliasPresentation(slug: string): { displayName: string; description: string } | undefined { | ||
| return NATIVE_OPENAI_ALIAS_PRESENTATION[slug]; | ||
| } | ||
|
|
||
| /** | ||
| * Native OpenAI model ids that this release can route and restore with authoritative metadata. | ||
| * | ||
|
|
@@ -70,6 +103,7 @@ export const NATIVE_OPENAI_MODELS = [ | |
| "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark", | ||
| "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", | ||
| NATIVE_DAYBREAK_BLUE_MODEL, | ||
| NATIVE_GPT6_ASTRA_MODEL, | ||
| ]; | ||
|
|
||
| export const SUPPORTED_NATIVE_OPENAI_SLUGS = new Set(NATIVE_OPENAI_MODELS); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,8 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; | |
| import { existsSync, mkdtempSync, readFileSync} from "node:fs"; | ||
| import { tmpdir } from "node:os"; | ||
| import { join } from "node:path"; | ||
| import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../src/codex/catalog"; | ||
| import { codexAccountGatedCanonicalWireModel } from "../src/server/responses/core"; | ||
| import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../src/codex/catalog"; | ||
| import { applyProviderConfigHints, mergeConfiguredModelsIntoLiveCatalog } from "../src/codex/catalog/provider-fetch"; | ||
| import { | ||
| CODEX_CUSTOM_MODEL_CATALOG_KIND, | ||
|
|
@@ -3353,6 +3354,46 @@ describe("Codex catalog routed normalization", () => { | |
| expect(projected.some(entry => entry.slug === "daybreak-blue-latest")).toBe(false); | ||
| }); | ||
|
|
||
| test("gpt-6-astra is registered gated with Sol capabilities and no wire normalization", () => { | ||
| // Leak-based preemptive registration (2026-09-03): the slug must be a gated native with | ||
| // Sol's capability shape so an entitled account routes it the moment it ships, and it must | ||
| // go to the wire AS gpt-6-astra (it is NOT a Daybreak-style serving alias). | ||
| expect(NATIVE_GPT6_ASTRA_MODEL).toBe("gpt-6-astra"); | ||
| expect(nativeOpenAiCapabilitySourceSlug(NATIVE_GPT6_ASTRA_MODEL)).toBe("gpt-5.6-sol"); | ||
| expect(nativeOpenAiContextWindow(NATIVE_GPT6_ASTRA_MODEL)).toBe(272_000); | ||
| expect(nativeReasoningEfforts(NATIVE_GPT6_ASTRA_MODEL)) | ||
| .toEqual(["low", "medium", "high", "xhigh", "max", "ultra"]); | ||
| expect(nativeDefaultReasoningEffort(NATIVE_GPT6_ASTRA_MODEL)).toBe("low"); | ||
| expect(NATIVE_OPENAI_MODELS).toContain(NATIVE_GPT6_ASTRA_MODEL); | ||
|
|
||
| const projected = buildCatalogEntries( | ||
| nativeTemplate(), | ||
| NATIVE_OPENAI_MODELS, | ||
| [], | ||
| undefined, | ||
| false, | ||
| "default", | ||
| new Set(), | ||
| ["main"], | ||
| new Set(), | ||
| new Set(), | ||
| undefined, | ||
| [...NATIVE_OPENAI_MODELS], | ||
| new Map([["main", [...NATIVE_OPENAI_MODELS]]]), | ||
| ); | ||
| expect(projected.filter(entry => entry.slug === NATIVE_GPT6_ASTRA_MODEL)).toHaveLength(1); | ||
| expect(projected.filter(entry => entry.slug === `main/${NATIVE_GPT6_ASTRA_MODEL}`)).toHaveLength(1); | ||
|
|
||
| // Its own product identity, not the Daybreak label (review: alias presentation is per-alias). | ||
| expect(upstreamNativeEntry(NATIVE_GPT6_ASTRA_MODEL)).toMatchObject({ | ||
| display_name: "GPT-6 Astra", | ||
| }); | ||
| expect(upstreamNativeEntry(NATIVE_GPT6_ASTRA_MODEL)?.description).toContain("leaked API identifier"); | ||
|
|
||
| // Never rewritten to another model on the wire: the leaked slug IS the API id. | ||
| expect(codexAccountGatedCanonicalWireModel(NATIVE_GPT6_ASTRA_MODEL)).toBeUndefined(); | ||
| }); | ||
|
|
||
| test("configured ChatGPT-forward Daybreak gets Sol native metadata without API-key crossover", async () => { | ||
| globalThis.fetch = (() => { throw new Error("forward providers must not fetch /models"); }) as typeof fetch; | ||
| const forwardConfig: OcxConfig = { | ||
|
|
@@ -3419,6 +3460,43 @@ describe("Codex catalog routed normalization", () => { | |
| .toMatchObject({ contextWindow: 1_050_000, maxInputTokens: 922_000 }); | ||
| }); | ||
|
|
||
| test("a ChatGPT-forward custom Astra row projects the Astra product identity", async () => { | ||
| globalThis.fetch = (() => { throw new Error("forward providers must not fetch /models"); }) as typeof fetch; | ||
| const forwardConfig: OcxConfig = { | ||
| port: 10100, | ||
| defaultProvider: "openai", | ||
| providers: { | ||
| openai: { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://chatgpt.com/backend-api/codex", | ||
| codexAccountMode: "pool", | ||
| }, | ||
| }, | ||
| codexAccountPickerEnabled: false, | ||
| codexAccountNamespaces: { main: "@main" }, | ||
| customModels: [{ | ||
| id: "astra-codex-forward", | ||
| provider: "openai", | ||
| modelId: NATIVE_GPT6_ASTRA_MODEL, | ||
| }], | ||
| }; | ||
|
|
||
| const models = await gatherRoutedModels(forwardConfig); | ||
| const model = models.find(row => row.provider === "openai" && row.id === NATIVE_GPT6_ASTRA_MODEL); | ||
| // Per-alias presentation (review follow-up): the custom row must not borrow Daybreak's label. | ||
| expect(model).toMatchObject({ | ||
| displayName: "GPT-6 Astra", | ||
| codexForwardNativeCapabilityAlias: true, | ||
| reasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], | ||
| }); | ||
|
|
||
| const entries = buildCatalogEntries(nativeTemplate(), [], models); | ||
| const astra = entries.find(entry => entry.slug === `openai/${NATIVE_GPT6_ASTRA_MODEL}`); | ||
| expect(astra).toMatchObject({ display_name: "GPT-6 Astra" }); | ||
| expect(astra?.base_instructions).toContain("powered by the gpt-6-astra"); | ||
| expect(astra?.base_instructions).not.toContain("daybreak"); | ||
|
Comment on lines
+3493
to
+3497
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win Assert the complete Astra presentation contract. This custom-row test checks 🤖 Prompt for AI Agents |
||
| }); | ||
|
|
||
| test("Daybreak metadata inheritance rejects noncanonical providers", async () => { | ||
| const models = await gatherRoutedModels({ | ||
| port: 10100, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add blank lines after both headings.
markdownlint-cli2reports MD022 at Line 3 and Line 10 because each heading is immediately followed by list content. Insert one blank line after## Evidenceand## Change.Also applies to: 10-10
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 3-3: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Source: Linters/SAST tools