Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/background/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
isUsingOpenRouterApiModel,
isUsingAimlApiModel,
isUsingDeepSeekApiModel,
isUsingNvidiaNimApiModel,
isUsingGoogleApiModel,
} from '../config/index.mjs'
import '../_locales/i18n'
Expand Down Expand Up @@ -398,6 +399,7 @@ function isUsingOpenAICompatibleApiSession(session) {
isUsingMoonshotApiModel(session) ||
isUsingChatGLMApiModel(session) ||
isUsingDeepSeekApiModel(session) ||
isUsingNvidiaNimApiModel(session) ||
isUsingOllamaApiModel(session) ||
isUsingOpenRouterApiModel(session) ||
isUsingAimlApiModel(session) ||
Expand Down
48 changes: 48 additions & 0 deletions src/config/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ export const deepSeekApiModelKeys = [
'deepseek_v4_flash',
'deepseek_v4_pro',
]
export const nvidiaNimApiModelKeys = [
'nvidiaNim_nemotron_3_super',
'nvidiaNim_nemotron_3_ultra',
'nvidiaNim_deepseek_v4_flash',
'nvidiaNim_deepseek_v4_pro',
'nvidiaNim_glm_5_2',
'nvidiaNim_inkling',
'nvidiaNim_minimax_m3',
]
export const openRouterApiModelKeys = [
'openRouter_auto',
'openRouter_free',
Expand Down Expand Up @@ -249,6 +258,10 @@ export const ModelGroups = {
value: githubThirdPartyApiModelKeys,
desc: 'Github Third Party Waylaidwanderer (API)',
},
nvidiaNimApiModelKeys: {
value: nvidiaNimApiModelKeys,
desc: 'NVIDIA NIM (API)',
},
deepSeekApiModelKeys: {
value: deepSeekApiModelKeys,
desc: 'DeepSeek (API)',
Expand Down Expand Up @@ -415,6 +428,35 @@ export const Models = {
desc: 'Kimi.Moonshot (128k)',
},

nvidiaNim_nemotron_3_super: {
value: 'nvidia/nemotron-3-super-120b-a12b',
desc: 'NVIDIA NIM (Nemotron-3-Super)',
},
nvidiaNim_nemotron_3_ultra: {
value: 'nvidia/nemotron-3-ultra-550b-a55b',
desc: 'NVIDIA NIM (Nemotron-3-Ultra)',
},
nvidiaNim_deepseek_v4_flash: {
value: 'deepseek-ai/deepseek-v4-flash',
desc: 'NVIDIA NIM (DeepSeek V4 Flash)',
},
nvidiaNim_deepseek_v4_pro: {
value: 'deepseek-ai/deepseek-v4-pro',
desc: 'NVIDIA NIM (DeepSeek V4 Pro)',
},
nvidiaNim_glm_5_2: {
value: 'z-ai/glm-5.2',
desc: 'NVIDIA NIM (GLM-5.2)',
},
nvidiaNim_inkling: {
value: 'thinkingmachines/inkling',
desc: 'NVIDIA NIM (Inkling)',
},
nvidiaNim_minimax_m3: {
value: 'minimaxai/minimax-m3',
desc: 'NVIDIA NIM (MiniMax M3)',
},

deepseek_chat: {
value: 'deepseek-chat',
desc: 'DeepSeek (Chat)',
Expand Down Expand Up @@ -692,6 +734,7 @@ export const defaultConfig = {
chatglmApiKey: '',
moonshotApiKey: '',
deepSeekApiKey: '',
nvidiaNimApiKey: '',

customApiKey: '',

Expand Down Expand Up @@ -752,6 +795,7 @@ export const defaultConfig = {
'googleGemini3_5Flash',
'openRouter_auto',
'openRouter_free',
'nvidiaNim_nemotron_3_super',
],
customApiModes: [
{
Expand Down Expand Up @@ -899,6 +943,10 @@ export function isUsingDeepSeekApiModel(configOrSession) {
return isInApiModeGroup(deepSeekApiModelKeys, configOrSession)
}

export function isUsingNvidiaNimApiModel(configOrSession) {
return isInApiModeGroup(nvidiaNimApiModelKeys, configOrSession)
}

export function isUsingOpenRouterApiModel(configOrSession) {
return isInApiModeGroup(openRouterApiModelKeys, configOrSession)
}
Expand Down
2 changes: 2 additions & 0 deletions src/config/openai-provider-mappings.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const LEGACY_API_KEY_FIELD_BY_PROVIDER_ID = {
openai: 'apiKey',
deepseek: 'deepSeekApiKey',
'nvidia-nim': 'nvidiaNimApiKey',
moonshot: 'moonshotApiKey',
openrouter: 'openRouterApiKey',
aiml: 'aimlApiKey',
Expand All @@ -22,6 +23,7 @@ export const OPENAI_COMPATIBLE_GROUP_TO_PROVIDER_ID = {
gptApiModelKeys: 'openai',
moonshotApiModelKeys: 'moonshot',
deepSeekApiModelKeys: 'deepseek',
nvidiaNimApiModelKeys: 'nvidia-nim',
openRouterApiModelKeys: 'openrouter',
aimlModelKeys: 'aiml',
aimlApiModelKeys: 'aiml',
Expand Down
2 changes: 2 additions & 0 deletions src/popup/sections/GeneralPart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ function isUsingSpecialCustomModel(configOrSession) {

function getProviderApiKeySetupUrl(providerId) {
switch (String(providerId || '').trim()) {
case 'nvidia-nim':
return 'https://build.nvidia.com/settings/keys'
case 'openai':
return 'https://platform.openai.com/account/api-keys'
case 'moonshot':
Expand Down
9 changes: 9 additions & 0 deletions src/services/apis/provider-registry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ const BUILTIN_PROVIDER_TEMPLATE = [
builtin: true,
enabled: true,
},
{
id: 'nvidia-nim',
name: 'NVIDIA NIM',
baseUrl: 'https://integrate.api.nvidia.com',
chatCompletionsPath: '/v1/chat/completions',
builtin: true,
enabled: true,
},
{
id: 'moonshot',
name: 'Kimi.Moonshot',
Expand Down Expand Up @@ -110,6 +118,7 @@ function resolveProviderIdFromLegacyModelName(modelName) {
return 'openai'
}
if (preset.startsWith('deepseek_') || preset === 'deepSeekApiModelKeys') return 'deepseek'
if (preset.startsWith('nvidiaNim_') || preset === 'nvidiaNimApiModelKeys') return 'nvidia-nim'
if (preset.startsWith('moonshot_') || preset === 'moonshotApiModelKeys') return 'moonshot'
if (preset.startsWith('openRouter_') || preset === 'openRouterApiModelKeys') return 'openrouter'
if (preset.startsWith('aiml_') || preset === 'aimlModelKeys' || preset === 'aimlApiModelKeys') {
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/config/config-predicates.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
gptApiModelKeys,
claudeApiModelKeys,
openRouterApiModelKeys,
nvidiaNimApiModelKeys,
aimlApiModelKeys,
isUsingAimlApiModel,
isUsingAzureOpenAiApiModel,
Expand All @@ -19,6 +20,7 @@ import {
isUsingCustomModel,
isUsingCustomNameOnlyModel,
isUsingDeepSeekApiModel,
isUsingNvidiaNimApiModel,
isUsingGeminiWebModel,
isUsingGithubThirdPartyApiModel,
isUsingMoonshotApiModel,
Expand Down Expand Up @@ -229,6 +231,13 @@ test('isUsingDeepSeekApiModel detects DeepSeek models', () => {
assert.equal(isUsingDeepSeekApiModel({ modelName: 'chatgptApi4oMini' }), false)
})

test('isUsingNvidiaNimApiModel accepts exported NVIDIA NIM API model keys', () => {
for (const modelName of nvidiaNimApiModelKeys) {
assert.equal(isUsingNvidiaNimApiModel({ modelName }), true)
}
assert.equal(isUsingNvidiaNimApiModel({ modelName: 'chatgptApi4oMini' }), false)
})

test('isUsingOpenRouterApiModel matches representative OpenRouter API keys', () => {
for (const modelName of representativeOpenRouterApiModelNames) {
assert.equal(isUsingOpenRouterApiModel({ modelName }), true)
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/services/apis/provider-registry.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ test('resolveProviderIdForSession resolves legacy Google preset keys', () => {
assert.equal(resolveProviderIdForSession({ modelName: 'googleApiModelKeys-custom' }), 'google')
})

test('resolveProviderIdForSession resolves legacy NVIDIA NIM preset keys', () => {
assert.equal(
resolveProviderIdForSession({ modelName: 'nvidiaNim_nemotron_3_super' }),
'nvidia-nim',
)
assert.equal(
resolveProviderIdForSession({ modelName: 'nvidiaNimApiModelKeys-custom' }),
'nvidia-nim',
)
})

test('resolveProviderIdForSession does not treat raw Gemini model IDs as legacy presets', () => {
assert.equal(resolveProviderIdForSession({ modelName: 'gemini-2.5-flash' }), null)
})
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/services/apis/thin-adapters.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ const adapters = [
expectedBaseUrl: 'https://api.deepseek.com',
expectedApiKey: 'ds-key',
},
{
name: 'nvidia-nim-api',
apiMode: {
groupName: 'nvidiaNimApiModelKeys',
itemName: 'nvidiaNim_nemotron_3_super',
},
providerId: 'nvidia-nim',
expectedBaseUrl: 'https://integrate.api.nvidia.com/v1',
expectedApiKey: 'nv-key',
},
{
name: 'moonshot-api',
apiMode: { groupName: 'moonshotApiModelKeys', itemName: 'moonshot_kimi_latest' },
Expand Down