mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
313 lines
9.6 KiB
TypeScript
313 lines
9.6 KiB
TypeScript
// ========================================
|
|
// API Settings Page
|
|
// ========================================
|
|
// Main page for managing LiteLLM API providers, endpoints, cache, model pools, and CLI settings
|
|
|
|
import { useState, useMemo } from 'react';
|
|
import { useIntl } from 'react-intl';
|
|
import {
|
|
Server,
|
|
RefreshCw,
|
|
} from 'lucide-react';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { TabsNavigation } from '@/components/ui/TabsNavigation';
|
|
import {
|
|
ProviderList,
|
|
ProviderModal,
|
|
EndpointList,
|
|
EndpointModal,
|
|
CacheSettings,
|
|
ModelPoolList,
|
|
ModelPoolModal,
|
|
CliSettingsList,
|
|
CliSettingsModal,
|
|
MultiKeySettingsModal,
|
|
ManageModelsModal,
|
|
} from '@/components/api-settings';
|
|
import { ConfigSync } from '@/components/shared';
|
|
import { useProviders, useEndpoints, useModelPools, useCliSettings, useSyncApiConfig } from '@/hooks/useApiSettings';
|
|
import { useNotifications } from '@/hooks/useNotifications';
|
|
|
|
// Tab type definitions
|
|
type TabType = 'providers' | 'endpoints' | 'cache' | 'modelPools' | 'cliSettings' | 'configSync';
|
|
|
|
export function ApiSettingsPage() {
|
|
const { formatMessage } = useIntl();
|
|
const { success, error } = useNotifications();
|
|
const [activeTab, setActiveTab] = useState<TabType>('providers');
|
|
const syncMutation = useSyncApiConfig();
|
|
|
|
// Get providers, endpoints, model pools, and CLI settings data
|
|
const { providers } = useProviders();
|
|
const { endpoints } = useEndpoints();
|
|
const { pools } = useModelPools();
|
|
const { cliSettings } = useCliSettings();
|
|
|
|
// Modal states
|
|
const [providerModalOpen, setProviderModalOpen] = useState(false);
|
|
const [editingProviderId, setEditingProviderId] = useState<string | null>(null);
|
|
const [endpointModalOpen, setEndpointModalOpen] = useState(false);
|
|
const [editingEndpointId, setEditingEndpointId] = useState<string | null>(null);
|
|
const [modelPoolModalOpen, setModelPoolModalOpen] = useState(false);
|
|
const [editingPoolId, setEditingPoolId] = useState<string | null>(null);
|
|
const [cliSettingsModalOpen, setCliSettingsModalOpen] = useState(false);
|
|
const [editingCliSettingsId, setEditingCliSettingsId] = useState<string | null>(null);
|
|
|
|
// Additional modal states for multi-key settings and model management
|
|
const [multiKeyModalOpen, setMultiKeyModalOpen] = useState(false);
|
|
const [multiKeyProviderId, setMultiKeyProviderId] = useState<string | null>(null);
|
|
const [manageModelsModalOpen, setManageModelsModalOpen] = useState(false);
|
|
const [manageModelsProviderId, setManageModelsProviderId] = useState<string | null>(null);
|
|
|
|
// Find the provider being edited
|
|
const editingProvider = useMemo(
|
|
() => providers.find((p) => p.id === editingProviderId) || null,
|
|
[providers, editingProviderId]
|
|
);
|
|
|
|
// Find the endpoint being edited
|
|
const editingEndpoint = useMemo(
|
|
() => endpoints.find((e) => e.id === editingEndpointId) || null,
|
|
[endpoints, editingEndpointId]
|
|
);
|
|
|
|
// Find the pool being edited
|
|
const editingPool = useMemo(
|
|
() => pools.find((p) => p.id === editingPoolId) || null,
|
|
[pools, editingPoolId]
|
|
);
|
|
|
|
// Find the CLI settings being edited
|
|
const editingCliSettings = useMemo(
|
|
() => cliSettings.find((s) => s.id === editingCliSettingsId) || null,
|
|
[cliSettings, editingCliSettingsId]
|
|
);
|
|
|
|
// Provider modal handlers
|
|
const handleAddProvider = () => {
|
|
setEditingProviderId(null);
|
|
setProviderModalOpen(true);
|
|
};
|
|
|
|
const handleEditProvider = (providerId: string) => {
|
|
setEditingProviderId(providerId);
|
|
setProviderModalOpen(true);
|
|
};
|
|
|
|
const handleCloseProviderModal = () => {
|
|
setProviderModalOpen(false);
|
|
setEditingProviderId(null);
|
|
};
|
|
|
|
// Endpoint modal handlers
|
|
const handleAddEndpoint = () => {
|
|
setEditingEndpointId(null);
|
|
setEndpointModalOpen(true);
|
|
};
|
|
|
|
const handleEditEndpoint = (endpointId: string) => {
|
|
setEditingEndpointId(endpointId);
|
|
setEndpointModalOpen(true);
|
|
};
|
|
|
|
const handleCloseEndpointModal = () => {
|
|
setEndpointModalOpen(false);
|
|
setEditingEndpointId(null);
|
|
};
|
|
|
|
// Model pool modal handlers
|
|
const handleAddPool = () => {
|
|
setEditingPoolId(null);
|
|
setModelPoolModalOpen(true);
|
|
};
|
|
|
|
const handleEditPool = (poolId: string) => {
|
|
setEditingPoolId(poolId);
|
|
setModelPoolModalOpen(true);
|
|
};
|
|
|
|
const handleClosePoolModal = () => {
|
|
setModelPoolModalOpen(false);
|
|
setEditingPoolId(null);
|
|
};
|
|
|
|
// CLI Settings modal handlers
|
|
const handleAddCliSettings = () => {
|
|
setEditingCliSettingsId(null);
|
|
setCliSettingsModalOpen(true);
|
|
};
|
|
|
|
const handleEditCliSettings = (endpointId: string) => {
|
|
setEditingCliSettingsId(endpointId);
|
|
setCliSettingsModalOpen(true);
|
|
};
|
|
|
|
const handleCloseCliSettingsModal = () => {
|
|
setCliSettingsModalOpen(false);
|
|
setEditingCliSettingsId(null);
|
|
};
|
|
|
|
// Multi-key settings modal handlers
|
|
const handleMultiKeySettings = (providerId: string) => {
|
|
setMultiKeyProviderId(providerId);
|
|
setMultiKeyModalOpen(true);
|
|
};
|
|
|
|
const handleCloseMultiKeyModal = () => {
|
|
setMultiKeyModalOpen(false);
|
|
setMultiKeyProviderId(null);
|
|
};
|
|
|
|
// Manage models modal handlers
|
|
const handleManageModels = (providerId: string) => {
|
|
setManageModelsProviderId(providerId);
|
|
setManageModelsModalOpen(true);
|
|
};
|
|
|
|
const handleCloseManageModelsModal = () => {
|
|
setManageModelsModalOpen(false);
|
|
setManageModelsProviderId(null);
|
|
};
|
|
|
|
// Sync to CodexLens handler
|
|
const handleSyncToCodexLens = async (providerId: string) => {
|
|
const providerName = providers.find((p) => p.id === providerId)?.name ?? providerId;
|
|
|
|
try {
|
|
const result = await syncMutation.mutateAsync();
|
|
const messageParts = [
|
|
providerName,
|
|
result.yamlPath ?? result.message,
|
|
].filter(Boolean);
|
|
|
|
success(
|
|
formatMessage({ id: 'apiSettings.messages.configSynced' }),
|
|
messageParts.length > 0 ? messageParts.join('\n') : undefined
|
|
);
|
|
} catch (err) {
|
|
error(formatMessage({ id: 'apiSettings.providers.saveError' }));
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Page Header */}
|
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-foreground flex items-center gap-2">
|
|
<Server className="w-6 h-6 text-primary" />
|
|
{formatMessage({ id: 'apiSettings.title' })}
|
|
</h1>
|
|
<p className="text-muted-foreground mt-1">
|
|
{formatMessage({ id: 'apiSettings.description' })}
|
|
</p>
|
|
</div>
|
|
<Button variant="outline" onClick={() => window.location.reload()}>
|
|
<RefreshCw className="w-4 h-4 mr-2" />
|
|
{formatMessage({ id: 'common.actions.refresh' })}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Tabbed Interface */}
|
|
<TabsNavigation
|
|
value={activeTab}
|
|
onValueChange={(v) => setActiveTab(v as TabType)}
|
|
tabs={[
|
|
{ value: 'providers', label: formatMessage({ id: 'apiSettings.tabs.providers' }) },
|
|
{ value: 'endpoints', label: formatMessage({ id: 'apiSettings.tabs.endpoints' }) },
|
|
{ value: 'cache', label: formatMessage({ id: 'apiSettings.tabs.cache' }) },
|
|
{ value: 'modelPools', label: formatMessage({ id: 'apiSettings.tabs.modelPools' }) },
|
|
{ value: 'cliSettings', label: formatMessage({ id: 'apiSettings.tabs.cliSettings' }) },
|
|
{ value: 'configSync', label: formatMessage({ id: 'apiSettings.tabs.configSync' }) || 'Config Sync' },
|
|
]}
|
|
/>
|
|
|
|
{/* Tab Content */}
|
|
{activeTab === 'providers' && (
|
|
<div className="mt-4">
|
|
<ProviderList
|
|
onAddProvider={handleAddProvider}
|
|
onEditProvider={handleEditProvider}
|
|
onMultiKeySettings={handleMultiKeySettings}
|
|
onSyncToCodexLens={handleSyncToCodexLens}
|
|
onManageModels={handleManageModels}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'endpoints' && (
|
|
<div className="mt-4">
|
|
<EndpointList
|
|
onAddEndpoint={handleAddEndpoint}
|
|
onEditEndpoint={handleEditEndpoint}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'cache' && (
|
|
<div className="mt-4">
|
|
<CacheSettings />
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'modelPools' && (
|
|
<div className="mt-4">
|
|
<ModelPoolList
|
|
onAddPool={handleAddPool}
|
|
onEditPool={handleEditPool}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'cliSettings' && (
|
|
<div className="mt-4">
|
|
<CliSettingsList
|
|
onAddCliSettings={handleAddCliSettings}
|
|
onEditCliSettings={handleEditCliSettings}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'configSync' && (
|
|
<div className="mt-4">
|
|
<ConfigSync />
|
|
</div>
|
|
)}
|
|
|
|
{/* Modals */}
|
|
<ProviderModal
|
|
open={providerModalOpen}
|
|
onClose={handleCloseProviderModal}
|
|
provider={editingProvider}
|
|
/>
|
|
<EndpointModal
|
|
open={endpointModalOpen}
|
|
onClose={handleCloseEndpointModal}
|
|
endpoint={editingEndpoint}
|
|
/>
|
|
<ModelPoolModal
|
|
open={modelPoolModalOpen}
|
|
onClose={handleClosePoolModal}
|
|
pool={editingPool}
|
|
/>
|
|
<CliSettingsModal
|
|
open={cliSettingsModalOpen}
|
|
onClose={handleCloseCliSettingsModal}
|
|
cliSettings={editingCliSettings}
|
|
/>
|
|
<MultiKeySettingsModal
|
|
open={multiKeyModalOpen}
|
|
onClose={handleCloseMultiKeyModal}
|
|
providerId={multiKeyProviderId || ''}
|
|
/>
|
|
<ManageModelsModal
|
|
open={manageModelsModalOpen}
|
|
onClose={handleCloseManageModelsModal}
|
|
providerId={manageModelsProviderId || ''}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default ApiSettingsPage;
|