fix(ai): use provider name instead of config name for auth profile keys

This commit is contained in:
digua committed 2026-05-19 23:50:50 +08:00
1 parent 0bd5bc9f38
commit 415dcefc7d
2 files changed
+55 -34

No files matched your search

@@ -13,6 +13,31 @@ import type { Migration, MigrationContext } from './types'
import { isEncrypted, decryptApiKey } from './crypto-legacy'
import { writeAuthProfile } from '../auth-profiles'
/**
* Derive a human-readable profile name from config fields.
* Official providers → provider id (e.g. "deepseek")
* openai-compatible → hostname from baseUrl (e.g. "api.example.com") or config name
*/
function deriveProfileName(provider: string, config: Record<string, unknown>): string {
if (provider !== 'openai-compatible') {
return provider.toLowerCase().replace(/\s+/g, '-')
}
const baseUrl = config.baseUrl as string
if (baseUrl) {
try {
return new URL(baseUrl).hostname.toLowerCase()
} catch {
// invalid URL, fall through
}
}
const name = config.name as string
if (name) return name.toLowerCase().replace(/\s+/g, '-')
return 'custom'
}
export const m004EncryptedKeysToAuthProfiles: Migration = {
version: 4,
name: 'encrypted-keys-to-auth-profiles',
@@ -31,34 +56,40 @@ export const m004EncryptedKeysToAuthProfiles: Migration = {
const configs = (data.configs as Array<Record<string, unknown>>) || []
let migrated = false
const usedProfileNames = new Set<string>()
for (const config of configs) {
const apiKey = config.apiKey as string
if (!apiKey) continue
if (isEncrypted(apiKey)) {
const plainKey = decryptApiKey(apiKey)
if (plainKey) {
const provider = (config.provider as string) || 'unknown'
const name = (config.name as string) || provider
const profileName = name.toLowerCase().replace(/\s+/g, '-')
const provider = (config.provider as string) || 'unknown'
let plainKey: string | null = null
writeAuthProfile(profileName, { type: 'api_key', provider, key: plainKey })
config.apiKey = ''
migrated = true
ctx.logger.info('Migration', `Migrated API key for "${name}" to auth-profiles.json`)
} else {
if (isEncrypted(apiKey)) {
plainKey = decryptApiKey(apiKey)
if (!plainKey) {
ctx.logger.warn('Migration', `Failed to decrypt API key for "${config.name}", skipping`)
continue
}
} else if (apiKey.length > 0) {
const provider = (config.provider as string) || 'unknown'
const name = (config.name as string) || provider
const profileName = name.toLowerCase().replace(/\s+/g, '-')
plainKey = apiKey
}
writeAuthProfile(profileName, { type: 'api_key', provider, key: apiKey })
if (plainKey) {
const baseName = deriveProfileName(provider, config)
let profileName = baseName
if (usedProfileNames.has(profileName)) {
let i = 2
while (usedProfileNames.has(`${profileName}-${i}`)) i++
profileName = `${profileName}-${i}`
}
usedProfileNames.add(profileName)
writeAuthProfile(profileName, { type: 'api_key', provider, key: plainKey })
config.apiKey = ''
migrated = true
ctx.logger.info('Migration', `Migrated plaintext API key for "${name}" to auth-profiles.json`)
ctx.logger.info('Migration', `Migrated API key → profile "${profileName}"`)
}
}
@@ -597,32 +597,22 @@ export function useAIConfigForm(props: {
// ============ 保存 ============
function generateName(): string {
let providerName: string
if (isCompatMode.value && formData.value.baseUrl) {
try {
const url = new URL(formData.value.baseUrl)
providerName = url.hostname
return url.hostname
} catch {
providerName = t('settings.aiConfig.modal.customService')
return t('settings.aiConfig.modal.customService')
}
} else {
const def = currentProviderDef.value
providerName = def
? getLocalizedProviderName(def.id) || def.name
: (() => {
const legacy = props.providers.value.find((p) => p.id === formData.value.provider)
if (legacy) return legacy.name
return formData.value.baseUrl || t('settings.aiConfig.modal.customService')
})()
}
const modelId = formData.value.model.trim()
if (!modelId) return providerName
const def = currentProviderDef.value
if (def) return getLocalizedProviderName(def.id) || def.name
const modelDef = llmStore.getModelById(formData.value.provider, modelId)
const modelName = modelDef?.name || modelId
return `${providerName} - ${modelName}`
const legacy = props.providers.value.find((p) => p.id === formData.value.provider)
if (legacy) return legacy.name
return formData.value.baseUrl || t('settings.aiConfig.modal.customService')
}
async function doSave() {