diff --git a/src/shared/provider-preset-catalog.ts b/src/shared/provider-preset-catalog.ts index a1704d0d..b64d22d4 100644 --- a/src/shared/provider-preset-catalog.ts +++ b/src/shared/provider-preset-catalog.ts @@ -21,6 +21,7 @@ export const PROVIDER_PRESET_IDS = [ 'deepseek', 'qwen', 'ollama-cloud', + 'novita', ] as const; export type ProviderPresetId = (typeof PROVIDER_PRESET_IDS)[number]; @@ -254,6 +255,20 @@ const RAW_PROVIDER_PRESET_DEFINITIONS: readonly ProviderPresetDefinition[] = [ badge: 'Cloud', icon: '/icons/ollama.svg', }, + { + id: 'novita', + name: 'Novita AI', + description: 'OpenAI-compatible API (Llama, Mistral, Qwen, and more)', + baseUrl: 'https://api.novita.ai/openai', + defaultProfileName: 'novita', + defaultModel: 'deepseek/deepseek-v3.2', + apiKeyPlaceholder: 'YOUR_NOVITA_API_KEY', + apiKeyHint: 'Get your API key at novita.ai', + category: 'alternative', + requiresApiKey: true, + badge: 'OpenAI-compatible', + icon: '/icons/novita.svg', + }, ]; function clonePresetDefinition(preset: ProviderPresetDefinition): ProviderPresetDefinition { diff --git a/tests/unit/api/provider-presets-novita.test.ts b/tests/unit/api/provider-presets-novita.test.ts new file mode 100644 index 00000000..976737b5 --- /dev/null +++ b/tests/unit/api/provider-presets-novita.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'bun:test'; +import { getPresetById, isValidPresetId } from '../../../src/api/services/provider-presets'; + +describe('provider-presets-novita', () => { + it('resolves novita preset id', () => { + const preset = getPresetById('novita'); + expect(preset?.id).toBe('novita'); + expect(preset?.baseUrl).toBe('https://api.novita.ai/openai'); + expect(preset?.defaultProfileName).toBe('novita'); + }); + + it('resolves novita preset with expected model IDs', () => { + const preset = getPresetById('novita'); + expect(preset?.defaultModel).toBe('deepseek/deepseek-v3.2'); + }); + + it('validates novita preset requires API key', () => { + const preset = getPresetById('novita'); + expect(preset?.requiresApiKey).toBe(true); + }); + + it('treats novita as a valid preset id', () => { + expect(isValidPresetId('novita')).toBe(true); + }); + + it('handles whitespace in novita preset id', () => { + const preset = getPresetById(' novita '); + expect(preset?.id).toBe('novita'); + }); + + it('handles uppercase novita preset id', () => { + const preset = getPresetById('NOVITA'); + expect(preset?.id).toBe('novita'); + }); +});