Declarative providers (#5084)
Co-authored-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
@@ -3,7 +3,11 @@ import { ProviderCard } from './subcomponents/ProviderCard';
|
||||
import CardContainer from './subcomponents/CardContainer';
|
||||
import { ProviderModalProvider, useProviderModal } from './modal/ProviderModalProvider';
|
||||
import ProviderConfigurationModal from './modal/ProviderConfiguationModal';
|
||||
import { ProviderDetails, CreateCustomProviderRequest } from '../../../api';
|
||||
import {
|
||||
DeclarativeProviderConfig,
|
||||
ProviderDetails,
|
||||
UpdateCustomProviderRequest,
|
||||
} from '../../../api';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
import CustomProviderForm from './modal/subcomponents/forms/CustomProviderForm';
|
||||
@@ -43,7 +47,6 @@ const CustomProviderCard = memo(function CustomProviderCard({ onClick }: { onCli
|
||||
);
|
||||
});
|
||||
|
||||
// Memoize the ProviderCards component
|
||||
const ProviderCards = memo(function ProviderCards({
|
||||
providers,
|
||||
isOnboarding,
|
||||
@@ -57,28 +60,69 @@ const ProviderCards = memo(function ProviderCards({
|
||||
}) {
|
||||
const { openModal } = useProviderModal();
|
||||
const [showCustomProviderModal, setShowCustomProviderModal] = useState(false);
|
||||
const [editingProvider, setEditingProvider] = useState<{
|
||||
id: string;
|
||||
config: DeclarativeProviderConfig;
|
||||
isEditable: boolean;
|
||||
} | null>(null);
|
||||
|
||||
// Memoize these functions so they don't get recreated on every render
|
||||
const configureProviderViaModal = useCallback(
|
||||
(provider: ProviderDetails) => {
|
||||
openModal(provider, {
|
||||
onSubmit: () => {
|
||||
// Only refresh if the function is provided
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
onDelete: (_values: unknown) => {
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
formProps: {},
|
||||
});
|
||||
async (provider: ProviderDetails) => {
|
||||
if (provider.provider_type === 'Custom' || provider.provider_type === 'Declarative') {
|
||||
const { getCustomProvider } = await import('../../../api');
|
||||
const result = await getCustomProvider({ path: { id: provider.name }, throwOnError: true });
|
||||
|
||||
if (result.data) {
|
||||
setEditingProvider({
|
||||
id: provider.name,
|
||||
config: result.data.config,
|
||||
isEditable: result.data.is_editable,
|
||||
});
|
||||
setShowCustomProviderModal(true);
|
||||
}
|
||||
} else {
|
||||
openModal(provider, {
|
||||
onSubmit: () => {
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
onDelete: (_values: unknown) => {
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
formProps: {},
|
||||
});
|
||||
}
|
||||
},
|
||||
[openModal, refreshProviders]
|
||||
);
|
||||
|
||||
const handleUpdateCustomProvider = useCallback(
|
||||
async (data: UpdateCustomProviderRequest) => {
|
||||
if (!editingProvider) return;
|
||||
|
||||
const { updateCustomProvider } = await import('../../../api');
|
||||
await updateCustomProvider({
|
||||
path: { id: editingProvider.id },
|
||||
body: data,
|
||||
throwOnError: true,
|
||||
});
|
||||
setShowCustomProviderModal(false);
|
||||
setEditingProvider(null);
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
[editingProvider, refreshProviders]
|
||||
);
|
||||
|
||||
const handleCloseModal = useCallback(() => {
|
||||
setShowCustomProviderModal(false);
|
||||
setEditingProvider(null);
|
||||
}, []);
|
||||
|
||||
const deleteProviderConfigViaModal = useCallback(
|
||||
(provider: ProviderDetails) => {
|
||||
openModal(provider, {
|
||||
@@ -95,22 +139,17 @@ const ProviderCards = memo(function ProviderCards({
|
||||
);
|
||||
|
||||
const handleCreateCustomProvider = useCallback(
|
||||
async (data: CreateCustomProviderRequest) => {
|
||||
try {
|
||||
const { createCustomProvider } = await import('../../../api');
|
||||
await createCustomProvider({ body: data });
|
||||
setShowCustomProviderModal(false);
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to create custom provider:', error);
|
||||
async (data: UpdateCustomProviderRequest) => {
|
||||
const { createCustomProvider } = await import('../../../api');
|
||||
await createCustomProvider({ body: data, throwOnError: true });
|
||||
setShowCustomProviderModal(false);
|
||||
if (refreshProviders) {
|
||||
refreshProviders();
|
||||
}
|
||||
},
|
||||
[refreshProviders]
|
||||
);
|
||||
|
||||
// Use useMemo to memoize the cards array
|
||||
const providerCards = useMemo(() => {
|
||||
// providers needs to be an array
|
||||
const providersArray = Array.isArray(providers) ? providers : [];
|
||||
@@ -138,21 +177,33 @@ const ProviderCards = memo(function ProviderCards({
|
||||
onProviderLaunch,
|
||||
]);
|
||||
|
||||
const initialData = editingProvider && {
|
||||
engine: editingProvider.config.engine.toLowerCase() + '_compatible',
|
||||
display_name: editingProvider.config.display_name,
|
||||
api_url: editingProvider.config.base_url,
|
||||
api_key: '',
|
||||
models: editingProvider.config.models.map((m) => m.name),
|
||||
supports_streaming: editingProvider.config.supports_streaming ?? true,
|
||||
};
|
||||
|
||||
const editable = editingProvider ? editingProvider.isEditable : true;
|
||||
const title = (editingProvider ? (editable ? 'Edit' : 'Configure') : 'Add') + ' Provider';
|
||||
return (
|
||||
<>
|
||||
{providerCards}
|
||||
|
||||
<Dialog open={showCustomProviderModal} onOpenChange={setShowCustomProviderModal}>
|
||||
<Dialog open={showCustomProviderModal} onOpenChange={handleCloseModal}>
|
||||
<DialogContent className="sm:max-w-[600px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Custom Provider</DialogTitle>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<CustomProviderForm
|
||||
onSubmit={handleCreateCustomProvider}
|
||||
onCancel={() => setShowCustomProviderModal(false)}
|
||||
initialData={initialData}
|
||||
isEditable={editable}
|
||||
onSubmit={editingProvider ? handleUpdateCustomProvider : handleCreateCustomProvider}
|
||||
onCancel={handleCloseModal}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Dialog>{' '}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user