diff --git a/.gitignore b/.gitignore index 69d2790..b43105b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ dist-ssr _worker.bundle Modelfile +modelfiles diff --git a/README.md b/README.md index fb70e75..a1132c8 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ If you see usr/local/bin in the output then you're good to go. git clone https://github.com/coleam00/bolt.new-any-llm.git ``` -3. Rename .env.example to .env and add your LLM API keys. You will find this file on a Mac at "[your name]/bold.new-any-llm/.env.example". For Windows and Linux the path will be similar. +3. Rename .env.example to .env.local and add your LLM API keys. You will find this file on a Mac at "[your name]/bold.new-any-llm/.env.example". For Windows and Linux the path will be similar. ![image](https://github.com/user-attachments/assets/7e6a532c-2268-401f-8310-e8d20c731328) @@ -115,7 +115,7 @@ Optionally, you can set the debug level: VITE_LOG_LEVEL=debug ``` -**Important**: Never commit your `.env` file to version control. It's already included in .gitignore. +**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore. ## Run with Docker diff --git a/app/components/chat/APIKeyManager.tsx b/app/components/chat/APIKeyManager.tsx new file mode 100644 index 0000000..a35724c --- /dev/null +++ b/app/components/chat/APIKeyManager.tsx @@ -0,0 +1,49 @@ +import React, { useState } from 'react'; +import { IconButton } from '~/components/ui/IconButton'; + +interface APIKeyManagerProps { + provider: string; + apiKey: string; + setApiKey: (key: string) => void; +} + +export const APIKeyManager: React.FC = ({ provider, apiKey, setApiKey }) => { + const [isEditing, setIsEditing] = useState(false); + const [tempKey, setTempKey] = useState(apiKey); + + const handleSave = () => { + setApiKey(tempKey); + setIsEditing(false); + }; + + return ( +
+ {provider} API Key: + {isEditing ? ( + <> + setTempKey(e.target.value)} + className="flex-1 p-1 text-sm rounded border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus" + /> + +
+ + setIsEditing(false)} title="Cancel"> +
+ + + ) : ( + <> + + {apiKey ? '••••••••' : 'Not set (will still work if set in .env file)'} + + setIsEditing(true)} title="Edit API Key"> +
+ + + )} +
+ ); +}; diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index 68f852a..f331147 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -1,7 +1,7 @@ // @ts-nocheck // Preventing TS checks with files presented in the video for a better presentation. import type { Message } from 'ai'; -import React, { type RefCallback } from 'react'; +import React, { type RefCallback, useEffect } from 'react'; import { ClientOnly } from 'remix-utils/client-only'; import { Menu } from '~/components/sidebar/Menu.client'; import { IconButton } from '~/components/ui/IconButton'; @@ -11,6 +11,8 @@ import { MODEL_LIST, DEFAULT_PROVIDER } from '~/utils/constants'; import { Messages } from './Messages.client'; import { SendButton } from './SendButton.client'; import { useState } from 'react'; +import { APIKeyManager } from './APIKeyManager'; +import Cookies from 'js-cookie'; import styles from './BaseChat.module.scss'; @@ -24,18 +26,17 @@ const EXAMPLE_PROMPTS = [ const providerList = [...new Set(MODEL_LIST.map((model) => model.provider))] -const ModelSelector = ({ model, setModel, modelList, providerList }) => { - const [provider, setProvider] = useState(DEFAULT_PROVIDER); +const ModelSelector = ({ model, setModel, provider, setProvider, modelList, providerList }) => { return ( -
- { setProvider(e.target.value); const firstModel = [...modelList].find(m => m.provider == e.target.value); setModel(firstModel ? firstModel.name : ''); }} - className="w-full p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none" + className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all" > {providerList.map((provider) => (