Skip to content

Commit ff81bc8

Browse files
committed
fix(openai): restore adapter→builtin→override precedence in createModel
The merge order in createModel spread builtIn.compat first then this.compat, so the adapter's generic default (maxTokensField: 'max_tokens') silently clobbered the model-specific override that the built-in entry sets ('max_completion_tokens' for reasoning-capable models). Result: every reasoning model loaded via createModel sent the wrong field name and OpenAI returned 400 "Unsupported parameter: 'max_tokens'". Same bug applied to headers. The mock-mode unit tests didn't catch it because the mocked fetch never validated the request body — the live smoke test caught it on the first real call. Swap to: adapter defaults → built-in catalog → caller overrides, so the most specific source wins. Adds two regression tests.
1 parent f368197 commit ff81bc8

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

packages/openai/__tests__/openai.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ describe('OpenAIAdapter', () => {
132132
expect(message.usage.totalTokens).toBe(40);
133133
});
134134

135+
it('createModel preserves model-specific compat overriding adapter defaults', () => {
136+
const adapter = new OpenAIAdapter({ apiKey: 'k' });
137+
const model = adapter.createModel('gpt-5.4-nano');
138+
expect(model.compat?.maxTokensField).toBe('max_completion_tokens');
139+
});
140+
141+
it('createModel lets caller overrides win over both', () => {
142+
const adapter = new OpenAIAdapter({ apiKey: 'k' });
143+
const model = adapter.createModel('gpt-5.4-nano', {
144+
compat: { maxTokensField: 'max_tokens' },
145+
});
146+
expect(model.compat?.maxTokensField).toBe('max_tokens');
147+
});
148+
135149
it('falls back to built-in models when no API key is configured', async () => {
136150
const adapter = new OpenAIAdapter();
137151
const models = await adapter.listModels();

packages/openai/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ export class OpenAIAdapter {
389389
return {
390390
...builtIn,
391391
baseUrl: this.baseUrl,
392-
headers: { ...(builtIn.headers ?? {}), ...(this.defaultHeaders ?? {}), ...(overrides?.headers ?? {}) },
393-
compat: { ...(builtIn.compat ?? {}), ...(this.compat ?? {}), ...(overrides?.compat ?? {}) },
392+
headers: { ...(this.defaultHeaders ?? {}), ...(builtIn.headers ?? {}), ...(overrides?.headers ?? {}) },
393+
compat: { ...(this.compat ?? {}), ...(builtIn.compat ?? {}), ...(overrides?.compat ?? {}) },
394394
...overrides,
395395
};
396396
}

0 commit comments

Comments
 (0)