diff --git a/frontend/components/APIKeyForm.tsx b/frontend/components/APIKeyForm.tsx index 86336e0..89c1594 100644 --- a/frontend/components/APIKeyForm.tsx +++ b/frontend/components/APIKeyForm.tsx @@ -18,9 +18,7 @@ import { useAPIKeyStore } from '@/frontend/stores/APIKeyStore'; import { Badge } from './ui/badge'; const formSchema = z.object({ - google: z.string().trim().min(1, { - message: 'Google API key is required for Title Generation', - }), + google: z.string().trim().optional(), openrouter: z.string().trim().optional(), openai: z.string().trim().optional(), }); @@ -81,7 +79,6 @@ const Form = () => { placeholder="AIza..." register={register} error={errors.google} - required /> !input.trim() || status === 'streaming' || status === 'submitted', @@ -87,14 +89,16 @@ function PureChatInput({ const messageId = uuidv4(); - if (!id) { - navigate(`/chat/${threadId}`); - await createThread(threadId); - complete(currentInput.trim(), { - body: { threadId, messageId, isTitle: true }, - }); - } else { - complete(currentInput.trim(), { body: { messageId, threadId } }); + if (getModelConfig(selectedModel).provider === MODEL_PROVIDERS.GOOGLE) { + if (!id) { + navigate(`/chat/${threadId}`); + await createThread(threadId); + complete(currentInput.trim(), { + body: { threadId, messageId, isTitle: true }, + }); + } else { + complete(currentInput.trim(), { body: { messageId, threadId } }); + } } const userMessage = createUserMessage(messageId, currentInput.trim()); @@ -113,6 +117,7 @@ function PureChatInput({ textareaRef, threadId, complete, + selectedModel, ]); if (!canChat) { diff --git a/frontend/components/MessageEditor.tsx b/frontend/components/MessageEditor.tsx index 15fed69..ad23ae6 100644 --- a/frontend/components/MessageEditor.tsx +++ b/frontend/components/MessageEditor.tsx @@ -12,6 +12,9 @@ import { Textarea } from './ui/textarea'; import { Button } from './ui/button'; import { useAPIKeyStore } from '@/frontend/stores/APIKeyStore'; import { toast } from 'sonner'; +import { useModelStore } from '../stores/ModelStore'; +import { MODEL_PROVIDERS } from '@/lib/constants'; +import { getModelConfig } from '@/lib/models'; export default function MessageEditor({ threadId, @@ -32,11 +35,12 @@ export default function MessageEditor({ }) { const [draftContent, setDraftContent] = useState(content); const getKey = useAPIKeyStore((state) => state.getKey); + const { selectedModel } = useModelStore(); const { complete } = useCompletion({ api: '/api/completion', - ...(getKey('google') && { - headers: { 'X-Google-API-Key': getKey('google')! }, + ...(getKey(MODEL_PROVIDERS.GOOGLE) && { + headers: { 'X-Google-API-Key': getKey(MODEL_PROVIDERS.GOOGLE)! }, }), onResponse: async (response) => { try { @@ -85,12 +89,14 @@ export default function MessageEditor({ return messages; }); - complete(draftContent, { - body: { - messageId: updatedMessage.id, - threadId, - }, - }); + if (getModelConfig(selectedModel).provider === MODEL_PROVIDERS.GOOGLE) { + complete(draftContent, { + body: { + messageId: updatedMessage.id, + threadId, + }, + }); + } setMode('view'); // stop the current stream if any diff --git a/frontend/hooks/useMessageSummary.ts b/frontend/hooks/useMessageSummary.ts index 832931f..edcf686 100644 --- a/frontend/hooks/useMessageSummary.ts +++ b/frontend/hooks/useMessageSummary.ts @@ -2,6 +2,7 @@ import { useCompletion } from '@ai-sdk/react'; import { useAPIKeyStore } from '@/frontend/stores/APIKeyStore'; import { toast } from 'sonner'; import { createMessageSummary, updateThread } from '@/frontend/dexie/queries'; +import { MODEL_PROVIDERS } from '@/lib/constants'; interface MessageSummaryPayload { title: string; @@ -15,8 +16,8 @@ export const useMessageSummary = () => { const { complete, isLoading } = useCompletion({ api: '/api/completion', - ...(getKey('google') && { - headers: { 'X-Google-API-Key': getKey('google')! }, + ...(getKey(MODEL_PROVIDERS.GOOGLE) && { + headers: { 'X-Google-API-Key': getKey(MODEL_PROVIDERS.GOOGLE)! }, }), onResponse: async (response) => { try { diff --git a/lib/constants.ts b/lib/constants.ts new file mode 100644 index 0000000..0a8bfc5 --- /dev/null +++ b/lib/constants.ts @@ -0,0 +1,19 @@ +import { Provider } from '@/frontend/stores/APIKeyStore'; + +const GOOGLE = 'google'; +const OPEN_ROUTER = 'openrouter'; +const OPEN_AI = 'openai'; + +export const MODEL_PROVIDERS: { + [key: string]: Provider; +} = { + GOOGLE, + OPEN_ROUTER, + OPEN_AI, +} as const; + +export const MODEL_HEADER_KEYS: Record = { + [OPEN_ROUTER]: 'X-OpenRouter-API-Key', + [GOOGLE]: 'X-Google-API-Key', + [OPEN_AI]: 'X-OpenAI-API-Key', +} as const; diff --git a/lib/models.ts b/lib/models.ts index a868083..82efa2b 100644 --- a/lib/models.ts +++ b/lib/models.ts @@ -1,4 +1,5 @@ import { Provider } from '@/frontend/stores/APIKeyStore'; +import { MODEL_HEADER_KEYS, MODEL_PROVIDERS } from '@/lib/constants'; export const AI_MODELS = [ 'Deepseek R1 0528', @@ -20,33 +21,33 @@ export type ModelConfig = { export const MODEL_CONFIGS = { 'Deepseek R1 0528': { modelId: 'deepseek/deepseek-r1-0528:free', - provider: 'openrouter', - headerKey: 'X-OpenRouter-API-Key', + provider: MODEL_PROVIDERS.OPEN_ROUTER, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.OPEN_ROUTER], }, 'Deepseek V3': { modelId: 'deepseek/deepseek-chat-v3-0324:free', - provider: 'openrouter', - headerKey: 'X-OpenRouter-API-Key', + provider: MODEL_PROVIDERS.OPEN_ROUTER, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.OPEN_ROUTER], }, 'Gemini 2.5 Pro': { modelId: 'gemini-2.5-pro-preview-05-06', - provider: 'google', - headerKey: 'X-Google-API-Key', + provider: MODEL_PROVIDERS.GOOGLE, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.GOOGLE], }, 'Gemini 2.5 Flash': { modelId: 'gemini-2.5-flash-preview-04-17', - provider: 'google', - headerKey: 'X-Google-API-Key', + provider: MODEL_PROVIDERS.GOOGLE, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.GOOGLE], }, 'GPT-4o': { modelId: 'gpt-4o', - provider: 'openai', - headerKey: 'X-OpenAI-API-Key', + provider: MODEL_PROVIDERS.OPEN_AI, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.OPEN_AI], }, 'GPT-4.1-mini': { modelId: 'gpt-4.1-mini', - provider: 'openai', - headerKey: 'X-OpenAI-API-Key', + provider: MODEL_PROVIDERS.OPEN_AI, + headerKey: MODEL_HEADER_KEYS[MODEL_PROVIDERS.OPEN_AI], }, } as const satisfies Record;