import fs from 'fs/promises' import path from 'path' import os from 'os' import { Provider } from '../shared/types' /** * 清理供应商名称,确保文件名安全 */ export function sanitizeProviderName(name: string): string { return name.replace(/[<>:"/\\|?*]/g, '-').toLowerCase() } export function getClaudeCodeConfig() { // Claude Code 配置文件路径 const configDir = path.join(os.homedir(), '.claude') const configPath = path.join(configDir, 'settings.json') return { path: configPath, dir: configDir } } /** * 获取供应商配置文件路径 */ export function getProviderConfigPath(providerId: string): string { const { dir } = getClaudeCodeConfig() return path.join(dir, `settings-${sanitizeProviderName(providerId)}.json`) } /** * 保存供应商配置到独立文件 */ export async function saveProviderConfig(provider: Provider): Promise { try { const { dir } = getClaudeCodeConfig() const providerConfigPath = getProviderConfigPath(provider.id) // 确保目录存在 await fs.mkdir(dir, { recursive: true }) // 保存配置到供应商专用文件 await fs.writeFile( providerConfigPath, JSON.stringify(provider.settingsConfig, null, 2), 'utf-8' ) return true } catch (error) { console.error('保存供应商配置失败:', error) return false } } /** * 检查文件是否存在 */ export async function fileExists(filePath: string): Promise { try { await fs.access(filePath) return true } catch { return false } } /** * 切换供应商配置(基于文件重命名) */ export async function switchProvider(provider: Provider, currentProviderId?: string): Promise { try { const { path: settingsPath, dir: configDir } = getClaudeCodeConfig() const newSettingsPath = getProviderConfigPath(provider.id) // 确保目录存在 await fs.mkdir(configDir, { recursive: true }) // 检查目标配置文件是否存在 if (!(await fileExists(newSettingsPath))) { console.error(`供应商配置文件不存在: ${newSettingsPath}`) return false } // 1. 如果当前存在settings.json,先备份到当前供应商的配置文件 if (await fileExists(settingsPath)) { if (currentProviderId) { const currentProviderPath = getProviderConfigPath(currentProviderId) await fs.rename(settingsPath, currentProviderPath) } else { // 如果没有当前供应商ID,创建临时备份 const backupPath = path.join(configDir, `settings-backup-${Date.now()}.json`) await fs.rename(settingsPath, backupPath) console.log(`已备份当前配置到: ${backupPath}`) } } // 2. 将目标供应商配置重命名为settings.json await fs.rename(newSettingsPath, settingsPath) console.log(`成功切换到供应商: ${provider.name}`) return true } catch (error) { console.error('切换供应商失败:', error) return false } } /** * 导入当前 settings.json 配置为一个供应商 */ export async function importCurrentConfig(name: string): Promise<{ success: boolean; provider?: Provider }> { try { const { path: settingsPath } = getClaudeCodeConfig() // 检查当前配置是否存在 if (!(await fileExists(settingsPath))) { return { success: false } } // 读取当前配置 const configContent = await fs.readFile(settingsPath, 'utf-8') const settingsConfig = JSON.parse(configContent) // 生成唯一的供应商ID let providerId = name.toLowerCase().replace(/[^a-z0-9]/g, '-') let counter = 1 // 检查ID是否已存在,如果存在则添加数字后缀 while (await fileExists(getProviderConfigPath(providerId))) { providerId = `${name.toLowerCase().replace(/[^a-z0-9]/g, '-')}-${counter}` counter++ } // 创建供应商对象 const provider: Provider = { id: providerId, name: name, settingsConfig: settingsConfig, createdAt: Date.now(), updatedAt: Date.now() } // 保存为供应商配置 const success = await saveProviderConfig(provider) if (success) { console.log(`已导入当前配置为供应商: ${name} (${providerId})`) return { success: true, provider } } else { return { success: false } } } catch (error: any) { console.error('导入当前配置失败:', error) return { success: false } } } /** * 删除供应商配置文件 */ export async function deleteProviderConfig(providerId: string): Promise { try { const providerConfigPath = getProviderConfigPath(providerId) if (await fileExists(providerConfigPath)) { await fs.unlink(providerConfigPath) console.log(`已删除供应商配置文件: ${providerConfigPath}`) } return true } catch (error) { console.error('删除供应商配置失败:', error) return false } }