auto-save 2026-05-27 17:24 (~4)
This commit is contained in:
@@ -103,6 +103,49 @@ const isModelSupported = (model, provider) => {
|
||||
return model.provider.includes(provider)
|
||||
}
|
||||
|
||||
const normalizeRuntimeSizeOptions = (items = []) => {
|
||||
if (!Array.isArray(items)) return []
|
||||
return items
|
||||
.map(item => {
|
||||
const key = item?.value || item?.key || item?.id
|
||||
if (!key) return null
|
||||
return {
|
||||
label: item.label || key,
|
||||
key
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
const normalizeRuntimeImageModel = (item) => {
|
||||
const key = item?.id || item?.model
|
||||
if (!key) return null
|
||||
const sizeOptions = normalizeRuntimeSizeOptions(item.size_options)
|
||||
return {
|
||||
label: item.label || item.model || key,
|
||||
key,
|
||||
provider: ['chatfire'],
|
||||
sizes: sizeOptions.map(option => option.key),
|
||||
sizeOptions,
|
||||
qualities: [{ label: '标准', key: 'standard' }],
|
||||
defaultParams: {
|
||||
size: item.default_size || sizeOptions[0]?.key || 'auto',
|
||||
quality: 'standard',
|
||||
style: item.provider === 'ark_seedream' ? 'commercial' : 'vivid'
|
||||
},
|
||||
available: item.available !== false,
|
||||
providerName: item.provider,
|
||||
isRuntime: true
|
||||
}
|
||||
}
|
||||
|
||||
const mergeModels = (builtInModels, runtimeModels) => {
|
||||
const byKey = new Map()
|
||||
builtInModels.forEach(model => byKey.set(model.key, { ...model, isCustom: false }))
|
||||
runtimeModels.forEach(model => byKey.set(model.key, { ...byKey.get(model.key), ...model, isCustom: false }))
|
||||
return Array.from(byKey.values())
|
||||
}
|
||||
|
||||
export const useModelStore = defineStore('model', () => {
|
||||
// ============ Provider 状态 | Provider State ============
|
||||
|
||||
@@ -162,6 +205,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
const customChatModelsByProvider = ref(getStoredJson(STORAGE_KEYS.CUSTOM_CHAT_MODELS_BY_PROVIDER, {}))
|
||||
const customImageModelsByProvider = ref(getStoredJson(STORAGE_KEYS.CUSTOM_IMAGE_MODELS_BY_PROVIDER, {}))
|
||||
const customVideoModelsByProvider = ref(getStoredJson(STORAGE_KEYS.CUSTOM_VIDEO_MODELS_BY_PROVIDER, {}))
|
||||
const runtimeImageModels = ref([])
|
||||
|
||||
// 选中的模型
|
||||
const selectedChatModel = ref(getStored(STORAGE_KEYS.SELECTED_CHAT_MODEL, DEFAULT_CHAT_MODEL))
|
||||
@@ -211,7 +255,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
])
|
||||
|
||||
const allImageModels = computed(() =>
|
||||
IMAGE_MODELS.map(m => ({ ...m, isCustom: false }))
|
||||
mergeModels(IMAGE_MODELS, runtimeImageModels.value)
|
||||
)
|
||||
|
||||
const allVideoModels = computed(() =>
|
||||
@@ -226,7 +270,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
)
|
||||
|
||||
const availableImageModels = computed(() =>
|
||||
allImageModels.value.filter(m => isModelSupported(m, currentProvider.value))
|
||||
allImageModels.value.filter(m => isModelSupported(m, currentProvider.value) && m.available !== false)
|
||||
)
|
||||
|
||||
const availableVideoModels = computed(() =>
|
||||
@@ -239,7 +283,8 @@ export const useModelStore = defineStore('model', () => {
|
||||
const allImageModelOptions = computed(() =>
|
||||
allImageModels.value.map(m => ({
|
||||
label: m.label,
|
||||
key: m.key
|
||||
key: m.key,
|
||||
disabled: m.available === false
|
||||
}))
|
||||
)
|
||||
|
||||
@@ -263,7 +308,8 @@ export const useModelStore = defineStore('model', () => {
|
||||
const imageModelOptions = computed(() =>
|
||||
availableImageModels.value.map(m => ({
|
||||
label: m.label,
|
||||
key: m.key
|
||||
key: m.key,
|
||||
disabled: m.available === false
|
||||
}))
|
||||
)
|
||||
|
||||
@@ -343,6 +389,23 @@ export const useModelStore = defineStore('model', () => {
|
||||
const getImageModel = (key) => allImageModels.value.find(m => m.key === key)
|
||||
const getVideoModel = (key) => allVideoModels.value.find(m => m.key === key)
|
||||
|
||||
const loadRuntimeModels = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/health', { credentials: 'include' })
|
||||
if (!response.ok) return false
|
||||
const data = await response.json()
|
||||
const imageOptions = data?.models?.image_options || []
|
||||
runtimeImageModels.value = imageOptions
|
||||
.filter(item => item?.id && item.id !== 'auto')
|
||||
.map(normalizeRuntimeImageModel)
|
||||
.filter(Boolean)
|
||||
return true
|
||||
} catch (err) {
|
||||
console.warn('[model store] runtime model load failed', err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ============ Methods: Get API Endpoints ============
|
||||
|
||||
// 获取图片端点
|
||||
@@ -383,7 +446,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
provider: [provider]
|
||||
}))
|
||||
]
|
||||
const image = IMAGE_MODELS
|
||||
const image = allImageModels.value
|
||||
.filter(m => isModelSupported(m, provider))
|
||||
.map(m => ({ ...m, isCustom: false }))
|
||||
const video = VIDEO_MODELS
|
||||
@@ -500,6 +563,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
allChatModels,
|
||||
allImageModels,
|
||||
allVideoModels,
|
||||
runtimeImageModels,
|
||||
|
||||
// Available models filtered by provider
|
||||
availableChatModels,
|
||||
@@ -551,6 +615,7 @@ export const useModelStore = defineStore('model', () => {
|
||||
getChatModel,
|
||||
getImageModel,
|
||||
getVideoModel,
|
||||
loadRuntimeModels,
|
||||
|
||||
// Get API endpoints
|
||||
getImageEndpoint,
|
||||
|
||||
@@ -319,6 +319,7 @@ const isApiConfigured = computed(() => !!modelStore.currentApiKey)
|
||||
// Initialize models on page load | 页面加载时初始化模型
|
||||
onMounted(() => {
|
||||
loadAllModels()
|
||||
modelStore.loadRuntimeModels()
|
||||
})
|
||||
|
||||
// Chat templates | 问答模板
|
||||
|
||||
Reference in New Issue
Block a user