diff --git a/src/core/ai/dims.ts b/src/core/ai/dims.ts index b88a4e175..ab8b7ab95 100644 --- a/src/core/ai/dims.ts +++ b/src/core/ai/dims.ts @@ -244,9 +244,10 @@ export function dimsProviderOptions( // configured for a smaller width (e.g. 1536) hard-fail at first embed. // Azure/OpenAI-compat embeddings are symmetric — inputType ignored. // v0.36.0.0 (D13): same range validation as native-openai path. - if (modelId.startsWith('text-embedding-3')) { - if (isOpenAITextEmbedding3Model(modelId) && !isValidOpenAITextEmbedding3Dim(modelId, dims)) { - const max = maxOpenAITextEmbedding3Dim(modelId)!; + const bareModelId = modelId.includes('/') ? modelId.split('/').pop()! : modelId; + if (bareModelId.startsWith('text-embedding-3')) { + if (isOpenAITextEmbedding3Model(bareModelId) && !isValidOpenAITextEmbedding3Dim(bareModelId, dims)) { + const max = maxOpenAITextEmbedding3Dim(bareModelId)!; throw new AIConfigError( `OpenAI model "${modelId}" supports embedding_dimensions in 1..${max}, got ${dims}.`, `Set \`embedding_dimensions\` to a value between 1 and ${max} ` + diff --git a/test/ai/dims-openai.test.ts b/test/ai/dims-openai.test.ts index c1359fdfc..2d05a4dcb 100644 --- a/test/ai/dims-openai.test.ts +++ b/test/ai/dims-openai.test.ts @@ -134,3 +134,30 @@ describe('dimsProviderOptions — OpenAI on openai-compatible adapter (Azure cas expect(JSON.stringify(opts)).not.toContain('input_type'); }); }); + +describe('dimsProviderOptions — prefixed model IDs (OpenRouter / proxy providers)', () => { + test('openai/text-embedding-3-large at 1536d returns dimensions=1536', () => { + const opts = dimsProviderOptions('openai-compatible', 'openai/text-embedding-3-large', 1536); + expect(opts).toEqual({ openaiCompatible: { dimensions: 1536 } }); + }); + + test('openai/text-embedding-3-small at 768d returns dimensions=768', () => { + const opts = dimsProviderOptions('openai-compatible', 'openai/text-embedding-3-small', 768); + expect(opts).toEqual({ openaiCompatible: { dimensions: 768 } }); + }); + + test('openai/text-embedding-3-large at 5000d throws AIConfigError', () => { + expect(() => dimsProviderOptions('openai-compatible', 'openai/text-embedding-3-large', 5000)) + .toThrow(AIConfigError); + }); + + test('error message preserves full prefixed model ID for clarity', () => { + try { + dimsProviderOptions('openai-compatible', 'openai/text-embedding-3-large', 5000); + throw new Error('should have thrown'); + } catch (err) { + expect(err).toBeInstanceOf(AIConfigError); + expect((err as Error).message).toContain('openai/text-embedding-3-large'); + } + }); +});