Upload 26 files
Browse files
app/components/chat/ApiKeyWarning.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import type { ProviderInfo } from '~/types/model';
|
| 3 |
+
|
| 4 |
+
interface ApiKeyWarningProps {
|
| 5 |
+
provider: ProviderInfo;
|
| 6 |
+
apiKeys: Record<string, string>;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
export const ApiKeyWarning: React.FC<ApiKeyWarningProps> = ({ provider, apiKeys }) => {
|
| 10 |
+
const isApiKeyMissing = !apiKeys[provider.name];
|
| 11 |
+
|
| 12 |
+
if (!isApiKeyMissing) return null;
|
| 13 |
+
|
| 14 |
+
return (
|
| 15 |
+
<div className="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-4">
|
| 16 |
+
<div className="flex">
|
| 17 |
+
<div className="flex-shrink-0">
|
| 18 |
+
<div className="i-ph:warning-circle text-yellow-400 text-2xl" />
|
| 19 |
+
</div>
|
| 20 |
+
<div className="ml-3">
|
| 21 |
+
<p className="text-sm text-yellow-700">
|
| 22 |
+
API key is missing for {provider.name}. Please add an API key in the settings to send messages.
|
| 23 |
+
</p>
|
| 24 |
+
</div>
|
| 25 |
+
</div>
|
| 26 |
+
</div>
|
| 27 |
+
);
|
| 28 |
+
};
|
app/components/chat/BaseChat.tsx
CHANGED
|
@@ -77,6 +77,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
| 77 |
isStreaming = false,
|
| 78 |
model,
|
| 79 |
setModel,
|
|
|
|
| 80 |
provider,
|
| 81 |
setProvider,
|
| 82 |
providerList,
|
|
@@ -312,12 +313,18 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
| 312 |
}
|
| 313 |
};
|
| 314 |
|
|
|
|
|
|
|
| 315 |
const baseChat = (
|
| 316 |
<div
|
| 317 |
ref={ref}
|
| 318 |
className={classNames(styles.BaseChat, 'relative flex h-full w-full overflow-hidden')}
|
| 319 |
data-chat-visible={showChat}
|
| 320 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
<ClientOnly>{() => <Menu />}</ClientOnly>
|
| 322 |
<div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
|
| 323 |
<div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
|
|
@@ -528,7 +535,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
| 528 |
<SendButton
|
| 529 |
show={input.length > 0 || isStreaming || uploadedFiles.length > 0}
|
| 530 |
isStreaming={isStreaming}
|
| 531 |
-
disabled={!providerList || providerList.length === 0}
|
| 532 |
onClick={(event) => {
|
| 533 |
if (isStreaming) {
|
| 534 |
handleStop?.();
|
|
|
|
| 77 |
isStreaming = false,
|
| 78 |
model,
|
| 79 |
setModel,
|
| 80 |
+
apiKeys,
|
| 81 |
provider,
|
| 82 |
setProvider,
|
| 83 |
providerList,
|
|
|
|
| 313 |
}
|
| 314 |
};
|
| 315 |
|
| 316 |
+
const isApiKeyAvailable = apiKeys && apiKeys[provider.name];
|
| 317 |
+
|
| 318 |
const baseChat = (
|
| 319 |
<div
|
| 320 |
ref={ref}
|
| 321 |
className={classNames(styles.BaseChat, 'relative flex h-full w-full overflow-hidden')}
|
| 322 |
data-chat-visible={showChat}
|
| 323 |
>
|
| 324 |
+
<ApiKeyWarning
|
| 325 |
+
provider={provider}
|
| 326 |
+
apiKeys={apiKeys}
|
| 327 |
+
/>
|
| 328 |
<ClientOnly>{() => <Menu />}</ClientOnly>
|
| 329 |
<div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
|
| 330 |
<div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
|
|
|
|
| 535 |
<SendButton
|
| 536 |
show={input.length > 0 || isStreaming || uploadedFiles.length > 0}
|
| 537 |
isStreaming={isStreaming}
|
| 538 |
+
disabled={!isApiKeyAvailable || !providerList || providerList.length === 0}
|
| 539 |
onClick={(event) => {
|
| 540 |
if (isStreaming) {
|
| 541 |
handleStop?.();
|
app/components/chat/Chat.client.tsx
CHANGED
|
@@ -110,8 +110,8 @@ interface ChatProps {
|
|
| 110 |
|
| 111 |
export const ChatImpl = memo(
|
| 112 |
({ description, initialMessages, storeMessageHistory, importChat, exportChat }: ChatProps) => {
|
| 113 |
-
useShortcuts();
|
| 114 |
|
|
|
|
| 115 |
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
| 116 |
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
|
| 117 |
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
|
|
@@ -511,6 +511,7 @@ export const ChatImpl = memo(
|
|
| 511 |
setModel={handleModelChange}
|
| 512 |
provider={provider}
|
| 513 |
setProvider={handleProviderChange}
|
|
|
|
| 514 |
providerList={activeProviders}
|
| 515 |
messageRef={messageRef}
|
| 516 |
scrollRef={scrollRef}
|
|
|
|
| 110 |
|
| 111 |
export const ChatImpl = memo(
|
| 112 |
({ description, initialMessages, storeMessageHistory, importChat, exportChat }: ChatProps) => {
|
|
|
|
| 113 |
|
| 114 |
+
useShortcuts();
|
| 115 |
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
| 116 |
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
|
| 117 |
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
|
|
|
|
| 511 |
setModel={handleModelChange}
|
| 512 |
provider={provider}
|
| 513 |
setProvider={handleProviderChange}
|
| 514 |
+
apiKeys={apiKeys}
|
| 515 |
providerList={activeProviders}
|
| 516 |
messageRef={messageRef}
|
| 517 |
scrollRef={scrollRef}
|