feat(model): enhance parseModelId to handle identifiers without provider prefix and improve edge case handling

This commit is contained in:
suyao 2025-12-18 15:19:59 +08:00
parent 4173fcbb98
commit eb57f50cfe
No known key found for this signature in database
2 changed files with 58 additions and 11 deletions

View File

@ -118,13 +118,42 @@ describe('model', () => {
})
})
it('should handle model identifiers without provider prefix', () => {
expect(parseModelId('claude-3-sonnet')).toEqual({
providerId: undefined,
modelId: 'claude-3-sonnet'
})
expect(parseModelId('gpt-4')).toEqual({
providerId: undefined,
modelId: 'gpt-4'
})
})
it('should return undefined for invalid inputs', () => {
expect(parseModelId(undefined)).toBeUndefined()
expect(parseModelId('')).toBeUndefined()
expect(parseModelId('no-colon')).toBeUndefined()
expect(parseModelId(':missing-provider')).toBeUndefined()
expect(parseModelId('missing-model:')).toBeUndefined()
expect(parseModelId(':')).toBeUndefined()
expect(parseModelId(' ')).toBeUndefined()
})
it('should handle edge cases with colons', () => {
// Colon at start - treat as modelId without provider
expect(parseModelId(':missing-provider')).toEqual({
providerId: undefined,
modelId: ':missing-provider'
})
// Colon at end - treat everything before as modelId
expect(parseModelId('missing-model:')).toEqual({
providerId: undefined,
modelId: 'missing-model'
})
// Only colon - treat as modelId without provider
expect(parseModelId(':')).toEqual({
providerId: undefined,
modelId: ':'
})
})
it('should handle edge cases', () => {

View File

@ -87,7 +87,7 @@ export const apiModelAdapter = (model: ApiModel): AdaptedApiModel => {
* where modelId may contain additional colons (e.g., "openrouter:anthropic/claude-3.5-sonnet:free")
*
* @param modelIdentifier - The full model identifier string
* @returns Object with providerId and modelId, or undefined if invalid
* @returns Object with providerId and modelId. If no provider prefix found, providerId will be undefined
*
* @example
* parseModelId("openrouter:anthropic/claude-3.5-sonnet:free")
@ -98,20 +98,38 @@ export const apiModelAdapter = (model: ApiModel): AdaptedApiModel => {
* // => { providerId: "anthropic", modelId: "claude-3-sonnet" }
*
* @example
* parseModelId("invalid") // => undefined
* parseModelId("claude-3-sonnet")
* // => { providerId: undefined, modelId: "claude-3-sonnet" }
*
* @example
* parseModelId("") // => undefined
*/
export function parseModelId(modelIdentifier: string | undefined): { providerId: string; modelId: string } | undefined {
if (!modelIdentifier || typeof modelIdentifier !== 'string') {
export function parseModelId(
modelIdentifier: string | undefined
): { providerId: string | undefined; modelId: string } | undefined {
if (!modelIdentifier || typeof modelIdentifier !== 'string' || modelIdentifier.trim() === '') {
return undefined
}
const colonIndex = modelIdentifier.indexOf(':')
// Must contain at least one colon and have content on both sides
if (colonIndex <= 0 || colonIndex >= modelIdentifier.length - 1) {
return undefined
// No colon found or colon at the start - treat entire string as modelId
if (colonIndex <= 0) {
return {
providerId: undefined,
modelId: modelIdentifier
}
}
// Colon at the end - treat everything before as modelId
if (colonIndex >= modelIdentifier.length - 1) {
return {
providerId: undefined,
modelId: modelIdentifier.substring(0, colonIndex)
}
}
// Standard format: "provider:modelId"
return {
providerId: modelIdentifier.substring(0, colonIndex),
modelId: modelIdentifier.substring(colonIndex + 1)