Cleanup Phase 1: Remove unused React imports from safe components (#2702)

Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Zane
2025-05-29 09:13:26 -07:00
committed by GitHub
parent bf1c0d51e4
commit 3d5d3cedca
108 changed files with 203 additions and 194 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { IpcRendererEvent } from 'electron'; import { IpcRendererEvent } from 'electron';
import { openSharedSessionFromDeepLink } from './sessionLinks'; import { openSharedSessionFromDeepLink } from './sessionLinks';
import { initializeSystem } from './utils/providerUtils'; import { initializeSystem } from './utils/providerUtils';
@@ -8,6 +8,7 @@ import { ToastContainer } from 'react-toastify';
import { toastService } from './toasts'; import { toastService } from './toasts';
import { extractExtensionName } from './components/settings/extensions/utils'; import { extractExtensionName } from './components/settings/extensions/utils';
import { GoosehintsModal } from './components/GoosehintsModal'; import { GoosehintsModal } from './components/GoosehintsModal';
import { type ExtensionConfig } from './extensions';
import ChatView from './components/ChatView'; import ChatView from './components/ChatView';
import SuspenseLoader from './suspense-loader'; import SuspenseLoader from './suspense-loader';
@@ -46,10 +47,28 @@ export type View =
| 'recipeEditor' | 'recipeEditor'
| 'permission'; | 'permission';
export type ViewOptions = export type ViewOptions = {
| SettingsViewOptions // Settings view options
| { resumedSession?: SessionDetails } extensionId?: string;
| Record<string, unknown>; showEnvVars?: boolean;
deepLinkConfig?: ExtensionConfig;
// Session view options
resumedSession?: SessionDetails;
sessionDetails?: SessionDetails;
error?: string;
shareToken?: string;
baseUrl?: string;
// Recipe editor options
config?: unknown;
// Permission view options
parentView?: View;
// Generic options
[key: string]: unknown;
};
export type ViewConfig = { export type ViewConfig = {
view: View; view: View;
@@ -103,7 +122,7 @@ export default function App() {
return `${cmd} ${args.join(' ')}`.trim(); return `${cmd} ${args.join(' ')}`.trim();
} }
function extractRemoteUrl(link: string): string { function extractRemoteUrl(link: string): string | null {
const url = new URL(link); const url = new URL(link);
return url.searchParams.get('url'); return url.searchParams.get('url');
} }
@@ -164,7 +183,7 @@ export default function App() {
if (provider && model) { if (provider && model) {
setView('chat'); setView('chat');
try { try {
await initializeSystem(provider, model, { await initializeSystem(provider as string, model as string, {
getExtensions, getExtensions,
addExtension, addExtension,
}); });
@@ -289,7 +308,7 @@ export default function App() {
}; };
setView(viewFromUrl, initialViewOptions); setView(viewFromUrl, initialViewOptions);
} else { } else {
setView(viewFromUrl); setView(viewFromUrl as View);
} }
} }
window.electron.on('set-view', handleSetView); window.electron.on('set-view', handleSetView);

View File

@@ -1,4 +1,3 @@
import React from 'react';
interface AgentHeaderProps { interface AgentHeaderProps {
title: string; title: string;

View File

@@ -1,4 +1,4 @@
import React, { useRef, useState, useEffect, useCallback } from 'react'; import React, { useRef, useState, useEffect, useMemo } from 'react';
import { Button } from './ui/button'; import { Button } from './ui/button';
import type { View } from '../App'; import type { View } from '../App';
import Stop from './ui/Stop'; import Stop from './ui/Stop';
@@ -148,21 +148,20 @@ export default function ChatInput({
}, [droppedFiles, processedFilePaths, displayValue]); }, [droppedFiles, processedFilePaths, displayValue]);
// Debounced function to update actual value // Debounced function to update actual value
const debouncedSetValue = useCallback((val: string) => { const debouncedSetValue = useMemo(
debounce((value: string) => { () => debounce((value: string) => {
setValue(value); setValue(value);
}, 150)(val); }, 150),
}, []); [setValue]
);
// Debounced autosize function // Debounced autosize function
const debouncedAutosize = useCallback( const debouncedAutosize = useMemo(
(textArea: HTMLTextAreaElement) => { () => debounce((element: HTMLTextAreaElement) => {
debounce((element: HTMLTextAreaElement) => {
element.style.height = '0px'; // Reset height element.style.height = '0px'; // Reset height
const scrollHeight = element.scrollHeight; const scrollHeight = element.scrollHeight;
element.style.height = Math.min(scrollHeight, maxHeight) + 'px'; element.style.height = Math.min(scrollHeight, maxHeight) + 'px';
}, 150)(textArea); }, 150),
},
[maxHeight] [maxHeight]
); );

View File

@@ -272,7 +272,7 @@ function ChatContent({
// Update chat messages when they change and save to sessionStorage // Update chat messages when they change and save to sessionStorage
useEffect(() => { useEffect(() => {
setChat((prevChat) => { setChat((prevChat: ChatType) => {
const updatedChat = { ...prevChat, messages }; const updatedChat = { ...prevChat, messages };
return updatedChat; return updatedChat;
}); });

View File

@@ -74,7 +74,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
const reloadConfig = useCallback(async () => { const reloadConfig = useCallback(async () => {
const response = await readAllConfig(); const response = await readAllConfig();
setConfig(response.data.config || {}); setConfig(response.data?.config || {});
}, []); }, []);
const upsert = useCallback( const upsert = useCallback(
@@ -186,7 +186,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
(async () => { (async () => {
// Load config // Load config
const configResponse = await readAllConfig(); const configResponse = await readAllConfig();
setConfig(configResponse.data.config || {}); setConfig(configResponse.data?.config || {});
// Load providers // Load providers
try { try {
@@ -199,7 +199,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
// Load extensions // Load extensions
try { try {
const extensionsResponse = await apiGetExtensions(); const extensionsResponse = await apiGetExtensions();
setExtensionsList(extensionsResponse.data.extensions); setExtensionsList(extensionsResponse.data?.extensions || []);
} catch (error) { } catch (error) {
console.error('Failed to load extensions:', error); console.error('Failed to load extensions:', error);
} }

View File

@@ -14,7 +14,7 @@ window.addEventListener('error', (event) => {
); );
}); });
export function ErrorUI({ error }) { export function ErrorUI({ error }: { error: Error }) {
return ( return (
<div className="fixed inset-0 w-full h-full flex flex-col items-center justify-center gap-6 bg-background"> <div className="fixed inset-0 w-full h-full flex flex-col items-center justify-center gap-6 bg-background">
<div className="flex flex-col items-center gap-4 max-w-[600px] text-center px-6"> <div className="flex flex-col items-center gap-4 max-w-[600px] text-center px-6">

View File

@@ -216,7 +216,7 @@ const FlappyGoose: React.FC<FlappyGooseProps> = ({ onClose }) => {
useEffect(() => { useEffect(() => {
const frames = [svg1, svg7]; const frames = [svg1, svg7];
frames.forEach((src, index) => { frames.forEach((src, index) => {
const img = new Image(); const img = new Image() as HTMLImageElement;
img.src = src; img.src = src;
img.onload = () => { img.onload = () => {
framesLoaded.current += 1; framesLoaded.current += 1;

View File

@@ -1,7 +1,12 @@
import React from 'react';
import { Goose, Rain } from './icons/Goose'; import { Goose, Rain } from './icons/Goose';
export default function GooseLogo({ className = '', size = 'default', hover = true }) { interface GooseLogoProps {
className?: string;
size?: 'default' | 'small';
hover?: boolean;
}
export default function GooseLogo({ className = '', size = 'default', hover = true }: GooseLogoProps) {
const sizes = { const sizes = {
default: { default: {
frame: 'w-16 h-16', frame: 'w-16 h-16',
@@ -13,15 +18,18 @@ export default function GooseLogo({ className = '', size = 'default', hover = tr
rain: 'w-[150px] h-[150px]', rain: 'w-[150px] h-[150px]',
goose: 'w-8 h-8', goose: 'w-8 h-8',
}, },
}; } as const;
const currentSize = sizes[size];
return ( return (
<div <div
className={`${className} ${sizes[size].frame} ${hover ? 'group/with-hover' : ''} relative overflow-hidden`} className={`${className} ${currentSize.frame} ${hover ? 'group/with-hover' : ''} relative overflow-hidden`}
> >
<Rain <Rain
className={`${sizes[size].rain} absolute left-0 bottom-0 ${hover ? 'opacity-0 group-hover/with-hover:opacity-100' : ''} transition-all duration-300 z-1`} className={`${currentSize.rain} absolute left-0 bottom-0 ${hover ? 'opacity-0 group-hover/with-hover:opacity-100' : ''} transition-all duration-300 z-1`}
/> />
<Goose className={`${sizes[size].goose} absolute left-0 bottom-0 z-2`} /> <Goose className={`${currentSize.goose} absolute left-0 bottom-0 z-2`} />
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import LinkPreview from './LinkPreview'; import LinkPreview from './LinkPreview';
import ImagePreview from './ImagePreview'; import ImagePreview from './ImagePreview';
import GooseResponseForm from './GooseResponseForm'; import GooseResponseForm from './GooseResponseForm';

View File

@@ -3,7 +3,7 @@ import { Card } from './ui/card';
import { Button } from './ui/button'; import { Button } from './ui/button';
import { Check } from './icons'; import { Check } from './icons';
const Modal = ({ children }) => ( const Modal = ({ children }: { children: React.ReactNode }) => (
<div className="fixed inset-0 bg-black/20 dark:bg-white/20 backdrop-blur-sm transition-colors animate-[fadein_200ms_ease-in_forwards] z-[1000]"> <div className="fixed inset-0 bg-black/20 dark:bg-white/20 backdrop-blur-sm transition-colors animate-[fadein_200ms_ease-in_forwards] z-[1000]">
<Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col min-w-[80%] min-h-[80%] bg-bgApp rounded-xl overflow-hidden shadow-none px-8 pt-[24px] pb-0"> <Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col min-w-[80%] min-h-[80%] bg-bgApp rounded-xl overflow-hidden shadow-none px-8 pt-[24px] pb-0">
<div className="flex flex-col flex-1 space-y-8 text-base text-textStandard h-full"> <div className="flex flex-col flex-1 space-y-8 text-base text-textStandard h-full">
@@ -48,13 +48,13 @@ const ModalHelpText = () => (
</div> </div>
); );
const ModalError = ({ error }) => ( const ModalError = ({ error }: { error: Error }) => (
<div className="text-sm text-textSubtle"> <div className="text-sm text-textSubtle">
<div className="text-red-600">Error reading .goosehints file: {JSON.stringify(error)}</div> <div className="text-red-600">Error reading .goosehints file: {JSON.stringify(error)}</div>
</div> </div>
); );
const ModalFileInfo = ({ filePath, found }) => ( const ModalFileInfo = ({ filePath, found }: { filePath: string; found: boolean }) => (
<div className="text-sm font-medium"> <div className="text-sm font-medium">
{found ? ( {found ? (
<div className="text-green-600"> <div className="text-green-600">
@@ -66,7 +66,7 @@ const ModalFileInfo = ({ filePath, found }) => (
</div> </div>
); );
const ModalButtons = ({ onSubmit, onCancel }) => ( const ModalButtons = ({ onSubmit, onCancel }: { onSubmit: () => void; onCancel: () => void }) => (
<div className="-ml-8 -mr-8"> <div className="-ml-8 -mr-8">
<Button <Button
type="submit" type="submit"
@@ -87,7 +87,7 @@ const ModalButtons = ({ onSubmit, onCancel }) => (
</div> </div>
); );
const getGoosehintsFile = async (filePath) => await window.electron.readFile(filePath); const getGoosehintsFile = async (filePath: string) => await window.electron.readFile(filePath);
type GoosehintsModalProps = { type GoosehintsModalProps = {
directory: string; directory: string;

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
interface ImagePreviewProps { interface ImagePreviewProps {
src: string; src: string;

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Geese } from './icons/Geese'; import { Geese } from './icons/Geese';
export default function LayingEggLoader() { export default function LayingEggLoader() {

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Card } from './ui/card'; import { Card } from './ui/card';
interface Metadata { interface Metadata {
@@ -85,10 +85,11 @@ export default function LinkPreview({ url }: LinkPreviewProps) {
if (mounted) { if (mounted) {
setMetadata(data); setMetadata(data);
} }
} catch (error) { } catch (err) {
if (mounted) { if (mounted) {
console.error('❌ Failed to fetch metadata:', error); console.error('❌ Failed to fetch metadata:', err);
setError(error.message || 'Failed to fetch metadata'); const errorMessage = err instanceof Error ? err.message : 'Failed to fetch metadata';
setError(errorMessage);
} }
} finally { } finally {
if (mounted) { if (mounted) {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import GooseLogo from './GooseLogo'; import GooseLogo from './GooseLogo';
const LoadingGoose = () => { const LoadingGoose = () => {

View File

@@ -1,4 +1,3 @@
import React from 'react';
export function LoadingPlaceholder() { export function LoadingPlaceholder() {
return ( return (

View File

@@ -43,7 +43,7 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
}); });
}, [activeKeys]); }, [activeKeys]);
const handleConfigure = async (provider) => { const handleConfigure = async (provider: { id: string; name: string; isConfigured: boolean; description: string }) => {
const providerId = provider.id.toLowerCase(); const providerId = provider.id.toLowerCase();
const modelName = getDefaultModel(providerId); const modelName = getDefaultModel(providerId);
@@ -63,7 +63,7 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
onSubmit?.(); onSubmit?.();
}; };
const handleAddKeys = (provider) => { const handleAddKeys = (provider: { id: string; name: string; isConfigured: boolean; description: string }) => {
setSelectedId(provider.id); setSelectedId(provider.id);
setShowSetupModal(true); setShowSetupModal(true);
}; };
@@ -74,7 +74,7 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
const provider = providers.find((p) => p.id === selectedId)?.name; const provider = providers.find((p) => p.id === selectedId)?.name;
if (!provider) return; if (!provider) return;
const requiredKeys = required_keys[provider]; const requiredKeys = required_keys[provider as keyof typeof required_keys];
if (!requiredKeys || requiredKeys.length === 0) { if (!requiredKeys || requiredKeys.length === 0) {
console.error(`No keys found for provider ${provider}`); console.error(`No keys found for provider ${provider}`);
return; return;
@@ -145,12 +145,13 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
setShowSetupModal(false); setShowSetupModal(false);
setSelectedId(null); setSelectedId(null);
} catch (error) { } catch (err) {
console.error('Error handling modal submit:', error); console.error('Error handling modal submit:', err);
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
toastError({ toastError({
title: provider, title: provider,
msg: `Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration`, msg: `Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration`,
traceback: error.message, traceback: errorMessage,
}); });
} }
}; };

View File

@@ -54,7 +54,7 @@ export default function RecipeEditor({ config }: RecipeEditorProps) {
} }
} }
// Fall back to config if available, using extension names // Fall back to config if available, using extension names
const exts = []; const exts: string[] = [];
return exts; return exts;
}); });
// Section visibility state // Section visibility state
@@ -125,7 +125,10 @@ export default function RecipeEditor({ config }: RecipeEditorProps) {
delete cleanExtension.enabled; delete cleanExtension.enabled;
// Remove legacy envs which could potentially include secrets // Remove legacy envs which could potentially include secrets
// env_keys will work but rely on the end user having setup those keys themselves // env_keys will work but rely on the end user having setup those keys themselves
delete cleanExtension.envs; if ('envs' in cleanExtension) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (cleanExtension as any).envs;
}
return cleanExtension; return cleanExtension;
}) })
.filter(Boolean) as FullExtensionConfig[], .filter(Boolean) as FullExtensionConfig[],

View File

@@ -1,4 +1,3 @@
import React from 'react';
import SplashPills from './SplashPills'; import SplashPills from './SplashPills';
import GooseLogo from './GooseLogo'; import GooseLogo from './GooseLogo';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import MarkdownContent from './MarkdownContent'; import MarkdownContent from './MarkdownContent';
function truncateText(text: string, maxLength: number = 100): string { function truncateText(text: string, maxLength: number = 100): string {

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import { useState } from 'react';
import MarkdownContent from './MarkdownContent'; import MarkdownContent from './MarkdownContent';
import Expand from './ui/Expand'; import Expand from './ui/Expand';

View File

@@ -1,4 +1,4 @@
import React, { useRef, useMemo } from 'react'; import { useRef, useMemo } from 'react';
import LinkPreview from './LinkPreview'; import LinkPreview from './LinkPreview';
import ImagePreview from './ImagePreview'; import ImagePreview from './ImagePreview';
import { extractUrls } from '../utils/urlUtils'; import { extractUrls } from '../utils/urlUtils';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Goose, Rain } from './icons/Goose'; import { Goose, Rain } from './icons/Goose';
export default function WelcomeGooseLogo({ className = '' }) { export default function WelcomeGooseLogo({ className = '' }) {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { ProviderGrid } from './ProviderGrid'; import { ProviderGrid } from './ProviderGrid';
import { ScrollArea } from './ui/scroll-area'; import { ScrollArea } from './ui/scroll-area';
import { Button } from './ui/button'; import { Button } from './ui/button';

View File

@@ -33,10 +33,10 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => {
className={cn( className={cn(
'h-[2px] w-[2px] rounded-full', 'h-[2px] w-[2px] rounded-full',
alert.type === AlertType.Info alert.type === AlertType.Info
? i < Math.round((alert.progress.current / alert.progress.total) * 30) ? i < Math.round((alert.progress!.current / alert.progress!.total) * 30)
? 'dark:bg-black bg-white' ? 'dark:bg-black bg-white'
: 'dark:bg-black/20 bg-white/20' : 'dark:bg-black/20 bg-white/20'
: i < Math.round((alert.progress.current / alert.progress.total) * 30) : i < Math.round((alert.progress!.current / alert.progress!.total) * 30)
? 'bg-white' ? 'bg-white'
: 'bg-white/20' : 'bg-white/20'
)} )}
@@ -46,18 +46,18 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => {
<div className="flex justify-between items-baseline text-[11px]"> <div className="flex justify-between items-baseline text-[11px]">
<div className="flex gap-1 items-baseline"> <div className="flex gap-1 items-baseline">
<span className={'dark:text-black/60 text-white/60'}> <span className={'dark:text-black/60 text-white/60'}>
{alert.progress.current >= 1000 {alert.progress!.current >= 1000
? (alert.progress.current / 1000).toFixed(1) + 'k' ? (alert.progress!.current / 1000).toFixed(1) + 'k'
: alert.progress.current} : alert.progress!.current}
</span> </span>
<span className={'dark:text-black/40 text-white/40'}> <span className={'dark:text-black/40 text-white/40'}>
{Math.round((alert.progress.current / alert.progress.total) * 100)}% {Math.round((alert.progress!.current / alert.progress!.total) * 100)}%
</span> </span>
</div> </div>
<span className={'dark:text-black/60 text-white/60'}> <span className={'dark:text-black/60 text-white/60'}>
{alert.progress.total >= 1000 {alert.progress!.total >= 1000
? (alert.progress.total / 1000).toFixed(0) + 'k' ? (alert.progress!.total / 1000).toFixed(0) + 'k'
: alert.progress.total} : alert.progress!.total}
</span> </span>
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState, useCallback } from 'react'; import { useEffect, useRef, useState, useCallback } from 'react';
import { all_goose_modes, ModeSelectionItem } from '../settings_v2/mode/ModeSelectionItem'; import { all_goose_modes, ModeSelectionItem } from '../settings_v2/mode/ModeSelectionItem';
import { useConfig } from '../ConfigContext'; import { useConfig } from '../ConfigContext';
import { View, ViewOptions } from '../../App'; import { View, ViewOptions } from '../../App';

View File

@@ -168,7 +168,7 @@ export const SearchBar: React.FC<SearchBarProps> = ({
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<div className="w-16 text-right text-sm text-textStandardInverse flex items-center justify-end"> <div className="w-16 text-right text-sm text-textStandardInverse flex items-center justify-end">
{(() => { {(() => {
return localSearchResults?.count > 0 && searchTerm return localSearchResults?.count && localSearchResults.count > 0 && searchTerm
? `${localSearchResults.currentIndex}/${localSearchResults.count}` ? `${localSearchResults.currentIndex}/${localSearchResults.count}`
: null; : null;
})()} })()}

View File

@@ -231,23 +231,19 @@ export const SearchView: React.FC<PropsWithChildren<SearchViewProps>> = ({
highlighterRef.current = null; highlighterRef.current = null;
} }
// Cancel any pending highlight operations
debouncedHighlight.cancel?.();
// Clear search when closing // Clear search when closing
onSearch?.('', false); onSearch?.('', false);
}, [debouncedHighlight, onSearch]); }, [onSearch]);
// Clean up highlighter and debounced functions on unmount // Clean up highlighter on unmount
useEffect(() => { useEffect(() => {
return () => { return () => {
if (highlighterRef.current) { if (highlighterRef.current) {
highlighterRef.current.destroy(); highlighterRef.current.destroy();
highlighterRef.current = null; highlighterRef.current = null;
} }
debouncedHighlight.cancel?.();
}; };
}, [debouncedHighlight]); }, []);
// Listen for keyboard events // Listen for keyboard events
useEffect(() => { useEffect(() => {

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function ArrowDown({ className = '' }) { export default function ArrowDown({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function ArrowUp({ className = '' }) { export default function ArrowUp({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Attach({ className = '' }) { export default function Attach({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Back({ className = '' }) { export default function Back({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export function Bars() { export function Bars() {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function ChatSmart({ className = '' }) { export default function ChatSmart({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Check({ className = '' }) { export default function Check({ className = '' }) {
return ( return (

View File

@@ -1,6 +1,5 @@
import React from 'react';
export default function ChevronDown({ className }) { export default function ChevronDown({ className }: { className?: string }) {
return ( return (
<svg <svg
width="1.5rem" width="1.5rem"

View File

@@ -1,4 +1,3 @@
import React from 'react';
interface Props { interface Props {
className?: string; className?: string;

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function ChevronUp({ className = '' }) { export default function ChevronUp({ className = '' }) {
return ( return (

View File

@@ -1,6 +1,5 @@
import React from 'react';
export default function Close({ className }) { export default function Close({ className }: { className?: string }) {
return ( return (
<svg <svg
fill="none" fill="none"

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Copy({ className = '' }) { export default function Copy({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Document({ className = '' }) { export default function Document({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Edit({ className = '' }) { export default function Edit({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export function Gear({ className = '' }: { className?: string }) { export function Gear({ className = '' }: { className?: string }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
interface Props { interface Props {
// eslint-disable-next-line // eslint-disable-next-line

View File

@@ -1,4 +1,3 @@
import React from 'react';
export function Goose({ className = '' }) { export function Goose({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Idea({ className = '' }) { export default function Idea({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function More({ className = '' }) { export default function More({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Refresh({ className = '' }) { export default function Refresh({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Send({ className = '' }) { export default function Send({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function SensitiveHidden({ className = '' }) { export default function SensitiveHidden({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function SensitiveVisible({ className = '' }) { export default function SensitiveVisible({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Settings({ className = '' }) { export default function Settings({ className = '' }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Time({ className = '' }) { export default function Time({ className = '' }) {
return ( return (

View File

@@ -1,5 +1,4 @@
// /Users/mnovich/Development/goose-1.0/ui/desktop/src/components/icons/TrashIcon.tsx // /Users/mnovich/Development/goose-1.0/ui/desktop/src/components/icons/TrashIcon.tsx
import React from 'react';
interface IconProps extends React.SVGProps<globalThis.SVGSVGElement> {} interface IconProps extends React.SVGProps<globalThis.SVGSVGElement> {}

View File

@@ -30,10 +30,11 @@ const SessionsView: React.FC<SessionsViewProps> = ({ setView }) => {
// Keep the selected session null if there's an error // Keep the selected session null if there's an error
setSelectedSession(null); setSelectedSession(null);
const errorMessage = err instanceof Error ? err.message : String(err);
toastError({ toastError({
title: 'Failed to load session. The file may be corrupted.', title: 'Failed to load session. The file may be corrupted.',
msg: 'Please try again later.', msg: 'Please try again later.',
traceback: err, traceback: errorMessage,
}); });
} finally { } finally {
setIsLoadingSession(false); setIsLoadingSession(false);

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
// Import actual PNG images // Import actual PNG images
import llamaSprite from '../../assets/battle-game/llama.png'; import llamaSprite from '../../assets/battle-game/llama.png';
@@ -22,11 +22,10 @@ interface OllamaBattleGameProps {
requiredKeys: string[]; requiredKeys: string[];
} }
export function OllamaBattleGame({ onComplete, _requiredKeys }: OllamaBattleGameProps) { export function OllamaBattleGame({ onComplete, requiredKeys: _ }: OllamaBattleGameProps) {
// Use Audio element type for audioRef // Use Audio element type for audioRef
const audioRef = useRef<{ play: () => Promise<void>; pause: () => void; volume: number } | null>( // eslint-disable-next-line no-undef
null const audioRef = useRef<HTMLAudioElement | null>(null);
);
const [isMuted, setIsMuted] = useState(false); const [isMuted, setIsMuted] = useState(false);
const [battleState, setBattleState] = useState<BattleState>({ const [battleState, setBattleState] = useState<BattleState>({
@@ -169,10 +168,10 @@ export function OllamaBattleGame({ onComplete, _requiredKeys }: OllamaBattleGame
if (!currentStep) return; if (!currentStep) return;
// Handle host input // Handle host input
if (currentStep.action === 'host_input' && value) { if (currentStep.action === 'host_input' && value && currentStep.configKey) {
setConfigValues((prev) => ({ setConfigValues((prev) => ({
...prev, ...prev,
[currentStep.configKey]: value, [currentStep.configKey!]: value,
})); }));
return; return;
} }
@@ -405,8 +404,8 @@ export function OllamaBattleGame({ onComplete, _requiredKeys }: OllamaBattleGame
!battleState.processingAction && ( !battleState.processingAction && (
<div className="space-y-2"> <div className="space-y-2">
{(typeof battleSteps[battleState.currentStep].choices === 'function' {(typeof battleSteps[battleState.currentStep].choices === 'function'
? battleSteps[battleState.currentStep].choices(battleState.lastChoice || '') ? (battleSteps[battleState.currentStep].choices as (choice: string) => string[])(battleState.lastChoice || '')
: battleSteps[battleState.currentStep].choices : battleSteps[battleState.currentStep].choices as string[]
)?.map((choice: string) => ( )?.map((choice: string) => (
<button <button
key={choice} key={choice}

View File

@@ -19,8 +19,8 @@ interface ProviderSetupModalProps {
export function ProviderSetupModal({ export function ProviderSetupModal({
provider, provider,
_model, _model: _,
_endpoint, _endpoint: __,
title, title,
onSubmit, onSubmit,
onCancel, onCancel,

View File

@@ -1,4 +1,4 @@
import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react'; import { createContext, useContext, useState, ReactNode, useEffect } from 'react';
import { getActiveProviders } from './utils'; import { getActiveProviders } from './utils';
import SuspenseLoader from '../../../suspense-loader'; import SuspenseLoader from '../../../suspense-loader';

View File

@@ -56,16 +56,16 @@ export async function getActiveProviders(): Promise<string[]> {
// For providers with multiple keys or keys without defaults: // For providers with multiple keys or keys without defaults:
// Check if all required keys without defaults are set // Check if all required keys without defaults are set
const requiredNonDefaultKeys = providerRequiredKeys.filter( const requiredNonDefaultKeys = providerRequiredKeys.filter(
(key) => !(key in default_key_value) (key: string) => !(key in default_key_value)
); );
// If there are no non-default keys, this provider needs at least one key explicitly set // If there are no non-default keys, this provider needs at least one key explicitly set
if (requiredNonDefaultKeys.length === 0) { if (requiredNonDefaultKeys.length === 0) {
return providerRequiredKeys.some((key) => configStatus[key]?.is_set === true); return providerRequiredKeys.some((key: string) => configStatus[key]?.is_set === true);
} }
// Otherwise, all non-default keys must be set // Otherwise, all non-default keys must be set
return requiredNonDefaultKeys.every((key) => configStatus[key]?.is_set === true); return requiredNonDefaultKeys.every((key: string) => configStatus[key]?.is_set === true);
}) })
.map((provider) => provider.name || 'Unknown Provider'); .map((provider) => provider.name || 'Unknown Provider');
@@ -96,14 +96,14 @@ export async function getConfigSettings(): Promise<Record<string, ProviderRespon
// Convert the response to the expected format // Convert the response to the expected format
const data: Record<string, ProviderResponse> = {}; const data: Record<string, ProviderResponse> = {};
providers.forEach((provider) => { providers.forEach((provider) => {
const providerRequiredKeys = required_keys[provider.name] || []; const providerRequiredKeys = required_keys[provider.name as keyof typeof required_keys] || [];
data[provider.name] = { data[provider.name] = {
name: provider.name, name: provider.name,
supported: true, supported: true,
description: provider.metadata.description, description: provider.metadata.description,
models: provider.metadata.models, models: provider.metadata.models,
config_status: providerRequiredKeys.reduce<Record<string, ConfigDetails>>((acc, key) => { config_status: providerRequiredKeys.reduce<Record<string, ConfigDetails>>((acc: Record<string, ConfigDetails>, key: string) => {
acc[key] = { acc[key] = {
key, key,
is_set: provider.is_configured, is_set: provider.is_configured,

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback } from 'react'; import { useEffect, useState, useCallback } from 'react';
import { all_goose_modes, filterGooseModes, ModeSelectionItem } from './ModeSelectionItem'; import { all_goose_modes, filterGooseModes, ModeSelectionItem } from './ModeSelectionItem';
import { useConfig } from '../../ConfigContext'; import { useConfig } from '../../ConfigContext';

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Gear } from '../../icons'; import { Gear } from '../../icons';
import { ConfigureApproveMode } from './ConfigureApproveMode'; import { ConfigureApproveMode } from './ConfigureApproveMode';

View File

@@ -74,12 +74,13 @@ export function ConfigureBuiltInExtensionModal({
}); });
onSubmit(); onSubmit();
onClose(); onClose();
} catch (error) { } catch (err) {
console.error('Error configuring extension:', error); console.error('Error configuring extension:', err);
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
toastError({ toastError({
title: extension.name, title: extension.name,
msg: `Failed to configure the extension`, msg: `Failed to configure the extension`,
traceback: error.message, traceback: errorMessage,
}); });
} finally { } finally {
setIsSubmitting(false); setIsSubmitting(false);

View File

@@ -76,12 +76,13 @@ export function ConfigureExtensionModal({
}); });
onSubmit(); onSubmit();
onClose(); onClose();
} catch (error) { } catch (err) {
console.error('Error configuring extension:', error); console.error('Error configuring extension:', err);
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
toastError({ toastError({
title: extension.name, title: extension.name,
msg: `Failed to configure extension`, msg: `Failed to configure extension`,
traceback: error.message, traceback: errorMessage,
}); });
} finally { } finally {
setIsSubmitting(false); setIsSubmitting(false);

View File

@@ -142,7 +142,7 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
<Select <Select
options={typeOptions} options={typeOptions}
value={typeOptions.find((option) => option.value === formData.type)} value={typeOptions.find((option) => option.value === formData.type)}
onChange={(option) => onChange={(option: { value: string; label: string } | null) =>
setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] }) setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] })
} }
/> />

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Button } from '../../ui/button'; import { Button } from '../../ui/button';
import { Input } from '../../ui/input'; import { Input } from '../../ui/input';
import Select from 'react-select'; import Select from 'react-select';
@@ -19,7 +19,7 @@ export function AddModelInline() {
const [selectedProvider, setSelectedProvider] = useState<string | null>(null); const [selectedProvider, setSelectedProvider] = useState<string | null>(null);
const [modelName, setModelName] = useState<string>(''); const [modelName, setModelName] = useState<string>('');
const [filteredModels, setFilteredModels] = useState([]); const [filteredModels, setFilteredModels] = useState<{ id: string; name: string; provider: string }[]>([]);
const [showSuggestions, setShowSuggestions] = useState(false); const [showSuggestions, setShowSuggestions] = useState(false);
const handleModelSelection = useHandleModelSelection(); const handleModelSelection = useHandleModelSelection();
@@ -61,7 +61,7 @@ export function AddModelInline() {
setShowSuggestions(false); setShowSuggestions(false);
}; };
const handleSelectSuggestion = (suggestion) => { const handleSelectSuggestion = (suggestion: { provider: string; name: string }) => {
setModelName(suggestion.name); setModelName(suggestion.name);
setShowSuggestions(false); // Hide suggestions after selection setShowSuggestions(false); // Hide suggestions after selection
}; };

View File

@@ -1,4 +1,4 @@
import React, { createContext, useContext, useState, ReactNode } from 'react'; import { createContext, useContext, useState, ReactNode } from 'react';
import { GOOSE_MODEL, GOOSE_PROVIDER } from '../../../env_vars'; import { GOOSE_MODEL, GOOSE_PROVIDER } from '../../../env_vars';
import { gooseModels } from './GooseModels'; // Assuming hardcoded models are here import { gooseModels } from './GooseModels'; // Assuming hardcoded models are here

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { RecentModels } from './RecentModels'; import { RecentModels } from './RecentModels';
import { ProviderButtons } from './ProviderButtons'; import { ProviderButtons } from './ProviderButtons';
import BackButton from '../../ui/BackButton'; import BackButton from '../../ui/BackButton';

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Button } from '../../ui/button'; import { Button } from '../../ui/button';
import { Switch } from '../../ui/switch'; import { Switch } from '../../ui/switch';
import { useActiveKeys } from '../api_keys/ActiveKeysContext'; import { useActiveKeys } from '../api_keys/ActiveKeysContext';

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Clock } from 'lucide-react'; import { Clock } from 'lucide-react';
import { Model } from './ModelContext'; import { Model } from './ModelContext';
import { ModelRadioList, SeeMoreModelsButtons } from './ModelRadioList'; import { ModelRadioList, SeeMoreModelsButtons } from './ModelRadioList';

View File

@@ -49,7 +49,7 @@ export function useHandleModelSelection() {
}; };
} }
export function createSelectedModel(selectedProvider, modelName) { export function createSelectedModel(selectedProvider: string, modelName: string) {
let selectedModel = gooseModels.find( let selectedModel = gooseModels.find(
(model) => (model) =>
model.provider.toLowerCase() === selectedProvider && model.provider.toLowerCase() === selectedProvider &&

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Check, Plus, Settings, X, Rocket } from 'lucide-react'; import { Check, Plus, Settings, X, Rocket } from 'lucide-react';
import { Button } from '../../ui/button'; import { Button } from '../../ui/button';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/Tooltip'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/Tooltip';
@@ -34,7 +33,7 @@ function getArticle(word: string): string {
return 'aeiouAEIOU'.indexOf(word[0]) >= 0 ? 'an' : 'a'; return 'aeiouAEIOU'.indexOf(word[0]) >= 0 ? 'an' : 'a';
} }
export function getProviderDescription(provider) { export function getProviderDescription(provider: string) {
const descriptions = { const descriptions = {
OpenAI: 'Access GPT-4 and other OpenAI models, including OpenAI compatible ones', OpenAI: 'Access GPT-4 and other OpenAI models, including OpenAI compatible ones',
Anthropic: 'Access Claude and other Anthropic models', Anthropic: 'Access Claude and other Anthropic models',
@@ -44,7 +43,7 @@ export function getProviderDescription(provider) {
OpenRouter: 'Access a variety of AI models through OpenRouter', OpenRouter: 'Access a variety of AI models through OpenRouter',
Ollama: 'Run and use open-source models locally', Ollama: 'Run and use open-source models locally',
}; };
return descriptions[provider] || `Access ${provider} models`; return descriptions[provider as keyof typeof descriptions] || `Access ${provider} models`;
} }
function BaseProviderCard({ function BaseProviderCard({

View File

@@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useActiveKeys } from '../api_keys/ActiveKeysContext'; import { useActiveKeys } from '../api_keys/ActiveKeysContext';
import { BaseProviderGrid, getProviderDescription } from './BaseProviderGrid'; import { BaseProviderGrid, getProviderDescription } from './BaseProviderGrid';
import { supported_providers, provider_aliases, required_keys } from '../models/hardcoded_stuff'; import { supported_providers, provider_aliases, required_keys } from '../models/hardcoded_stuff';
@@ -43,7 +43,7 @@ export function ConfigureProvidersGrid() {
const [selectedForSetup, setSelectedForSetup] = useState<string | null>(null); const [selectedForSetup, setSelectedForSetup] = useState<string | null>(null);
const [modalMode, setModalMode] = useState<'edit' | 'setup' | 'battle'>('setup'); const [modalMode, setModalMode] = useState<'edit' | 'setup' | 'battle'>('setup');
const [isConfirmationOpen, setIsConfirmationOpen] = useState(false); const [isConfirmationOpen, setIsConfirmationOpen] = useState(false);
const [providerToDelete, setProviderToDelete] = useState(null); const [providerToDelete, setProviderToDelete] = useState<{ name: string; id: string; isConfigured: boolean; description: string } | null>(null);
const { currentModel } = useModel(); const { currentModel } = useModel();
const providers = useMemo(() => { const providers = useMemo(() => {
@@ -170,7 +170,7 @@ export function ConfigureProvidersGrid() {
const confirmDelete = async () => { const confirmDelete = async () => {
if (!providerToDelete) return; if (!providerToDelete) return;
const requiredKeys = required_keys[providerToDelete.name]; const requiredKeys = required_keys[providerToDelete.name as keyof typeof required_keys];
if (!requiredKeys || requiredKeys.length === 0) { if (!requiredKeys || requiredKeys.length === 0) {
console.error(`No keys found for provider ${providerToDelete.name}`); console.error(`No keys found for provider ${providerToDelete.name}`);
return; return;

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { ScrollArea } from '../../ui/scroll-area'; import { ScrollArea } from '../../ui/scroll-area';
import BackButton from '../../ui/BackButton'; import BackButton from '../../ui/BackButton';
import { ConfigureProvidersGrid } from './ConfigureProvidersGrid'; import { ConfigureProvidersGrid } from './ConfigureProvidersGrid';

View File

@@ -29,11 +29,11 @@ export async function extensionApiCall(
}; };
// for adding the payload is an extensionConfig, for removing payload is just the name // for adding the payload is an extensionConfig, for removing payload is just the name
const extensionName = isActivating ? payload.name : payload; const extensionName = isActivating ? (payload as ExtensionConfig).name : payload as string;
let toastId; let toastId;
// Step 1: Show loading toast (only for activation of stdio) // Step 1: Show loading toast (only for activation of stdio)
if (isActivating && (payload as ExtensionConfig) && payload.type == 'stdio') { if (isActivating && typeof payload === 'object' && payload.type === 'stdio') {
toastId = toastService.loading({ toastId = toastService.loading({
title: extensionName, title: extensionName,
msg: `${action.verb} ${extensionName} extension...`, msg: `${action.verb} ${extensionName} extension...`,

View File

@@ -1,5 +1,4 @@
import { Input } from '../../../ui/input'; import { Input } from '../../../ui/input';
import React from 'react';
interface ExtensionConfigFieldsProps { interface ExtensionConfigFieldsProps {
type: 'stdio' | 'sse' | 'builtin'; type: 'stdio' | 'sse' | 'builtin';

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import { useState } from 'react';
import { Button } from '../../../ui/button'; import { Button } from '../../../ui/button';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { ExtensionFormData } from '../utils'; import { ExtensionFormData } from '../utils';

View File

@@ -1,5 +1,4 @@
import { Input } from '../../../ui/input'; import { Input } from '../../../ui/input';
import React from 'react';
interface ExtensionTimeoutFieldProps { interface ExtensionTimeoutFieldProps {
timeout: number; timeout: number;

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Switch } from '../../../ui/switch'; import { Switch } from '../../../ui/switch';
import { Gear } from '../../../icons/Gear'; import { Gear } from '../../../icons/Gear';
import { FixedExtensionEntry } from '../../../ConfigContext'; import { FixedExtensionEntry } from '../../../ConfigContext';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { FixedExtensionEntry } from '../../../ConfigContext'; import { FixedExtensionEntry } from '../../../ConfigContext';
import { ExtensionConfig } from '../../../../api/types.gen'; import { ExtensionConfig } from '../../../../api/types.gen';
import ExtensionItem from './ExtensionItem'; import ExtensionItem from './ExtensionItem';

View File

@@ -83,7 +83,7 @@ export function extensionToFormData(extension: FixedExtensionEntry): ExtensionFo
cmd: extension.type === 'stdio' ? combineCmdAndArgs(extension.cmd, extension.args) : undefined, cmd: extension.type === 'stdio' ? combineCmdAndArgs(extension.cmd, extension.args) : undefined,
endpoint: extension.type === 'sse' ? extension.uri : undefined, endpoint: extension.type === 'sse' ? extension.uri : undefined,
enabled: extension.enabled, enabled: extension.enabled,
timeout: extension.timeout, timeout: 'timeout' in extension ? extension.timeout : undefined,
envVars, envVars,
}; };
} }

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback } from 'react'; import { useEffect, useState, useCallback } from 'react';
import type { View } from '../../../App'; import type { View } from '../../../App';
import ModelSettingsButtons from './subcomponents/ModelSettingsButtons'; import ModelSettingsButtons from './subcomponents/ModelSettingsButtons';
import { useConfig } from '../../ConfigContext'; import { useConfig } from '../../ConfigContext';

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import { useState } from 'react';
import { Button } from '../../../ui/button'; import { Button } from '../../../ui/button';
import { AddModelModal } from './AddModelModal'; import { AddModelModal } from './AddModelModal';
import type { View } from '../../../../App'; import type { View } from '../../../../App';

View File

@@ -12,7 +12,7 @@ import type { View } from '../../../../App';
import Model, { getProviderMetadata } from '../modelInterface'; import Model, { getProviderMetadata } from '../modelInterface';
import { useModel } from '../../../settings/models/ModelContext'; import { useModel } from '../../../settings/models/ModelContext';
const ModalButtons = ({ onSubmit, onCancel, _isValid, _validationErrors }) => ( const ModalButtons = ({ onSubmit, onCancel, _isValid: _, _validationErrors: __ }) => (
<div> <div>
<Button <Button
type="submit" type="submit"
@@ -40,8 +40,8 @@ type AddModelModalProps = {
export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => { export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
const { getProviders, upsert } = useConfig(); const { getProviders, upsert } = useConfig();
const { switchModel } = useModel(); const { switchModel } = useModel();
const [providerOptions, setProviderOptions] = useState([]); const [providerOptions, setProviderOptions] = useState<{ value: string; label: string }[]>([]);
const [modelOptions, setModelOptions] = useState([]); const [modelOptions, setModelOptions] = useState<{ options: { value: string; label: string; provider: string }[] }[]>([]);
const [provider, setProvider] = useState<string | null>(null); const [provider, setProvider] = useState<string | null>(null);
const [model, setModel] = useState<string>(''); const [model, setModel] = useState<string>('');
const [isCustomModel, setIsCustomModel] = useState(false); const [isCustomModel, setIsCustomModel] = useState(false);
@@ -169,7 +169,7 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
}; };
// Store the original model options in state, initialized from modelOptions // Store the original model options in state, initialized from modelOptions
const [originalModelOptions, setOriginalModelOptions] = useState(modelOptions); const [originalModelOptions, setOriginalModelOptions] = useState<{ options: { value: string; label: string; provider: string }[] }[]>(modelOptions);
const handleInputChange = (inputValue: string) => { const handleInputChange = (inputValue: string) => {
if (!provider) return; if (!provider) return;

View File

@@ -1,7 +1,6 @@
import { AddModelButton } from './AddModelButton'; import { AddModelButton } from './AddModelButton';
import { Button } from '../../../ui/button'; import { Button } from '../../../ui/button';
import { Sliders } from 'lucide-react'; import { Sliders } from 'lucide-react';
import React from 'react';
import type { View } from '../../../../App'; import type { View } from '../../../../App';
interface ConfigureModelButtonsProps { interface ConfigureModelButtonsProps {

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback, useRef } from 'react'; import { useEffect, useState, useCallback, useRef } from 'react';
import { ScrollArea } from '../../ui/scroll-area'; import { ScrollArea } from '../../ui/scroll-area';
import BackButton from '../../ui/BackButton'; import BackButton from '../../ui/BackButton';
import ProviderGrid from './ProviderGrid'; import ProviderGrid from './ProviderGrid';

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import Modal from '../../../../components/Modal'; import Modal from '../../../../components/Modal';
import ProviderSetupHeader from './subcomponents/ProviderSetupHeader'; import ProviderSetupHeader from './subcomponents/ProviderSetupHeader';
import DefaultProviderSetupForm from './subcomponents/forms/DefaultProviderSetupForm'; import DefaultProviderSetupForm from './subcomponents/forms/DefaultProviderSetupForm';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import OpenAILogo from './icons/openai@3x.png'; import OpenAILogo from './icons/openai@3x.png';
import AnthropicLogo from './icons/anthropic@3x.png'; import AnthropicLogo from './icons/anthropic@3x.png';
import GoogleLogo from './icons/google@3x.png'; import GoogleLogo from './icons/google@3x.png';

View File

@@ -1,4 +1,4 @@
import React, { SyntheticEvent } from 'react'; import { SyntheticEvent } from 'react';
import { Button } from '../../../../ui/button'; import { Button } from '../../../../ui/button';
import { Trash2, AlertTriangle } from 'lucide-react'; import { Trash2, AlertTriangle } from 'lucide-react';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { ExternalLink } from 'lucide-react'; import { ExternalLink } from 'lucide-react';
import { QUICKSTART_GUIDE_URL } from '../constants'; import { QUICKSTART_GUIDE_URL } from '../constants';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Lock } from 'lucide-react'; import { Lock } from 'lucide-react';
/** /**

View File

@@ -1,6 +1,5 @@
import { PROVIDER_REGISTRY } from '../../../ProviderRegistry'; import { PROVIDER_REGISTRY } from '../../../ProviderRegistry';
import { Input } from '../../../../../ui/input'; import { Input } from '../../../../../ui/input';
import React from 'react';
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { RefreshCw } from 'lucide-react'; import { RefreshCw } from 'lucide-react';

View File

@@ -1,4 +1,4 @@
import React, { memo } from 'react'; import { memo } from 'react';
import { GreenCheckButton } from './buttons/CardButtons'; import { GreenCheckButton } from './buttons/CardButtons';
import { ConfiguredProviderTooltipMessage, ProviderDescription } from './utils/StringUtils'; import { ConfiguredProviderTooltipMessage, ProviderDescription } from './utils/StringUtils';

View File

@@ -1,4 +1,4 @@
import React, { memo, useMemo } from 'react'; import { memo, useMemo } from 'react';
import CardContainer from './CardContainer'; import CardContainer from './CardContainer';
import CardHeader from './CardHeader'; import CardHeader from './CardHeader';
import CardBody from './CardBody'; import CardBody from './CardBody';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { ConfigureSettingsButton, RocketButton } from './CardButtons'; import { ConfigureSettingsButton, RocketButton } from './CardButtons';
import { ProviderDetails } from '../../../../../api'; import { ProviderDetails } from '../../../../../api';

View File

@@ -1,4 +1,3 @@
import React from 'react';
// Functions for string / string-based element creation (e.g. tooltips for each provider, descriptions, etc) // Functions for string / string-based element creation (e.g. tooltips for each provider, descriptions, etc)
export function OllamaNotConfiguredTooltipMessage() { export function OllamaNotConfiguredTooltipMessage() {

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Box({ size }: { size: number }) { export default function Box({ size }: { size: number }) {
return ( return (

View File

@@ -1,5 +1,4 @@
import { BaseModal } from './BaseModal'; import { BaseModal } from './BaseModal';
import React from 'react';
export function ConfirmationModal({ export function ConfirmationModal({
isOpen, isOpen,

View File

@@ -1,4 +1,3 @@
import React from 'react';
/** /**
* CustomRadio - A reusable radio button component with dark mode support * CustomRadio - A reusable radio button component with dark mode support

View File

@@ -1,4 +1,3 @@
import React from 'react';
import ReactSelect from 'react-select'; import ReactSelect from 'react-select';
export const Select = (props) => { export const Select = (props) => {

View File

@@ -1,4 +1,3 @@
import React from 'react';
export default function Send({ size }: { size: number }) { export default function Send({ size }: { size: number }) {
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react';
interface StopProps { interface StopProps {
size?: number; size?: number;

Some files were not shown because too many files have changed in this diff Show More