Skip to content
Merged
24 changes: 22 additions & 2 deletions packages/api/src/endpoints/models.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ describe('getOpenAIModels', () => {

it('returns default models when no environment configurations are provided (and fetch fails)', async () => {
const models = await getOpenAIModels({ user: 'user456' });
expect(models).toContain('gpt-4');
expect(models).toContain('gpt-5.5');
});

it('returns default models when OpenAI API key is user provided', async () => {
Expand All @@ -220,7 +220,7 @@ describe('getOpenAIModels', () => {

expect(mockedAxios.get).not.toHaveBeenCalled();
expect(models).not.toContain('should-not-appear');
expect(models).toContain('gpt-4');
expect(models).toContain('gpt-5.5');
});

it('fetches models when OpenAI API key is provided through options', async () => {
Expand Down Expand Up @@ -335,6 +335,26 @@ describe('getOpenAIModels sorting behavior', () => {
];
expect(models).toEqual(expectedOrder);
});

it('keeps chat-latest when filtering official OpenAI results', async () => {
mockedAxios.get.mockResolvedValue({
data: {
data: [
{ id: 'chat-latest' },
{ id: 'gpt-5.5' },
{ id: 'dall-e-3' },
{ id: 'gpt-realtime-2' },
],
},
});

const models = await getOpenAIModels({ user: 'user456' });

expect(models).toContain('chat-latest');
expect(models).toContain('gpt-5.5');
expect(models).not.toContain('dall-e-3');
expect(models).not.toContain('gpt-realtime-2');
});
});

describe('fetchModels with Ollama specific logic', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/endpoints/models.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import crypto from 'crypto';
import axios from 'axios';
import crypto from 'crypto';
import { logger } from '@librechat/data-schemas';
import { HttpsProxyAgent } from 'https-proxy-agent';
import {
Expand Down Expand Up @@ -274,7 +274,7 @@ export async function fetchOpenAIModels(
}

if (baseURL === openaiBaseURL) {
const regex = /(text-davinci-003|gpt-|o\d+)/;
const regex = /(text-davinci-003|gpt-|o\d+|chat-latest)/;
const excludeRegex = /audio|realtime/;
models = models.filter((model) => regex.test(model) && !excludeRegex.test(model));
const instructModels = models.filter((model) => model.includes('instruct'));
Expand Down
10 changes: 8 additions & 2 deletions packages/api/src/utils/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ const openAIModels = {
'gpt-5.1': 400000,
'gpt-5.2': 400000,
'gpt-5.3': 400000,
'gpt-5.4': 272000, // standard context; 1M experimental available via API opt-in (2x rate)
'gpt-5.4-pro': 272000, // same window as gpt-5.4
'gpt-5.4': 1050000, // >272K input prices at the long-context tier (2x input, 1.5x output)
'gpt-5.4-pro': 1050000,
'gpt-5.4-mini': 400000,
'gpt-5.4-nano': 400000,
'gpt-5.5': 1050000,
'gpt-5.5-pro': 1050000,
'chat-latest': 400000,
'gpt-5-mini': 400000,
'gpt-5-nano': 400000,
'gpt-5-pro': 400000,
Expand Down Expand Up @@ -383,8 +386,11 @@ export const modelMaxOutputs = {
'gpt-5.3': 128000,
'gpt-5.4': 128000,
'gpt-5.4-pro': 128000,
'gpt-5.4-mini': 128000,
'gpt-5.4-nano': 128000,
'gpt-5.5': 128000,
'gpt-5.5-pro': 128000,
'chat-latest': 128000,
'gpt-5-mini': 128000,
'gpt-5-nano': 128000,
'gpt-5-pro': 128000,
Expand Down
29 changes: 8 additions & 21 deletions packages/data-provider/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1578,40 +1578,27 @@ export const alternateName = {
};

const sharedOpenAIModels = [
'gpt-5.5',
'gpt-5.5-pro',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't expose GPT-5.5 Pro with streaming enabled

OpenAI documents gpt-5.5-pro with streaming as unsupported (https://developers.openai.com/api/docs/models/gpt-5.5-pro), while getOpenAIConfig defaults streaming = true for OpenAI requests. Adding this model to the default list means a user who selects it in the normal OpenAI flow will send a streaming request by default and hit an API failure unless they know to disable streaming first.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 3968115 β€” getOpenAILLMConfig now forces streaming: false for pro reasoning models (o1-pro, o3-pro, gpt-5-pro, gpt-5.x-pro), with spec coverage for both the pro and non-pro paths. This also covers gpt-5.4-pro, which was already in the default list before this PR with the same constraint.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: the endpoint/handler fix for this was reverted in 1c4d1fd β€” this PR is intentionally trimmed to model-catalog changes only (lists, token windows, pricing, fetched-model filter). The OpenAI-compat endpoint/handler surface is moving out of LibreChat into the agents SDK, where this behavior belongs.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide gpt-5.5-pro until streaming is handled

Exposing gpt-5.5-pro in the default OpenAI model list lets users select it even though the OpenAI model page marks streaming as unsupported, while this endpoint still defaults to streaming = true in packages/api/src/endpoints/openai/config.ts. In the default setup (no explicit OPENAI_MODELS override and streaming left enabled), selecting this newly listed model will send a streaming chat request that the model rejects; either omit it from defaults or add the non-streaming/pro-model handling before advertising it.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping it listed, deliberately β€” the maintainer descoped endpoint/handler behavior from this PR: the OpenAI-compat surface (including pro-model streaming handling) is moving into the agents SDK, and the catalog should reflect the current frontier lineup. The same constraint class already ships today via gpt-5.4-pro, which predates this PR in the default list; users can disable streaming via model parameters until the SDK-side handling lands.

'chat-latest',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include chat-latest in fetched OpenAI model filtering

Adding chat-latest to the default list does not make it available for the common server-key path: getOpenAIModels calls fetchOpenAIModels, and when the OpenAI /models response is non-empty it filters official OpenAI results with /(text-davinci-003|gpt-|o\d+)/ in packages/api/src/endpoints/models.ts:276-279. Because chat-latest does not match that regex and fallback defaults are only used on an empty response, deployments that fetch models from OpenAI will drop this new slug from the model picker.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in ea432bc β€” added chat-latest to the official-OpenAI filter regex in fetchOpenAIModels, with a spec covering that it survives filtering while dall-e-3/gpt-realtime-2 are still excluded.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle max-token conversion for chat-latest

When users select the new chat-latest default and set a max token limit, getOpenAILLMConfig still leaves it on llmConfig.maxTokens because the GPT-5 conversion guard only matches /\bgpt-[5-9]/ in packages/api/src/endpoints/openai/llm.ts. Since this alias is being treated as the latest GPT-5 chat model, those requests will send the legacy max-token field instead of max_completion_tokens/max_output_tokens, unlike the other GPT-5 defaults, and can fail only for conversations that configure a max token limit.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 13aa046 β€” the max-token conversion guard now also matches chat-latest, so it sends max_completion_tokens (or max_output_tokens on the Responses API) like the rest of the GPT-5 family. Spec added.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: the endpoint/handler fix for this was reverted in 1c4d1fd β€” this PR is intentionally trimmed to model-catalog changes only (lists, token windows, pricing, fetched-model filter). The OpenAI-compat endpoint/handler surface is moving out of LibreChat into the agents SDK, where this behavior belongs.

'gpt-5.4',
// TODO: gpt-5.4-thinking may have separate reasoning token pricing β€” verify before release
'gpt-5.4-thinking',
'gpt-5.4-pro',
'gpt-5.4-mini',
'gpt-5.4-nano',
'gpt-5.3-codex',
'gpt-5.2',
'gpt-5.1',
'gpt-5.1-chat-latest',
'gpt-5.1-codex',
'gpt-5.1-codex-max',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove deprecated Codex model from defaults

OpenAI now marks gpt-5.1-codex-max as deprecated in its model page (https://developers.openai.com/api/docs/models/gpt-5.1-codex-max). Adding it to the default OpenAI model list exposes a deprecated option to new configurations, so users can select a model that is already on the removal path instead of the current gpt-5.3-codex entry added next to it.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping this one β€” the model page only marks a dated snapshot as deprecated; the default gpt-5.1-codex-max listing carries no deprecation marking and the page still describes it as the current default for long-running agentic coding tasks, with no recommended replacement. The deprecations page doesn't list it either. (For contrast, gpt-5.2-codex is marked deprecated at the model level, which is why it was deliberately left out of this PR.)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove deprecated Codex-Max from defaults

When the OpenAI model fetch is skipped or fails, this static list is what users can select, so adding gpt-5.1-codex-max reintroduces a model that the current OpenAI model page marks as deprecated (source). That works against the "drop deprecated defaults" change and can leave fallback/user-provided-key setups presenting a model that may fail as soon as OpenAI disables the alias; it should be omitted from defaults unless it is returned by the live models endpoint.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked the model page just now: the Deprecated label still applies only to a dated snapshot row in the Snapshots section β€” the model itself carries no deprecation marking, the page describes it as current ("purpose-built for agentic coding") with active pricing, no replacement is recommended, and it is absent from the deprecations page. Same conclusion as the earlier thread on this entry; keeping it. If OpenAI deprecates the model proper (as with gpt-5.2-codex, which this PR deliberately excludes), it should come out in a catalog follow-up.

'gpt-5.1-codex-mini',
'gpt-5',
'gpt-5-mini',
'gpt-5-nano',
'gpt-5-chat-latest',
'gpt-4.1',
'gpt-4.1-mini',
'gpt-4.1-nano',
'gpt-4o-mini',
'gpt-4o',
'gpt-4.5-preview',
'gpt-4.5-preview-2025-02-27',
'gpt-3.5-turbo',
'gpt-3.5-turbo-0125',
'gpt-4-turbo',
'gpt-4-turbo-2024-04-09',
'gpt-4-0125-preview',
'gpt-4-turbo-preview',
'gpt-4-1106-preview',
'gpt-3.5-turbo-1106',
'gpt-3.5-turbo-16k-0613',
'gpt-3.5-turbo-16k',
'gpt-4',
'gpt-4-0314',
'gpt-4-32k-0314',
'gpt-4-0613',
'gpt-3.5-turbo-0613',
];

const sharedAnthropicModels = [
Expand Down
10 changes: 9 additions & 1 deletion packages/data-schemas/src/methods/tx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,19 @@ describe('getValueKey', () => {

it('should return "gpt-5.3" for model name containing "gpt-5.3"', () => {
expect(getValueKey('gpt-5.3')).toBe('gpt-5.3');
expect(getValueKey('gpt-5.3-chat-latest')).toBe('gpt-5.3');
expect(getValueKey('gpt-5.3-codex')).toBe('gpt-5.3');
expect(getValueKey('openai/gpt-5.3')).toBe('gpt-5.3');
});

it('should return explicit keys for chat-latest aliases', () => {
expect(getValueKey('chat-latest')).toBe('chat-latest');
expect(getValueKey('openai/chat-latest')).toBe('chat-latest');
expect(getValueKey('gpt-5-chat-latest')).toBe('gpt-5-chat-latest');
expect(getValueKey('gpt-5.1-chat-latest')).toBe('gpt-5.1-chat-latest');
expect(getValueKey('gpt-5.2-chat-latest')).toBe('gpt-5.2-chat-latest');
expect(getValueKey('gpt-5.3-chat-latest')).toBe('gpt-5.3-chat-latest');
});

it('should return "gpt-5.4" for model name containing "gpt-5.4"', () => {
expect(getValueKey('gpt-5.4')).toBe('gpt-5.4');
expect(getValueKey('gpt-5.4-thinking')).toBe('gpt-5.4');
Expand Down
24 changes: 22 additions & 2 deletions packages/data-schemas/src/methods/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,16 @@ export const tokenValues: Record<string, { prompt: number; completion: number }>
'gpt-5.2': { prompt: 1.75, completion: 14 },
'gpt-5.3': { prompt: 1.75, completion: 14 },
'gpt-5.4': { prompt: 2.5, completion: 15 },
// TODO: gpt-5.4-pro pricing not yet officially published β€” verify before release
'gpt-5.4-pro': { prompt: 5, completion: 30 },
'gpt-5.4-pro': { prompt: 30, completion: 180 },
'gpt-5.4-mini': { prompt: 0.75, completion: 4.5 },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the missing gpt-5.4-nano pricing key

When OpenAI returns gpt-5.4-nano from /v1/models or an admin configures it manually, this table has no explicit key for it even though the current pricing page lists it as part of the GPT-5.4 family at much lower rates ($0.20 input / $1.25 output, with cached input). Because getValueKey uses the longest substring match over tokenValues, gpt-5.4-nano resolves to the generic gpt-5.4 entry here and is billed at $2.50/$15 instead, so the new catalog refresh will substantially overcharge nano usage.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in ffa6359 β€” gpt-5.4-nano is registered in the default list, pricing ($0.20/$1.25, cached $0.02), and token maps (400K context; an explicit entry was also needed there since the substring match would have given it gpt-5.4's 1.05M window). Good catch β€” this model hadn't surfaced in any of the catalog sweeps.

'gpt-5.4-nano': { prompt: 0.2, completion: 1.25 },
'gpt-5.5': { prompt: 5, completion: 30 },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Account for GPT-5.5 long-context pricing

For GPT-5.5, OpenAI publishes separate long-context rates ($10/$45, cached $1) in addition to the short-context rates added here (https://developers.openai.com/api/docs/pricing). Since this commit also gives gpt-5.5 a ~1M context window, any request that enters the long-context tier will still be billed internally at the short-context $5/$30 rates because there is no premiumTokenValues entry keyed by inputTokenCount, causing under-accounting for large prompts.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 3968115 β€” added premiumTokenValues entries: gpt-5.5 at $10/$45 and gpt-5.4 at $5/$22.50 (its published long-context tier follows the same 2x input / 1.5x output structure), both with a 272K threshold per the model page: "prompts with >272K input tokens are priced at 2x input and 1.5x output for the full session." Cached-read tiering isn't representable in the current cache map structure, so long-context cached reads still bill at the standard rate β€” same limitation as the existing gemini entry.

'gpt-5.5-pro': { prompt: 30, completion: 180 },
'chat-latest': { prompt: 5, completion: 30 },
'gpt-5-chat-latest': { prompt: 1.25, completion: 10 },
'gpt-5.1-chat-latest': { prompt: 1.25, completion: 10 },
'gpt-5.2-chat-latest': { prompt: 1.75, completion: 14 },
'gpt-5.3-chat-latest': { prompt: 1.75, completion: 14 },
'gpt-5-nano': { prompt: 0.05, completion: 0.4 },
'gpt-5-mini': { prompt: 0.25, completion: 2 },
'gpt-5-pro': { prompt: 15, completion: 120 },
Expand Down Expand Up @@ -310,6 +318,14 @@ export const cacheTokenValues: Record<string, { write: number; read: number }> =
'gpt-5.2': { write: 1.75, read: 0.175 },
'gpt-5.3': { write: 1.75, read: 0.175 },
'gpt-5.4': { write: 2.5, read: 0.25 },
'gpt-5.4-mini': { write: 0.75, read: 0.075 },
'gpt-5.4-nano': { write: 0.2, read: 0.02 },
'gpt-5.5': { write: 5, read: 0.5 },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Charge cached GPT-5.5 long context at the long rate

For gpt-5.5 requests above the 272K-token long-context breakpoint, cached input is billed at $1.00/1M rather than $0.50/1M in OpenAI’s pricing table (https://developers.openai.com/api/docs/pricing), but getCacheMultiplier() has no input-token-count path and will always return this short-context read value. That undercounts any cached portion of long-context GPT-5.5 sessions even though prompt/output long-context rates are handled separately in premiumTokenValues.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real but deferred β€” getCacheMultiplier() has no input-token-count path: its callers in the transaction layer don't carry prompt size, so tiered cache pricing isn't representable without extending the billing mechanism (the same limitation applies to the existing gemini premium entry). That's beyond this catalog-scoped PR; flagging it for the billing-mechanism follow-up. The long-context prompt/output rates themselves are handled via premiumTokenValues.

'chat-latest': { write: 5, read: 0.5 },
'gpt-5-chat-latest': { write: 1.25, read: 0.125 },
'gpt-5.1-chat-latest': { write: 1.25, read: 0.125 },
'gpt-5.2-chat-latest': { write: 1.75, read: 0.175 },
'gpt-5.3-chat-latest': { write: 1.75, read: 0.175 },
'gpt-5-mini': { write: 0.25, read: 0.025 },
'gpt-5-nano': { write: 0.05, read: 0.005 },
o1: { write: 15, read: 7.5 },
Expand Down Expand Up @@ -348,6 +364,10 @@ export const premiumTokenValues: Record<
{ threshold: number; prompt: number; completion: number }
> = {
'gemini-3.1': { threshold: 200000, prompt: 4, completion: 18 },
'gpt-5.4': { threshold: 272000, prompt: 5, completion: 22.5 },
'gpt-5.4-pro': { threshold: 272000, prompt: 60, completion: 270 },
'gpt-5.5': { threshold: 272000, prompt: 10, completion: 45 },
Comment on lines +367 to +369

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Apply long-context pricing to pro models

When a gpt-5.4-pro or gpt-5.5-pro request exceeds 272K input tokens, getValueKey() resolves to the exact pro key added above, but premiumTokenValues only contains the non-pro keys, so getPremiumRate() never applies the long-context pro rates. OpenAI’s pricing table includes long-context columns for both pro models (https://developers.openai.com/api/docs/pricing), so these sessions would be billed at the short-context $30/$180 rate instead of $60/$270.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially confirmed, fixed in 70c841a β€” added gpt-5.4-pro long-context premium rates ($60/$270 above 272K), whose model page states the 2x input / 1.5x output rule verbatim. gpt-5.5-pro was left out deliberately: its model page documents flat $30/$180 pricing with no long-context tier or breakpoint (checked twice), so applying $60/$270 there would overbill. Happy to add it if OpenAI publishes a tier for it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply long-context rates to gpt-5.5-pro

For gpt-5.5-pro requests over the 272K-token long-context breakpoint, getMultiplier only switches rates when the model has an entry in premiumTokenValues; the current pricing table lists gpt-5.5-pro long-context standard rates as $60 input / $270 output, but this block only adds the tier for gpt-5.5. As a result, any >272K gpt-5.5-pro session falls back to the standard $30/$180 rates from tokenValues and underbills long-context pro usage.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in ffa6359 β€” gpt-5.5-pro now has the $60/$270 long-context premium entry. This also corrects my reply on the earlier thread: the pricing page's long-context table does list gpt-5.5-pro, even though its model page presents only flat $30/$180 with no breakpoint mention β€” the pricing table is the canonical source here.

'gpt-5.5-pro': { threshold: 272000, prompt: 60, completion: 270 },
Comment on lines +367 to +370

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply long-context pricing to cached input

For GPT-5.4/5.5 requests above the 272K-token breakpoint, these new premium entries only affect uncached prompt and completion multipliers; structured cached reads still go through getCacheMultiplier, which has no inputTokenCount and returns the standard cacheTokenValues read rate. In a long-context request with cached input (e.g. read tokens plus total input >272K), the prompt and completion are billed at the premium tier but cached input remains at the below-threshold rate, undercharging those runs unless the cache multiplier is also made threshold-aware.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate of the earlier cached-input thread on this file β€” same answer: getCacheMultiplier has no input-token-count path (its transaction-layer callers don't carry prompt size), so threshold-aware cache rates require a billing-mechanism change that is deferred beyond this catalog-scoped PR. The gemini premium entry shares the same limitation.

};

export function createTxMethods(
Expand Down
Loading