mirror of https://github.com/openclaw/openclaw.git
Models: add native GPT-5.4 mini and nano support (#49289)
* Models: add GPT-5.4 mini and nano support * Tests: cover OpenAI GPT-5.4 mini and nano extension support
This commit is contained in:
parent
e99963100d
commit
0e4c072f37
|
|
@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai
|
|||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Models/OpenAI: add native forward-compat support for `gpt-5.4-mini` and `gpt-5.4-nano` in the OpenAI provider catalog, runtime resolution, and reasoning capability gates. Thanks @vincentkoc.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` seam for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { buildOpenAIProvider } from "./openai-provider.js";
|
||||
|
||||
describe("buildOpenAIProvider", () => {
|
||||
it("resolves gpt-5.4 mini and nano from GPT-5 small-model templates", () => {
|
||||
const provider = buildOpenAIProvider();
|
||||
const registry = {
|
||||
find(providerId: string, id: string) {
|
||||
if (providerId !== "openai") {
|
||||
return null;
|
||||
}
|
||||
if (id === "gpt-5-mini") {
|
||||
return {
|
||||
id,
|
||||
name: "GPT-5 mini",
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
};
|
||||
}
|
||||
if (id === "gpt-5-nano") {
|
||||
return {
|
||||
id,
|
||||
name: "GPT-5 nano",
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.5, output: 1, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 64_000,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
const mini = provider.resolveDynamicModel?.({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.4-mini",
|
||||
modelRegistry: registry as never,
|
||||
});
|
||||
const nano = provider.resolveDynamicModel?.({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.4-nano",
|
||||
modelRegistry: registry as never,
|
||||
});
|
||||
|
||||
expect(mini).toMatchObject({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-mini",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
});
|
||||
expect(nano).toMatchObject({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-nano",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 64_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("surfaces gpt-5.4 mini and nano in xhigh and augmented catalog metadata", () => {
|
||||
const provider = buildOpenAIProvider();
|
||||
|
||||
expect(
|
||||
provider.supportsXHighThinking?.({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.4-mini",
|
||||
} as never),
|
||||
).toBe(true);
|
||||
expect(
|
||||
provider.supportsXHighThinking?.({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.4-nano",
|
||||
} as never),
|
||||
).toBe(true);
|
||||
|
||||
const entries = provider.augmentModelCatalog?.({
|
||||
env: process.env,
|
||||
entries: [
|
||||
{ provider: "openai", id: "gpt-5-mini", name: "GPT-5 mini" },
|
||||
{ provider: "openai", id: "gpt-5-nano", name: "GPT-5 nano" },
|
||||
],
|
||||
} as never);
|
||||
|
||||
expect(entries).toContainEqual({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-mini",
|
||||
name: "gpt-5.4-mini",
|
||||
});
|
||||
expect(entries).toContainEqual({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-nano",
|
||||
name: "gpt-5.4-nano",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -5,6 +5,7 @@ import {
|
|||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
|
||||
import {
|
||||
applyOpenAIConfig,
|
||||
DEFAULT_CONTEXT_TOKENS,
|
||||
normalizeModelCompat,
|
||||
normalizeProviderId,
|
||||
OPENAI_DEFAULT_MODEL,
|
||||
|
|
@ -20,12 +21,29 @@ import {
|
|||
const PROVIDER_ID = "openai";
|
||||
const OPENAI_GPT_54_MODEL_ID = "gpt-5.4";
|
||||
const OPENAI_GPT_54_PRO_MODEL_ID = "gpt-5.4-pro";
|
||||
const OPENAI_GPT_54_MINI_MODEL_ID = "gpt-5.4-mini";
|
||||
const OPENAI_GPT_54_NANO_MODEL_ID = "gpt-5.4-nano";
|
||||
const OPENAI_GPT_54_CONTEXT_TOKENS = 1_050_000;
|
||||
const OPENAI_GPT_54_MAX_TOKENS = 128_000;
|
||||
const OPENAI_GPT_54_TEMPLATE_MODEL_IDS = ["gpt-5.2"] as const;
|
||||
const OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS = ["gpt-5.2-pro", "gpt-5.2"] as const;
|
||||
const OPENAI_XHIGH_MODEL_IDS = ["gpt-5.4", "gpt-5.4-pro", "gpt-5.2"] as const;
|
||||
const OPENAI_MODERN_MODEL_IDS = ["gpt-5.4", "gpt-5.4-pro", "gpt-5.2", "gpt-5.0"] as const;
|
||||
const OPENAI_GPT_54_MINI_TEMPLATE_MODEL_IDS = ["gpt-5-mini"] as const;
|
||||
const OPENAI_GPT_54_NANO_TEMPLATE_MODEL_IDS = ["gpt-5-nano", "gpt-5-mini"] as const;
|
||||
const OPENAI_XHIGH_MODEL_IDS = [
|
||||
"gpt-5.4",
|
||||
"gpt-5.4-pro",
|
||||
"gpt-5.4-mini",
|
||||
"gpt-5.4-nano",
|
||||
"gpt-5.2",
|
||||
] as const;
|
||||
const OPENAI_MODERN_MODEL_IDS = [
|
||||
"gpt-5.4",
|
||||
"gpt-5.4-pro",
|
||||
"gpt-5.4-mini",
|
||||
"gpt-5.4-nano",
|
||||
"gpt-5.2",
|
||||
"gpt-5.0",
|
||||
] as const;
|
||||
const OPENAI_DIRECT_SPARK_MODEL_ID = "gpt-5.3-codex-spark";
|
||||
const SUPPRESSED_SPARK_PROVIDERS = new Set(["openai", "azure-openai-responses"]);
|
||||
|
||||
|
|
@ -49,10 +67,47 @@ function resolveOpenAIGpt54ForwardCompatModel(
|
|||
const trimmedModelId = ctx.modelId.trim();
|
||||
const lower = trimmedModelId.toLowerCase();
|
||||
let templateIds: readonly string[];
|
||||
let patch: Partial<ProviderRuntimeModel>;
|
||||
if (lower === OPENAI_GPT_54_MODEL_ID) {
|
||||
templateIds = OPENAI_GPT_54_TEMPLATE_MODEL_IDS;
|
||||
patch = {
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: OPENAI_GPT_54_CONTEXT_TOKENS,
|
||||
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
|
||||
};
|
||||
} else if (lower === OPENAI_GPT_54_PRO_MODEL_ID) {
|
||||
templateIds = OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS;
|
||||
patch = {
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: OPENAI_GPT_54_CONTEXT_TOKENS,
|
||||
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
|
||||
};
|
||||
} else if (lower === OPENAI_GPT_54_MINI_MODEL_ID) {
|
||||
templateIds = OPENAI_GPT_54_MINI_TEMPLATE_MODEL_IDS;
|
||||
patch = {
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
};
|
||||
} else if (lower === OPENAI_GPT_54_NANO_MODEL_ID) {
|
||||
templateIds = OPENAI_GPT_54_NANO_TEMPLATE_MODEL_IDS;
|
||||
patch = {
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
|
|
@ -63,27 +118,15 @@ function resolveOpenAIGpt54ForwardCompatModel(
|
|||
modelId: trimmedModelId,
|
||||
templateIds,
|
||||
ctx,
|
||||
patch: {
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: OPENAI_GPT_54_CONTEXT_TOKENS,
|
||||
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
|
||||
},
|
||||
patch,
|
||||
}) ??
|
||||
normalizeModelCompat({
|
||||
id: trimmedModelId,
|
||||
name: trimmedModelId,
|
||||
api: "openai-responses",
|
||||
provider: PROVIDER_ID,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
...patch,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: OPENAI_GPT_54_CONTEXT_TOKENS,
|
||||
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
|
||||
contextWindow: patch.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
|
||||
maxTokens: patch.maxTokens ?? DEFAULT_CONTEXT_TOKENS,
|
||||
} as ProviderRuntimeModel)
|
||||
);
|
||||
}
|
||||
|
|
@ -157,6 +200,16 @@ export function buildOpenAIProvider(): ProviderPlugin {
|
|||
providerId: PROVIDER_ID,
|
||||
templateIds: OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS,
|
||||
});
|
||||
const openAiGpt54MiniTemplate = findCatalogTemplate({
|
||||
entries: ctx.entries,
|
||||
providerId: PROVIDER_ID,
|
||||
templateIds: OPENAI_GPT_54_MINI_TEMPLATE_MODEL_IDS,
|
||||
});
|
||||
const openAiGpt54NanoTemplate = findCatalogTemplate({
|
||||
entries: ctx.entries,
|
||||
providerId: PROVIDER_ID,
|
||||
templateIds: OPENAI_GPT_54_NANO_TEMPLATE_MODEL_IDS,
|
||||
});
|
||||
return [
|
||||
openAiGpt54Template
|
||||
? {
|
||||
|
|
@ -172,6 +225,20 @@ export function buildOpenAIProvider(): ProviderPlugin {
|
|||
name: OPENAI_GPT_54_PRO_MODEL_ID,
|
||||
}
|
||||
: undefined,
|
||||
openAiGpt54MiniTemplate
|
||||
? {
|
||||
...openAiGpt54MiniTemplate,
|
||||
id: OPENAI_GPT_54_MINI_MODEL_ID,
|
||||
name: OPENAI_GPT_54_MINI_MODEL_ID,
|
||||
}
|
||||
: undefined,
|
||||
openAiGpt54NanoTemplate
|
||||
? {
|
||||
...openAiGpt54NanoTemplate,
|
||||
id: OPENAI_GPT_54_NANO_MODEL_ID,
|
||||
name: OPENAI_GPT_54_NANO_MODEL_ID,
|
||||
}
|
||||
: undefined,
|
||||
].filter((entry): entry is NonNullable<typeof entry> => entry !== undefined);
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -181,6 +181,22 @@ describe("loadModelCatalog", () => {
|
|||
contextWindow: 1_050_000,
|
||||
input: ["text", "image"],
|
||||
},
|
||||
{
|
||||
id: "gpt-5-mini",
|
||||
provider: "openai",
|
||||
name: "GPT-5 mini",
|
||||
reasoning: true,
|
||||
contextWindow: 400_000,
|
||||
input: ["text", "image"],
|
||||
},
|
||||
{
|
||||
id: "gpt-5-nano",
|
||||
provider: "openai",
|
||||
name: "GPT-5 nano",
|
||||
reasoning: true,
|
||||
contextWindow: 400_000,
|
||||
input: ["text", "image"],
|
||||
},
|
||||
{
|
||||
id: "gpt-5.3-codex",
|
||||
provider: "openai-codex",
|
||||
|
|
@ -207,6 +223,20 @@ describe("loadModelCatalog", () => {
|
|||
name: "gpt-5.4-pro",
|
||||
}),
|
||||
);
|
||||
expect(result).toContainEqual(
|
||||
expect.objectContaining({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-mini",
|
||||
name: "gpt-5.4-mini",
|
||||
}),
|
||||
);
|
||||
expect(result).toContainEqual(
|
||||
expect.objectContaining({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-nano",
|
||||
name: "gpt-5.4-nano",
|
||||
}),
|
||||
);
|
||||
expect(result).toContainEqual(
|
||||
expect.objectContaining({
|
||||
provider: "openai-codex",
|
||||
|
|
|
|||
|
|
@ -347,7 +347,8 @@ describe("isModernModelRef", () => {
|
|||
|
||||
it("includes plugin-advertised modern models", () => {
|
||||
providerRuntimeMocks.resolveProviderModernModelRef.mockImplementation(({ provider, context }) =>
|
||||
provider === "openai" && ["gpt-5.4", "gpt-5.4-pro"].includes(context.modelId)
|
||||
provider === "openai" &&
|
||||
["gpt-5.4", "gpt-5.4-pro", "gpt-5.4-mini", "gpt-5.4-nano"].includes(context.modelId)
|
||||
? true
|
||||
: provider === "openai-codex" && context.modelId === "gpt-5.4"
|
||||
? true
|
||||
|
|
@ -360,6 +361,8 @@ describe("isModernModelRef", () => {
|
|||
|
||||
expect(isModernModelRef({ provider: "openai", id: "gpt-5.4" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "openai", id: "gpt-5.4-pro" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "openai", id: "gpt-5.4-mini" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "openai", id: "gpt-5.4-nano" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "openai-codex", id: "gpt-5.4" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode", id: "claude-opus-4-6" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode", id: "gemini-3-pro" })).toBe(true);
|
||||
|
|
|
|||
|
|
@ -757,6 +757,70 @@ describe("resolveModel", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("builds an openai fallback for gpt-5.4 mini from the gpt-5-mini template", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5-mini",
|
||||
templateModel: buildForwardCompatTemplate({
|
||||
id: "gpt-5-mini",
|
||||
name: "GPT-5 mini",
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
}),
|
||||
});
|
||||
|
||||
const result = resolveModel("openai", "gpt-5.4-mini", "/tmp/agent");
|
||||
|
||||
expect(result.error).toBeUndefined();
|
||||
expect(result.model).toMatchObject({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-mini",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("builds an openai fallback for gpt-5.4 nano from the gpt-5-nano template", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5-nano",
|
||||
templateModel: buildForwardCompatTemplate({
|
||||
id: "gpt-5-nano",
|
||||
name: "GPT-5 nano",
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
}),
|
||||
});
|
||||
|
||||
const result = resolveModel("openai", "gpt-5.4-nano", "/tmp/agent");
|
||||
|
||||
expect(result.error).toBeUndefined();
|
||||
expect(result.model).toMatchObject({
|
||||
provider: "openai",
|
||||
id: "gpt-5.4-nano",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes stale native openai gpt-5.4 completions transport to responses", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "openai",
|
||||
|
|
|
|||
|
|
@ -232,14 +232,19 @@ describe("directive behavior", () => {
|
|||
expect(text).toContain("Current thinking level: high");
|
||||
expect(text).toContain("Options: off, minimal, low, medium, high, adaptive.");
|
||||
|
||||
for (const model of ["openai-codex/gpt-5.2-codex", "openai/gpt-5.2"]) {
|
||||
for (const model of [
|
||||
"openai-codex/gpt-5.2-codex",
|
||||
"openai/gpt-5.2",
|
||||
"openai/gpt-5.4-mini",
|
||||
"openai/gpt-5.4-nano",
|
||||
]) {
|
||||
const texts = await runThinkingDirective(home, model);
|
||||
expect(texts).toContain("Thinking level set to xhigh.");
|
||||
}
|
||||
|
||||
const unsupportedModelTexts = await runThinkingDirective(home, "openai/gpt-4.1-mini");
|
||||
expect(unsupportedModelTexts).toContain(
|
||||
'Thinking level "xhigh" is only supported for openai/gpt-5.4, openai/gpt-5.4-pro, openai/gpt-5.2, openai-codex/gpt-5.4, openai-codex/gpt-5.3-codex, openai-codex/gpt-5.3-codex-spark, openai-codex/gpt-5.2-codex, openai-codex/gpt-5.1-codex, github-copilot/gpt-5.2-codex or github-copilot/gpt-5.2.',
|
||||
'Thinking level "xhigh" is only supported for openai/gpt-5.4, openai/gpt-5.4-pro, openai/gpt-5.4-mini, openai/gpt-5.4-nano, openai/gpt-5.2, openai-codex/gpt-5.4, openai-codex/gpt-5.3-codex, openai-codex/gpt-5.3-codex-spark, openai-codex/gpt-5.2-codex, openai-codex/gpt-5.1-codex, github-copilot/gpt-5.2-codex or github-copilot/gpt-5.2.',
|
||||
);
|
||||
expect(runEmbeddedPiAgent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -330,6 +330,38 @@ describe("provider runtime contract", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("owns openai gpt-5.4 mini forward-compat resolution", () => {
|
||||
const provider = requireProviderContractProvider("openai");
|
||||
const model = provider.resolveDynamicModel?.({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.4-mini",
|
||||
modelRegistry: {
|
||||
find: (_provider: string, id: string) =>
|
||||
id === "gpt-5-mini"
|
||||
? createModel({
|
||||
id,
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
input: ["text", "image"],
|
||||
reasoning: true,
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
})
|
||||
: null,
|
||||
} as never,
|
||||
});
|
||||
|
||||
expect(model).toMatchObject({
|
||||
id: "gpt-5.4-mini",
|
||||
provider: "openai",
|
||||
api: "openai-responses",
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
contextWindow: 400_000,
|
||||
maxTokens: 128_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("owns direct openai transport normalization", () => {
|
||||
const provider = requireProviderContractProvider("openai");
|
||||
expect(
|
||||
|
|
|
|||
|
|
@ -38,6 +38,16 @@ export function augmentBundledProviderCatalog(
|
|||
providerId: OPENAI_PROVIDER_ID,
|
||||
templateIds: ["gpt-5.2-pro", "gpt-5.2"],
|
||||
});
|
||||
const openAiGpt54MiniTemplate = findCatalogTemplate({
|
||||
entries: context.entries,
|
||||
providerId: OPENAI_PROVIDER_ID,
|
||||
templateIds: ["gpt-5-mini"],
|
||||
});
|
||||
const openAiGpt54NanoTemplate = findCatalogTemplate({
|
||||
entries: context.entries,
|
||||
providerId: OPENAI_PROVIDER_ID,
|
||||
templateIds: ["gpt-5-nano", "gpt-5-mini"],
|
||||
});
|
||||
const openAiCodexGpt54Template = findCatalogTemplate({
|
||||
entries: context.entries,
|
||||
providerId: OPENAI_CODEX_PROVIDER_ID,
|
||||
|
|
@ -64,6 +74,20 @@ export function augmentBundledProviderCatalog(
|
|||
name: "gpt-5.4-pro",
|
||||
}
|
||||
: undefined,
|
||||
openAiGpt54MiniTemplate
|
||||
? {
|
||||
...openAiGpt54MiniTemplate,
|
||||
id: "gpt-5.4-mini",
|
||||
name: "gpt-5.4-mini",
|
||||
}
|
||||
: undefined,
|
||||
openAiGpt54NanoTemplate
|
||||
? {
|
||||
...openAiGpt54NanoTemplate,
|
||||
id: "gpt-5.4-nano",
|
||||
name: "gpt-5.4-nano",
|
||||
}
|
||||
: undefined,
|
||||
openAiCodexGpt54Template
|
||||
? {
|
||||
...openAiCodexGpt54Template,
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@ import { expect } from "vitest";
|
|||
export const openaiCodexCatalogEntries = [
|
||||
{ provider: "openai", id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ provider: "openai", id: "gpt-5.2-pro", name: "GPT-5.2 Pro" },
|
||||
{ provider: "openai", id: "gpt-5-mini", name: "GPT-5 mini" },
|
||||
{ provider: "openai", id: "gpt-5-nano", name: "GPT-5 nano" },
|
||||
{ provider: "openai-codex", id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
];
|
||||
|
||||
export const expectedAugmentedOpenaiCodexCatalogEntries = [
|
||||
{ provider: "openai", id: "gpt-5.4", name: "gpt-5.4" },
|
||||
{ provider: "openai", id: "gpt-5.4-pro", name: "gpt-5.4-pro" },
|
||||
{ provider: "openai", id: "gpt-5.4-mini", name: "gpt-5.4-mini" },
|
||||
{ provider: "openai", id: "gpt-5.4-nano", name: "gpt-5.4-nano" },
|
||||
{ provider: "openai-codex", id: "gpt-5.4", name: "gpt-5.4" },
|
||||
{
|
||||
provider: "openai-codex",
|
||||
|
|
|
|||
|
|
@ -471,6 +471,8 @@ describe("provider-runtime", () => {
|
|||
entries: [
|
||||
{ provider: "openai", id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ provider: "openai", id: "gpt-5.2-pro", name: "GPT-5.2 Pro" },
|
||||
{ provider: "openai", id: "gpt-5-mini", name: "GPT-5 mini" },
|
||||
{ provider: "openai", id: "gpt-5-nano", name: "GPT-5 nano" },
|
||||
{ provider: "openai-codex", id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
],
|
||||
},
|
||||
|
|
@ -478,6 +480,8 @@ describe("provider-runtime", () => {
|
|||
).resolves.toEqual([
|
||||
{ provider: "openai", id: "gpt-5.4", name: "gpt-5.4" },
|
||||
{ provider: "openai", id: "gpt-5.4-pro", name: "gpt-5.4-pro" },
|
||||
{ provider: "openai", id: "gpt-5.4-mini", name: "gpt-5.4-mini" },
|
||||
{ provider: "openai", id: "gpt-5.4-nano", name: "gpt-5.4-nano" },
|
||||
{ provider: "openai-codex", id: "gpt-5.4", name: "gpt-5.4" },
|
||||
{
|
||||
provider: "openai-codex",
|
||||
|
|
|
|||
Loading…
Reference in New Issue