mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-20 15:44:25 +01:00
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:
@@ -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);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface AgentHeaderProps {
|
interface AgentHeaderProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -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),
|
||||||
}, 150)(textArea);
|
|
||||||
},
|
|
||||||
[maxHeight]
|
[maxHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface ImagePreviewProps {
|
interface ImagePreviewProps {
|
||||||
src: string;
|
src: string;
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import GooseLogo from './GooseLogo';
|
import GooseLogo from './GooseLogo';
|
||||||
|
|
||||||
const LoadingGoose = () => {
|
const LoadingGoose = () => {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function LoadingPlaceholder() {
|
export function LoadingPlaceholder() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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[],
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import SplashPills from './SplashPills';
|
import SplashPills from './SplashPills';
|
||||||
import GooseLogo from './GooseLogo';
|
import GooseLogo from './GooseLogo';
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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 = '' }) {
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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;
|
||||||
})()}
|
})()}
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function ArrowDown({ className = '' }) {
|
export default function ArrowDown({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function ArrowUp({ className = '' }) {
|
export default function ArrowUp({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Attach({ className = '' }) {
|
export default function Attach({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Back({ className = '' }) {
|
export default function Back({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function Bars() {
|
export function Bars() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function ChatSmart({ className = '' }) {
|
export default function ChatSmart({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Check({ className = '' }) {
|
export default function Check({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function ChevronUp({ className = '' }) {
|
export default function ChevronUp({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Copy({ className = '' }) {
|
export default function Copy({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Document({ className = '' }) {
|
export default function Document({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Edit({ className = '' }) {
|
export default function Edit({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function Gear({ className = '' }: { className?: string }) {
|
export function Gear({ className = '' }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function Goose({ className = '' }) {
|
export function Goose({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Idea({ className = '' }) {
|
export default function Idea({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function More({ className = '' }) {
|
export default function More({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Refresh({ className = '' }) {
|
export default function Refresh({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Send({ className = '' }) {
|
export default function Send({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function SensitiveHidden({ className = '' }) {
|
export default function SensitiveHidden({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function SensitiveVisible({ className = '' }) {
|
export default function SensitiveVisible({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Settings({ className = '' }) {
|
export default function Settings({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Time({ className = '' }) {
|
export default function Time({ className = '' }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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> {}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ interface ProviderSetupModalProps {
|
|||||||
|
|
||||||
export function ProviderSetupModal({
|
export function ProviderSetupModal({
|
||||||
provider,
|
provider,
|
||||||
_model,
|
_model: _,
|
||||||
_endpoint,
|
_endpoint: __,
|
||||||
title,
|
title,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onCancel,
|
onCancel,
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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'] })
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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 &&
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
@@ -169,8 +169,8 @@ 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;
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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...`,
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Lock } from 'lucide-react';
|
import { Lock } from 'lucide-react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Box({ size }: { size: number }) {
|
export default function Box({ size }: { size: number }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { BaseModal } from './BaseModal';
|
import { BaseModal } from './BaseModal';
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function ConfirmationModal({
|
export function ConfirmationModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function Send({ size }: { size: number }) {
|
export default function Send({ size }: { size: number }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user