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
39 changes: 34 additions & 5 deletions src/main/presenter/configPresenter/modelCapabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,41 @@ export class ModelCapabilities {
}

private getModel(providerId: string, modelId: string): ProviderModel | undefined {
const pid = this.resolveProviderId(providerId?.toLowerCase())
const mid = modelId?.toLowerCase()
if (!pid || !mid) return undefined
const p = this.index.get(pid)
if (!p) return undefined
return p.get(mid)
if (!mid) return undefined

const normalizedProviderId = providerId ? providerId.toLowerCase() : ''
const hasProviderId = normalizedProviderId.length > 0
const pid = hasProviderId ? this.resolveProviderId(normalizedProviderId) : undefined

if (pid) {
const providerModels = this.index.get(pid)
if (providerModels) {
const providerMatch = providerModels.get(mid)
if (providerMatch) {
return providerMatch
}
return undefined
}

return this.findModelAcrossProviders(mid)
}

if (!hasProviderId) {
return undefined
}

return this.findModelAcrossProviders(mid)
}

private findModelAcrossProviders(modelId: string): ProviderModel | undefined {
for (const models of this.index.values()) {
const fallbackModel = models.get(modelId)
if (fallbackModel) {
return fallbackModel
}
}
return undefined
}

resolveProviderId(providerId: string | undefined): string | undefined {
Expand Down
76 changes: 54 additions & 22 deletions src/main/presenter/configPresenter/modelConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ModelType } from '@shared/model'
import { IModelConfig, ModelConfig, ModelConfigSource } from '@shared/presenter'
import ElectronStore from 'electron-store'
import { providerDbLoader } from './providerDbLoader'
import { isImageInputSupported } from '@shared/types/model-db'
import { isImageInputSupported, ProviderModel } from '@shared/types/model-db'

const SPECIAL_CONCAT_CHAR = '-_-'

Expand Down Expand Up @@ -51,6 +51,25 @@ export class ModelConfigHelper {
return alias || providerId
}

private buildConfigFromProviderModel(model: ProviderModel): ModelConfig {
return {
maxTokens: model.limit?.output ?? 4096,
contextLength: model.limit?.context ?? 8192,
temperature: 0.6,
vision: isImageInputSupported(model),
functionCall: model.tool_call ?? false,
reasoning: Boolean(model.reasoning?.default ?? false),
type: ModelType.Chat,
thinkingBudget: model.reasoning?.budget?.default ?? undefined,
enableSearch: Boolean(model.search?.default ?? false),
forcedSearch: Boolean(model.search?.forced_search),
searchStrategy: model.search?.search_strategy === 'max' ? 'max' : 'turbo',
reasoningEffort: undefined,
verbosity: undefined,
maxCompletionTokens: undefined
}
}

private initializeMetaFromLegacyStore(): void {
const legacyEntries = this.modelConfigStore.store
const userKeys: Set<string> = new Set()
Expand Down Expand Up @@ -283,27 +302,40 @@ export class ModelConfigHelper {
let finalConfig: ModelConfig | null = null

// 严格匹配:仅当提供 providerId 时从 Provider DB 查找
if (normProviderId) {
const db = providerDbLoader.getDb()
const resolvedProviderId = this.resolveProviderId(normProviderId)
const provider = db?.providers?.[resolvedProviderId!]
const model = provider?.models.find((m) => m.id === normModelId)
if (model) {
finalConfig = {
maxTokens: model.limit?.output ?? 4096,
contextLength: model.limit?.context ?? 8192,
temperature: 0.6,
vision: isImageInputSupported(model),
functionCall: model.tool_call ?? false,
reasoning: Boolean(model.reasoning?.default ?? false),
type: ModelType.Chat,
thinkingBudget: model.reasoning?.budget?.default ?? undefined,
enableSearch: Boolean(model.search?.default ?? false),
forcedSearch: Boolean(model.search?.forced_search),
searchStrategy: model.search?.search_strategy === 'max' ? 'max' : 'turbo',
reasoningEffort: undefined,
verbosity: undefined,
maxCompletionTokens: undefined
const db = providerDbLoader.getDb()
const providers = db?.providers
const resolvedProviderId = normProviderId ? this.resolveProviderId(normProviderId) : undefined
const providerEntry = resolvedProviderId ? providers?.[resolvedProviderId] : undefined
const providerFound = Boolean(providerEntry)

if (normProviderId && providerEntry && Array.isArray(providerEntry.models)) {
for (let i = 0; i < providerEntry.models.length; i += 1) {
const candidate = providerEntry.models[i]
if (candidate && candidate.id === normModelId) {
finalConfig = this.buildConfigFromProviderModel(candidate)
break
}
}
}

if (!finalConfig && normProviderId && !providerFound && providers && normModelId) {
for (const key in providers) {
if (!Object.prototype.hasOwnProperty.call(providers, key)) continue
const candidateProvider = providers[key]
if (!candidateProvider || !Array.isArray(candidateProvider.models)) {
continue
}

for (let j = 0; j < candidateProvider.models.length; j += 1) {
const candidateModel = candidateProvider.models[j]
if (candidateModel && candidateModel.id === normModelId) {
finalConfig = this.buildConfigFromProviderModel(candidateModel)
break
}
}

if (finalConfig) {
break
}
}
}
Expand Down