feat: auto-populate contextWindowLimit from model ID lookup tables (#954)

This commit is contained in:
opieter-aws
2026-05-01 15:23:00 +00:00
committed by GitHub
parent 68b5143d45
commit 7c00a77aa6
11 changed files with 449 additions and 7 deletions
@@ -136,6 +136,45 @@ describe('AnthropicModel', () => {
expect.stringContaining('using default modelId')
)
})
it('auto-populates contextWindowLimit from model ID lookup', () => {
const provider = new AnthropicModel({ apiKey: 'sk-test', modelId: 'claude-sonnet-4-20250514' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'claude-sonnet-4-20250514',
maxTokens: 64_000,
contextWindowLimit: 1_000_000,
})
})
it('auto-populates contextWindowLimit for default model ID', () => {
const provider = new AnthropicModel({ apiKey: 'sk-test' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'claude-sonnet-4-6',
maxTokens: 64_000,
contextWindowLimit: 1_000_000,
})
})
it('does not override explicit contextWindowLimit', () => {
const provider = new AnthropicModel({
apiKey: 'sk-test',
modelId: 'claude-sonnet-4-20250514',
contextWindowLimit: 100_000,
})
expect(provider.getConfig()).toStrictEqual({
modelId: 'claude-sonnet-4-20250514',
maxTokens: 64_000,
contextWindowLimit: 100_000,
})
})
it('leaves contextWindowLimit undefined for unknown model IDs', () => {
const provider = new AnthropicModel({ apiKey: 'sk-test', modelId: 'unknown-model' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'unknown-model',
maxTokens: 64_000,
})
})
})
describe('updateConfig', () => {
@@ -147,6 +186,22 @@ describe('AnthropicModel', () => {
maxTokens: 8192,
})
})
it('re-resolves contextWindowLimit when modelId changes and it was auto-resolved', () => {
const provider = new AnthropicModel({ apiKey: 'sk-test' })
expect(provider.getConfig().contextWindowLimit).toBe(1_000_000) // claude-sonnet-4-6 default
provider.updateConfig({ modelId: 'claude-sonnet-4-20250514' })
expect(provider.getConfig().contextWindowLimit).toBe(1_000_000) // claude-sonnet-4-20250514 value
})
it('preserves explicit contextWindowLimit when modelId changes', () => {
const provider = new AnthropicModel({ apiKey: 'sk-test', contextWindowLimit: 50_000 })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
provider.updateConfig({ modelId: 'claude-sonnet-4-20250514' })
expect(provider.getConfig().contextWindowLimit).toBe(50_000) // preserved
})
})
describe('stream event handling', () => {
@@ -208,6 +208,7 @@ describe('BedrockModel', () => {
const provider = new BedrockModel({ modelId: customModelId })
expect(provider.getConfig()).toStrictEqual({
modelId: customModelId,
contextWindowLimit: 200_000,
})
})
@@ -292,6 +293,7 @@ describe('BedrockModel', () => {
expect(config).toStrictEqual({
modelId: 'global.anthropic.claude-sonnet-4-6',
temperature: 0.5,
contextWindowLimit: 1_000_000,
})
})
@@ -305,6 +307,48 @@ describe('BedrockModel', () => {
contextWindowLimit: 200_000,
})
})
it('auto-populates contextWindowLimit from model ID lookup', () => {
const provider = new BedrockModel({ modelId: 'anthropic.claude-sonnet-4-20250514-v1:0' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
contextWindowLimit: 1_000_000,
})
})
it('auto-populates contextWindowLimit for cross-region model IDs', () => {
const provider = new BedrockModel({ modelId: 'us.anthropic.claude-sonnet-4-6' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'us.anthropic.claude-sonnet-4-6',
contextWindowLimit: 1_000_000,
})
})
it('auto-populates contextWindowLimit for default model ID', () => {
const provider = new BedrockModel()
expect(provider.getConfig()).toStrictEqual({
modelId: 'global.anthropic.claude-sonnet-4-6',
contextWindowLimit: 1_000_000,
})
})
it('does not override explicit contextWindowLimit', () => {
const provider = new BedrockModel({
modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
contextWindowLimit: 100_000,
})
expect(provider.getConfig()).toStrictEqual({
modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
contextWindowLimit: 100_000,
})
})
it('leaves contextWindowLimit undefined for unknown model IDs', () => {
const provider = new BedrockModel({ modelId: 'unknown.model-v1:0' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'unknown.model-v1:0',
})
})
})
describe('updateConfig', () => {
@@ -315,6 +359,7 @@ describe('BedrockModel', () => {
modelId: 'global.anthropic.claude-sonnet-4-6',
temperature: 0.8,
maxTokens: 2048,
contextWindowLimit: 1_000_000,
})
})
@@ -332,6 +377,30 @@ describe('BedrockModel', () => {
maxTokens: 1024,
})
})
it('re-resolves contextWindowLimit when modelId changes and it was auto-resolved', () => {
const provider = new BedrockModel({ region: 'us-west-2' })
expect(provider.getConfig().contextWindowLimit).toBe(1_000_000)
provider.updateConfig({ modelId: 'anthropic.claude-haiku-4-5-20251001-v1:0' })
expect(provider.getConfig().contextWindowLimit).toBe(200_000)
})
it('clears contextWindowLimit when modelId changes to unknown model', () => {
const provider = new BedrockModel({ region: 'us-west-2' })
expect(provider.getConfig().contextWindowLimit).toBe(1_000_000)
provider.updateConfig({ modelId: 'my-custom-finetuned-model' })
expect(provider.getConfig().contextWindowLimit).toBeUndefined()
})
it('preserves explicit contextWindowLimit when modelId changes', () => {
const provider = new BedrockModel({ region: 'us-west-2', contextWindowLimit: 50_000 })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
provider.updateConfig({ modelId: 'anthropic.claude-haiku-4-5-20251001-v1:0' })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
})
})
describe('getConfig', () => {
@@ -0,0 +1,39 @@
import { describe, it, expect } from 'vitest'
import { getContextWindowLimit } from '../defaults.js'
describe('getContextWindowLimit', () => {
it('returns the context window limit for known model IDs across all providers', () => {
// Anthropic direct API
expect(getContextWindowLimit('claude-sonnet-4-6')).toBe(1_000_000)
expect(getContextWindowLimit('claude-opus-4-6')).toBe(1_000_000)
expect(getContextWindowLimit('claude-opus-4-5')).toBe(200_000)
expect(getContextWindowLimit('claude-haiku-4-5')).toBe(200_000)
// Bedrock Anthropic
expect(getContextWindowLimit('anthropic.claude-sonnet-4-6')).toBe(1_000_000)
// Bedrock Amazon Nova
expect(getContextWindowLimit('amazon.nova-pro-v1:0')).toBe(300_000)
expect(getContextWindowLimit('amazon.nova-micro-v1:0')).toBe(128_000)
// OpenAI
expect(getContextWindowLimit('gpt-5.4')).toBe(1_050_000)
expect(getContextWindowLimit('gpt-4o')).toBe(128_000)
expect(getContextWindowLimit('o3')).toBe(200_000)
expect(getContextWindowLimit('o4-mini')).toBe(200_000)
// Gemini
expect(getContextWindowLimit('gemini-2.5-flash')).toBe(1_048_576)
expect(getContextWindowLimit('gemini-2.5-pro')).toBe(1_048_576)
})
it('strips Bedrock cross-region prefix before lookup', () => {
expect(getContextWindowLimit('us.anthropic.claude-sonnet-4-6')).toBe(1_000_000)
expect(getContextWindowLimit('global.anthropic.claude-sonnet-4-6')).toBe(1_000_000)
})
it('does not strip unknown prefixes', () => {
expect(getContextWindowLimit('custom.gpt-5.4')).toBeUndefined()
})
it('returns undefined for unknown model IDs', () => {
expect(getContextWindowLimit('unknown-model-xyz')).toBeUndefined()
expect(getContextWindowLimit('us.unknown.model-v1:0')).toBeUndefined()
})
})
@@ -139,8 +139,33 @@ describe('GoogleModel', () => {
expect(provider.getConfig()).toStrictEqual({
modelId: 'gemini-2.5-flash',
params: { temperature: 0.5 },
contextWindowLimit: 1_048_576,
})
})
it('re-resolves contextWindowLimit when modelId changes and it was auto-resolved', () => {
const provider = new GoogleModel({ apiKey: 'test-key' })
expect(provider.getConfig().contextWindowLimit).toBe(1_048_576)
provider.updateConfig({ modelId: 'gemini-2.0-flash' })
expect(provider.getConfig().contextWindowLimit).toBe(1_048_576)
})
it('clears contextWindowLimit when modelId changes to unknown model', () => {
const provider = new GoogleModel({ apiKey: 'test-key' })
expect(provider.getConfig().contextWindowLimit).toBe(1_048_576)
provider.updateConfig({ modelId: 'my-custom-finetuned-model' })
expect(provider.getConfig().contextWindowLimit).toBeUndefined()
})
it('preserves explicit contextWindowLimit when modelId changes', () => {
const provider = new GoogleModel({ apiKey: 'test-key', contextWindowLimit: 50_000 })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
provider.updateConfig({ modelId: 'gemini-2.0-flash' })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
})
})
describe('getConfig', () => {
@@ -153,6 +178,7 @@ describe('GoogleModel', () => {
expect(provider.getConfig()).toStrictEqual({
modelId: 'gemini-2.5-flash',
params: { maxOutputTokens: 1024, temperature: 0.7 },
contextWindowLimit: 1_048_576,
})
})
@@ -167,6 +193,40 @@ describe('GoogleModel', () => {
contextWindowLimit: 1_048_576,
})
})
it('auto-populates contextWindowLimit from model ID lookup', () => {
const provider = new GoogleModel({ apiKey: 'test-key', modelId: 'gemini-2.5-pro' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'gemini-2.5-pro',
contextWindowLimit: 1_048_576,
})
})
it('auto-populates contextWindowLimit for default model ID', () => {
const provider = new GoogleModel({ apiKey: 'test-key' })
expect(provider.getConfig()).toStrictEqual({
contextWindowLimit: 1_048_576,
})
})
it('does not override explicit contextWindowLimit', () => {
const provider = new GoogleModel({
apiKey: 'test-key',
modelId: 'gemini-2.5-flash',
contextWindowLimit: 500_000,
})
expect(provider.getConfig()).toStrictEqual({
modelId: 'gemini-2.5-flash',
contextWindowLimit: 500_000,
})
})
it('leaves contextWindowLimit undefined for unknown model IDs', () => {
const provider = new GoogleModel({ apiKey: 'test-key', modelId: 'unknown-model' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'unknown-model',
})
})
})
describe('stream', () => {
+8 -2
View File
@@ -1,5 +1,11 @@
import Anthropic, { type ClientOptions } from '@anthropic-ai/sdk'
import { Model, type BaseModelConfig, type CountTokensOptions, type StreamOptions } from '../models/model.js'
import {
Model,
type BaseModelConfig,
type CountTokensOptions,
type StreamOptions,
resolveConfigMetadata,
} from '../models/model.js'
import type { Message, ContentBlock } from '../types/messages.js'
import type { ModelStreamEvent } from '../models/streaming.js'
import { createEmptyUsage } from '../models/streaming.js'
@@ -81,7 +87,7 @@ export class AnthropicModel extends Model<AnthropicModelConfig> {
}
getConfig(): AnthropicModelConfig {
return this._config
return resolveConfigMetadata(this._config, this._config.modelId ?? MODEL_DEFAULTS.anthropic.modelId)
}
/**
+2 -1
View File
@@ -48,6 +48,7 @@ import {
type CountTokensOptions,
Model,
type StreamOptions,
resolveConfigMetadata,
} from '../models/model.js'
import type { ContentBlock, Message, StopReason, ToolUseBlock } from '../types/messages.js'
import type { ImageSource, VideoSource, DocumentSource } from '../types/media.js'
@@ -463,7 +464,7 @@ export class BedrockModel extends Model<BedrockModelConfig> {
* ```
*/
getConfig(): BedrockModelConfig {
return this._config
return resolveConfigMetadata(this._config, this._config.modelId ?? MODEL_DEFAULTS.bedrock.modelId)
}
/**
+137
View File
@@ -41,3 +41,140 @@ export function defaultModelWarningMessage(defaultModelId: string): string {
export function defaultMaxTokensWarningMessage(defaultMaxTokens: number): string {
return `max_tokens=<${defaultMaxTokens}> | using default maxTokens, which is subject to change | set maxTokens explicitly to pin the value`
}
/**
* Context window limits (in tokens) for known model IDs.
*
* Best-effort lookup table — unknown models return `undefined` and callers
* fall back gracefully (e.g. proactive compression is disabled).
* Entries can be pruned when a model is no longer available from the provider.
* Users can always override with an explicit `contextWindowLimit` in their model config.
*
* Values sourced from provider documentation and
* https://github.com/BerriAI/litellm/blob/litellm_internal_staging/model_prices_and_context_window.json
*
* For Bedrock models with cross-region prefixes (e.g. `us.`, `eu.`, `global.`),
* {@link getContextWindowLimit} strips the prefix before lookup so only the base model ID is needed here.
*/
const CONTEXT_WINDOW_LIMITS: Record<string, number> = {
// Anthropic (direct API)
'claude-sonnet-4-6': 1_000_000,
'claude-sonnet-4-20250514': 1_000_000,
'claude-sonnet-4-5': 200_000,
'claude-sonnet-4-5-20250929': 200_000,
'claude-opus-4-6': 1_000_000,
'claude-opus-4-6-20260205': 1_000_000,
'claude-opus-4-7': 1_000_000,
'claude-opus-4-7-20260416': 1_000_000,
'claude-opus-4-5': 200_000,
'claude-opus-4-5-20251101': 200_000,
'claude-opus-4-20250514': 200_000,
'claude-opus-4-1': 200_000,
'claude-opus-4-1-20250805': 200_000,
'claude-haiku-4-5': 200_000,
'claude-haiku-4-5-20251001': 200_000,
'claude-3-7-sonnet-20250219': 200_000,
'claude-3-5-sonnet-20241022': 200_000,
'claude-3-5-sonnet-20240620': 200_000,
'claude-3-5-haiku-20241022': 200_000,
'claude-3-opus-20240229': 200_000,
'claude-3-haiku-20240307': 200_000,
// Bedrock Anthropic (base model IDs — cross-region prefixes stripped by getContextWindowLimit)
'anthropic.claude-sonnet-4-6': 1_000_000,
'anthropic.claude-sonnet-4-20250514-v1:0': 1_000_000,
'anthropic.claude-sonnet-4-5-20250929-v1:0': 200_000,
'anthropic.claude-opus-4-6-v1': 1_000_000,
'anthropic.claude-opus-4-7': 1_000_000,
'anthropic.claude-opus-4-5-20251101-v1:0': 200_000,
'anthropic.claude-opus-4-20250514-v1:0': 200_000,
'anthropic.claude-opus-4-1-20250805-v1:0': 200_000,
'anthropic.claude-haiku-4-5-20251001-v1:0': 200_000,
'anthropic.claude-haiku-4-5@20251001': 200_000,
'anthropic.claude-3-7-sonnet-20250219-v1:0': 200_000,
'anthropic.claude-3-7-sonnet-20240620-v1:0': 200_000,
'anthropic.claude-3-5-sonnet-20241022-v2:0': 200_000,
'anthropic.claude-3-5-sonnet-20240620-v1:0': 200_000,
'anthropic.claude-3-5-haiku-20241022-v1:0': 200_000,
'anthropic.claude-3-opus-20240229-v1:0': 200_000,
'anthropic.claude-3-haiku-20240307-v1:0': 200_000,
'anthropic.claude-3-sonnet-20240229-v1:0': 200_000,
'anthropic.claude-mythos-preview': 1_000_000,
// Bedrock Amazon Nova
'amazon.nova-pro-v1:0': 300_000,
'amazon.nova-lite-v1:0': 300_000,
'amazon.nova-micro-v1:0': 128_000,
'amazon.nova-premier-v1:0': 1_000_000,
'amazon.nova-2-lite-v1:0': 1_000_000,
'amazon.nova-2-pro-preview-20251202-v1:0': 1_000_000,
// OpenAI
'gpt-5.5': 1_050_000,
'gpt-5.5-pro': 1_050_000,
'gpt-5.4': 1_050_000,
'gpt-5.4-pro': 1_050_000,
'gpt-5.4-mini': 272_000,
'gpt-5.4-nano': 272_000,
'gpt-5.2': 272_000,
'gpt-5.2-pro': 272_000,
'gpt-5.1': 272_000,
'gpt-5': 272_000,
'gpt-5-mini': 272_000,
'gpt-5-nano': 272_000,
'gpt-5-pro': 128_000,
'gpt-4.1': 1_047_576,
'gpt-4.1-mini': 1_047_576,
'gpt-4.1-nano': 1_047_576,
'gpt-4o': 128_000,
'gpt-4o-mini': 128_000,
'gpt-4-turbo': 128_000,
o3: 200_000,
'o3-mini': 200_000,
'o3-pro': 200_000,
'o4-mini': 200_000,
o1: 200_000,
// Google Gemini
'gemini-2.5-flash': 1_048_576,
'gemini-2.5-flash-lite': 1_048_576,
'gemini-2.5-pro': 1_048_576,
'gemini-2.0-flash': 1_048_576,
'gemini-2.0-flash-lite': 1_048_576,
'gemini-3-pro-preview': 1_048_576,
'gemini-3-flash-preview': 1_048_576,
'gemini-3.1-pro-preview': 1_048_576,
'gemini-3.1-flash-lite-preview': 1_048_576,
}
/**
* Known Bedrock cross-region routing prefixes.
*
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html
*/
const BEDROCK_REGION_PREFIXES = new Set(['us', 'eu', 'ap', 'global', 'apac', 'au', 'jp', 'us-gov'])
/**
* Looks up the context window limit for a model ID.
*
* For Bedrock cross-region model IDs (e.g. `us.anthropic.claude-sonnet-4-6`),
* the region prefix is stripped before lookup.
*
* @param modelId - The model ID to look up
* @returns The context window limit in tokens, or undefined if not found
*/
export function getContextWindowLimit(modelId: string): number | undefined {
const direct = CONTEXT_WINDOW_LIMITS[modelId]
if (direct !== undefined) return direct
// Strip known Bedrock cross-region prefixes
const dotIndex = modelId.indexOf('.')
if (dotIndex !== -1) {
const prefix = modelId.substring(0, dotIndex)
if (BEDROCK_REGION_PREFIXES.has(prefix)) {
return CONTEXT_WINDOW_LIMITS[modelId.substring(dotIndex + 1)]
}
}
return undefined
}
+2 -2
View File
@@ -13,7 +13,7 @@ import {
type GenerateContentConfig,
type GenerateContentParameters,
} from '@google/genai'
import { Model } from '../model.js'
import { Model, resolveConfigMetadata } from '../model.js'
import type { CountTokensOptions, StreamOptions } from '../model.js'
import type { Message } from '../../types/messages.js'
import type { ModelStreamEvent } from '../streaming.js'
@@ -144,7 +144,7 @@ export class GoogleModel extends Model<GoogleModelConfig> {
* ```
*/
getConfig(): GoogleModelConfig {
return this._config
return resolveConfigMetadata(this._config, this._config.modelId ?? MODEL_DEFAULTS.gemini.modelId)
}
/**
+22
View File
@@ -26,6 +26,23 @@ import {
import { MaxTokensError, ModelError, normalizeError } from '../errors.js'
import type { Redaction } from '../hooks/events.js'
import { logger } from '../logging/logger.js'
import { getContextWindowLimit } from './defaults.js'
/**
* Resolves model metadata fields on a config object from built-in lookup tables
* when not explicitly set. Explicit values pass through unchanged.
*
* @internal
* @param config - The stored model config
* @param modelId - The model ID to look up
* @returns A new config with resolved metadata, or the original config if nothing to resolve
*/
export function resolveConfigMetadata<T extends BaseModelConfig>(config: T, modelId: string): T {
if (config.contextWindowLimit !== undefined) return config
const limit = getContextWindowLimit(modelId)
if (limit === undefined) return config
return { ...config, contextWindowLimit: limit }
}
class CitationAccumulator {
citations: Citation[] = []
@@ -98,6 +115,11 @@ export interface BaseModelConfig {
* Maximum context window size in tokens for the model.
*
* This value represents the total token capacity shared between input and output.
* When not provided, it is automatically resolved from a built-in lookup table
* based on the configured model ID. An explicit value always takes precedence.
*
* When `modelId` is changed via `updateConfig()`, this value is automatically
* re-resolved if it was initially auto-populated. Explicitly set values are preserved.
*/
contextWindowLimit?: number
}
@@ -229,6 +229,7 @@ describe('OpenAIModel', () => {
modelId: 'gpt-5.4',
temperature: 0.8,
maxTokens: 2048,
contextWindowLimit: 1_050_000,
})
})
@@ -247,6 +248,22 @@ describe('OpenAIModel', () => {
maxTokens: 1024,
})
})
it('re-resolves contextWindowLimit when modelId changes and it was auto-resolved', () => {
const provider = new OpenAIModel({ api: 'chat', apiKey: 'sk-test' })
expect(provider.getConfig().contextWindowLimit).toBe(1_050_000) // gpt-5.4 default
provider.updateConfig({ modelId: 'gpt-4o' })
expect(provider.getConfig().contextWindowLimit).toBe(128_000) // gpt-4o value
})
it('preserves explicit contextWindowLimit when modelId changes', () => {
const provider = new OpenAIModel({ api: 'chat', apiKey: 'sk-test', contextWindowLimit: 50_000 })
expect(provider.getConfig().contextWindowLimit).toBe(50_000)
provider.updateConfig({ modelId: 'gpt-4o' })
expect(provider.getConfig().contextWindowLimit).toBe(50_000) // preserved
})
})
describe('getConfig', () => {
@@ -262,6 +279,7 @@ describe('OpenAIModel', () => {
modelId: 'gpt-5.4',
maxTokens: 1024,
temperature: 0.7,
contextWindowLimit: 1_050_000,
})
})
@@ -277,6 +295,41 @@ describe('OpenAIModel', () => {
contextWindowLimit: 128_000,
})
})
it('auto-populates contextWindowLimit from model ID lookup', () => {
const provider = new OpenAIModel({ api: 'chat', modelId: 'gpt-4o', apiKey: 'sk-test' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'gpt-4o',
contextWindowLimit: 128_000,
})
})
it('auto-populates contextWindowLimit for default model ID', () => {
const provider = new OpenAIModel({ api: 'chat', apiKey: 'sk-test' })
expect(provider.getConfig()).toStrictEqual({
contextWindowLimit: 1_050_000,
})
})
it('does not override explicit contextWindowLimit', () => {
const provider = new OpenAIModel({
api: 'chat',
modelId: 'gpt-4o',
apiKey: 'sk-test',
contextWindowLimit: 50_000,
})
expect(provider.getConfig()).toStrictEqual({
modelId: 'gpt-4o',
contextWindowLimit: 50_000,
})
})
it('leaves contextWindowLimit undefined for unknown model IDs', () => {
const provider = new OpenAIModel({ api: 'chat', modelId: 'unknown-model', apiKey: 'sk-test' })
expect(provider.getConfig()).toStrictEqual({
modelId: 'unknown-model',
})
})
})
describe('managed params warning', () => {
+2 -2
View File
@@ -10,7 +10,7 @@
import OpenAI from 'openai'
import type { ResponseStreamEvent } from 'openai/resources/responses/responses'
import { Model } from '../model.js'
import { Model, resolveConfigMetadata } from '../model.js'
import type { StreamOptions } from '../model.js'
import type { Message } from '../../types/messages.js'
import type { ModelStreamEvent } from '../streaming.js'
@@ -156,7 +156,7 @@ export class OpenAIModel extends Model<OpenAIModelConfig> {
}
getConfig(): OpenAIModelConfig {
return this._config
return resolveConfigMetadata(this._config, this._config.modelId ?? MODEL_DEFAULTS.openai.modelId)
}
async *stream(messages: Message[], options?: StreamOptions): AsyncIterable<ModelStreamEvent> {