Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Dec 31, 2024
2 parents 9776edb + 1cf8345 commit d90a4a6
Show file tree
Hide file tree
Showing 26 changed files with 606 additions and 610 deletions.
165 changes: 100 additions & 65 deletions app/components/chat/BaseChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Preventing TS checks with files presented in the video for a better presentation.
*/
import type { Message } from 'ai';
import React, { type RefCallback, useEffect, useState } from 'react';
import React, { type RefCallback, useCallback, useEffect, useState } from 'react';
import { ClientOnly } from 'remix-utils/client-only';
import { Menu } from '~/components/sidebar/Menu.client';
import { IconButton } from '~/components/ui/IconButton';
Expand Down Expand Up @@ -31,6 +31,7 @@ import { toast } from 'react-toastify';
import StarterTemplates from './StarterTemplates';
import type { ActionAlert } from '~/types/actions';
import ChatAlert from './ChatAlert';
import { LLMManager } from '~/lib/modules/llm/manager';

const TEXTAREA_MIN_HEIGHT = 76;

Expand Down Expand Up @@ -100,26 +101,36 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
ref,
) => {
const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200;
const [apiKeys, setApiKeys] = useState<Record<string, string>>(() => {
const savedKeys = Cookies.get('apiKeys');

if (savedKeys) {
try {
return JSON.parse(savedKeys);
} catch (error) {
console.error('Failed to parse API keys from cookies:', error);
return {};
}
}

return {};
});
const [apiKeys, setApiKeys] = useState<Record<string, string>>(getApiKeysFromCookies());
const [modelList, setModelList] = useState(MODEL_LIST);
const [isModelSettingsCollapsed, setIsModelSettingsCollapsed] = useState(false);
const [isListening, setIsListening] = useState(false);
const [recognition, setRecognition] = useState<SpeechRecognition | null>(null);
const [transcript, setTranscript] = useState('');
const [isModelLoading, setIsModelLoading] = useState<string | undefined>('all');

const getProviderSettings = useCallback(() => {
let providerSettings: Record<string, IProviderSetting> | undefined = undefined;

try {
const savedProviderSettings = Cookies.get('providers');

if (savedProviderSettings) {
const parsedProviderSettings = JSON.parse(savedProviderSettings);

if (typeof parsedProviderSettings === 'object' && parsedProviderSettings !== null) {
providerSettings = parsedProviderSettings;
}
}
} catch (error) {
console.error('Error loading Provider Settings from cookies:', error);

// Clear invalid cookie data
Cookies.remove('providers');
}

return providerSettings;
}, []);
useEffect(() => {
console.log(transcript);
}, [transcript]);
Expand Down Expand Up @@ -157,42 +168,63 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
}, []);

useEffect(() => {
let providerSettings: Record<string, IProviderSetting> | undefined = undefined;

try {
const savedProviderSettings = Cookies.get('providers');
if (typeof window !== 'undefined') {
const providerSettings = getProviderSettings();
let parsedApiKeys: Record<string, string> | undefined = {};

if (savedProviderSettings) {
const parsedProviderSettings = JSON.parse(savedProviderSettings);
try {
parsedApiKeys = getApiKeysFromCookies();
setApiKeys(parsedApiKeys);
} catch (error) {
console.error('Error loading API keys from cookies:', error);

if (typeof parsedProviderSettings === 'object' && parsedProviderSettings !== null) {
providerSettings = parsedProviderSettings;
}
// Clear invalid cookie data
Cookies.remove('apiKeys');
}
} catch (error) {
console.error('Error loading Provider Settings from cookies:', error);

// Clear invalid cookie data
Cookies.remove('providers');
setIsModelLoading('all');
initializeModelList({ apiKeys: parsedApiKeys, providerSettings })
.then((modelList) => {
// console.log('Model List: ', modelList);
setModelList(modelList);
})
.catch((error) => {
console.error('Error initializing model list:', error);
})
.finally(() => {
setIsModelLoading(undefined);
});
}
}, [providerList]);

let parsedApiKeys: Record<string, string> | undefined = {};
const onApiKeysChange = async (providerName: string, apiKey: string) => {
const newApiKeys = { ...apiKeys, [providerName]: apiKey };
setApiKeys(newApiKeys);
Cookies.set('apiKeys', JSON.stringify(newApiKeys));

try {
parsedApiKeys = getApiKeysFromCookies();
setApiKeys(parsedApiKeys);
} catch (error) {
console.error('Error loading API keys from cookies:', error);
const provider = LLMManager.getInstance(import.meta.env || process.env || {}).getProvider(providerName);

// Clear invalid cookie data
Cookies.remove('apiKeys');
}
if (provider && provider.getDynamicModels) {
setIsModelLoading(providerName);

initializeModelList({ apiKeys: parsedApiKeys, providerSettings }).then((modelList) => {
console.log('Model List: ', modelList);
setModelList(modelList);
});
}, [apiKeys]);
try {
const providerSettings = getProviderSettings();
const staticModels = provider.staticModels;
const dynamicModels = await provider.getDynamicModels(
newApiKeys,
providerSettings,
import.meta.env || process.env || {},
);

setModelList((preModels) => {
const filteredOutPreModels = preModels.filter((x) => x.provider !== providerName);
return [...filteredOutPreModels, ...staticModels, ...dynamicModels];
});
} catch (error) {
console.error('Error loading dynamic models:', error);
}
setIsModelLoading(undefined);
}
};

