Merge pull request #4603 from mattiacerutti/fix/openai-codex-model-list
fix(ai): update OpenAI Codex model list
This commit is contained in:
@@ -240,9 +240,6 @@ function applyThinkingLevelMetadata(model: Model<any>): void {
|
|||||||
if (model.provider === "openai-codex" && supportsOpenAiXhigh(model.id)) {
|
if (model.provider === "openai-codex" && supportsOpenAiXhigh(model.id)) {
|
||||||
mergeThinkingLevelMap(model, { minimal: "low" });
|
mergeThinkingLevelMap(model, { minimal: "low" });
|
||||||
}
|
}
|
||||||
if (model.provider === "openai-codex" && model.id === "gpt-5.1-codex-mini") {
|
|
||||||
mergeThinkingLevelMap(model, { minimal: "medium", low: "medium", medium: "medium", high: "high" });
|
|
||||||
}
|
|
||||||
if (model.provider === "openrouter" && model.id.startsWith("inception/mercury-2")) {
|
if (model.provider === "openrouter" && model.id.startsWith("inception/mercury-2")) {
|
||||||
// Mercury 2 in instant mode (reasoning_effort: "none") disables tool calling.
|
// Mercury 2 in instant mode (reasoning_effort: "none") disables tool calling.
|
||||||
// Mark "off" unsupported so the openai-completions provider omits the reasoning param
|
// Mark "off" unsupported so the openai-completions provider omits the reasoning param
|
||||||
@@ -1500,42 +1497,6 @@ async function generateModels() {
|
|||||||
const CODEX_CONTEXT = 272000;
|
const CODEX_CONTEXT = 272000;
|
||||||
const CODEX_MAX_TOKENS = 128000;
|
const CODEX_MAX_TOKENS = 128000;
|
||||||
const codexModels: Model<"openai-codex-responses">[] = [
|
const codexModels: Model<"openai-codex-responses">[] = [
|
||||||
{
|
|
||||||
id: "gpt-5.1",
|
|
||||||
name: "GPT-5.1",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: CODEX_BASE_URL,
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
|
|
||||||
contextWindow: CODEX_CONTEXT,
|
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "gpt-5.1-codex-max",
|
|
||||||
name: "GPT-5.1 Codex Max",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: CODEX_BASE_URL,
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
|
|
||||||
contextWindow: CODEX_CONTEXT,
|
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "gpt-5.1-codex-mini",
|
|
||||||
name: "GPT-5.1 Codex Mini",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: CODEX_BASE_URL,
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 },
|
|
||||||
contextWindow: CODEX_CONTEXT,
|
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "gpt-5.2",
|
id: "gpt-5.2",
|
||||||
name: "GPT-5.2",
|
name: "GPT-5.2",
|
||||||
@@ -1548,18 +1509,6 @@ async function generateModels() {
|
|||||||
contextWindow: CODEX_CONTEXT,
|
contextWindow: CODEX_CONTEXT,
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "gpt-5.2-codex",
|
|
||||||
name: "GPT-5.2 Codex",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: CODEX_BASE_URL,
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
|
|
||||||
contextWindow: CODEX_CONTEXT,
|
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "gpt-5.3-codex",
|
id: "gpt-5.3-codex",
|
||||||
name: "GPT-5.3 Codex",
|
name: "GPT-5.3 Codex",
|
||||||
@@ -1572,6 +1521,18 @@ async function generateModels() {
|
|||||||
contextWindow: CODEX_CONTEXT,
|
contextWindow: CODEX_CONTEXT,
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "gpt-5.3-codex-spark",
|
||||||
|
name: "GPT-5.3 Codex Spark",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: CODEX_BASE_URL,
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
|
||||||
|
contextWindow: CODEX_CONTEXT,
|
||||||
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "gpt-5.4",
|
id: "gpt-5.4",
|
||||||
name: "GPT-5.4",
|
name: "GPT-5.4",
|
||||||
@@ -1584,6 +1545,42 @@ async function generateModels() {
|
|||||||
contextWindow: CODEX_CONTEXT,
|
contextWindow: CODEX_CONTEXT,
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "gpt-5.4-fast",
|
||||||
|
name: "GPT-5.4 Fast",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: CODEX_BASE_URL,
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
|
||||||
|
contextWindow: CODEX_CONTEXT,
|
||||||
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 mini",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: CODEX_BASE_URL,
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
|
||||||
|
contextWindow: CODEX_CONTEXT,
|
||||||
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "gpt-5.4-mini-fast",
|
||||||
|
name: "GPT-5.4 mini Fast",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: CODEX_BASE_URL,
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0 },
|
||||||
|
contextWindow: CODEX_CONTEXT,
|
||||||
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "gpt-5.5",
|
id: "gpt-5.5",
|
||||||
name: "GPT-5.5",
|
name: "GPT-5.5",
|
||||||
@@ -1597,29 +1594,17 @@ async function generateModels() {
|
|||||||
maxTokens: CODEX_MAX_TOKENS,
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "gpt-5.4-mini",
|
id: "gpt-5.5-fast",
|
||||||
name: "GPT-5.4 Mini",
|
name: "GPT-5.5 Fast",
|
||||||
api: "openai-codex-responses",
|
api: "openai-codex-responses",
|
||||||
provider: "openai-codex",
|
provider: "openai-codex",
|
||||||
baseUrl: CODEX_BASE_URL,
|
baseUrl: CODEX_BASE_URL,
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
|
cost: { input: 12.5, output: 75, cacheRead: 1.25, cacheWrite: 0 },
|
||||||
contextWindow: CODEX_CONTEXT,
|
contextWindow: CODEX_CONTEXT,
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
maxTokens: CODEX_MAX_TOKENS,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "gpt-5.3-codex-spark",
|
|
||||||
name: "GPT-5.3 Codex Spark",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: CODEX_BASE_URL,
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text"],
|
|
||||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
||||||
contextWindow: 128000,
|
|
||||||
maxTokens: CODEX_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
allModels.push(...codexModels);
|
allModels.push(...codexModels);
|
||||||
|
|
||||||
|
|||||||
@@ -7155,58 +7155,6 @@ export const MODELS = {
|
|||||||
} satisfies Model<"openai-responses">,
|
} satisfies Model<"openai-responses">,
|
||||||
},
|
},
|
||||||
"openai-codex": {
|
"openai-codex": {
|
||||||
"gpt-5.1": {
|
|
||||||
id: "gpt-5.1",
|
|
||||||
name: "GPT-5.1",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: "https://chatgpt.com/backend-api",
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 1.25,
|
|
||||||
output: 10,
|
|
||||||
cacheRead: 0.125,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 272000,
|
|
||||||
maxTokens: 128000,
|
|
||||||
} satisfies Model<"openai-codex-responses">,
|
|
||||||
"gpt-5.1-codex-max": {
|
|
||||||
id: "gpt-5.1-codex-max",
|
|
||||||
name: "GPT-5.1 Codex Max",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: "https://chatgpt.com/backend-api",
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 1.25,
|
|
||||||
output: 10,
|
|
||||||
cacheRead: 0.125,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 272000,
|
|
||||||
maxTokens: 128000,
|
|
||||||
} satisfies Model<"openai-codex-responses">,
|
|
||||||
"gpt-5.1-codex-mini": {
|
|
||||||
id: "gpt-5.1-codex-mini",
|
|
||||||
name: "GPT-5.1 Codex Mini",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: "https://chatgpt.com/backend-api",
|
|
||||||
reasoning: true,
|
|
||||||
thinkingLevelMap: {"minimal":"medium","low":"medium","medium":"medium","high":"high"},
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 0.25,
|
|
||||||
output: 2,
|
|
||||||
cacheRead: 0.025,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 272000,
|
|
||||||
maxTokens: 128000,
|
|
||||||
} satisfies Model<"openai-codex-responses">,
|
|
||||||
"gpt-5.2": {
|
"gpt-5.2": {
|
||||||
id: "gpt-5.2",
|
id: "gpt-5.2",
|
||||||
name: "GPT-5.2",
|
name: "GPT-5.2",
|
||||||
@@ -7225,24 +7173,6 @@ export const MODELS = {
|
|||||||
contextWindow: 272000,
|
contextWindow: 272000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-codex-responses">,
|
} satisfies Model<"openai-codex-responses">,
|
||||||
"gpt-5.2-codex": {
|
|
||||||
id: "gpt-5.2-codex",
|
|
||||||
name: "GPT-5.2 Codex",
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
provider: "openai-codex",
|
|
||||||
baseUrl: "https://chatgpt.com/backend-api",
|
|
||||||
reasoning: true,
|
|
||||||
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 1.75,
|
|
||||||
output: 14,
|
|
||||||
cacheRead: 0.175,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 272000,
|
|
||||||
maxTokens: 128000,
|
|
||||||
} satisfies Model<"openai-codex-responses">,
|
|
||||||
"gpt-5.3-codex": {
|
"gpt-5.3-codex": {
|
||||||
id: "gpt-5.3-codex",
|
id: "gpt-5.3-codex",
|
||||||
name: "GPT-5.3 Codex",
|
name: "GPT-5.3 Codex",
|
||||||
@@ -7271,12 +7201,12 @@ export const MODELS = {
|
|||||||
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0,
|
input: 1.75,
|
||||||
output: 0,
|
output: 14,
|
||||||
cacheRead: 0,
|
cacheRead: 0.175,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 128000,
|
contextWindow: 272000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-codex-responses">,
|
} satisfies Model<"openai-codex-responses">,
|
||||||
"gpt-5.4": {
|
"gpt-5.4": {
|
||||||
@@ -7297,9 +7227,27 @@ export const MODELS = {
|
|||||||
contextWindow: 272000,
|
contextWindow: 272000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-codex-responses">,
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.4-fast": {
|
||||||
|
id: "gpt-5.4-fast",
|
||||||
|
name: "GPT-5.4 Fast",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
"gpt-5.4-mini": {
|
"gpt-5.4-mini": {
|
||||||
id: "gpt-5.4-mini",
|
id: "gpt-5.4-mini",
|
||||||
name: "GPT-5.4 Mini",
|
name: "GPT-5.4 mini",
|
||||||
api: "openai-codex-responses",
|
api: "openai-codex-responses",
|
||||||
provider: "openai-codex",
|
provider: "openai-codex",
|
||||||
baseUrl: "https://chatgpt.com/backend-api",
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
@@ -7315,6 +7263,24 @@ export const MODELS = {
|
|||||||
contextWindow: 272000,
|
contextWindow: 272000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-codex-responses">,
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.4-mini-fast": {
|
||||||
|
id: "gpt-5.4-mini-fast",
|
||||||
|
name: "GPT-5.4 mini Fast",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 9,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
"gpt-5.5": {
|
"gpt-5.5": {
|
||||||
id: "gpt-5.5",
|
id: "gpt-5.5",
|
||||||
name: "GPT-5.5",
|
name: "GPT-5.5",
|
||||||
@@ -7333,6 +7299,24 @@ export const MODELS = {
|
|||||||
contextWindow: 272000,
|
contextWindow: 272000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-codex-responses">,
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.5-fast": {
|
||||||
|
id: "gpt-5.5-fast",
|
||||||
|
name: "GPT-5.5 Fast",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 12.5,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
},
|
},
|
||||||
"opencode": {
|
"opencode": {
|
||||||
"big-pickle": {
|
"big-pickle": {
|
||||||
|
|||||||
@@ -276,12 +276,12 @@ describe("AI Providers Abort Tests", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider Abort", () => {
|
describe("OpenAI Codex Provider Abort", () => {
|
||||||
it.skipIf(!openaiCodexToken)("should abort mid-stream", { retry: 3 }, async () => {
|
it.skipIf(!openaiCodexToken)("should abort mid-stream", { retry: 3 }, async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testAbortSignal(llm, { apiKey: openaiCodexToken });
|
await testAbortSignal(llm, { apiKey: openaiCodexToken });
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)("should handle immediate abort", { retry: 3 }, async () => {
|
it.skipIf(!openaiCodexToken)("should handle immediate abort", { retry: 3 }, async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testImmediateAbort(llm, { apiKey: openaiCodexToken });
|
await testImmediateAbort(llm, { apiKey: openaiCodexToken });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -228,9 +228,9 @@ describe("Context overflow error handling", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex (OAuth)", () => {
|
describe("OpenAI Codex (OAuth)", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should detect overflow via isContextOverflow",
|
"gpt-5.5 - should detect overflow via isContextOverflow",
|
||||||
async () => {
|
async () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.2-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
const result = await testContextOverflow(model, openaiCodexToken!);
|
const result = await testContextOverflow(model, openaiCodexToken!);
|
||||||
logResult(result);
|
logResult(result);
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const PROVIDER_MODEL_PAIRS: ProviderModelPair[] = [
|
|||||||
{ provider: "openai", model: "gpt-5-mini", label: "openai-responses-gpt-5-mini" },
|
{ provider: "openai", model: "gpt-5-mini", label: "openai-responses-gpt-5-mini" },
|
||||||
{ provider: "azure-openai-responses", model: "gpt-4o-mini", label: "azure-openai-responses-gpt-4o-mini" },
|
{ provider: "azure-openai-responses", model: "gpt-4o-mini", label: "azure-openai-responses-gpt-4o-mini" },
|
||||||
// OpenAI Codex
|
// OpenAI Codex
|
||||||
{ provider: "openai-codex", model: "gpt-5.2-codex", label: "openai-codex-gpt-5.2-codex" },
|
{ provider: "openai-codex", model: "gpt-5.5", label: "openai-codex-gpt-5.5" },
|
||||||
// GitHub Copilot
|
// GitHub Copilot
|
||||||
{ provider: "github-copilot", model: "claude-sonnet-4.5", label: "copilot-claude-sonnet-4.5" },
|
{ provider: "github-copilot", model: "claude-sonnet-4.5", label: "copilot-claude-sonnet-4.5" },
|
||||||
{ provider: "github-copilot", model: "gpt-5.1-codex", label: "copilot-gpt-5.1-codex" },
|
{ provider: "github-copilot", model: "gpt-5.1-codex", label: "copilot-gpt-5.1-codex" },
|
||||||
|
|||||||
@@ -704,37 +704,37 @@ describe("AI Providers Empty Message Tests", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider Empty Messages", () => {
|
describe("OpenAI Codex Provider Empty Messages", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle empty content array",
|
"gpt-5.5 - should handle empty content array",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testEmptyMessage(llm, { apiKey: openaiCodexToken });
|
await testEmptyMessage(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle empty string content",
|
"gpt-5.5 - should handle empty string content",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testEmptyStringMessage(llm, { apiKey: openaiCodexToken });
|
await testEmptyStringMessage(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle whitespace-only content",
|
"gpt-5.5 - should handle whitespace-only content",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testWhitespaceOnlyMessage(llm, { apiKey: openaiCodexToken });
|
await testWhitespaceOnlyMessage(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle empty assistant message in conversation",
|
"gpt-5.5 - should handle empty assistant message in conversation",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testEmptyAssistantMessage(llm, { apiKey: openaiCodexToken });
|
await testEmptyAssistantMessage(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -481,19 +481,19 @@ describe("Tool Results with Images", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider", () => {
|
describe("OpenAI Codex Provider", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle tool result with only image",
|
"gpt-5.5 - should handle tool result with only image",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await handleToolWithImageResult(llm, { apiKey: openaiCodexToken });
|
await handleToolWithImageResult(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle tool result with text and image",
|
"gpt-5.5 - should handle tool result with text and image",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await handleToolWithTextAndImageResult(llm, { apiKey: openaiCodexToken });
|
await handleToolWithTextAndImageResult(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const codexToken = await resolveApiKey("openai-codex");
|
|||||||
|
|
||||||
describe("openai-codex cache affinity e2e", () => {
|
describe("openai-codex cache affinity e2e", () => {
|
||||||
it.skipIf(!codexToken)("handles SSE requests with aligned cache-affinity identifiers", async () => {
|
it.skipIf(!codexToken)("handles SSE requests with aligned cache-affinity identifiers", async () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.3-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
const sessionId = "0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3";
|
const sessionId = "0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3";
|
||||||
const context: Context = {
|
const context: Context = {
|
||||||
systemPrompt: "You are a helpful assistant. Reply exactly as requested.",
|
systemPrompt: "You are a helpful assistant. Reply exactly as requested.",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const usage: Usage = {
|
|||||||
|
|
||||||
describe("OpenAI Responses foreign tool call ID normalization", () => {
|
describe("OpenAI Responses foreign tool call ID normalization", () => {
|
||||||
it("hashes foreign Copilot tool item IDs into a bounded Codex-safe fc_<hash> shape", () => {
|
it("hashes foreign Copilot tool item IDs into a bounded Codex-safe fc_<hash> shape", () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.3-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
const assistant: AssistantMessage = {
|
const assistant: AssistantMessage = {
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
content: [
|
content: [
|
||||||
@@ -31,7 +31,7 @@ describe("OpenAI Responses foreign tool call ID normalization", () => {
|
|||||||
],
|
],
|
||||||
api: "openai-responses",
|
api: "openai-responses",
|
||||||
provider: "github-copilot",
|
provider: "github-copilot",
|
||||||
model: "gpt-5.3-codex",
|
model: "gpt-5.5",
|
||||||
usage,
|
usage,
|
||||||
stopReason: "toolUse",
|
stopReason: "toolUse",
|
||||||
timestamp: Date.now() - 2000,
|
timestamp: Date.now() - 2000,
|
||||||
|
|||||||
@@ -183,8 +183,8 @@ describe("Responses API tool result images", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("OpenAI Codex Responses Provider (gpt-5.2-codex)", () => {
|
describe("OpenAI Codex Responses Provider (gpt-5.5)", () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.2-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"should send tool result images in function_call_output",
|
"should send tool result images in function_call_output",
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ describe("responseId E2E Tests", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider", () => {
|
describe("OpenAI Codex Provider", () => {
|
||||||
it.skipIf(!openaiCodexToken)("should expose responseId", { retry: 3, timeout: 30000 }, async () => {
|
it.skipIf(!openaiCodexToken)("should expose responseId", { retry: 3, timeout: 30000 }, async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await expectResponseId(llm, { apiKey: openaiCodexToken });
|
await expectResponseId(llm, { apiKey: openaiCodexToken });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -309,10 +309,10 @@ describe("Token Statistics on Abort", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider", () => {
|
describe("OpenAI Codex Provider", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should include token stats when aborted mid-stream",
|
"gpt-5.5 - should include token stats when aborted mid-stream",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testTokensOnAbort(llm, { apiKey: openaiCodexToken });
|
await testTokensOnAbort(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const echoTool: Tool<typeof echoToolSchema> = {
|
|||||||
*
|
*
|
||||||
* 1. Use github-copilot gpt-5.2-codex to generate a tool call
|
* 1. Use github-copilot gpt-5.2-codex to generate a tool call
|
||||||
* 2. Switch to openrouter openai/gpt-5.2-codex and complete
|
* 2. Switch to openrouter openai/gpt-5.2-codex and complete
|
||||||
* 3. Switch to openai-codex gpt-5.2-codex and complete
|
* 3. Switch to openai-codex gpt-5.5 and complete
|
||||||
*
|
*
|
||||||
* Both should succeed without "call_id too long" errors.
|
* Both should succeed without "call_id too long" errors.
|
||||||
*/
|
*/
|
||||||
@@ -117,7 +117,7 @@ describe("Tool Call ID Normalization - Live Handoff", () => {
|
|||||||
"github-copilot -> openai-codex should normalize pipe-separated IDs",
|
"github-copilot -> openai-codex should normalize pipe-separated IDs",
|
||||||
async () => {
|
async () => {
|
||||||
const copilotModel = getModel("github-copilot", "gpt-5.2-codex");
|
const copilotModel = getModel("github-copilot", "gpt-5.2-codex");
|
||||||
const codexModel = getModel("openai-codex", "gpt-5.2-codex");
|
const codexModel = getModel("openai-codex", "gpt-5.5");
|
||||||
|
|
||||||
// Step 1: Generate tool call with github-copilot
|
// Step 1: Generate tool call with github-copilot
|
||||||
const userMessage: Message = {
|
const userMessage: Message = {
|
||||||
@@ -266,7 +266,7 @@ describe("Tool Call ID Normalization - Prefilled Context", () => {
|
|||||||
it.skipIf(!codexToken)(
|
it.skipIf(!codexToken)(
|
||||||
"openai-codex should handle prefilled context with long pipe-separated IDs",
|
"openai-codex should handle prefilled context with long pipe-separated IDs",
|
||||||
async () => {
|
async () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.2-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
const messages = buildPrefilledMessages();
|
const messages = buildPrefilledMessages();
|
||||||
|
|
||||||
const response = await completeSimple(
|
const response = await completeSimple(
|
||||||
|
|||||||
@@ -317,10 +317,10 @@ describe("Tool Call Without Result Tests", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider", () => {
|
describe("OpenAI Codex Provider", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should filter out tool calls without corresponding tool results",
|
"gpt-5.5 - should filter out tool calls without corresponding tool results",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const model = getModel("openai-codex", "gpt-5.2-codex");
|
const model = getModel("openai-codex", "gpt-5.5");
|
||||||
await testToolCallWithoutResult(model, { apiKey: openaiCodexToken });
|
await testToolCallWithoutResult(model, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -771,10 +771,10 @@ describe("totalTokens field", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex (OAuth)", () => {
|
describe("OpenAI Codex (OAuth)", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should return totalTokens equal to sum of components",
|
"gpt-5.5 - should return totalTokens equal to sum of components",
|
||||||
{ retry: 3, timeout: 60000 },
|
{ retry: 3, timeout: 60000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
|
|
||||||
console.log(`\nOpenAI Codex / ${llm.id}:`);
|
console.log(`\nOpenAI Codex / ${llm.id}:`);
|
||||||
const { first, second } = await testTotalTokensWithCache(llm, { apiKey: openaiCodexToken });
|
const { first, second } = await testTotalTokensWithCache(llm, { apiKey: openaiCodexToken });
|
||||||
|
|||||||
@@ -746,28 +746,28 @@ describe("AI Providers Unicode Surrogate Pair Tests", () => {
|
|||||||
|
|
||||||
describe("OpenAI Codex Provider Unicode Handling", () => {
|
describe("OpenAI Codex Provider Unicode Handling", () => {
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle emoji in tool results",
|
"gpt-5.5 - should handle emoji in tool results",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testEmojiInToolResults(llm, { apiKey: openaiCodexToken });
|
await testEmojiInToolResults(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle real-world LinkedIn comment data with emoji",
|
"gpt-5.5 - should handle real-world LinkedIn comment data with emoji",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testRealWorldLinkedInData(llm, { apiKey: openaiCodexToken });
|
await testRealWorldLinkedInData(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!openaiCodexToken)(
|
it.skipIf(!openaiCodexToken)(
|
||||||
"gpt-5.2-codex - should handle unpaired high surrogate (0xD83D) in tool results",
|
"gpt-5.5 - should handle unpaired high surrogate (0xD83D) in tool results",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
async () => {
|
async () => {
|
||||||
const llm = getModel("openai-codex", "gpt-5.2-codex");
|
const llm = getModel("openai-codex", "gpt-5.5");
|
||||||
await testUnpairedHighSurrogate(llm, { apiKey: openaiCodexToken });
|
await testUnpairedHighSurrogate(llm, { apiKey: openaiCodexToken });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user