mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-26 18:26:38 +00:00
Bug Fixes part1
This commit is contained in:
parent
5791dafcd1
commit
af620d0197
@ -311,6 +311,24 @@ export default function ConnectionsTab() {
|
|||||||
'disabled:opacity-50',
|
'disabled:opacity-50',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<div className="mt-2 text-sm text-bolt-elements-textSecondary">
|
||||||
|
<a
|
||||||
|
href={`https://github.com/settings/tokens${connection.tokenType === 'fine-grained' ? '/beta' : '/new'}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-purple-500 hover:underline inline-flex items-center gap-1"
|
||||||
|
>
|
||||||
|
Get your token
|
||||||
|
<div className="i-ph:arrow-square-out w-10 h-5" />
|
||||||
|
</a>
|
||||||
|
<span className="mx-2">•</span>
|
||||||
|
<span>
|
||||||
|
Required scopes:{' '}
|
||||||
|
{connection.tokenType === 'classic'
|
||||||
|
? 'repo, read:org, read:user'
|
||||||
|
: 'Repository access, Organization access'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,11 @@
|
|||||||
import React, { memo, useEffect, useState } from 'react';
|
// Remove unused imports
|
||||||
|
import React, { memo, useCallback } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { Switch } from '~/components/ui/Switch';
|
import { Switch } from '~/components/ui/Switch';
|
||||||
import { useSettings } from '~/lib/hooks/useSettings';
|
import { useSettings } from '~/lib/hooks/useSettings';
|
||||||
import { classNames } from '~/utils/classNames';
|
import { classNames } from '~/utils/classNames';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { PromptLibrary } from '~/lib/common/prompt-library';
|
import { PromptLibrary } from '~/lib/common/prompt-library';
|
||||||
import {
|
|
||||||
latestBranchStore,
|
|
||||||
autoSelectStarterTemplate,
|
|
||||||
enableContextOptimizationStore,
|
|
||||||
isLocalModelsEnabled,
|
|
||||||
isEventLogsEnabled,
|
|
||||||
promptStore as promptAtom,
|
|
||||||
} from '~/lib/stores/settings';
|
|
||||||
import { logStore } from '~/lib/stores/logs';
|
|
||||||
|
|
||||||
interface FeatureToggle {
|
interface FeatureToggle {
|
||||||
id: string;
|
id: string;
|
||||||
@ -114,133 +106,85 @@ const FeatureSection = memo(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default function FeaturesTab() {
|
export default function FeaturesTab() {
|
||||||
const { autoSelectTemplate, isLatestBranch, contextOptimizationEnabled, eventLogs, isLocalModel } = useSettings();
|
const {
|
||||||
|
autoSelectTemplate,
|
||||||
|
isLatestBranch,
|
||||||
|
contextOptimizationEnabled,
|
||||||
|
eventLogs,
|
||||||
|
isLocalModel,
|
||||||
|
setAutoSelectTemplate,
|
||||||
|
enableLatestBranch,
|
||||||
|
enableContextOptimization,
|
||||||
|
setEventLogs,
|
||||||
|
enableLocalModels,
|
||||||
|
setPromptId,
|
||||||
|
promptId,
|
||||||
|
} = useSettings();
|
||||||
|
|
||||||
const getLocalStorageBoolean = (key: string, defaultValue: boolean): boolean => {
|
const handleToggleFeature = useCallback(
|
||||||
const value = localStorage.getItem(key);
|
(id: string, enabled: boolean) => {
|
||||||
|
switch (id) {
|
||||||
|
case 'latestBranch':
|
||||||
|
enableLatestBranch(enabled);
|
||||||
|
toast.success(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
|
break;
|
||||||
|
case 'autoSelectTemplate':
|
||||||
|
setAutoSelectTemplate(enabled);
|
||||||
|
toast.success(`Auto select template ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
|
break;
|
||||||
|
case 'contextOptimization':
|
||||||
|
enableContextOptimization(enabled);
|
||||||
|
toast.success(`Context optimization ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
|
break;
|
||||||
|
case 'eventLogs':
|
||||||
|
setEventLogs(enabled);
|
||||||
|
toast.success(`Event logging ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
|
break;
|
||||||
|
case 'localModels':
|
||||||
|
enableLocalModels(enabled);
|
||||||
|
toast.success(`Experimental providers ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[enableLatestBranch, setAutoSelectTemplate, enableContextOptimization, setEventLogs, enableLocalModels],
|
||||||
|
);
|
||||||
|
|
||||||
if (value === null) {
|
const features = {
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return JSON.parse(value);
|
|
||||||
} catch {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const autoSelectTemplateState = getLocalStorageBoolean('autoSelectTemplate', autoSelectTemplate);
|
|
||||||
const enableLatestBranchState = getLocalStorageBoolean('enableLatestBranch', isLatestBranch);
|
|
||||||
const contextOptimizationState = getLocalStorageBoolean('contextOptimization', contextOptimizationEnabled);
|
|
||||||
const eventLogsState = getLocalStorageBoolean('eventLogs', eventLogs);
|
|
||||||
const experimentalProvidersState = getLocalStorageBoolean('experimentalProviders', isLocalModel);
|
|
||||||
const promptLibraryState = getLocalStorageBoolean('promptLibrary', false);
|
|
||||||
const promptIdState = localStorage.getItem('promptId') ?? '';
|
|
||||||
|
|
||||||
const [autoSelectTemplateLocal, setAutoSelectTemplateLocal] = useState(autoSelectTemplateState);
|
|
||||||
const [enableLatestBranchLocal, setEnableLatestBranchLocal] = useState(enableLatestBranchState);
|
|
||||||
const [contextOptimizationLocal, setContextOptimizationLocal] = useState(contextOptimizationState);
|
|
||||||
const [eventLogsLocal, setEventLogsLocal] = useState(eventLogsState);
|
|
||||||
const [experimentalProvidersLocal, setExperimentalProvidersLocal] = useState(experimentalProvidersState);
|
|
||||||
const [promptLibraryLocal, setPromptLibraryLocal] = useState(promptLibraryState);
|
|
||||||
const [promptIdLocal, setPromptIdLocal] = useState(promptIdState);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
localStorage.setItem('autoSelectTemplate', JSON.stringify(autoSelectTemplateLocal));
|
|
||||||
localStorage.setItem('enableLatestBranch', JSON.stringify(enableLatestBranchLocal));
|
|
||||||
localStorage.setItem('contextOptimization', JSON.stringify(contextOptimizationLocal));
|
|
||||||
localStorage.setItem('eventLogs', JSON.stringify(eventLogsLocal));
|
|
||||||
localStorage.setItem('experimentalProviders', JSON.stringify(experimentalProvidersLocal));
|
|
||||||
localStorage.setItem('promptLibrary', JSON.stringify(promptLibraryLocal));
|
|
||||||
localStorage.setItem('promptId', promptIdLocal);
|
|
||||||
|
|
||||||
autoSelectStarterTemplate.set(autoSelectTemplateLocal);
|
|
||||||
latestBranchStore.set(enableLatestBranchLocal);
|
|
||||||
enableContextOptimizationStore.set(contextOptimizationLocal);
|
|
||||||
isEventLogsEnabled.set(eventLogsLocal);
|
|
||||||
isLocalModelsEnabled.set(experimentalProvidersLocal);
|
|
||||||
promptAtom.set(promptIdLocal);
|
|
||||||
}, [
|
|
||||||
autoSelectTemplateLocal,
|
|
||||||
enableLatestBranchLocal,
|
|
||||||
contextOptimizationLocal,
|
|
||||||
eventLogsLocal,
|
|
||||||
experimentalProvidersLocal,
|
|
||||||
promptLibraryLocal,
|
|
||||||
promptIdLocal,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const handleToggleFeature = (featureId: string, enabled: boolean) => {
|
|
||||||
logStore.logFeatureToggle(featureId, enabled);
|
|
||||||
|
|
||||||
switch (featureId) {
|
|
||||||
case 'latestBranch':
|
|
||||||
setEnableLatestBranchLocal(enabled);
|
|
||||||
latestBranchStore.set(enabled);
|
|
||||||
toast.success(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
case 'autoSelectTemplate':
|
|
||||||
setAutoSelectTemplateLocal(enabled);
|
|
||||||
autoSelectStarterTemplate.set(enabled);
|
|
||||||
toast.success(`Auto template selection ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
case 'contextOptimization':
|
|
||||||
setContextOptimizationLocal(enabled);
|
|
||||||
enableContextOptimizationStore.set(enabled);
|
|
||||||
toast.success(`Context optimization ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
case 'localModels':
|
|
||||||
setExperimentalProvidersLocal(enabled);
|
|
||||||
isLocalModelsEnabled.set(enabled);
|
|
||||||
toast.success(`Experimental providers ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
case 'eventLogs':
|
|
||||||
setEventLogsLocal(enabled);
|
|
||||||
isEventLogsEnabled.set(enabled);
|
|
||||||
toast.success(`Event logging ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
case 'promptLibrary':
|
|
||||||
setPromptLibraryLocal(enabled);
|
|
||||||
toast.success(`Prompt Library ${enabled ? 'enabled' : 'disabled'}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const features: Record<'stable' | 'beta' | 'experimental', FeatureToggle[]> = {
|
|
||||||
stable: [
|
stable: [
|
||||||
|
{
|
||||||
|
id: 'latestBranch',
|
||||||
|
title: 'Main Branch Updates',
|
||||||
|
description: 'Get the latest updates from the main branch',
|
||||||
|
icon: 'i-ph:git-branch',
|
||||||
|
enabled: isLatestBranch,
|
||||||
|
tooltip: 'Enable to receive updates from the main development branch',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'autoSelectTemplate',
|
id: 'autoSelectTemplate',
|
||||||
title: 'Auto Select Code Template',
|
title: 'Auto Select Template',
|
||||||
description: 'Let Bolt select the best starter template for your project',
|
description: 'Automatically select starter template',
|
||||||
icon: 'i-ph:magic-wand',
|
icon: 'i-ph:selection',
|
||||||
enabled: autoSelectTemplateLocal,
|
enabled: autoSelectTemplate,
|
||||||
tooltip: 'Automatically choose the most suitable template based on your project type',
|
tooltip: 'Automatically select the most appropriate starter template',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'contextOptimization',
|
id: 'contextOptimization',
|
||||||
title: 'Context Optimization',
|
title: 'Context Optimization',
|
||||||
description: 'Optimize chat context by redacting file contents and using system prompts',
|
description: 'Optimize context for better responses',
|
||||||
icon: 'i-ph:arrows-in',
|
icon: 'i-ph:brain',
|
||||||
enabled: contextOptimizationLocal,
|
enabled: contextOptimizationEnabled,
|
||||||
tooltip: 'Improve AI responses by optimizing the context window and system prompts',
|
tooltip: 'Enable context optimization for improved AI responses',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'eventLogs',
|
id: 'eventLogs',
|
||||||
title: 'Event Logging',
|
title: 'Event Logging',
|
||||||
description: 'Enable detailed event logging and history',
|
description: 'Enable detailed event logging and history',
|
||||||
icon: 'i-ph:list-bullets',
|
icon: 'i-ph:list-bullets',
|
||||||
enabled: eventLogsLocal,
|
enabled: eventLogs,
|
||||||
tooltip: 'Record detailed logs of system events and user actions',
|
tooltip: 'Record detailed logs of system events and user actions',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'promptLibrary',
|
|
||||||
title: 'Prompt Library',
|
|
||||||
description: 'Manage your prompt library settings',
|
|
||||||
icon: 'i-ph:library',
|
|
||||||
enabled: promptLibraryLocal,
|
|
||||||
tooltip: 'Enable or disable the prompt library',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
beta: [],
|
beta: [],
|
||||||
experimental: [
|
experimental: [
|
||||||
@ -249,7 +193,7 @@ export default function FeaturesTab() {
|
|||||||
title: 'Experimental Providers',
|
title: 'Experimental Providers',
|
||||||
description: 'Enable experimental providers like Ollama, LMStudio, and OpenAILike',
|
description: 'Enable experimental providers like Ollama, LMStudio, and OpenAILike',
|
||||||
icon: 'i-ph:robot',
|
icon: 'i-ph:robot',
|
||||||
enabled: experimentalProvidersLocal,
|
enabled: isLocalModel,
|
||||||
experimental: true,
|
experimental: true,
|
||||||
tooltip: 'Try out new AI providers and models in development',
|
tooltip: 'Try out new AI providers and models in development',
|
||||||
},
|
},
|
||||||
@ -319,9 +263,9 @@ export default function FeaturesTab() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<select
|
<select
|
||||||
value={promptIdLocal}
|
value={promptId}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setPromptIdLocal(e.target.value);
|
setPromptId(e.target.value);
|
||||||
toast.success('Prompt template updated');
|
toast.success('Prompt template updated');
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
|||||||
@ -62,74 +62,73 @@ const CloudProvidersTab = () => {
|
|||||||
const [filteredProviders, setFilteredProviders] = useState<IProviderConfig[]>([]);
|
const [filteredProviders, setFilteredProviders] = useState<IProviderConfig[]>([]);
|
||||||
const [categoryEnabled, setCategoryEnabled] = useState<boolean>(false);
|
const [categoryEnabled, setCategoryEnabled] = useState<boolean>(false);
|
||||||
|
|
||||||
// Effect to filter and sort providers
|
// Load and filter providers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newFilteredProviders = Object.entries(settings.providers || {})
|
const newFilteredProviders = Object.entries(settings.providers || {})
|
||||||
.filter(([key]) => !['Ollama', 'LMStudio', 'OpenAILike'].includes(key)) // Filter out local providers
|
.filter(([key]) => !['Ollama', 'LMStudio', 'OpenAILike'].includes(key))
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => ({
|
||||||
const provider = value as IProviderConfig;
|
name: key,
|
||||||
return {
|
settings: value.settings,
|
||||||
name: key,
|
staticModels: value.staticModels || [],
|
||||||
settings: provider.settings,
|
getDynamicModels: value.getDynamicModels,
|
||||||
staticModels: provider.staticModels || [],
|
getApiKeyLink: value.getApiKeyLink,
|
||||||
getDynamicModels: provider.getDynamicModels,
|
labelForGetApiKey: value.labelForGetApiKey,
|
||||||
getApiKeyLink: provider.getApiKeyLink,
|
icon: value.icon,
|
||||||
labelForGetApiKey: provider.labelForGetApiKey,
|
}));
|
||||||
icon: provider.icon,
|
|
||||||
} as IProviderConfig;
|
|
||||||
});
|
|
||||||
|
|
||||||
const sorted = newFilteredProviders.sort((a, b) => a.name.localeCompare(b.name));
|
const sorted = newFilteredProviders.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
const regular = sorted.filter((p) => !URL_CONFIGURABLE_PROVIDERS.includes(p.name));
|
setFilteredProviders(sorted);
|
||||||
const urlConfigurable = sorted.filter((p) => URL_CONFIGURABLE_PROVIDERS.includes(p.name));
|
|
||||||
|
|
||||||
setFilteredProviders([...regular, ...urlConfigurable]);
|
// Update category enabled state
|
||||||
|
const allEnabled = newFilteredProviders.every((p) => p.settings.enabled);
|
||||||
|
setCategoryEnabled(allEnabled);
|
||||||
}, [settings.providers]);
|
}, [settings.providers]);
|
||||||
|
|
||||||
// Add effect to update category toggle state based on provider states
|
|
||||||
useEffect(() => {
|
|
||||||
const newCategoryState = filteredProviders.every((p) => p.settings.enabled);
|
|
||||||
setCategoryEnabled(newCategoryState);
|
|
||||||
}, [filteredProviders]);
|
|
||||||
|
|
||||||
const handleToggleCategory = useCallback(
|
const handleToggleCategory = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
setCategoryEnabled(enabled);
|
// Update all providers
|
||||||
filteredProviders.forEach((provider) => {
|
filteredProviders.forEach((provider) => {
|
||||||
settings.updateProviderSettings(provider.name, { ...provider.settings, enabled });
|
settings.updateProviderSettings(provider.name, { ...provider.settings, enabled });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setCategoryEnabled(enabled);
|
||||||
toast.success(enabled ? 'All cloud providers enabled' : 'All cloud providers disabled');
|
toast.success(enabled ? 'All cloud providers enabled' : 'All cloud providers disabled');
|
||||||
},
|
},
|
||||||
[filteredProviders, settings],
|
[filteredProviders, settings],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleProvider = (provider: IProviderConfig, enabled: boolean) => {
|
const handleToggleProvider = useCallback(
|
||||||
settings.updateProviderSettings(provider.name, { ...provider.settings, enabled });
|
(provider: IProviderConfig, enabled: boolean) => {
|
||||||
|
// Update the provider settings in the store
|
||||||
|
settings.updateProviderSettings(provider.name, { ...provider.settings, enabled });
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
logStore.logProvider(`Provider ${provider.name} enabled`, { provider: provider.name });
|
logStore.logProvider(`Provider ${provider.name} enabled`, { provider: provider.name });
|
||||||
toast.success(`${provider.name} enabled`);
|
toast.success(`${provider.name} enabled`);
|
||||||
} else {
|
} else {
|
||||||
logStore.logProvider(`Provider ${provider.name} disabled`, { provider: provider.name });
|
logStore.logProvider(`Provider ${provider.name} disabled`, { provider: provider.name });
|
||||||
toast.success(`${provider.name} disabled`);
|
toast.success(`${provider.name} disabled`);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[settings],
|
||||||
|
);
|
||||||
|
|
||||||
const handleUpdateBaseUrl = (provider: IProviderConfig, baseUrl: string) => {
|
const handleUpdateBaseUrl = useCallback(
|
||||||
let newBaseUrl: string | undefined = baseUrl;
|
(provider: IProviderConfig, baseUrl: string) => {
|
||||||
|
const newBaseUrl: string | undefined = baseUrl.trim() || undefined;
|
||||||
|
|
||||||
if (newBaseUrl && newBaseUrl.trim().length === 0) {
|
// Update the provider settings in the store
|
||||||
newBaseUrl = undefined;
|
settings.updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
|
||||||
}
|
|
||||||
|
|
||||||
settings.updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
|
logStore.logProvider(`Base URL updated for ${provider.name}`, {
|
||||||
logStore.logProvider(`Base URL updated for ${provider.name}`, {
|
provider: provider.name,
|
||||||
provider: provider.name,
|
baseUrl: newBaseUrl,
|
||||||
baseUrl: newBaseUrl,
|
});
|
||||||
});
|
toast.success(`${provider.name} base URL updated`);
|
||||||
toast.success(`${provider.name} base URL updated`);
|
setEditingProvider(null);
|
||||||
setEditingProvider(null);
|
},
|
||||||
};
|
[settings],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|||||||
@ -12,6 +12,13 @@ import {
|
|||||||
tabConfigurationStore,
|
tabConfigurationStore,
|
||||||
updateTabConfiguration as updateTabConfig,
|
updateTabConfiguration as updateTabConfig,
|
||||||
resetTabConfiguration as resetTabConfig,
|
resetTabConfiguration as resetTabConfig,
|
||||||
|
updateProviderSettings as updateProviderSettingsStore,
|
||||||
|
updateLatestBranch,
|
||||||
|
updateAutoSelectTemplate,
|
||||||
|
updateContextOptimization,
|
||||||
|
updateEventLogs,
|
||||||
|
updateLocalModels,
|
||||||
|
updatePromptId,
|
||||||
} from '~/lib/stores/settings';
|
} from '~/lib/stores/settings';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
@ -64,8 +71,13 @@ export interface UseSettingsReturn {
|
|||||||
resetTabConfiguration: () => void;
|
resetTabConfiguration: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add interface to match ProviderSetting type
|
||||||
|
interface ProviderSettingWithIndex extends IProviderSetting {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
export function useSettings(): UseSettingsReturn {
|
export function useSettings(): UseSettingsReturn {
|
||||||
const providers = useStore(providersStore) as Record<string, IProviderConfig>;
|
const providers = useStore(providersStore);
|
||||||
const debug = useStore(isDebugMode);
|
const debug = useStore(isDebugMode);
|
||||||
const eventLogs = useStore(isEventLogsEnabled);
|
const eventLogs = useStore(isEventLogsEnabled);
|
||||||
const promptId = useStore(promptStore);
|
const promptId = useStore(promptStore);
|
||||||
@ -87,16 +99,6 @@ export function useSettings(): UseSettingsReturn {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// writing values to cookies on change
|
|
||||||
useEffect(() => {
|
|
||||||
const providers = providersStore.get();
|
|
||||||
const providerSetting: Record<string, IProviderSetting> = {};
|
|
||||||
Object.keys(providers).forEach((provider) => {
|
|
||||||
providerSetting[provider] = providers[provider].settings;
|
|
||||||
});
|
|
||||||
Cookies.set('providers', JSON.stringify(providerSetting));
|
|
||||||
}, [providers]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let active = Object.entries(providers)
|
let active = Object.entries(providers)
|
||||||
.filter(([_key, provider]) => provider.settings.enabled)
|
.filter(([_key, provider]) => provider.settings.enabled)
|
||||||
@ -118,8 +120,8 @@ export function useSettings(): UseSettingsReturn {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateProviderSettings = useCallback((provider: string, config: IProviderSetting) => {
|
const updateProviderSettings = useCallback((provider: string, config: ProviderSettingWithIndex) => {
|
||||||
providersStore.setKey(provider, { settings: config } as IProviderConfig);
|
updateProviderSettingsStore(provider, config);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const enableDebugMode = useCallback((enabled: boolean) => {
|
const enableDebugMode = useCallback((enabled: boolean) => {
|
||||||
@ -129,38 +131,33 @@ export function useSettings(): UseSettingsReturn {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setEventLogs = useCallback((enabled: boolean) => {
|
const setEventLogs = useCallback((enabled: boolean) => {
|
||||||
isEventLogsEnabled.set(enabled);
|
updateEventLogs(enabled);
|
||||||
logStore.logSystem(`Event logs ${enabled ? 'enabled' : 'disabled'}`);
|
logStore.logSystem(`Event logs ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
Cookies.set('isEventLogsEnabled', String(enabled));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const enableLocalModels = useCallback((enabled: boolean) => {
|
const enableLocalModels = useCallback((enabled: boolean) => {
|
||||||
isLocalModelsEnabled.set(enabled);
|
updateLocalModels(enabled);
|
||||||
logStore.logSystem(`Local models ${enabled ? 'enabled' : 'disabled'}`);
|
logStore.logSystem(`Local models ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
Cookies.set('isLocalModelsEnabled', String(enabled));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setPromptId = useCallback((promptId: string) => {
|
const setPromptId = useCallback((id: string) => {
|
||||||
promptStore.set(promptId);
|
updatePromptId(id);
|
||||||
Cookies.set('promptId', promptId);
|
logStore.logSystem(`Prompt template updated to ${id}`);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const enableLatestBranch = useCallback((enabled: boolean) => {
|
const enableLatestBranch = useCallback((enabled: boolean) => {
|
||||||
latestBranchStore.set(enabled);
|
updateLatestBranch(enabled);
|
||||||
logStore.logSystem(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
|
logStore.logSystem(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
Cookies.set('isLatestBranch', String(enabled));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setAutoSelectTemplate = useCallback((enabled: boolean) => {
|
const setAutoSelectTemplate = useCallback((enabled: boolean) => {
|
||||||
autoSelectStarterTemplate.set(enabled);
|
updateAutoSelectTemplate(enabled);
|
||||||
logStore.logSystem(`Auto select template ${enabled ? 'enabled' : 'disabled'}`);
|
logStore.logSystem(`Auto select template ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
Cookies.set('autoSelectTemplate', String(enabled));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const enableContextOptimization = useCallback((enabled: boolean) => {
|
const enableContextOptimization = useCallback((enabled: boolean) => {
|
||||||
enableContextOptimizationStore.set(enabled);
|
updateContextOptimization(enabled);
|
||||||
logStore.logSystem(`Context optimization ${enabled ? 'enabled' : 'disabled'}`);
|
logStore.logSystem(`Context optimization ${enabled ? 'enabled' : 'disabled'}`);
|
||||||
Cookies.set('contextOptimizationEnabled', String(enabled));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setTheme = useCallback(
|
const setTheme = useCallback(
|
||||||
@ -191,6 +188,18 @@ export function useSettings(): UseSettingsReturn {
|
|||||||
[saveSettings],
|
[saveSettings],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fix the providers cookie sync
|
||||||
|
useEffect(() => {
|
||||||
|
const providers = providersStore.get();
|
||||||
|
const providerSetting: Record<string, { enabled: boolean }> = {};
|
||||||
|
Object.keys(providers).forEach((provider) => {
|
||||||
|
providerSetting[provider] = {
|
||||||
|
enabled: providers[provider].settings.enabled || false, // Add fallback for undefined
|
||||||
|
};
|
||||||
|
});
|
||||||
|
Cookies.set('providers', JSON.stringify(providerSetting));
|
||||||
|
}, [providers]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...settings,
|
...settings,
|
||||||
providers,
|
providers,
|
||||||
|
|||||||
@ -59,40 +59,142 @@ export const shortcutsStore = map<Shortcuts>({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialProviderSettings: ProviderSetting = {};
|
// Create a single key for provider settings
|
||||||
PROVIDER_LIST.forEach((provider) => {
|
const PROVIDER_SETTINGS_KEY = 'provider_settings';
|
||||||
initialProviderSettings[provider.name] = {
|
|
||||||
...provider,
|
// Initialize provider settings from both localStorage and defaults
|
||||||
|
const getInitialProviderSettings = (): ProviderSetting => {
|
||||||
|
const savedSettings = localStorage.getItem(PROVIDER_SETTINGS_KEY);
|
||||||
|
const initialSettings: ProviderSetting = {};
|
||||||
|
|
||||||
|
// Start with default settings
|
||||||
|
PROVIDER_LIST.forEach((provider) => {
|
||||||
|
initialSettings[provider.name] = {
|
||||||
|
...provider,
|
||||||
|
settings: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override with saved settings if they exist
|
||||||
|
if (savedSettings) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(savedSettings);
|
||||||
|
Object.entries(parsed).forEach(([key, value]) => {
|
||||||
|
if (initialSettings[key]) {
|
||||||
|
initialSettings[key].settings = (value as IProviderConfig).settings;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing saved provider settings:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const providersStore = map<ProviderSetting>(getInitialProviderSettings());
|
||||||
|
|
||||||
|
// Create a function to update provider settings that handles both store and persistence
|
||||||
|
export const updateProviderSettings = (provider: string, settings: ProviderSetting) => {
|
||||||
|
const currentSettings = providersStore.get();
|
||||||
|
|
||||||
|
// Create new provider config with updated settings
|
||||||
|
const updatedProvider = {
|
||||||
|
...currentSettings[provider],
|
||||||
settings: {
|
settings: {
|
||||||
enabled: true,
|
...currentSettings[provider].settings,
|
||||||
|
...settings,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
||||||
//TODO: need to create one single map for all these flags
|
// Update the store with new settings
|
||||||
|
providersStore.setKey(provider, updatedProvider);
|
||||||
|
|
||||||
export const providersStore = map<ProviderSetting>(initialProviderSettings);
|
// Save to localStorage
|
||||||
|
const allSettings = providersStore.get();
|
||||||
|
localStorage.setItem(PROVIDER_SETTINGS_KEY, JSON.stringify(allSettings));
|
||||||
|
};
|
||||||
|
|
||||||
export const isDebugMode = atom(false);
|
export const isDebugMode = atom(false);
|
||||||
|
|
||||||
// Initialize event logs from cookie or default to false
|
// Define keys for localStorage
|
||||||
const savedEventLogs = Cookies.get('isEventLogsEnabled');
|
const SETTINGS_KEYS = {
|
||||||
export const isEventLogsEnabled = atom(savedEventLogs === 'true');
|
LATEST_BRANCH: 'isLatestBranch',
|
||||||
|
AUTO_SELECT_TEMPLATE: 'autoSelectTemplate',
|
||||||
|
CONTEXT_OPTIMIZATION: 'contextOptimizationEnabled',
|
||||||
|
EVENT_LOGS: 'isEventLogsEnabled',
|
||||||
|
LOCAL_MODELS: 'isLocalModelsEnabled',
|
||||||
|
PROMPT_ID: 'promptId',
|
||||||
|
} as const;
|
||||||
|
|
||||||
// Local models settings
|
// Initialize settings from localStorage or defaults
|
||||||
export const isLocalModelsEnabled = atom(true);
|
const getInitialSettings = () => {
|
||||||
|
const getStoredBoolean = (key: string, defaultValue: boolean): boolean => {
|
||||||
|
const stored = localStorage.getItem(key);
|
||||||
|
|
||||||
// Prompt settings
|
if (stored === null) {
|
||||||
export const promptStore = atom<string>('default');
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
// Branch settings
|
try {
|
||||||
export const latestBranchStore = atom(false);
|
return JSON.parse(stored);
|
||||||
|
} catch {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Template settings
|
return {
|
||||||
export const autoSelectStarterTemplate = atom(false);
|
latestBranch: getStoredBoolean(SETTINGS_KEYS.LATEST_BRANCH, false),
|
||||||
|
autoSelectTemplate: getStoredBoolean(SETTINGS_KEYS.AUTO_SELECT_TEMPLATE, false),
|
||||||
|
contextOptimization: getStoredBoolean(SETTINGS_KEYS.CONTEXT_OPTIMIZATION, false),
|
||||||
|
eventLogs: getStoredBoolean(SETTINGS_KEYS.EVENT_LOGS, true),
|
||||||
|
localModels: getStoredBoolean(SETTINGS_KEYS.LOCAL_MODELS, true),
|
||||||
|
promptId: localStorage.getItem(SETTINGS_KEYS.PROMPT_ID) || 'default',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Context optimization settings
|
// Initialize stores with persisted values
|
||||||
export const enableContextOptimizationStore = atom(false);
|
const initialSettings = getInitialSettings();
|
||||||
|
|
||||||
|
export const latestBranchStore = atom<boolean>(initialSettings.latestBranch);
|
||||||
|
export const autoSelectStarterTemplate = atom<boolean>(initialSettings.autoSelectTemplate);
|
||||||
|
export const enableContextOptimizationStore = atom<boolean>(initialSettings.contextOptimization);
|
||||||
|
export const isEventLogsEnabled = atom<boolean>(initialSettings.eventLogs);
|
||||||
|
export const isLocalModelsEnabled = atom<boolean>(initialSettings.localModels);
|
||||||
|
export const promptStore = atom<string>(initialSettings.promptId);
|
||||||
|
|
||||||
|
// Helper functions to update settings with persistence
|
||||||
|
export const updateLatestBranch = (enabled: boolean) => {
|
||||||
|
latestBranchStore.set(enabled);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.LATEST_BRANCH, JSON.stringify(enabled));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateAutoSelectTemplate = (enabled: boolean) => {
|
||||||
|
autoSelectStarterTemplate.set(enabled);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.AUTO_SELECT_TEMPLATE, JSON.stringify(enabled));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateContextOptimization = (enabled: boolean) => {
|
||||||
|
enableContextOptimizationStore.set(enabled);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.CONTEXT_OPTIMIZATION, JSON.stringify(enabled));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateEventLogs = (enabled: boolean) => {
|
||||||
|
isEventLogsEnabled.set(enabled);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.EVENT_LOGS, JSON.stringify(enabled));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateLocalModels = (enabled: boolean) => {
|
||||||
|
isLocalModelsEnabled.set(enabled);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.LOCAL_MODELS, JSON.stringify(enabled));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updatePromptId = (id: string) => {
|
||||||
|
promptStore.set(id);
|
||||||
|
localStorage.setItem(SETTINGS_KEYS.PROMPT_ID, id);
|
||||||
|
};
|
||||||
|
|
||||||
// Initialize tab configuration from cookie or default
|
// Initialize tab configuration from cookie or default
|
||||||
const savedTabConfig = Cookies.get('tabConfiguration');
|
const savedTabConfig = Cookies.get('tabConfiguration');
|
||||||
|
|||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user