mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
feat: initial commit adding support for credentials on proxy ui
This commit is contained in:
parent
051f346fa6
commit
c039a1e948
4 changed files with 168 additions and 1 deletions
|
|
@ -2,4 +2,16 @@ model_list:
|
|||
- model_name: amazon.nova-canvas-v1:0
|
||||
litellm_params:
|
||||
model: bedrock/amazon.nova-canvas-v1:0
|
||||
aws_region_name: "us-east-1"
|
||||
aws_region_name: "us-east-1"
|
||||
|
||||
credential_list:
|
||||
- credential_name: azure
|
||||
credential_values:
|
||||
api_key: os.environ/AZURE_API_KEY
|
||||
api_base: os.environ/AZURE_API_BASE
|
||||
credential_info:
|
||||
description: "Azure API Key and Base URL"
|
||||
type: "azure"
|
||||
required: true
|
||||
default: "azure"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import CacheDashboard from "@/components/cache_dashboard";
|
|||
import { setGlobalLitellmHeaderName } from "@/components/networking";
|
||||
import { Organization } from "@/components/networking";
|
||||
import GuardrailsPanel from "@/components/guardrails";
|
||||
import CredentialsPanel from "@/components/credentials";
|
||||
import TransformRequestPanel from "@/components/transform_request";
|
||||
import { fetchUserModels } from "@/components/create_key_button";
|
||||
import { fetchTeams } from "@/components/common_components/fetch_teams";
|
||||
|
|
@ -312,6 +313,8 @@ export default function CreateKeyPage() {
|
|||
<GuardrailsPanel accessToken={accessToken} />
|
||||
) : page == "transform-request" ? (
|
||||
<TransformRequestPanel accessToken={accessToken} />
|
||||
) : page == "credentials" ? (
|
||||
<CredentialsPanel accessToken={accessToken} />
|
||||
) : page == "general-settings" ? (
|
||||
<GeneralSettings
|
||||
userID={userID}
|
||||
|
|
|
|||
150
ui/litellm-dashboard/src/components/credentials.tsx
Normal file
150
ui/litellm-dashboard/src/components/credentials.tsx
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
Card,
|
||||
Text,
|
||||
Badge
|
||||
} from "@tremor/react";
|
||||
import { PlusIcon } from "@heroicons/react/solid";
|
||||
import { getCredentialsList } from "./networking"; // Assume this is your networking function
|
||||
|
||||
interface CredentialsPanelProps {
|
||||
accessToken: string | null;
|
||||
}
|
||||
|
||||
interface CredentialsResponse {
|
||||
credentials: CredentialItem[];
|
||||
}
|
||||
|
||||
interface CredentialItem {
|
||||
credential_name: string | null;
|
||||
provider: string;
|
||||
credential_values: {
|
||||
api_key?: string;
|
||||
api_base?: string;
|
||||
};
|
||||
credential_info: {
|
||||
description?: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
default?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const CredentialsPanel: React.FC<CredentialsPanelProps> = ({ accessToken }) => {
|
||||
const [credentialsList, setCredentialsList] = useState<CredentialItem[]>([]);
|
||||
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!accessToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchCredentials = async () => {
|
||||
try {
|
||||
const response: CredentialsResponse = await getCredentialsList(accessToken);
|
||||
console.log(`credentials: ${JSON.stringify(response)}`);
|
||||
setCredentialsList(response.credentials);
|
||||
} catch (error) {
|
||||
console.error('Error fetching credentials:', error);
|
||||
}
|
||||
};
|
||||
fetchCredentials();
|
||||
}, [accessToken]);
|
||||
|
||||
const renderProviderBadge = (provider: string) => {
|
||||
const providerColors: Record<string, string> = {
|
||||
'openai': 'blue',
|
||||
'azure': 'indigo',
|
||||
'anthropic': 'purple',
|
||||
'default': 'gray'
|
||||
};
|
||||
|
||||
const color = providerColors[provider.toLowerCase()] || providerColors['default'];
|
||||
return (
|
||||
<Badge color={color as any} size="xs">
|
||||
{provider}
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full mx-auto flex-auto overflow-y-auto m-8 p-2">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<Text>
|
||||
Configured credentials for different AI providers. Add and manage your API credentials.{" "}
|
||||
<a
|
||||
href="https://docs.litellm.ai/docs/credentials"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-500 hover:text-blue-700 underline"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
</Text>
|
||||
<button
|
||||
onClick={() => setIsAddModalOpen(true)}
|
||||
className="flex items-center bg-blue-500 text-white px-3 py-2 rounded-md hover:bg-blue-600 transition-colors"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5 mr-2" />
|
||||
Add Credential
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell>Credential Name</TableHeaderCell>
|
||||
<TableHeaderCell>Provider</TableHeaderCell>
|
||||
<TableHeaderCell>Description</TableHeaderCell>
|
||||
<TableHeaderCell>Required</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{(!credentialsList || credentialsList.length === 0) ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} className="text-center py-4 text-gray-500">
|
||||
No credentials configured
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
credentialsList.map((credential: CredentialItem, index: number) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>{credential.credential_name}</TableCell>
|
||||
<TableCell>
|
||||
{renderProviderBadge(credential.provider)}
|
||||
</TableCell>
|
||||
<TableCell>{credential.credential_info.description || '-'}</TableCell>
|
||||
<TableCell>
|
||||
<div className={`inline-flex rounded-full px-2 py-1 text-xs font-medium
|
||||
${credential.credential_info.required
|
||||
? 'bg-green-100 text-green-800' // Required styling
|
||||
: 'bg-gray-100 text-gray-800' // Optional styling
|
||||
}`}>
|
||||
{credential.credential_info.required ? 'Required' : 'Optional'}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
|
||||
{/* TODO: Implement Add Credential Modal */}
|
||||
{isAddModalOpen && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
||||
{/* Modal content for adding credentials */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CredentialsPanel;
|
||||
|
|
@ -20,6 +20,7 @@ import {
|
|||
SafetyOutlined,
|
||||
ExperimentOutlined,
|
||||
ThunderboltOutlined,
|
||||
LockOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { old_admin_roles, v2_admin_role_names, all_admin_roles, rolesAllowedToSeeUsage, rolesWithWriteAccess } from '../utils/roles';
|
||||
|
||||
|
|
@ -68,6 +69,7 @@ const menuItems: MenuItem[] = [
|
|||
{ key: "10", page: "budgets", label: "Budgets", icon: <BankOutlined />, roles: all_admin_roles },
|
||||
{ key: "11", page: "guardrails", label: "Guardrails", icon: <SafetyOutlined />, roles: all_admin_roles },
|
||||
{ key: "18", page: "transform-request", label: "Playground", icon: <ThunderboltOutlined />, roles: all_admin_roles },
|
||||
{ key: "19", page: "credentials", label: "Credentials", icon: <LockOutlined />, roles: all_admin_roles },
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue