Merge PR #8614: fix(catalog): price Codex Daybreak aliases (@SJY051)
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
### Fixed
|
||||
|
||||
- Fixed Codex Daybreak Blue and Red model discovery reporting zero token prices, which made the model picker label the models as free.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ANTIGRAVITY_PRIMARY_ENDPOINT, fetchAntigravityDiscoveryModels } from ".
|
||||
import { buildGitLabDuoWorkflowFallbackModel } from "../src/discovery/gitlab-duo-workflow";
|
||||
import { createModelManager } from "../src/model-manager";
|
||||
import prevModelsJson from "../src/models.json" with { type: "json" };
|
||||
import { resolveOpenAIDaybreakStandardCost } from "../src/openai-pricing";
|
||||
import { toModelSpec } from "../src/provider-models/bundled-references";
|
||||
import {
|
||||
allowsUnauthenticatedCatalogDiscovery,
|
||||
@@ -285,7 +286,7 @@ function applyCodexPricingFallback(models: readonly ModelSpec[]): ModelSpec[] {
|
||||
return model;
|
||||
}
|
||||
|
||||
const openAICost = openAIModels.get(model.id);
|
||||
const openAICost = openAIModels.get(model.id) ?? resolveOpenAIDaybreakStandardCost(model.id);
|
||||
if (!openAICost) {
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type } from "@oh-my-pi/omptype";
|
||||
import { parseKnownModel, semverEqual } from "../identity/classify";
|
||||
import { resolveOpenAIDaybreakStandardCost } from "../openai-pricing";
|
||||
import type { FetchImpl, ModelSpec } from "../types";
|
||||
import { discoveryFetch } from "../utils";
|
||||
import { CODEX_BASE_URL, CODEX_CLIENT_VERSION, OPENAI_HEADER_VALUES, OPENAI_HEADERS } from "../wire/codex";
|
||||
@@ -237,6 +238,7 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
|
||||
const preferWebsockets = toBoolean(payload.prefer_websockets) === true;
|
||||
const useResponsesLite = toBoolean(payload.use_responses_lite) === true;
|
||||
const priority = toFiniteNumber(payload.priority) ?? Number.MAX_SAFE_INTEGER;
|
||||
const daybreakCost = resolveOpenAIDaybreakStandardCost(slug);
|
||||
|
||||
return {
|
||||
priority,
|
||||
@@ -248,7 +250,7 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
|
||||
baseUrl,
|
||||
reasoning,
|
||||
input,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
cost: daybreakCost ? { ...daybreakCost } : { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
remoteCompaction: CODEX_REMOTE_COMPACTION,
|
||||
contextWindow,
|
||||
maxTokens,
|
||||
|
||||
@@ -76276,10 +76276,10 @@
|
||||
"image"
|
||||
],
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
"input": 5,
|
||||
"output": 30,
|
||||
"cacheRead": 0.5,
|
||||
"cacheWrite": 6.25
|
||||
},
|
||||
"remoteCompaction": {
|
||||
"enabled": true,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { TokenCost } from "./types";
|
||||
|
||||
/** Standard GPT-5.6 Sol rates used by the Daybreak Blue aliases. */
|
||||
export const OPENAI_GPT_56_SOL_STANDARD_COST = {
|
||||
input: 5,
|
||||
output: 30,
|
||||
cacheRead: 0.5,
|
||||
cacheWrite: 6.25,
|
||||
} as const satisfies TokenCost;
|
||||
|
||||
/** Standard GPT-5.6 Cyber rates used by the Daybreak Red aliases. */
|
||||
export const OPENAI_GPT_56_CYBER_STANDARD_COST = {
|
||||
input: 12.5,
|
||||
output: 75,
|
||||
cacheRead: 1.25,
|
||||
cacheWrite: 15.625,
|
||||
} as const satisfies TokenCost;
|
||||
|
||||
/** Resolve standard rates for Codex-prefixed Daybreak aliases. */
|
||||
export function resolveOpenAIDaybreakStandardCost(modelId: string): TokenCost | undefined {
|
||||
switch (modelId) {
|
||||
case "gpt-daybreak-blue-latest":
|
||||
return OPENAI_GPT_56_SOL_STANDARD_COST;
|
||||
case "gpt-daybreak-red-latest":
|
||||
return OPENAI_GPT_56_CYBER_STANDARD_COST;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,17 @@ import {
|
||||
import { resolveModelReference } from "../identity/reference";
|
||||
import type { ModelManagerOptions } from "../model-manager";
|
||||
import { type GeneratedProvider, getBundledModels } from "../models";
|
||||
import type { Api, FetchImpl, Model, ModelSpec, OpenAICompat, Provider, ThinkingConfig } from "../types";
|
||||
import { OPENAI_GPT_56_CYBER_STANDARD_COST, OPENAI_GPT_56_SOL_STANDARD_COST } from "../openai-pricing";
|
||||
import type {
|
||||
Api,
|
||||
FetchImpl,
|
||||
LongContextTokenCost,
|
||||
Model,
|
||||
ModelSpec,
|
||||
OpenAICompat,
|
||||
Provider,
|
||||
ThinkingConfig,
|
||||
} from "../types";
|
||||
import { discoveryFetch, isAnthropicOAuthToken, isRecord, toBoolean, toNumber, toPositiveNumber } from "../utils";
|
||||
import { ALIBABA_TOKEN_PLAN_BASE_URL, parseAlibabaTokenPlanCredential } from "../wire/alibaba-token-plan";
|
||||
import { coreWeaveProjectHeaders } from "../wire/coreweave";
|
||||
@@ -870,6 +880,7 @@ export function umansModelManagerOptions(config?: UmansModelManagerConfig): Mode
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const OPENAI_API_BASE_URL = "https://api.openai.com/v1";
|
||||
/** GPT-5.6 rates applied when a first-party request exceeds 272K input tokens. */
|
||||
export const OPENAI_GPT_56_LONG_CONTEXT_COSTS = {
|
||||
luna: {
|
||||
inputThreshold: 272_000,
|
||||
@@ -892,20 +903,7 @@ export const OPENAI_GPT_56_LONG_CONTEXT_COSTS = {
|
||||
cacheRead: 0.4,
|
||||
cacheWrite: 5,
|
||||
},
|
||||
} as const;
|
||||
const OPENAI_GPT_56_SOL_STANDARD_COST = {
|
||||
input: 5,
|
||||
output: 30,
|
||||
cacheRead: 0.5,
|
||||
cacheWrite: 6.25,
|
||||
longContext: OPENAI_GPT_56_LONG_CONTEXT_COSTS.sol,
|
||||
} as const;
|
||||
const OPENAI_GPT_56_CYBER_STANDARD_COST = {
|
||||
input: 12.5,
|
||||
output: 75,
|
||||
cacheRead: 1.25,
|
||||
cacheWrite: 15.625,
|
||||
} as const;
|
||||
} as const satisfies Readonly<Record<"luna" | "sol" | "terra", LongContextTokenCost>>;
|
||||
|
||||
export interface OpenAIModelManagerConfig {
|
||||
apiKey?: string;
|
||||
@@ -939,7 +937,10 @@ export const OPENAI_DAYBREAK_CURATED_FALLBACK_MODELS: readonly ModelSpec<"openai
|
||||
baseUrl: OPENAI_API_BASE_URL,
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: OPENAI_GPT_56_SOL_STANDARD_COST,
|
||||
cost: {
|
||||
...OPENAI_GPT_56_SOL_STANDARD_COST,
|
||||
longContext: OPENAI_GPT_56_LONG_CONTEXT_COSTS.sol,
|
||||
},
|
||||
contextWindow: 1_050_000,
|
||||
maxTokens: 128_000,
|
||||
},
|
||||
|
||||
@@ -143,7 +143,7 @@ describe("Codex model discovery", () => {
|
||||
expect(legacy?.contextWindow).toBe(272_000);
|
||||
});
|
||||
|
||||
it("normalizes Codex Daybreak aliases to the GPT-5.6 window and effort ladder", async () => {
|
||||
it("normalizes Codex Daybreak aliases to GPT-5.6 capabilities and pricing", async () => {
|
||||
const fetchFn: typeof fetch = Object.assign(
|
||||
async () =>
|
||||
new Response(
|
||||
@@ -157,6 +157,15 @@ describe("Codex model discovery", () => {
|
||||
input_modalities: ["text", "image"],
|
||||
supported_in_api: true,
|
||||
},
|
||||
{
|
||||
slug: "gpt-daybreak-red-latest",
|
||||
display_name: "Daybreak Red",
|
||||
context_window: 400_000,
|
||||
default_reasoning_level: "high",
|
||||
supported_reasoning_levels: ["minimal", "low", "medium", "high", "xhigh"],
|
||||
input_modalities: ["text", "image"],
|
||||
supported_in_api: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
@@ -168,17 +177,22 @@ describe("Codex model discovery", () => {
|
||||
clientVersion: "0.99.0",
|
||||
fetchFn,
|
||||
});
|
||||
const spec = result?.models.find(model => model.id === "gpt-daybreak-blue-latest");
|
||||
if (!spec) throw new Error("Expected discovered Daybreak model");
|
||||
const blue = result?.models.find(model => model.id === "gpt-daybreak-blue-latest");
|
||||
if (!blue) throw new Error("Expected discovered Daybreak Blue model");
|
||||
const red = result?.models.find(model => model.id === "gpt-daybreak-red-latest");
|
||||
if (!red) throw new Error("Expected discovered Daybreak Red model");
|
||||
|
||||
expect(spec.contextWindow).toBe(372_000);
|
||||
expect(getSupportedEfforts(buildModel(spec))).toEqual([
|
||||
expect(blue.contextWindow).toBe(372_000);
|
||||
expect(getSupportedEfforts(buildModel(blue))).toEqual([
|
||||
Effort.Low,
|
||||
Effort.Medium,
|
||||
Effort.High,
|
||||
Effort.XHigh,
|
||||
Effort.Max,
|
||||
]);
|
||||
expect(blue.cost).toEqual({ input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 });
|
||||
expect(red.contextWindow).toBe(400_000);
|
||||
expect(red.cost).toEqual({ input: 12.5, output: 75, cacheRead: 1.25, cacheWrite: 15.625 });
|
||||
});
|
||||
|
||||
it("honors context_window when upstream actively reports it for GPT-5.6 SKUs", async () => {
|
||||
|
||||
Reference in New Issue
Block a user