diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts index e4384a8..1b185c6 100644 --- a/src/app/api/config/route.ts +++ b/src/app/api/config/route.ts @@ -51,15 +51,23 @@ export const GET = async (req: Request) => { }); } - config['openaiApiKey'] = getOpenaiApiKey(); + // Helper function to obfuscate API keys + const protectApiKey = (key: string | null | undefined) => { + return key ? "protected" : key; + }; + + // Obfuscate all API keys in the response + config['openaiApiKey'] = protectApiKey(getOpenaiApiKey()); + config['groqApiKey'] = protectApiKey(getGroqApiKey()); + config['anthropicApiKey'] = protectApiKey(getAnthropicApiKey()); + config['geminiApiKey'] = protectApiKey(getGeminiApiKey()); + config['deepseekApiKey'] = protectApiKey(getDeepseekApiKey()); + config['customOpenaiApiKey'] = protectApiKey(getCustomOpenaiApiKey()); + + // Non-sensitive values remain unchanged config['ollamaApiUrl'] = getOllamaApiEndpoint(); config['lmStudioApiUrl'] = getLMStudioApiEndpoint(); - config['anthropicApiKey'] = getAnthropicApiKey(); - config['groqApiKey'] = getGroqApiKey(); - config['geminiApiKey'] = getGeminiApiKey(); - config['deepseekApiKey'] = getDeepseekApiKey(); config['customOpenaiApiUrl'] = getCustomOpenaiApiUrl(); - config['customOpenaiApiKey'] = getCustomOpenaiApiKey(); config['customOpenaiModelName'] = getCustomOpenaiModelName(); config['baseUrl'] = getBaseUrl(); @@ -77,32 +85,39 @@ export const POST = async (req: Request) => { try { const config = await req.json(); + const getUpdatedProtectedValue = (newValue: string, currentConfig: string) => { + if (newValue === 'protected') { + return currentConfig; + } + return newValue; + } + const updatedConfig = { MODELS: { OPENAI: { - API_KEY: config.openaiApiKey, + API_KEY: getUpdatedProtectedValue(config.openaiApiKey, getOpenaiApiKey()), }, GROQ: { - API_KEY: config.groqApiKey, + API_KEY: getUpdatedProtectedValue(config.groqApiKey, getGroqApiKey()), }, ANTHROPIC: { - API_KEY: config.anthropicApiKey, + API_KEY: getUpdatedProtectedValue(config.anthropicApiKey, getAnthropicApiKey()), }, GEMINI: { - API_KEY: config.geminiApiKey, + API_KEY: getUpdatedProtectedValue(config.geminiApiKey, getGeminiApiKey()), }, OLLAMA: { API_URL: config.ollamaApiUrl, }, DEEPSEEK: { - API_KEY: config.deepseekApiKey, + API_KEY: getUpdatedProtectedValue(config.deepseekApiKey, getDeepseekApiKey()), }, LM_STUDIO: { API_URL: config.lmStudioApiUrl, }, CUSTOM_OPENAI: { API_URL: config.customOpenaiApiUrl, - API_KEY: config.customOpenaiApiKey, + API_KEY: getUpdatedProtectedValue(config.customOpenaiApiKey, getCustomOpenaiApiKey()), MODEL_NAME: config.customOpenaiModelName, }, }, diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index ee78052..aaee479 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Settings as SettingsIcon, ArrowLeft, Loader2 } from 'lucide-react'; +import { Settings as SettingsIcon, ArrowLeft, Loader2, Info } from 'lucide-react'; import { useEffect, useState } from 'react'; import { cn } from '@/lib/utils'; import { Switch } from '@headlessui/react'; @@ -117,12 +117,24 @@ const Select = ({ const SettingsSection = ({ title, children, + tooltip, }: { title: string; children: React.ReactNode; + tooltip?: string; }) => (
-

{title}

+
+

{title}

+ {tooltip && ( +
+ +
+ {tooltip} +
+
+ )} +
{children}
); @@ -226,7 +238,7 @@ const Page = () => { fetchConfig(); }, []); - const saveConfig = async (key: string, value: any) => { + const saveConfig = async (key: string, value: any) => { setSavingStates((prev) => ({ ...prev, [key]: true })); try { @@ -671,7 +683,7 @@ const Page = () => { Custom OpenAI API Key

{ )} - +

OpenAI API Key

{ GROQ API Key

{ Anthropic API Key

{ Gemini API Key

{ Deepseek API Key