fix: HuggingFace provider should be non-deletable (#5856)
* fix: HuggingFace provider should be non-deletable * refactor: rename const folder * test: correct test case
This commit is contained in:
parent
8e9cd2566b
commit
d347058d6b
@ -12,12 +12,12 @@ import {
|
|||||||
|
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { CardItem } from '../Card'
|
import { CardItem } from '../Card'
|
||||||
import { models } from 'token.js'
|
|
||||||
import { EngineManager } from '@janhq/core'
|
import { EngineManager } from '@janhq/core'
|
||||||
import { useModelProvider } from '@/hooks/useModelProvider'
|
import { useModelProvider } from '@/hooks/useModelProvider'
|
||||||
import { useRouter } from '@tanstack/react-router'
|
import { useRouter } from '@tanstack/react-router'
|
||||||
import { route } from '@/constants/routes'
|
import { route } from '@/constants/routes'
|
||||||
import { useTranslation } from '@/i18n/react-i18next-compat'
|
import { useTranslation } from '@/i18n/react-i18next-compat'
|
||||||
|
import { predefinedProviders } from '@/consts/providers'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
provider?: ProviderObject
|
provider?: ProviderObject
|
||||||
@ -28,7 +28,7 @@ const DeleteProvider = ({ provider }: Props) => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
if (
|
if (
|
||||||
!provider ||
|
!provider ||
|
||||||
Object.keys(models).includes(provider.provider) ||
|
predefinedProviders.some((e) => e.provider === provider.provider) ||
|
||||||
EngineManager.instance().get(provider.provider)
|
EngineManager.instance().get(provider.provider)
|
||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import { IconFolderPlus, IconLoader, IconRefresh } from '@tabler/icons-react'
|
|||||||
import { getProviders } from '@/services/providers'
|
import { getProviders } from '@/services/providers'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { predefinedProviders } from '@/mock/data'
|
import { predefinedProviders } from '@/consts/providers'
|
||||||
import { useModelLoad } from '@/hooks/useModelLoad'
|
import { useModelLoad } from '@/hooks/useModelLoad'
|
||||||
|
|
||||||
// as route.threadsDetail
|
// as route.threadsDetail
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { Switch } from '@/components/ui/switch'
|
import { Switch } from '@/components/ui/switch'
|
||||||
import { useCallback, useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import { openAIProviderSettings } from '@/mock/data'
|
import { openAIProviderSettings } from '@/consts/providers'
|
||||||
import cloneDeep from 'lodash/cloneDeep'
|
import cloneDeep from 'lodash/cloneDeep'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
|
|
||||||
@ -38,7 +38,9 @@ function ModelProviders() {
|
|||||||
const [name, setName] = useState('')
|
const [name, setName] = useState('')
|
||||||
|
|
||||||
const createProvider = useCallback(() => {
|
const createProvider = useCallback(() => {
|
||||||
if (providers.some((e) => e.provider.toLowerCase() === name.toLowerCase())) {
|
if (
|
||||||
|
providers.some((e) => e.provider.toLowerCase() === name.toLowerCase())
|
||||||
|
) {
|
||||||
toast.error(t('providerAlreadyExists', { name }))
|
toast.error(t('providerAlreadyExists', { name }))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
import { getProviders, fetchModelsFromProvider, updateSettings } from '../providers'
|
import {
|
||||||
|
getProviders,
|
||||||
|
fetchModelsFromProvider,
|
||||||
|
updateSettings,
|
||||||
|
} from '../providers'
|
||||||
import { models as providerModels } from 'token.js'
|
import { models as providerModels } from 'token.js'
|
||||||
import { predefinedProviders } from '@/mock/data'
|
import { predefinedProviders } from '@/mock/data'
|
||||||
import { EngineManager } from '@janhq/core'
|
import { EngineManager } from '@janhq/core'
|
||||||
@ -12,9 +16,9 @@ vi.mock('token.js', () => ({
|
|||||||
models: {
|
models: {
|
||||||
openai: {
|
openai: {
|
||||||
models: ['gpt-3.5-turbo', 'gpt-4'],
|
models: ['gpt-3.5-turbo', 'gpt-4'],
|
||||||
supportsToolCalls: ['gpt-3.5-turbo', 'gpt-4']
|
supportsToolCalls: ['gpt-3.5-turbo', 'gpt-4'],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/mock/data', () => ({
|
vi.mock('@/mock/data', () => ({
|
||||||
@ -27,73 +31,80 @@ vi.mock('@/mock/data', () => ({
|
|||||||
settings: [],
|
settings: [],
|
||||||
models: [
|
models: [
|
||||||
{ id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo' },
|
{ id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo' },
|
||||||
{ id: 'gpt-4', name: 'GPT-4' }
|
{ id: 'gpt-4', name: 'GPT-4' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@janhq/core', () => ({
|
vi.mock('@janhq/core', () => ({
|
||||||
EngineManager: {
|
EngineManager: {
|
||||||
instance: vi.fn(() => ({
|
instance: vi.fn(() => ({
|
||||||
engines: new Map([
|
engines: new Map([
|
||||||
['llamacpp', {
|
[
|
||||||
inferenceUrl: 'http://localhost:1337/chat/completions',
|
'llamacpp',
|
||||||
getSettings: vi.fn(() => Promise.resolve([
|
{
|
||||||
{
|
inferenceUrl: 'http://localhost:1337/chat/completions',
|
||||||
key: 'apiKey',
|
getSettings: vi.fn(() =>
|
||||||
title: 'API Key',
|
Promise.resolve([
|
||||||
description: 'Your API key',
|
{
|
||||||
controllerType: 'input',
|
key: 'apiKey',
|
||||||
controllerProps: { value: '' }
|
title: 'API Key',
|
||||||
}
|
description: 'Your API key',
|
||||||
]))
|
controllerType: 'input',
|
||||||
}]
|
controllerProps: { value: '' },
|
||||||
])
|
},
|
||||||
}))
|
])
|
||||||
}
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
})),
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('../models', () => ({
|
vi.mock('../models', () => ({
|
||||||
fetchModels: vi.fn(() => Promise.resolve([
|
fetchModels: vi.fn(() =>
|
||||||
{ id: 'llama-2-7b', name: 'Llama 2 7B', description: 'Llama model' }
|
Promise.resolve([
|
||||||
]))
|
{ id: 'llama-2-7b', name: 'Llama 2 7B', description: 'Llama model' },
|
||||||
|
])
|
||||||
|
),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/lib/extension', () => ({
|
vi.mock('@/lib/extension', () => ({
|
||||||
ExtensionManager: {
|
ExtensionManager: {
|
||||||
getInstance: vi.fn(() => ({
|
getInstance: vi.fn(() => ({
|
||||||
getEngine: vi.fn()
|
getEngine: vi.fn(),
|
||||||
}))
|
})),
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@tauri-apps/plugin-http', () => ({
|
vi.mock('@tauri-apps/plugin-http', () => ({
|
||||||
fetch: vi.fn()
|
fetch: vi.fn(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/types/models', () => ({
|
vi.mock('@/types/models', () => ({
|
||||||
ModelCapabilities: {
|
ModelCapabilities: {
|
||||||
COMPLETION: 'completion',
|
COMPLETION: 'completion',
|
||||||
TOOLS: 'tools'
|
TOOLS: 'tools',
|
||||||
},
|
},
|
||||||
DefaultToolUseSupportedModels: {
|
DefaultToolUseSupportedModels: {
|
||||||
'gpt-4': 'gpt-4',
|
'gpt-4': 'gpt-4',
|
||||||
'gpt-3.5-turbo': 'gpt-3.5-turbo'
|
'gpt-3.5-turbo': 'gpt-3.5-turbo',
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/lib/predefined', () => ({
|
vi.mock('@/lib/predefined', () => ({
|
||||||
modelSettings: {
|
modelSettings: {
|
||||||
temperature: {
|
temperature: {
|
||||||
key: 'temperature',
|
key: 'temperature',
|
||||||
controller_props: { value: 0.7 }
|
controller_props: { value: 0.7 },
|
||||||
},
|
},
|
||||||
ctx_len: {
|
ctx_len: {
|
||||||
key: 'ctx_len',
|
key: 'ctx_len',
|
||||||
controller_props: { value: 2048 }
|
controller_props: { value: 2048 },
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
describe('providers service', () => {
|
describe('providers service', () => {
|
||||||
@ -105,14 +116,14 @@ describe('providers service', () => {
|
|||||||
it('should return builtin and runtime providers', async () => {
|
it('should return builtin and runtime providers', async () => {
|
||||||
const providers = await getProviders()
|
const providers = await getProviders()
|
||||||
|
|
||||||
expect(providers).toHaveLength(2) // 1 runtime + 1 builtin
|
expect(providers).toHaveLength(9) // 8 runtime + 1 builtin
|
||||||
expect(providers.some(p => p.provider === 'llamacpp')).toBe(true)
|
expect(providers.some((p) => p.provider === 'llamacpp')).toBe(true)
|
||||||
expect(providers.some(p => p.provider === 'openai')).toBe(true)
|
expect(providers.some((p) => p.provider === 'openai')).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should map builtin provider models correctly', async () => {
|
it('should map builtin provider models correctly', async () => {
|
||||||
const providers = await getProviders()
|
const providers = await getProviders()
|
||||||
const openaiProvider = providers.find(p => p.provider === 'openai')
|
const openaiProvider = providers.find((p) => p.provider === 'openai')
|
||||||
|
|
||||||
expect(openaiProvider).toBeDefined()
|
expect(openaiProvider).toBeDefined()
|
||||||
expect(openaiProvider?.models).toHaveLength(2)
|
expect(openaiProvider?.models).toHaveLength(2)
|
||||||
@ -122,7 +133,7 @@ describe('providers service', () => {
|
|||||||
|
|
||||||
it('should create runtime providers from engine manager', async () => {
|
it('should create runtime providers from engine manager', async () => {
|
||||||
const providers = await getProviders()
|
const providers = await getProviders()
|
||||||
const llamacppProvider = providers.find(p => p.provider === 'llamacpp')
|
const llamacppProvider = providers.find((p) => p.provider === 'llamacpp')
|
||||||
|
|
||||||
expect(llamacppProvider).toBeDefined()
|
expect(llamacppProvider).toBeDefined()
|
||||||
expect(llamacppProvider?.base_url).toBe('http://localhost:1337')
|
expect(llamacppProvider?.base_url).toBe('http://localhost:1337')
|
||||||
@ -136,44 +147,44 @@ describe('providers service', () => {
|
|||||||
const mockResponse = {
|
const mockResponse = {
|
||||||
ok: true,
|
ok: true,
|
||||||
json: vi.fn().mockResolvedValue({
|
json: vi.fn().mockResolvedValue({
|
||||||
data: [
|
data: [{ id: 'gpt-3.5-turbo' }, { id: 'gpt-4' }],
|
||||||
{ id: 'gpt-3.5-turbo' },
|
}),
|
||||||
{ id: 'gpt-4' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'openai',
|
provider: 'openai',
|
||||||
base_url: 'https://api.openai.com/v1',
|
base_url: 'https://api.openai.com/v1',
|
||||||
api_key: 'test-key'
|
api_key: 'test-key',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
const models = await fetchModelsFromProvider(provider)
|
const models = await fetchModelsFromProvider(provider)
|
||||||
|
|
||||||
expect(fetchTauri).toHaveBeenCalledWith('https://api.openai.com/v1/models', {
|
expect(fetchTauri).toHaveBeenCalledWith(
|
||||||
method: 'GET',
|
'https://api.openai.com/v1/models',
|
||||||
headers: {
|
{
|
||||||
'Content-Type': 'application/json',
|
method: 'GET',
|
||||||
'x-api-key': 'test-key',
|
headers: {
|
||||||
'Authorization': 'Bearer test-key'
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': 'test-key',
|
||||||
|
'Authorization': 'Bearer test-key',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
expect(models).toEqual(['gpt-3.5-turbo', 'gpt-4'])
|
expect(models).toEqual(['gpt-3.5-turbo', 'gpt-4'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fetch models successfully with direct array format', async () => {
|
it('should fetch models successfully with direct array format', async () => {
|
||||||
const mockResponse = {
|
const mockResponse = {
|
||||||
ok: true,
|
ok: true,
|
||||||
json: vi.fn().mockResolvedValue(['model1', 'model2'])
|
json: vi.fn().mockResolvedValue(['model1', 'model2']),
|
||||||
}
|
}
|
||||||
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom',
|
provider: 'custom',
|
||||||
base_url: 'https://api.custom.com',
|
base_url: 'https://api.custom.com',
|
||||||
api_key: ''
|
api_key: '',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
const models = await fetchModelsFromProvider(provider)
|
const models = await fetchModelsFromProvider(provider)
|
||||||
@ -185,17 +196,14 @@ describe('providers service', () => {
|
|||||||
const mockResponse = {
|
const mockResponse = {
|
||||||
ok: true,
|
ok: true,
|
||||||
json: vi.fn().mockResolvedValue({
|
json: vi.fn().mockResolvedValue({
|
||||||
models: [
|
models: [{ id: 'model1' }, 'model2'],
|
||||||
{ id: 'model1' },
|
}),
|
||||||
'model2'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom',
|
provider: 'custom',
|
||||||
base_url: 'https://api.custom.com'
|
base_url: 'https://api.custom.com',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
const models = await fetchModelsFromProvider(provider)
|
const models = await fetchModelsFromProvider(provider)
|
||||||
@ -205,26 +213,30 @@ describe('providers service', () => {
|
|||||||
|
|
||||||
it('should throw error when provider has no base_url', async () => {
|
it('should throw error when provider has no base_url', async () => {
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom'
|
provider: 'custom',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
await expect(fetchModelsFromProvider(provider)).rejects.toThrow('Provider must have base_url configured')
|
await expect(fetchModelsFromProvider(provider)).rejects.toThrow(
|
||||||
|
'Provider must have base_url configured'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should throw error when API response is not ok', async () => {
|
it('should throw error when API response is not ok', async () => {
|
||||||
const mockResponse = {
|
const mockResponse = {
|
||||||
ok: false,
|
ok: false,
|
||||||
status: 404,
|
status: 404,
|
||||||
statusText: 'Not Found'
|
statusText: 'Not Found',
|
||||||
}
|
}
|
||||||
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom',
|
provider: 'custom',
|
||||||
base_url: 'https://api.custom.com'
|
base_url: 'https://api.custom.com',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
await expect(fetchModelsFromProvider(provider)).rejects.toThrow('Cannot connect to custom at https://api.custom.com')
|
await expect(fetchModelsFromProvider(provider)).rejects.toThrow(
|
||||||
|
'Cannot connect to custom at https://api.custom.com'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle network errors gracefully', async () => {
|
it('should handle network errors gracefully', async () => {
|
||||||
@ -232,16 +244,18 @@ describe('providers service', () => {
|
|||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom',
|
provider: 'custom',
|
||||||
base_url: 'https://api.custom.com'
|
base_url: 'https://api.custom.com',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
await expect(fetchModelsFromProvider(provider)).rejects.toThrow('Cannot connect to custom at https://api.custom.com')
|
await expect(fetchModelsFromProvider(provider)).rejects.toThrow(
|
||||||
|
'Cannot connect to custom at https://api.custom.com'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return empty array for unexpected response format', async () => {
|
it('should return empty array for unexpected response format', async () => {
|
||||||
const mockResponse = {
|
const mockResponse = {
|
||||||
ok: true,
|
ok: true,
|
||||||
json: vi.fn().mockResolvedValue({ unexpected: 'format' })
|
json: vi.fn().mockResolvedValue({ unexpected: 'format' }),
|
||||||
}
|
}
|
||||||
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
vi.mocked(fetchTauri).mockResolvedValue(mockResponse as any)
|
||||||
|
|
||||||
@ -249,14 +263,17 @@ describe('providers service', () => {
|
|||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
provider: 'custom',
|
provider: 'custom',
|
||||||
base_url: 'https://api.custom.com'
|
base_url: 'https://api.custom.com',
|
||||||
} as ModelProvider
|
} as ModelProvider
|
||||||
|
|
||||||
const models = await fetchModelsFromProvider(provider)
|
const models = await fetchModelsFromProvider(provider)
|
||||||
|
|
||||||
expect(models).toEqual([])
|
expect(models).toEqual([])
|
||||||
expect(consoleSpy).toHaveBeenCalledWith('Unexpected response format from provider API:', { unexpected: 'format' })
|
expect(consoleSpy).toHaveBeenCalledWith(
|
||||||
|
'Unexpected response format from provider API:',
|
||||||
|
{ unexpected: 'format' }
|
||||||
|
)
|
||||||
|
|
||||||
consoleSpy.mockRestore()
|
consoleSpy.mockRestore()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -264,12 +281,14 @@ describe('providers service', () => {
|
|||||||
describe('updateSettings', () => {
|
describe('updateSettings', () => {
|
||||||
it('should update provider settings successfully', async () => {
|
it('should update provider settings successfully', async () => {
|
||||||
const mockEngine = {
|
const mockEngine = {
|
||||||
updateSettings: vi.fn().mockResolvedValue(undefined)
|
updateSettings: vi.fn().mockResolvedValue(undefined),
|
||||||
}
|
}
|
||||||
const mockExtensionManager = {
|
const mockExtensionManager = {
|
||||||
getEngine: vi.fn().mockReturnValue(mockEngine)
|
getEngine: vi.fn().mockReturnValue(mockEngine),
|
||||||
}
|
}
|
||||||
vi.mocked(ExtensionManager.getInstance).mockReturnValue(mockExtensionManager)
|
vi.mocked(ExtensionManager.getInstance).mockReturnValue(
|
||||||
|
mockExtensionManager
|
||||||
|
)
|
||||||
|
|
||||||
const settings = [
|
const settings = [
|
||||||
{
|
{
|
||||||
@ -277,8 +296,8 @@ describe('providers service', () => {
|
|||||||
title: 'API Key',
|
title: 'API Key',
|
||||||
description: 'Your API key',
|
description: 'Your API key',
|
||||||
controller_type: 'input',
|
controller_type: 'input',
|
||||||
controller_props: { value: 'test-key' }
|
controller_props: { value: 'test-key' },
|
||||||
}
|
},
|
||||||
] as ProviderSetting[]
|
] as ProviderSetting[]
|
||||||
|
|
||||||
await updateSettings('openai', settings)
|
await updateSettings('openai', settings)
|
||||||
@ -292,16 +311,18 @@ describe('providers service', () => {
|
|||||||
controller_type: 'input',
|
controller_type: 'input',
|
||||||
controller_props: { value: 'test-key' },
|
controller_props: { value: 'test-key' },
|
||||||
controllerType: 'input',
|
controllerType: 'input',
|
||||||
controllerProps: { value: 'test-key' }
|
controllerProps: { value: 'test-key' },
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle missing engine gracefully', async () => {
|
it('should handle missing engine gracefully', async () => {
|
||||||
const mockExtensionManager = {
|
const mockExtensionManager = {
|
||||||
getEngine: vi.fn().mockReturnValue(null)
|
getEngine: vi.fn().mockReturnValue(null),
|
||||||
}
|
}
|
||||||
vi.mocked(ExtensionManager.getInstance).mockReturnValue(mockExtensionManager)
|
vi.mocked(ExtensionManager.getInstance).mockReturnValue(
|
||||||
|
mockExtensionManager
|
||||||
|
)
|
||||||
|
|
||||||
const settings = [] as ProviderSetting[]
|
const settings = [] as ProviderSetting[]
|
||||||
|
|
||||||
@ -312,12 +333,14 @@ describe('providers service', () => {
|
|||||||
|
|
||||||
it('should handle settings with undefined values', async () => {
|
it('should handle settings with undefined values', async () => {
|
||||||
const mockEngine = {
|
const mockEngine = {
|
||||||
updateSettings: vi.fn().mockResolvedValue(undefined)
|
updateSettings: vi.fn().mockResolvedValue(undefined),
|
||||||
}
|
}
|
||||||
const mockExtensionManager = {
|
const mockExtensionManager = {
|
||||||
getEngine: vi.fn().mockReturnValue(mockEngine)
|
getEngine: vi.fn().mockReturnValue(mockEngine),
|
||||||
}
|
}
|
||||||
vi.mocked(ExtensionManager.getInstance).mockReturnValue(mockExtensionManager)
|
vi.mocked(ExtensionManager.getInstance).mockReturnValue(
|
||||||
|
mockExtensionManager
|
||||||
|
)
|
||||||
|
|
||||||
const settings = [
|
const settings = [
|
||||||
{
|
{
|
||||||
@ -325,8 +348,8 @@ describe('providers service', () => {
|
|||||||
title: 'API Key',
|
title: 'API Key',
|
||||||
description: 'Your API key',
|
description: 'Your API key',
|
||||||
controller_type: 'input',
|
controller_type: 'input',
|
||||||
controller_props: { value: undefined }
|
controller_props: { value: undefined },
|
||||||
}
|
},
|
||||||
] as ProviderSetting[]
|
] as ProviderSetting[]
|
||||||
|
|
||||||
await updateSettings('openai', settings)
|
await updateSettings('openai', settings)
|
||||||
@ -339,9 +362,9 @@ describe('providers service', () => {
|
|||||||
controller_type: 'input',
|
controller_type: 'input',
|
||||||
controller_props: { value: undefined },
|
controller_props: { value: undefined },
|
||||||
controllerType: 'input',
|
controllerType: 'input',
|
||||||
controllerProps: { value: '' }
|
controllerProps: { value: '' },
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { models as providerModels } from 'token.js'
|
import { models as providerModels } from 'token.js'
|
||||||
import { predefinedProviders } from '@/mock/data'
|
import { predefinedProviders } from '@/consts/providers'
|
||||||
import { EngineManager, SettingComponentProps } from '@janhq/core'
|
import { EngineManager, SettingComponentProps } from '@janhq/core'
|
||||||
import {
|
import {
|
||||||
DefaultToolUseSupportedModels,
|
DefaultToolUseSupportedModels,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user