mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-11 14:22:48 +00:00
Standardize API Key vs Virtual Key in UI
This commit is contained in:
@@ -38,10 +38,9 @@ const ModelSection = ({ modelName, metrics }: { modelName: string; metrics: Mode
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
{/* Top API Keys Section */}
|
||||
{metrics.top_api_keys && metrics.top_api_keys.length > 0 && (
|
||||
<Card className="mt-4">
|
||||
<Title>Top API Keys by Spend</Title>
|
||||
<Title>Top Virtual Keys by Spend</Title>
|
||||
<div className="mt-3">
|
||||
<div className="grid grid-cols-1 gap-2">
|
||||
{metrics.top_api_keys.map((keyData, index) => (
|
||||
@@ -384,12 +383,12 @@ export const processActivityData = (
|
||||
});
|
||||
});
|
||||
|
||||
// Process API key breakdowns for each metric (skip if key is 'api_keys' to avoid duplication)
|
||||
// Process Virtual Key breakdowns for each metric (skip if key is 'api_keys' to avoid duplication)
|
||||
if (key !== "api_keys") {
|
||||
Object.entries(modelMetrics).forEach(([model, _]) => {
|
||||
const apiKeyBreakdown: Record<string, TopApiKeyData> = {};
|
||||
|
||||
// Aggregate API key data across all days
|
||||
// Aggregate Virtual Key data across all days
|
||||
dailyActivity.results.forEach((day) => {
|
||||
const modelData = day.breakdown[key]?.[model];
|
||||
if (modelData && "api_key_breakdown" in modelData) {
|
||||
|
||||
@@ -569,7 +569,7 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
|
||||
<li>Download our CSV template</li>
|
||||
<li>Add your users' information to the spreadsheet</li>
|
||||
<li>Save the file and upload it here</li>
|
||||
<li>After creation, download the results file containing the API keys for each user</li>
|
||||
<li>After creation, download the results file containing the Virtual Keys for each user</li>
|
||||
</ol>
|
||||
|
||||
<div className="bg-gray-50 p-4 rounded-md border border-gray-200 mb-4">
|
||||
@@ -809,9 +809,9 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
|
||||
<div>
|
||||
<Text className="font-medium text-blue-800">User creation complete</Text>
|
||||
<Text className="block text-sm text-blue-700 mt-1">
|
||||
<span className="font-medium">Next step:</span> Download the credentials file containing API
|
||||
keys and invitation links. Users will need these API keys to make LLM requests through
|
||||
LiteLLM.
|
||||
<span className="font-medium">Next step:</span> Download the credentials file containing
|
||||
Virtual Keys and invitation links. Users will need these Virtual Keys to make LLM requests
|
||||
through LiteLLM.
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -293,7 +293,11 @@ const CacheDashboard: React.FC<CachePageProps> = ({ accessToken, token, userRole
|
||||
<Card>
|
||||
<Grid numItems={3} className="gap-4 mt-4">
|
||||
<Col>
|
||||
<MultiSelect placeholder="Select API Keys" value={selectedApiKeys} onValueChange={setSelectedApiKeys}>
|
||||
<MultiSelect
|
||||
placeholder="Select Virtual Keys"
|
||||
value={selectedApiKeys}
|
||||
onValueChange={setSelectedApiKeys}
|
||||
>
|
||||
{uniqueApiKeys.map((key) => (
|
||||
<MultiSelectItem key={key} value={key}>
|
||||
{key}
|
||||
@@ -388,11 +392,7 @@ const CacheDashboard: React.FC<CachePageProps> = ({ accessToken, token, userRole
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<CacheSettings
|
||||
accessToken={accessToken}
|
||||
userRole={userRole}
|
||||
userID={userID}
|
||||
/>
|
||||
<CacheSettings accessToken={accessToken} userRole={userRole} userID={userID} />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</TabGroup>
|
||||
|
||||
+3
-13
@@ -21,7 +21,7 @@ const PassThroughSecuritySection: React.FC<PassThroughSecuritySectionProps> = ({
|
||||
<Card className="p-6">
|
||||
<Title className="text-lg font-semibold text-gray-900 mb-2">Security</Title>
|
||||
<Subtitle className="text-gray-600 mb-4">
|
||||
When enabled, requests to this endpoint will require a valid LiteLLM API key
|
||||
When enabled, requests to this endpoint will require a valid LiteLLM Virtual Key
|
||||
</Subtitle>
|
||||
{premiumUser ? (
|
||||
<Form.Item name="auth" valuePropName="checked" className="mb-0">
|
||||
@@ -35,22 +35,13 @@ const PassThroughSecuritySection: React.FC<PassThroughSecuritySectionProps> = ({
|
||||
) : (
|
||||
<div>
|
||||
<div className="flex items-center mb-3">
|
||||
<Switch
|
||||
disabled
|
||||
checked={false}
|
||||
style={{ outline: '2px solid #d1d5db', outlineOffset: '2px' }}
|
||||
/>
|
||||
<Switch disabled checked={false} style={{ outline: "2px solid #d1d5db", outlineOffset: "2px" }} />
|
||||
<span className="ml-2 text-sm text-gray-400">Authentication (Premium)</span>
|
||||
</div>
|
||||
<div className="p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||
<Text className="text-sm text-yellow-800">
|
||||
Setting authentication for pass-through endpoints is a LiteLLM Enterprise feature. Get a trial key{" "}
|
||||
<a
|
||||
href="https://www.litellm.ai/#pricing"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline"
|
||||
>
|
||||
<a href="https://www.litellm.ai/#pricing" target="_blank" rel="noopener noreferrer" className="underline">
|
||||
here
|
||||
</a>
|
||||
.
|
||||
@@ -63,4 +54,3 @@ const PassThroughSecuritySection: React.FC<PassThroughSecuritySectionProps> = ({
|
||||
};
|
||||
|
||||
export default PassThroughSecuritySection;
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ const DashboardTeam: React.FC<DashboardTeamProps> = ({
|
||||
<Title>Select Team</Title>
|
||||
|
||||
<Text>
|
||||
If you belong to multiple teams, this setting controls which team is used by default when creating new API Keys.
|
||||
If you belong to multiple teams, this setting controls which team is used by default when creating new Virtual
|
||||
Keys.
|
||||
</Text>
|
||||
<Text className="mt-3 mb-3">
|
||||
<b>Default Team:</b> If no team_id is set for a key, it will be grouped under here.
|
||||
|
||||
@@ -550,7 +550,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
|
||||
{/* Top API Keys */}
|
||||
<Col numColSpan={1}>
|
||||
<Card>
|
||||
<Title>Top API Keys</Title>
|
||||
<Title>Top Virtual Keys</Title>
|
||||
<TopKeyView
|
||||
topKeys={getTopAPIKeys()}
|
||||
accessToken={accessToken}
|
||||
|
||||
@@ -90,7 +90,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
||||
setLoading(true);
|
||||
try {
|
||||
const agentIdsToMakePublic = Array.from(selectedAgents);
|
||||
|
||||
|
||||
// Make batch API call for all agents
|
||||
await makeAgentsPublicCall(accessToken, agentIdsToMakePublic);
|
||||
|
||||
@@ -127,8 +127,8 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the agents you want to be visible on the public model hub. Users will still require a valid API key to
|
||||
use these agents.
|
||||
Select the agents you want to be visible on the public model hub. Users will still require a valid Virtual Key
|
||||
to use these agents.
|
||||
</Text>
|
||||
|
||||
<div className="max-h-96 overflow-y-auto border rounded-lg p-4">
|
||||
@@ -141,10 +141,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
||||
agentHubData.map((agent) => {
|
||||
const agentId = agent.agent_id || agent.name;
|
||||
return (
|
||||
<div
|
||||
key={agentId}
|
||||
className="flex items-center space-x-3 p-3 border rounded-lg hover:bg-gray-50"
|
||||
>
|
||||
<div key={agentId} className="flex items-center space-x-3 p-3 border rounded-lg hover:bg-gray-50">
|
||||
<Checkbox
|
||||
checked={selectedAgents.has(agentId)}
|
||||
onChange={(e) => handleAgentSelection(agentId, e.target.checked)}
|
||||
@@ -217,9 +214,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{agent?.description && (
|
||||
<Text className="text-xs text-gray-600 mt-1">{agent.description}</Text>
|
||||
)}
|
||||
{agent?.description && <Text className="text-xs text-gray-600 mt-1">{agent.description}</Text>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -296,4 +291,3 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
||||
};
|
||||
|
||||
export default MakeAgentPublicForm;
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
const publicServerIds = mcpHubData
|
||||
.filter((server) => server.mcp_info?.is_public === true)
|
||||
.map((server) => server.server_id);
|
||||
|
||||
|
||||
// Preselect servers that are already public
|
||||
setSelectedServers(new Set(publicServerIds));
|
||||
}
|
||||
@@ -91,7 +91,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
setLoading(true);
|
||||
try {
|
||||
const serverIdsToMakePublic = Array.from(selectedServers);
|
||||
|
||||
|
||||
// Make batch API call for all servers
|
||||
await makeMCPPublicCall(accessToken, serverIdsToMakePublic);
|
||||
|
||||
@@ -128,8 +128,8 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the MCP servers you want to be visible on the public model hub. Users will still require a valid API key to
|
||||
use these servers.
|
||||
Select the MCP servers you want to be visible on the public model hub. Users will still require a valid
|
||||
Virtual Key to use these servers.
|
||||
</Text>
|
||||
|
||||
<div className="max-h-96 overflow-y-auto border rounded-lg p-4">
|
||||
@@ -161,22 +161,20 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
<Badge color="blue" size="sm">
|
||||
{server.transport}
|
||||
</Badge>
|
||||
<Badge
|
||||
<Badge
|
||||
color={
|
||||
server.status === "active" || server.status === "healthy"
|
||||
? "green"
|
||||
server.status === "active" || server.status === "healthy"
|
||||
? "green"
|
||||
: server.status === "inactive" || server.status === "unhealthy"
|
||||
? "red"
|
||||
: "gray"
|
||||
}
|
||||
? "red"
|
||||
: "gray"
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{server.status || "unknown"}
|
||||
</Badge>
|
||||
</div>
|
||||
<Text className="text-xs text-gray-600 mt-1">
|
||||
{server.description || server.url}
|
||||
</Text>
|
||||
<Text className="text-xs text-gray-600 mt-1">{server.description || server.url}</Text>
|
||||
{server.allowed_tools && server.allowed_tools.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{server.allowed_tools.slice(0, 3).map((tool, idx) => (
|
||||
@@ -236,14 +234,14 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
<Badge color="blue" size="xs">
|
||||
{server.transport}
|
||||
</Badge>
|
||||
<Badge
|
||||
<Badge
|
||||
color={
|
||||
server.status === "active" || server.status === "healthy"
|
||||
? "green"
|
||||
server.status === "active" || server.status === "healthy"
|
||||
? "green"
|
||||
: server.status === "inactive" || server.status === "unhealthy"
|
||||
? "red"
|
||||
: "gray"
|
||||
}
|
||||
? "red"
|
||||
: "gray"
|
||||
}
|
||||
size="xs"
|
||||
>
|
||||
{server.status || "unknown"}
|
||||
@@ -251,12 +249,8 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{server?.description && (
|
||||
<Text className="text-xs text-gray-600 mt-1">{server.description}</Text>
|
||||
)}
|
||||
{server?.url && (
|
||||
<Text className="text-xs text-gray-500 mt-1">{server.url}</Text>
|
||||
)}
|
||||
{server?.description && <Text className="text-xs text-gray-600 mt-1">{server.description}</Text>}
|
||||
{server?.url && <Text className="text-xs text-gray-500 mt-1">{server.url}</Text>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -267,8 +261,8 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
Total: <strong>{selectedServers.size}</strong> MCP server{selectedServers.size !== 1 ? "s" : ""} will be made
|
||||
public
|
||||
Total: <strong>{selectedServers.size}</strong> MCP server{selectedServers.size !== 1 ? "s" : ""} will be
|
||||
made public
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
@@ -333,4 +327,3 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
||||
};
|
||||
|
||||
export default MakeMCPPublicForm;
|
||||
|
||||
|
||||
@@ -152,8 +152,8 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the models you want to be visible on the public model hub. Users will still require a valid API key to
|
||||
use these models.
|
||||
Select the models you want to be visible on the public model hub. Users will still require a valid Virtual Key
|
||||
to use these models.
|
||||
</Text>
|
||||
|
||||
{/* Filters */}
|
||||
|
||||
@@ -220,12 +220,12 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
|
||||
<Space direction="vertical" size="large" className="w-full">
|
||||
<FeatureCard
|
||||
icon={<KeyIcon className="text-emerald-600" size={16} />}
|
||||
title="API Key Setup"
|
||||
description="Configure your LiteLLM Proxy API key for authentication"
|
||||
title="Virtual Key Setup"
|
||||
description="Configure your LiteLLM Proxy Virtual Key for authentication"
|
||||
>
|
||||
<Space direction="vertical" size="middle" className="w-full">
|
||||
<div>
|
||||
<Text>Get your API key from your LiteLLM Proxy dashboard or contact your administrator</Text>
|
||||
<Text>Get your Virtual Key from your LiteLLM Proxy dashboard or contact your administrator</Text>
|
||||
</div>
|
||||
<CodeBlock title="Environment Variable" code='export LITELLM_API_KEY="sk-..."' copyKey="litellm-env" />
|
||||
</Space>
|
||||
@@ -249,7 +249,7 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
|
||||
<CodeBlock
|
||||
code={`curl --location '${proxyBaseUrl}/v1/responses' \\
|
||||
--header 'Content-Type: application/json' \\
|
||||
--header "Authorization: Bearer $LITELLM_API_KEY" \\
|
||||
--header "Authorization: Bearer $LITELLM_VIRTUAL_KEY" \\
|
||||
--data '{
|
||||
"model": "gpt-4",
|
||||
"tools": [
|
||||
@@ -259,7 +259,7 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
|
||||
"server_url": "${proxyBaseUrl}/mcp",
|
||||
"require_approval": "never",
|
||||
"headers": {
|
||||
"x-litellm-api-key": "Bearer YOUR_LITELLM_API_KEY",
|
||||
"x-litellm-api-key": "Bearer YOUR_LITELLM_VIRTUAL_KEY",
|
||||
"x-mcp-servers": ["Zapier_MCP,dev"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ describe("NewUsage", () => {
|
||||
|
||||
// Check for chart titles
|
||||
expect(screen.getByText("Daily Spend")).toBeInTheDocument();
|
||||
expect(screen.getByText("Top API Keys")).toBeInTheDocument();
|
||||
expect(screen.getByText("Top Virtual Keys")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should switch between tabs correctly", async () => {
|
||||
|
||||
@@ -580,7 +580,7 @@ const NewUsagePage: React.FC<NewUsagePageProps> = ({
|
||||
{/* Top API Keys */}
|
||||
<Col numColSpan={1}>
|
||||
<Card className="h-full">
|
||||
<Title>Top API Keys</Title>
|
||||
<Title>Top Virtual Keys</Title>
|
||||
<TopKeyView
|
||||
topKeys={getTopKeys()}
|
||||
accessToken={accessToken}
|
||||
|
||||
@@ -405,7 +405,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
|
||||
setApiKey(response["key"]);
|
||||
setSoftBudget(response["soft_budget"]);
|
||||
NotificationsManager.success("API Key Created");
|
||||
NotificationsManager.success("Virtual Key Created");
|
||||
form.resetFields();
|
||||
localStorage.removeItem("userData" + userID);
|
||||
} catch (error) {
|
||||
@@ -415,7 +415,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
};
|
||||
|
||||
const handleCopy = () => {
|
||||
NotificationsManager.success("API Key copied to clipboard");
|
||||
NotificationsManager.success("Virtual Key copied to clipboard");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -505,7 +505,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
label={
|
||||
<span>
|
||||
Owned By{" "}
|
||||
<Tooltip title="Select who will own this API key">
|
||||
<Tooltip title="Select who will own this Virtual Key">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
@@ -594,8 +594,8 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
{isFormDisabled && (
|
||||
<div className="mb-8 p-4 bg-blue-50 border border-blue-200 rounded-md">
|
||||
<Text className="text-blue-800 text-sm">
|
||||
Please select a team to continue configuring your API key. If you do not see any teams, please contact
|
||||
your Proxy Admin to either provide you with access to models or to add you to a team.
|
||||
Please select a team to continue configuring your Virtual Key. If you do not see any teams, please
|
||||
contact your Proxy Admin to either provide you with access to models or to add you to a team.
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
@@ -1277,7 +1277,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
<Col numColSpan={1}>
|
||||
{apiKey != null ? (
|
||||
<div>
|
||||
<Text className="mt-3">API Key:</Text>
|
||||
<Text className="mt-3">Virtual Key:</Text>
|
||||
<div
|
||||
style={{
|
||||
background: "#f8f8f8",
|
||||
@@ -1290,7 +1290,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({
|
||||
</div>
|
||||
|
||||
<CopyToClipboard text={apiKey} onCopy={handleCopy}>
|
||||
<Button className="mt-3">Copy API Key</Button>
|
||||
<Button className="mt-3">Copy Virtual Key</Button>
|
||||
</CopyToClipboard>
|
||||
{/* <Button className="mt-3" onClick={sendSlackAlert}>
|
||||
Test Key
|
||||
|
||||
@@ -113,7 +113,7 @@ export function RegenerateKeyModal({
|
||||
formValues,
|
||||
);
|
||||
setRegeneratedKey(response.key);
|
||||
NotificationManager.success("API Key regenerated successfully");
|
||||
NotificationManager.success("Virtual Key regenerated successfully");
|
||||
|
||||
console.log("Full regenerate response:", response); // Debug log to see what's returned
|
||||
|
||||
@@ -164,7 +164,7 @@ export function RegenerateKeyModal({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Regenerate API Key"
|
||||
title="Regenerate Virtual Key"
|
||||
open={visible}
|
||||
onCancel={handleClose}
|
||||
footer={
|
||||
@@ -199,15 +199,15 @@ export function RegenerateKeyModal({
|
||||
<div className="bg-gray-100 p-2 rounded mb-2">
|
||||
<pre className="break-words whitespace-normal">{selectedToken?.key_alias || "No alias set"}</pre>
|
||||
</div>
|
||||
<Text className="mt-3">New API Key:</Text>
|
||||
<Text className="mt-3">New Virtual Key:</Text>
|
||||
<div className="bg-gray-100 p-2 rounded mb-2">
|
||||
<pre className="break-words whitespace-normal">{regeneratedKey}</pre>
|
||||
</div>
|
||||
<CopyToClipboard
|
||||
text={regeneratedKey}
|
||||
onCopy={() => NotificationManager.success("API Key copied to clipboard")}
|
||||
onCopy={() => NotificationManager.success("Virtual Key copied to clipboard")}
|
||||
>
|
||||
<Button className="mt-3">Copy API Key</Button>
|
||||
<Button className="mt-3">Copy Virtual Key</Button>
|
||||
</CopyToClipboard>
|
||||
</Col>
|
||||
</Grid>
|
||||
|
||||
@@ -691,7 +691,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
||||
const effectiveApiKey = apiKeySource === "session" ? accessToken : apiKey;
|
||||
|
||||
if (!effectiveApiKey) {
|
||||
NotificationsManager.fromBackend("Please provide an API key or select Current UI Session");
|
||||
NotificationsManager.fromBackend("Please provide a Virtual Key or select Current UI Session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1003,7 +1003,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Text className="font-medium block mb-2 text-gray-700 flex items-center">
|
||||
<KeyOutlined className="mr-2" /> API Key Source
|
||||
<KeyOutlined className="mr-2" /> Virtual Key Source
|
||||
</Text>
|
||||
<Select
|
||||
disabled={disabledPersonalKeyCreation}
|
||||
@@ -1021,7 +1021,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
||||
{apiKeySource === "custom" && (
|
||||
<TextInput
|
||||
className="mt-2"
|
||||
placeholder="Enter custom API key"
|
||||
placeholder="Enter custom Virtual Key"
|
||||
type="password"
|
||||
onValueChange={setApiKey}
|
||||
value={apiKey}
|
||||
|
||||
@@ -395,7 +395,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
||||
return;
|
||||
}
|
||||
if (!effectiveApiKey) {
|
||||
NotificationsManager.fromBackend("Please provide an API key or select Current UI Session");
|
||||
NotificationsManager.fromBackend("Please provide a Virtual Key or select Current UI Session");
|
||||
return;
|
||||
}
|
||||
const targetComparisons = comparisons;
|
||||
@@ -551,7 +551,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
||||
<div className="border-b px-4 py-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-gray-600">API Key Source</span>
|
||||
<span className="text-sm font-medium text-gray-600">Virtual Key Source</span>
|
||||
<Select
|
||||
value={apiKeySource}
|
||||
onChange={(value) => setApiKeySource(value as "session" | "custom")}
|
||||
@@ -567,7 +567,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
||||
<Input.Password
|
||||
value={customApiKey}
|
||||
onChange={(event) => setCustomApiKey(event.target.value)}
|
||||
placeholder="Enter API key"
|
||||
placeholder="Enter Virtual Key"
|
||||
className="w-56"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function makeAnthropicMessagesRequest(
|
||||
selectedMCPTools?: string[],
|
||||
) {
|
||||
if (!accessToken) {
|
||||
throw new Error("API key is required");
|
||||
throw new Error("Virtual Key is required");
|
||||
}
|
||||
|
||||
const isLocal = process.env.NODE_ENV === "development";
|
||||
|
||||
@@ -9,7 +9,7 @@ export async function makeOpenAIEmbeddingsRequest(
|
||||
tags?: string[],
|
||||
) {
|
||||
if (!accessToken) {
|
||||
throw new Error("API key is required");
|
||||
throw new Error("Virtual Key is required");
|
||||
}
|
||||
|
||||
// Base URL should be the current base_url
|
||||
|
||||
@@ -24,7 +24,7 @@ export async function makeOpenAIResponsesRequest(
|
||||
onMCPEvent?: (event: MCPEvent) => void,
|
||||
) {
|
||||
if (!accessToken) {
|
||||
throw new Error("API key is required");
|
||||
throw new Error("Virtual Key is required");
|
||||
}
|
||||
|
||||
// Base URL should be the current base_url
|
||||
|
||||
@@ -245,7 +245,7 @@ import KeyInfoView from "./key_info_view";
|
||||
const baseKeyData = {
|
||||
token_id: "tok_123",
|
||||
token: "tok_123",
|
||||
key_alias: "My API Key",
|
||||
key_alias: "My Virtual Key",
|
||||
key_name: "sk-xxxx",
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
|
||||
@@ -297,7 +297,7 @@ export default function KeyInfoView({
|
||||
<Button icon={ArrowLeftIcon} variant="light" onClick={onClose} className="mb-4">
|
||||
{backButtonText}
|
||||
</Button>
|
||||
<Title>{currentKeyData.key_alias || "API Key"}</Title>
|
||||
<Title>{currentKeyData.key_alias || "Virtual Key"}</Title>
|
||||
|
||||
<div className="flex items-center cursor-pointer mb-2 space-y-6">
|
||||
<div>
|
||||
@@ -381,7 +381,7 @@ export default function KeyInfoView({
|
||||
{/* Delete Confirmation Modal */}
|
||||
{isDeleteModalOpen &&
|
||||
(() => {
|
||||
const keyName = currentKeyData?.key_alias || currentKeyData?.token_id || "API Key";
|
||||
const keyName = currentKeyData?.key_alias || currentKeyData?.token_id || "Virtual Key";
|
||||
const isValid = deleteConfirmInput === keyName;
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
@@ -415,7 +415,7 @@ export default function KeyInfoView({
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-base font-medium text-red-600">
|
||||
Warning: You are about to delete this API key.
|
||||
Warning: You are about to delete this Virtual Key.
|
||||
</p>
|
||||
<p className="text-base text-red-600 mt-2">
|
||||
This action is irreversible and will immediately revoke access for any applications using this
|
||||
@@ -423,7 +423,7 @@ export default function KeyInfoView({
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-base text-gray-600 mb-5">Are you sure you want to delete this API key?</p>
|
||||
<p className="text-base text-gray-600 mb-5">Are you sure you want to delete this Virtual Key?</p>
|
||||
<div className="mb-5">
|
||||
<label className="block text-base font-medium text-gray-700 mb-2">
|
||||
{`Type `}
|
||||
|
||||
@@ -273,7 +273,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
const handleRegenerateKey = async () => {
|
||||
if (!premiumUser) {
|
||||
NotificationManager.warning({
|
||||
description: "Regenerate API Key is an Enterprise feature. Please upgrade to use this feature.",
|
||||
description: "Regenerate Virtual Key is an Enterprise feature. Please upgrade to use this feature.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -298,10 +298,10 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
|
||||
setRegenerateDialogVisible(false);
|
||||
regenerateForm.resetFields();
|
||||
NotificationManager.success({ description: "API Key regenerated successfully" });
|
||||
NotificationManager.success({ description: "Virtual Key regenerated successfully" });
|
||||
} catch (error) {
|
||||
console.error("Error regenerating key:", error);
|
||||
NotificationManager.error({ description: "Failed to regenerate API Key" });
|
||||
NotificationManager.error({ description: "Failed to regenerate Virtual Key" });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -366,7 +366,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-base font-medium text-red-600">
|
||||
Warning: You are about to delete this API key.
|
||||
Warning: You are about to delete this Virtual Key.
|
||||
</p>
|
||||
<p className="text-base text-red-600 mt-2">
|
||||
This action is irreversible and will immediately revoke access for any applications using this
|
||||
@@ -374,7 +374,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-base text-gray-600 mb-5">Are you sure you want to delete this API key?</p>
|
||||
<p className="text-base text-gray-600 mb-5">Are you sure you want to delete this Virtual Key?</p>
|
||||
<div className="mb-5">
|
||||
<label className="block text-base font-medium text-gray-700 mb-2">
|
||||
{`Type `}
|
||||
@@ -407,7 +407,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
disabled={!isValid}
|
||||
className={`px-5 py-3 rounded-md text-base font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 ${isValid ? "bg-red-600 hover:bg-red-700" : "bg-red-300 cursor-not-allowed"}`}
|
||||
>
|
||||
Delete Key
|
||||
Delete Virtual Key
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -417,7 +417,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
|
||||
{/* Regenerate Key Form Modal */}
|
||||
<Modal
|
||||
title="Regenerate API Key"
|
||||
title="Regenerate Virtual Key"
|
||||
visible={regenerateDialogVisible}
|
||||
onCancel={() => {
|
||||
setRegenerateDialogVisible(false);
|
||||
@@ -516,7 +516,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
{selectedToken?.key_alias || "No alias set"}
|
||||
</pre>
|
||||
</div>
|
||||
<Text className="mt-3">New API Key:</Text>
|
||||
<Text className="mt-3">New Virtual Key:</Text>
|
||||
<div
|
||||
style={{
|
||||
background: "#f8f8f8",
|
||||
@@ -529,9 +529,9 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
||||
</div>
|
||||
<CopyToClipboard
|
||||
text={regeneratedKey}
|
||||
onCopy={() => NotificationManager.success({ description: "API Key copied to clipboard" })}
|
||||
onCopy={() => NotificationManager.success({ description: "Virtual Key copied to clipboard" })}
|
||||
>
|
||||
<Button className="mt-3">Copy API Key</Button>
|
||||
<Button className="mt-3">Copy Virtual Key</Button>
|
||||
</CopyToClipboard>
|
||||
</Col>
|
||||
</Grid>
|
||||
|
||||
@@ -615,7 +615,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ accessToken, token, userRole, use
|
||||
</Col>
|
||||
<Col numColSpan={1}>
|
||||
<Card className="h-full">
|
||||
<Title>Top API Keys</Title>
|
||||
<Title>Top Virtual Keys</Title>
|
||||
<TopKeyView
|
||||
topKeys={topKeys}
|
||||
accessToken={accessToken}
|
||||
|
||||
@@ -78,14 +78,14 @@ export const columns = (
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "API Keys",
|
||||
header: "Virtual Keys",
|
||||
accessorKey: "key_count",
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => (
|
||||
<Grid numItems={2}>
|
||||
{row.original.key_count > 0 ? (
|
||||
<Badge size="xs" color="indigo">
|
||||
{row.original.key_count} Keys
|
||||
{row.original.key_count} {row.original.key_count === 1 ? "Key" : "Keys"}
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge size="xs" color="gray">
|
||||
|
||||
@@ -320,9 +320,11 @@ export default function UserInfoView({
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Text>API Keys</Text>
|
||||
<Text>Virtual Keys</Text>
|
||||
<div className="mt-2">
|
||||
<Text>{userData.keys?.length || 0} keys</Text>
|
||||
<Text>
|
||||
{userData.keys?.length || 0} {userData.keys?.length === 1 ? "Key" : "Keys"}
|
||||
</Text>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -467,7 +469,7 @@ export default function UserInfoView({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text className="font-medium">API Keys</Text>
|
||||
<Text className="font-medium">Virtual Keys</Text>
|
||||
<div className="flex flex-wrap gap-2 mt-1">
|
||||
{userData.keys?.length && userData.keys?.length > 0 ? (
|
||||
userData.keys.map((key, index) => (
|
||||
@@ -476,7 +478,7 @@ export default function UserInfoView({
|
||||
</span>
|
||||
))
|
||||
) : (
|
||||
<Text>No API keys</Text>
|
||||
<Text>No Virtual Keys</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user