(messages, modelId, apiKey)
| 278 | const providerName = resolveProviderFromModelId(model.id).displayName; |
| 279 | |
| 280 | // Categorize models |
| 281 | let category = 'Other models'; |
| 282 | let categoryPriority = 5; // Default priority |
| 283 | |
| 284 | if (model.id.includes('gpt') || model.id.includes('claude') || model.id.includes('gemini')) { |
| 285 | category = 'Flagship models'; |
| 286 | categoryPriority = 1; |
| 287 | } else if (model.id.includes('llama') || model.id.includes('mistral')) { |
| 288 | category = 'Best roleplay models'; |
| 289 | categoryPriority = 2; |
| 290 | } else if (model.id.includes('code') || model.id.includes('deepseek')) { |
| 291 | category = 'Best coding models'; |
| 292 | categoryPriority = 3; |
| 293 | } else if (model.id.includes('o1')) { |
| 294 | category = 'Reasoning models'; |
| 295 | categoryPriority = 4; |
| 296 | } |
| 297 | |
| 298 | // Apply custom display name if one exists |
| 299 | const defaultName = typeof model.name === 'string' && model.name.trim() |
| 300 | ? model.name.trim() |
| 301 | : model.id; |
| 302 | const displayName = String( |
| 303 | this.getDisplayName(model.id, defaultName, providerName) || defaultName |
| 304 | ).trim(); |
| 305 | |
| 306 | return { |
| 307 | id: model.id, |
| 308 | name: displayName, |
| 309 | category: category, |
| 310 | categoryPriority: categoryPriority, |
| 311 | provider: providerName, |
| 312 | context_length: model.context_length, |
| 313 | pricing: model.pricing, |
| 314 | top_provider: model.top_provider |
| 315 | }; |
| 316 | }).filter(Boolean); |
| 317 | |
| 318 | // Sort by category priority first, then by pricing within each category |
| 319 | return formattedModels.sort((a, b) => { |
| 320 | // First sort by category priority |
| 321 | if (a.categoryPriority !== b.categoryPriority) { |
| 322 | return a.categoryPriority - b.categoryPriority; |
| 323 | } |
| 324 | // Within same category, sort by price |
| 325 | const priceA = a.pricing?.prompt || 0; |
| 326 | const priceB = b.pricing?.prompt || 0; |
| 327 | return priceA - priceB; |
| 328 | }); |
| 329 | } |
| 330 | |
| 331 | isReasoningDetailImage(detail) { |
| 332 | if (!detail || !detail.data) { |
| 333 | return false; |
| 334 | } |
| 335 | |
| 336 | const mimeType = detail.mime_type || detail.content_type; |
| 337 | if (mimeType && mimeType.startsWith('image/')) { |
no test coverage detected