diff --git a/src/app/api/settings/route.ts b/src/app/api/settings/route.ts index 6fa0000..675621c 100644 --- a/src/app/api/settings/route.ts +++ b/src/app/api/settings/route.ts @@ -9,7 +9,8 @@ import { encryptApiKey } from '@/lib/crypto'; const DEFAULT_SETTINGS = { cchUrl: process.env.CCH_DEFAULT_URL || 'https://claude.leocoder.cn/', cchApiKeyConfigured: false, - defaultModel: 'claude-sonnet-4-20250514', + apiFormat: 'claude' as 'claude' | 'openai', // API 格式:claude(原生)| openai(兼容) + defaultModel: 'claude-sonnet-4-5-20250929', defaultTools: ['web_search', 'code_execution', 'web_fetch'], systemPrompt: '', temperature: '0.7', @@ -29,6 +30,7 @@ function formatSettingsResponse(settings: typeof userSettings.$inferSelect | nul return { cchUrl: settings.cchUrl || DEFAULT_SETTINGS.cchUrl, cchApiKeyConfigured: settings.cchApiKeyConfigured || false, + apiFormat: (settings.apiFormat as 'claude' | 'openai') || DEFAULT_SETTINGS.apiFormat, defaultModel: settings.defaultModel || DEFAULT_SETTINGS.defaultModel, defaultTools: settings.defaultTools || DEFAULT_SETTINGS.defaultTools, systemPrompt: settings.systemPrompt || '', @@ -102,6 +104,7 @@ export async function PUT(request: Request) { const { cchUrl, cchApiKey, + apiFormat, defaultModel, defaultTools, systemPrompt, @@ -135,6 +138,11 @@ export async function PUT(request: Request) { } } + // API 格式类型 + if (apiFormat !== undefined) { + updateData.apiFormat = apiFormat; + } + if (defaultModel !== undefined) { updateData.defaultModel = defaultModel; } diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 61eb91b..9e7344c 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -52,6 +52,7 @@ export default function SettingsPage() { // CCH 配置状态 const [cchUrl, setCchUrl] = useState(''); const [cchApiKey, setCchApiKey] = useState(''); + const [apiFormat, setApiFormat] = useState<'claude' | 'openai'>('claude'); const [showApiKey, setShowApiKey] = useState(false); const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle'); @@ -70,6 +71,7 @@ export default function SettingsPage() { useEffect(() => { if (settings) { setCchUrl(settings.cchUrl || ''); + setApiFormat((settings.apiFormat as 'claude' | 'openai') || 'claude'); setSystemPrompt(settings.systemPrompt || ''); setTemperature(settings.temperature || '0.7'); } @@ -82,6 +84,7 @@ export default function SettingsPage() { const updates: Record = {}; if (cchUrl) updates.cchUrl = cchUrl; if (cchApiKey) updates.cchApiKey = cchApiKey; + updates.apiFormat = apiFormat; if (Object.keys(updates).length > 0) { await updateSettings(updates); @@ -333,6 +336,83 @@ export default function SettingsPage() { /> + {/* API 格式选择 */} +
+
+ API 格式 +
+
+ 选择中转站的 API 接口格式 +
+
+ {/* Claude 原生选项 */} + + + {/* OpenAI 兼容选项 */} + +
+
+ ().default(['web_search', 'code_execution', 'web_fetch']), // AI 行为设置 systemPrompt: text('system_prompt'), // 系统提示词 diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index 5b76f28..94ae9b5 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -5,6 +5,7 @@ import { useState, useEffect, useCallback } from 'react'; export interface Settings { cchUrl: string; cchApiKeyConfigured: boolean; + apiFormat: 'claude' | 'openai'; defaultModel: string; defaultTools: string[]; systemPrompt: string; @@ -50,7 +51,8 @@ export interface Model { const defaultSettings: Settings = { cchUrl: 'http://localhost:13500', cchApiKeyConfigured: false, - defaultModel: 'claude-sonnet-4-20250514', + apiFormat: 'claude', + defaultModel: 'claude-sonnet-4-5-20250929', defaultTools: ['web_search', 'code_execution', 'web_fetch'], systemPrompt: '', temperature: '0.7',