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
59 changes: 59 additions & 0 deletions src/renderer/settings/components/AddCustomModelButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<div class="inline-flex items-center">
<Button
variant="outline"
class="text-xs text-normal rounded-lg"
@click="showAddModelDialog = true"
>
<slot>
<Icon icon="lucide:plus" class="w-4 h-4 text-muted-foreground" />
{{ t('model.actions.add') }}
</slot>
</Button>
<ModelConfigDialog
v-model:open="showAddModelDialog"
:model-id="modelId"
:model-name="modelName"
:provider-id="providerId"
:mode="mode"
:is-custom-model="isCustomModel"
@saved="handleSaved"
/>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Button } from '@shadcn/components/ui/button'
import { Icon } from '@iconify/vue'
import { useI18n } from 'vue-i18n'
import ModelConfigDialog from '@/components/settings/ModelConfigDialog.vue'

const { t } = useI18n()
const showAddModelDialog = ref(false)

interface Props {
modelId?: string
modelName?: string
providerId?: string
mode?: 'create' | 'edit'
isCustomModel?: boolean
}

withDefaults(defineProps<Props>(), {
modelId: '',
modelName: '',
mode: 'create',
providerId: '',
isCustomModel: true
})

const emit = defineEmits<{
saved: []
}>()

const handleSaved = () => {
showAddModelDialog.value = false
emit('saved')
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@
:provider="provider"
:enabled-models="enabledModels"
:total-models-count="totalModelsCount"
@show-model-list-dialog="showModelListDialog = true"
:provider-models="providerModels"
:custom-models="customModels"
@custom-model-added="handleAddModelSaved"
@disable-all-models="handleDisableAllModels"
@model-enabled-change="handleModelEnabledChange"
@config-changed="handleConfigChanged"
Expand Down Expand Up @@ -323,14 +325,10 @@
</Dialog>
</div>
<ProviderDialogContainer
v-model:show-model-list-dialog="showModelListDialog"
v-model:show-delete-provider-dialog="showDeleteProviderDialog"
:provider="provider"
:provider-models="providerModels"
:custom-models="customModels"
:model-to-disable="null"
:check-result="false"
@model-enabled-change="handleModelEnabledChange"
@confirm-delete-provider="confirmDeleteProvider"
/>
</section>
Expand Down Expand Up @@ -389,7 +387,6 @@ const apiHost = ref(props.provider.baseUrl || '')
const apiKey = ref(props.provider.apiKey || '')
const showApiKey = ref(false)
const showCheckModelDialog = ref(false)
const showModelListDialog = ref(false)
const checkResult = ref<boolean>(false)
const isLoggingIn = ref(false)
const validationResult = ref<{ success: boolean; message: string } | null>(null)
Expand All @@ -413,7 +410,8 @@ const totalModelsCount = computed(() => {
const providerModels = modelStore.allProviderModels.find(
(provider) => provider.providerId === props.provider.id
)
return providerModels?.models.length || 0
const custom = modelStore.customModels.find((entry) => entry.providerId === props.provider.id)
return (providerModels?.models.length || 0) + (custom?.models.length || 0)
})

const providerModels = computed((): RENDERER_MODEL_META[] => {
Expand Down Expand Up @@ -692,6 +690,10 @@ const handleDisableAllModels = async () => {
}
}

const handleAddModelSaved = async () => {
await modelStore.refreshCustomModels(props.provider.id)
}

const handleModelEnabledChange = async (model: RENDERER_MODEL_META, enabled: boolean) => {
try {
await modelStore.updateModelStatus(props.provider.id, model.id, enabled)
Expand Down
41 changes: 27 additions & 14 deletions src/renderer/settings/components/BedrockProviderSettingsDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,10 @@
<ProviderModelManager
:provider="provider"
:enabled-models="enabledModels"
:total-models-count="providerModels.length"
@show-model-list-dialog="showModelListDialog = true"
:total-models-count="providerModels.length + customModels.length"
:provider-models="providerModels"
:custom-models="customModels"
@custom-model-added="handleAddModelSaved"
@disable-all-models="disableAllModelsConfirm"
@model-enabled-change="handleModelEnabledChange"
@config-changed="handleConfigChanged"
Expand All @@ -112,17 +114,13 @@
<!-- 对话框容器 -->
<ProviderDialogContainer
v-model:show-confirm-dialog="showConfirmDialog"
v-model:show-model-list-dialog="showModelListDialog"
v-model:show-check-model-dialog="showCheckModelDialog"
v-model:show-disable-all-confirm-dialog="showDisableAllConfirmDialog"
v-model:show-delete-provider-dialog="showDeleteProviderDialog"
:provider="provider"
:provider-models="providerModels"
:custom-models="[]"
:model-to-disable="modelToDisable"
:check-result="checkResult"
@confirm-disable-model="confirmDisable"
@model-enabled-change="handleModelEnabledChange"
@confirm-disable-all-models="confirmDisableAll"
@confirm-delete-provider="() => {}"
/>
Expand Down Expand Up @@ -153,11 +151,6 @@ const props = defineProps<{
provider: AWS_BEDROCK_PROVIDER
}>()

// const emit = defineEmits<{
// 'credential-change': [value: AwsBedrockCredential]
// 'validate-key': [value: AwsBedrockCredential]
// }>()

const { t } = useI18n()
const providerStore = useProviderStore()
const modelStore = useModelStore()
Expand All @@ -168,18 +161,33 @@ const region = ref(props.provider.credential?.region || '')
const showAccessKeyId = ref(false)
const showSecretAccessKey = ref(false)
const providerModels = ref<RENDERER_MODEL_META[]>([])
const customModels = computed(() => {
const providerCustomModels = modelStore.customModels.find(
(entry) => entry.providerId === props.provider.id
)
return providerCustomModels?.models || []
})
const checkResult = ref<boolean>(false)
const modelToDisable = ref<RENDERER_MODEL_META | null>(null)
const showConfirmDialog = ref(false)
const showCheckModelDialog = ref(false)
const showModelListDialog = ref(false)
const showDisableAllConfirmDialog = ref(false)
const showDeleteProviderDialog = ref(false)

const enabledModels = computed(() => {
const enabledModelsList = providerModels.value.filter((m) => m.enabled)
const enabledCustom = customModels.value.filter((m) => m.enabled)
const enabledBuiltIn = providerModels.value.filter((m) => m.enabled)
const uniqueModels = new Map<string, RENDERER_MODEL_META>()

const merged = [...enabledCustom, ...enabledBuiltIn]

return enabledModelsList
merged.forEach((model) => {
if (!uniqueModels.has(model.id)) {
uniqueModels.set(model.id, model)
}
})

return Array.from(uniqueModels.values())
})

const initData = async () => {
Expand Down Expand Up @@ -320,6 +328,11 @@ const handleConfigChanged = async () => {
// 模型配置变更后重新初始化数据
await initData()
}

const handleAddModelSaved = async () => {
await modelStore.refreshCustomModels(props.provider.id)
await initData()
}
</script>

<style scoped>
Expand Down
118 changes: 68 additions & 50 deletions src/renderer/settings/components/ModelProviderSettingsDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@
:provider="provider"
:enabled-models="enabledModels"
:total-models-count="providerModels.length + customModels.length"
@show-model-list-dialog="showModelListDialog = true"
:provider-models="providerModels"
:custom-models="customModels"
:is-model-list-loading="isModelListLoading"
@custom-model-added="handleAddModelSaved"
@disable-all-models="disableAllModelsConfirm"
@model-enabled-change="handleModelEnabledChange"
@config-changed="handleConfigChanged"
Expand All @@ -69,17 +72,13 @@
<!-- 对话框容器 -->
<ProviderDialogContainer
v-model:show-confirm-dialog="showConfirmDialog"
v-model:show-model-list-dialog="showModelListDialog"
v-model:show-check-model-dialog="showCheckModelDialog"
v-model:show-disable-all-confirm-dialog="showDisableAllConfirmDialog"
v-model:show-delete-provider-dialog="showDeleteProviderDialog"
:provider="provider"
:provider-models="providerModels"
:custom-models="customModels"
:model-to-disable="modelToDisable"
:check-result="checkResult"
@confirm-disable-model="confirmDisable"
@model-enabled-change="handleModelEnabledChange"
@confirm-disable-all-models="confirmDisableAll"
@confirm-delete-provider="confirmDeleteProvider"
/>
Expand Down Expand Up @@ -139,10 +138,11 @@ const geminiSafetyLevels = reactive<Record<string, number>>({})

const providerModels = ref<RENDERER_MODEL_META[]>([])
const customModels = ref<RENDERER_MODEL_META[]>([])
const isModelListLoading = ref(true)
const hasInitializedModelList = ref(false)

const modelToDisable = ref<RENDERER_MODEL_META | null>(null)
const showConfirmDialog = ref(false)
const showModelListDialog = ref(false)
const showDisableAllConfirmDialog = ref(false)
const showDeleteProviderDialog = ref(false)
const enabledModels = computed(() => {
Expand Down Expand Up @@ -196,59 +196,72 @@ const validateApiKey = async () => {

// Original initData implementation without debouncing
const _initData = async () => {
console.log('initData for provider:', props.provider.id)
const providerData = modelStore.allProviderModels.find((p) => p.providerId === props.provider.id)
if (providerData) {
providerModels.value = providerData.models
} else {
providerModels.value = [] // Reset if provider data not found
}
const customModelData = modelStore.customModels.find((p) => p.providerId === props.provider.id)
if (customModelData) {
customModels.value = customModelData.models
} else {
customModels.value = [] // Reset if custom data not found
if (!hasInitializedModelList.value) {
isModelListLoading.value = true
}

// Fetch Azure API Version if applicable
if (props.provider.id === 'azure-openai') {
try {
azureApiVersion.value = await providerStore.getAzureApiVersion()
console.log('Azure API Version fetched:', azureApiVersion.value)
} catch (error) {
console.error('Failed to fetch Azure API Version:', error)
azureApiVersion.value = '2024-02-01' // Default value on error
try {
console.log('initData for provider:', props.provider.id)
const providerData = modelStore.allProviderModels.find(
(p) => p.providerId === props.provider.id
)
if (providerData) {
providerModels.value = providerData.models
} else {
providerModels.value = [] // Reset if provider data not found
}
const customModelData = modelStore.customModels.find((p) => p.providerId === props.provider.id)
if (customModelData) {
customModels.value = customModelData.models
} else {
customModels.value = [] // Reset if custom data not found
}
}

// Fetch Gemini Safety Settings if applicable
if (props.provider.id === 'gemini') {
console.log('Fetching Gemini safety settings...')

// 先清空现有数据
Object.keys(geminiSafetyLevels).forEach((key) => {
delete geminiSafetyLevels[key]
})

for (const key in safetyCategories) {
const categoryKey = key as string
// Fetch Azure API Version if applicable
if (props.provider.id === 'azure-openai') {
try {
const savedValue = (await providerStore.getGeminiSafety(categoryKey)) as
| string
| 'HARM_BLOCK_THRESHOLD_UNSPECIFIED'
console.log(`Fetched Gemini safety for ${categoryKey}:`, savedValue)
geminiSafetyLevels[categoryKey] =
valueToLevelMap[savedValue as SafetySettingValue] ??
safetyCategories[categoryKey as SafetyCategoryKey].defaultLevel
console.log(`Set Gemini level for ${categoryKey}:`, geminiSafetyLevels[categoryKey])
azureApiVersion.value = await providerStore.getAzureApiVersion()
console.log('Azure API Version fetched:', azureApiVersion.value)
} catch (error) {
console.error(`Failed to fetch Gemini safety setting for ${categoryKey}:`, error)
geminiSafetyLevels[categoryKey] =
safetyCategories[categoryKey as SafetyCategoryKey].defaultLevel // Default on error
console.error('Failed to fetch Azure API Version:', error)
azureApiVersion.value = '2024-02-01' // Default value on error
}
}

console.log('All Gemini safety levels initialized:', JSON.stringify(geminiSafetyLevels))
// Fetch Gemini Safety Settings if applicable
if (props.provider.id === 'gemini') {
console.log('Fetching Gemini safety settings...')

// 先清空现有数据
Object.keys(geminiSafetyLevels).forEach((key) => {
delete geminiSafetyLevels[key]
})

for (const key in safetyCategories) {
const categoryKey = key as string
try {
const savedValue = (await providerStore.getGeminiSafety(categoryKey)) as
| string
| 'HARM_BLOCK_THRESHOLD_UNSPECIFIED'
console.log(`Fetched Gemini safety for ${categoryKey}:`, savedValue)
geminiSafetyLevels[categoryKey] =
valueToLevelMap[savedValue as SafetySettingValue] ??
safetyCategories[categoryKey as SafetyCategoryKey].defaultLevel
console.log(`Set Gemini level for ${categoryKey}:`, geminiSafetyLevels[categoryKey])
} catch (error) {
console.error(`Failed to fetch Gemini safety setting for ${categoryKey}:`, error)
geminiSafetyLevels[categoryKey] =
safetyCategories[categoryKey as SafetyCategoryKey].defaultLevel // Default on error
}
}

console.log('All Gemini safety levels initialized:', JSON.stringify(geminiSafetyLevels))
}
} finally {
if (!hasInitializedModelList.value) {
hasInitializedModelList.value = true
}
isModelListLoading.value = false
}
}

Expand Down Expand Up @@ -399,6 +412,11 @@ const openModelCheckDialog = () => {
modelCheckStore.openDialog(props.provider.id)
}

const handleAddModelSaved = async () => {
await modelStore.refreshCustomModels(props.provider.id)
await initDataImmediate()
}

// 使用 computed 确保响应性正确传递
const geminiSafetyLevelsForChild = computed(() => {
// 创建一个新的对象确保响应性
Expand Down
Loading