const startListening = () => {
if (recognition) {
Expand Down Expand Up @@ -371,29 +403,32 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
<rect className={classNames(styles.PromptShine)} x="48" y="24" width="70" height="1"></rect>
</svg>
<div>
<div className={isModelSettingsCollapsed ? 'hidden' : ''}>
<ModelSelector
key={provider?.name + ':' + modelList.length}
model={model}
setModel={setModel}
modelList={modelList}
provider={provider}
setProvider={setProvider}
providerList={providerList || (PROVIDER_LIST as ProviderInfo[])}
apiKeys={apiKeys}
/>
{(providerList || []).length > 0 && provider && (
<APIKeyManager
provider={provider}
apiKey={apiKeys[provider.name] || ''}
setApiKey={(key) => {
const newApiKeys = { ...apiKeys, [provider.name]: key };
setApiKeys(newApiKeys);
Cookies.set('apiKeys', JSON.stringify(newApiKeys));
}}
/>
<ClientOnly>
{() => (
<div className={isModelSettingsCollapsed ? 'hidden' : ''}>
<ModelSelector
key={provider?.name + ':' + modelList.length}
model={model}
setModel={setModel}
modelList={modelList}
provider={provider}
setProvider={setProvider}
providerList={providerList || (PROVIDER_LIST as ProviderInfo[])}
apiKeys={apiKeys}
modelLoading={isModelLoading}
/>
{(providerList || []).length > 0 && provider && (
<APIKeyManager
provider={provider}
apiKey={apiKeys[provider.name] || ''}
setApiKey={(key) => {
onApiKeysChange(provider.name, key);
}}
/>
)}
</div>
)}
</div>
</ClientOnly>
</div>
<FilePreview
files={uploadedFiles}
Expand Down
7 changes: 4 additions & 3 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ export const ChatImpl = memo(
});
useEffect(() => {
const prompt = searchParams.get('prompt');
console.log(prompt, searchParams, model, provider);

// console.log(prompt, searchParams, model, provider);

if (prompt) {
setSearchParams({});
Expand Down Expand Up @@ -289,14 +290,14 @@ export const ChatImpl = memo(

// reload();

const template = await selectStarterTemplate({
const { template, title } = await selectStarterTemplate({
message: messageInput,
model,
provider,
});

if (template !== 'blank') {
const temResp = await getTemplates(template);
const temResp = await getTemplates(template, title);

if (temResp) {
const { assistantMessage, userMessage } = temResp;
Expand Down
23 changes: 16 additions & 7 deletions app/components/chat/ModelSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface ModelSelectorProps {
modelList: ModelInfo[];
providerList: ProviderInfo[];
apiKeys: Record<string, string>;
modelLoading?: string;
}

export const ModelSelector = ({
Expand All @@ -19,6 +20,7 @@ export const ModelSelector = ({
setProvider,
modelList,
providerList,
modelLoading,
}: ModelSelectorProps) => {
// Load enabled providers from cookies

Expand Down Expand Up @@ -83,14 +85,21 @@ export const ModelSelector = ({
value={model}
onChange={(e) => setModel?.(e.target.value)}
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 lg:max-w-[70%]"
disabled={modelLoading === 'all' || modelLoading === provider?.name}
>
{[...modelList]
.filter((e) => e.provider == provider?.name && e.name)
.map((modelOption, index) => (
<option key={index} value={modelOption.name}>
{modelOption.label}
</option>
))}
{modelLoading == 'all' || modelLoading == provider?.name ? (
<option key={0} value="">
Loading...
</option>
) : (
[...modelList]
.filter((e) => e.provider == provider?.name && e.name)
.map((modelOption, index) => (
<option key={index} value={modelOption.name}>
{modelOption.label}
</option>
))
)}
</select>
</div>
);
Expand Down
3 changes: 2 additions & 1 deletion app/components/settings/providers/ProvidersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import type { IProviderConfig } from '~/types/model';
import { logStore } from '~/lib/stores/logs';

// Import a default fallback icon
import DefaultIcon from '/icons/Default.svg'; // Adjust the path as necessary
import { providerBaseUrlEnvKeys } from '~/utils/constants';

const DefaultIcon = '/icons/Default.svg'; // Adjust the path as necessary

export default function ProvidersTab() {
const { providers, updateProviderSettings, isLocalModel } = useSettings();
const [filteredProviders, setFilteredProviders] = useState<IProviderConfig[]>([]);
Expand Down
3 changes: 1 addition & 2 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { renderToReadableStream } from 'react-dom/server';
import { renderHeadToString } from 'remix-island';
import { Head } from './root';
import { themeStore } from '~/lib/stores/theme';
import { initializeModelList } from '~/utils/constants';

export default async function handleRequest(
request: Request,
Expand All @@ -14,7 +13,7 @@ export default async function handleRequest(
remixContext: EntryContext,
_loadContext: AppLoadContext,
) {
await initializeModelList({});
// await initializeModelList({});

const readable = await renderToReadableStream(<RemixServer context={remixContext} url={request.url} />, {
signal: request.signal,
Expand Down
Loading

0 comments on commit d90a4a6

Please sign in to comment.