mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
refactor(ui): swap @ant-design/icons for lucide-react (#37553)
The dashboard drew its icons from two libraries at once: lucide-react, which shadcn/ui ships with, and @ant-design/icons, left over from antd. This moves the last 39 files onto lucide and drops the dependency, so the icon set matches the component library everywhere. antd icons sized themselves from the inherited font-size and rendered as role="img" with an aria-label, neither of which a lucide svg does, so the swap carries explicit size classes and gives the two icon-only plugin buttons real accessible names.
This commit is contained in:
parent
f22eeb2ce0
commit
629d7683f2
45 changed files with 195 additions and 218 deletions
|
|
@ -62,6 +62,10 @@ const eslintConfig = [
|
|||
message:
|
||||
"antd is being phased out; build new UI with shadcn/ui primitives instead of adding antd imports.",
|
||||
},
|
||||
{
|
||||
group: ["@ant-design/icons", "@ant-design/icons/*"],
|
||||
message: "@ant-design/icons is gone from the dashboard; use lucide-react instead.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
1
ui/litellm-dashboard/package-lock.json
generated
1
ui/litellm-dashboard/package-lock.json
generated
|
|
@ -9,7 +9,6 @@
|
|||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@ant-design/cssinjs": "1.24.0",
|
||||
"@ant-design/icons": "5.6.1",
|
||||
"@anthropic-ai/sdk": "0.92.0",
|
||||
"@base-ui/react": "^1.6.0",
|
||||
"@headlessui/tailwindcss": "0.2.2",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@ant-design/cssinjs": "1.24.0",
|
||||
"@ant-design/icons": "5.6.1",
|
||||
"@anthropic-ai/sdk": "0.92.0",
|
||||
"@base-ui/react": "^1.6.0",
|
||||
"@headlessui/tailwindcss": "0.2.2",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Select, Steps, Tag } from "antd";
|
|||
import { FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import { toast } from "@/lib/toast";
|
||||
import { Logo } from "@/components/molecules/logo/Logo";
|
||||
import { CheckCircleFilled, KeyOutlined, RobotOutlined, AppstoreOutlined } from "@ant-design/icons";
|
||||
import { Bot, CircleCheck, Key, LayoutGrid } from "lucide-react";
|
||||
import CreatedKeyDisplay from "@/components/shared/CreatedKeyDisplay";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
||||
|
|
@ -707,7 +707,7 @@ const AddAgentForm: React.FC<AddAgentFormProps> = ({ visible, onClose, accessTok
|
|||
}`}
|
||||
onClick={() => handleAgentTypeChange(CUSTOM_AGENT_TYPE)}
|
||||
>
|
||||
<AppstoreOutlined className="text-lg text-amber-600 dark:text-amber-400" />
|
||||
<LayoutGrid className="size-4.5 text-amber-600 dark:text-amber-400" />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium text-amber-700 dark:text-amber-400">Custom / Other</span>
|
||||
|
|
@ -846,7 +846,8 @@ const AddAgentForm: React.FC<AddAgentFormProps> = ({ visible, onClose, accessTok
|
|||
<div>
|
||||
{/* Agent name chip */}
|
||||
<div className="mb-6 flex justify-center">
|
||||
<Tag icon={<RobotOutlined />} color="purple" className="px-3 py-1 text-sm">
|
||||
<Tag color="purple" className="inline-flex items-center gap-1.5 px-3 py-1 text-sm">
|
||||
<Bot className="size-3.5" />
|
||||
{agentName}
|
||||
</Tag>
|
||||
</div>
|
||||
|
|
@ -884,7 +885,7 @@ const AddAgentForm: React.FC<AddAgentFormProps> = ({ visible, onClose, accessTok
|
|||
<RadioGroupItem value="create_new" aria-label="Create a new key for this agent" />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<KeyOutlined className="text-indigo-600 dark:text-indigo-400" />
|
||||
<Key className="size-4 text-indigo-600 dark:text-indigo-400" />
|
||||
<span className="font-medium text-foreground">Create a new key for this agent</span>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-muted-foreground">A dedicated key scoped to this agent.</p>
|
||||
|
|
@ -920,7 +921,7 @@ const AddAgentForm: React.FC<AddAgentFormProps> = ({ visible, onClose, accessTok
|
|||
<RadioGroupItem value="existing_key" aria-label="Assign an existing key" />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<KeyOutlined className="text-muted-foreground" />
|
||||
<Key className="size-4 text-muted-foreground" />
|
||||
<span className="font-medium text-foreground">Assign an existing key</span>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-muted-foreground">Re-assign a key you already have to this agent.</p>
|
||||
|
|
@ -958,10 +959,11 @@ const AddAgentForm: React.FC<AddAgentFormProps> = ({ visible, onClose, accessTok
|
|||
|
||||
const renderReadyStep = () => (
|
||||
<div className="py-6 text-center">
|
||||
<CheckCircleFilled className="mb-4 text-5xl text-green-500" style={{ fontSize: 48 }} />
|
||||
<CircleCheck className="mb-4 size-12 text-green-500" />
|
||||
<h3 className="mb-2 text-xl font-semibold text-foreground">Agent Created!</h3>
|
||||
<div className="mb-4 flex justify-center">
|
||||
<Tag icon={<RobotOutlined />} color="purple" className="px-3 py-1 text-sm">
|
||||
<Tag color="purple" className="inline-flex items-center gap-1.5 px-3 py-1 text-sm">
|
||||
<Bot className="size-3.5" />
|
||||
{createdAgentName}
|
||||
</Tag>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
CheckCircleOutlined,
|
||||
CodeOutlined,
|
||||
PlayCircleOutlined,
|
||||
RollbackOutlined,
|
||||
SaveOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { CircleCheck, CirclePlay, Code, Save, Undo2 } from "lucide-react";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
|
@ -100,11 +94,11 @@ export function GuardrailConfig({ guardrailName, guardrailType, provider }: Guar
|
|||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline">
|
||||
<RollbackOutlined />
|
||||
<Undo2 />
|
||||
Revert
|
||||
</Button>
|
||||
<Button>
|
||||
<SaveOutlined />
|
||||
<Save />
|
||||
Save as v{parseInt(version.replace("v", ""), 10) + 1}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -214,7 +208,7 @@ export function GuardrailConfig({ guardrailName, guardrailType, provider }: Guar
|
|||
<div className="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-gray-900 flex items-center gap-2">
|
||||
<CodeOutlined className="text-gray-500" />
|
||||
<Code className="size-4 text-gray-500" />
|
||||
Custom Code Override
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 mt-0.5">Replace the built-in guardrail with custom evaluation code</p>
|
||||
|
|
@ -247,13 +241,13 @@ export function GuardrailConfig({ guardrailName, guardrailType, provider }: Guar
|
|||
|
||||
<div className="flex items-center gap-3">
|
||||
<Button disabled={rerunStatus === "running"} aria-busy={rerunStatus === "running"} onClick={handleRerun}>
|
||||
{rerunStatus === "running" ? null : <PlayCircleOutlined />}
|
||||
{rerunStatus === "running" ? null : <CirclePlay />}
|
||||
{rerunStatus === "running" ? "Running on 10 samples..." : "Re-run on failing logs"}
|
||||
</Button>
|
||||
|
||||
{rerunStatus === "success" && (
|
||||
<span className="text-sm text-green-600 flex items-center gap-2">
|
||||
<CheckCircleOutlined /> 7/10 would now pass with new config
|
||||
<CircleCheck className="size-4" /> 7/10 would now pass with new config
|
||||
</span>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,6 @@ import userEvent from "@testing-library/user-event";
|
|||
import GuardrailCard from "./guardrail_garden_card";
|
||||
import type { GuardrailCardInfo } from "./guardrail_garden_data";
|
||||
|
||||
vi.mock("@ant-design/icons", () => ({
|
||||
CheckCircleFilled: ({ style, ...props }: any) => <span data-testid="check-icon" {...props} />,
|
||||
}));
|
||||
|
||||
const baseCard: GuardrailCardInfo = {
|
||||
id: "test-guard",
|
||||
name: "Test Guardrail",
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ describe("Guardrail Info", () => {
|
|||
expect(getByText("Guardrail Settings")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await userEvent.hover(within(container).getByRole("img", { name: "info-circle" }));
|
||||
await userEvent.hover(within(container).getByRole("img", { name: "Config guardrail details" }));
|
||||
|
||||
expect(await findByText("Guardrail is defined in the config file and cannot be edited.")).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import {
|
|||
updateGuardrailCall,
|
||||
} from "@/components/networking";
|
||||
import { copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils";
|
||||
import { EyeInvisibleOutlined, InfoCircleOutlined, StopOutlined } from "@ant-design/icons";
|
||||
|
||||
import { ArrowLeft, CheckIcon, Code, CopyIcon } from "lucide-react";
|
||||
import { ArrowLeft, Ban, CheckIcon, Code, CopyIcon, EyeOff, Info } from "lucide-react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
|
@ -607,7 +606,7 @@ const GuardrailInfoView: React.FC<GuardrailInfoProps> = ({ guardrailId, onClose,
|
|||
value === "MASK" ? "text-blue-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{value === "MASK" ? <EyeInvisibleOutlined /> : <StopOutlined />}
|
||||
{value === "MASK" ? <EyeOff className="size-3.5" /> : <Ban className="size-3.5" />}
|
||||
{String(value)}
|
||||
</span>
|
||||
</p>
|
||||
|
|
@ -667,7 +666,7 @@ const GuardrailInfoView: React.FC<GuardrailInfoProps> = ({ guardrailId, onClose,
|
|||
<h3 className="text-lg font-medium">Guardrail Settings</h3>
|
||||
{isConfigGuardrail && (
|
||||
<SimpleTooltip content="Guardrail is defined in the config file and cannot be edited.">
|
||||
<InfoCircleOutlined />
|
||||
<Info role="img" aria-label="Config guardrail details" className="size-4 text-muted-foreground" />
|
||||
</SimpleTooltip>
|
||||
)}
|
||||
{!isEditing &&
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { antdRequired } from "@/components/common_components/antdFormRules";
|
||||
|
|
@ -12,7 +12,7 @@ const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, toolt
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
{label}
|
||||
<Tooltip title={tooltip}>
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import { Tooltip, Select, Input as AntdInput, InputNumber, Collapse } from "antd";
|
||||
import { FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
||||
|
|
@ -688,7 +688,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
MCP Server Name
|
||||
<Tooltip title="Best practice: Use a descriptive name that indicates the server's purpose (e.g., 'GitHub_MCP', 'Email_Service'). Cannot contain spaces or hyphens; use underscores instead. Names must comply with SEP-986 and will be rejected if invalid (https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-names).">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -709,7 +709,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Alias
|
||||
<Tooltip title="A short, unique identifier for this server. Defaults to the server name if not provided. Cannot contain spaces or hyphens; use underscores instead.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -827,7 +827,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Max Concurrent Requests (optional)
|
||||
<Tooltip title="Maximum number of tool calls LiteLLM will run against this server at the same time. Additional calls wait for a free slot. Leave blank for no limit.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -910,7 +910,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Authentication Value
|
||||
<Tooltip title="Token, password, or header value to send with each request for the selected auth type.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Switch, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { isClientForwardedTokenMode } from "@/components/mcp_tools/types";
|
||||
|
|
@ -29,7 +29,7 @@ export default function DcrBridgeToggle({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Gateway-hosted sign-in (DCR bridge)
|
||||
<Tooltip title="Lets OAuth-only clients like Claude Desktop register and sign in through the gateway. Turn off to relay the upstream server's own OAuth metadata instead (for clients pre-registered with the upstream IdP).">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import { Input, Select, Tooltip, Typography } from "antd";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { InfoCircleOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { CircleMinus, Info, Plus } from "lucide-react";
|
||||
import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
|
||||
|
||||
import {
|
||||
|
|
@ -55,7 +55,7 @@ const EnvVarsSection: React.FC = () => {
|
|||
</>
|
||||
}
|
||||
>
|
||||
<InfoCircleOutlined className="text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Text className="text-xs text-gray-600 block mb-3">
|
||||
|
|
@ -100,15 +100,15 @@ const EnvVarsSection: React.FC = () => {
|
|||
{(control) => <Select {...selectControl<string>(control)} options={SCOPE_OPTIONS} />}
|
||||
</MountedFormField>
|
||||
<div style={{ width: 24, height: 32 }} className="flex items-center justify-center">
|
||||
<MinusCircleOutlined
|
||||
<CircleMinus
|
||||
onClick={() => remove(index)}
|
||||
className="text-gray-500 hover:text-red-500 cursor-pointer"
|
||||
className="size-4 text-gray-500 hover:text-red-500 cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<Button variant="outline" className="w-full border-dashed" onClick={() => append({ scope: "global" })}>
|
||||
<PlusOutlined />
|
||||
<Plus />
|
||||
Add Variable
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -130,7 +130,7 @@ const ScopedValueOrDescription: React.FC<{ index: number }> = ({ index }) => {
|
|||
addonBefore={
|
||||
<Tooltip title="Per-user variables have no shared value. This text is only a hint shown to each user when they fill in their own value.">
|
||||
<span className="text-xs text-gray-500 cursor-help whitespace-nowrap">
|
||||
<InfoCircleOutlined className="mr-1" />
|
||||
<Info className="mr-1 inline size-3 align-text-bottom" />
|
||||
Hint
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input, Select, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { antdRequired } from "@/components/common_components/antdFormRules";
|
||||
|
|
@ -16,7 +16,7 @@ const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, toolt
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
{label}
|
||||
<Tooltip title={tooltip}>
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Select, Tooltip, Collapse, Input, Space, Switch } from "antd";
|
||||
import { TriangleAlert } from "lucide-react";
|
||||
import { CircleMinus, Info, Plus, TriangleAlert } from "lucide-react";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { InfoCircleOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
|
||||
import { MCPServer, AUTH_TYPE } from "@/components/mcp_tools/types";
|
||||
import {
|
||||
|
|
@ -74,14 +73,14 @@ const StaticHeadersFieldArray: React.FC = () => {
|
|||
/>
|
||||
)}
|
||||
</MountedFormField>
|
||||
<MinusCircleOutlined
|
||||
<CircleMinus
|
||||
onClick={() => remove(index)}
|
||||
className="text-gray-500 hover:text-red-500 cursor-pointer"
|
||||
className="size-4 text-gray-500 hover:text-red-500 cursor-pointer"
|
||||
/>
|
||||
</Space>
|
||||
))}
|
||||
<Button variant="outline" className="w-full border-dashed" onClick={() => append({})}>
|
||||
<PlusOutlined />
|
||||
<Plus />
|
||||
Add Static Header
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -196,7 +195,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Allow All LiteLLM Keys
|
||||
<Tooltip title="When enabled, every API key can access this MCP server.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
|
|
@ -213,7 +212,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Internal network only
|
||||
<Tooltip title="When on, only requests from within your internal network are accepted. Turn off to allow external clients (other clusters, ChatGPT, etc). API key authentication is always required regardless of this setting.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
|
|
@ -231,7 +230,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Delegate auth to upstream (PKCE passthrough)
|
||||
<Tooltip title="When on, LiteLLM skips its own API key/SSO check for this server and lets the client complete PKCE directly with the upstream MCP server. Only honored when Auth Type is oauth2. No spend tracking or per-key rate limiting will run on this route.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
|
|
@ -254,7 +253,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
OAuth pass-through
|
||||
<Tooltip title="When on, this server is treated as an OAuth pass-through: the gateway proxies the upstream /.well-known/oauth-protected-resource metadata, emits spec-compliant 401 challenges when no bearer is supplied, and propagates upstream 401/403 responses. Only honored when Auth Type is None and 'Authorization' is in Extra Headers.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
|
|
@ -289,7 +288,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
MCP Access Groups
|
||||
<Tooltip title="Specify access groups for this MCP server. Users must be in at least one of these groups to access the server.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -318,7 +317,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Extra Headers
|
||||
<Tooltip title="Forward custom headers from incoming requests to this MCP server (e.g., Authorization, X-Custom-Header, User-Agent)">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
{mcpServer?.extra_headers && mcpServer.extra_headers.length > 0 && (
|
||||
<span className="ml-2 text-xs bg-blue-100 text-blue-700 px-2 py-1 rounded-full">
|
||||
|
|
@ -351,7 +350,7 @@ const MCPPermissionManagement: React.FC<MCPPermissionManagementProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Static Headers
|
||||
<Tooltip title="Send these key-value headers with every request to this MCP server.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FieldLabel>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input as AntdInput, InputNumber, Select, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { OAUTH_FLOW } from "@/components/mcp_tools/types";
|
||||
|
|
@ -38,7 +38,7 @@ const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, toolt
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
{label}
|
||||
<Tooltip title={tooltip}>
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import { Input, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { AUTH_TYPE, OAUTH_FLOW } from "@/components/mcp_tools/types";
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { antdRequired } from "@/components/common_components/antdFormRules";
|
||||
|
|
@ -69,7 +69,7 @@ const OpenAPIFormSection: React.FC<OpenAPIFormSectionProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
OpenAPI Spec URL
|
||||
<Tooltip title="URL to an OpenAPI specification (JSON or YAML). MCP tools will be automatically generated from the API endpoints defined in the spec.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input, Select, Switch, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { useWatch } from "react-hook-form";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
|
|
@ -26,7 +26,7 @@ const OpenApiByokFields: React.FC = () => {
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center gap-2">
|
||||
BYOK (Bring Your Own Key)
|
||||
<Tooltip title="When enabled, each user provides their own API key for this service. Keys are stored per-user and never shared.">
|
||||
<InfoCircleOutlined className="text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ const OpenApiByokFields: React.FC = () => {
|
|||
<>
|
||||
{hasAuthType && (
|
||||
<div className="mb-4 p-3 bg-blue-50 rounded-lg text-sm text-blue-700 flex items-start gap-2">
|
||||
<InfoCircleOutlined className="mt-0.5 shrink-0" />
|
||||
<Info className="mt-0.5 size-4 shrink-0" />
|
||||
<span>
|
||||
User keys will be sent as:{" "}
|
||||
<code className="font-mono bg-blue-100 px-1 rounded-sm">
|
||||
|
|
@ -50,7 +50,7 @@ const OpenApiByokFields: React.FC = () => {
|
|||
)}
|
||||
{!authType && (
|
||||
<div className="mb-4 p-3 bg-yellow-50 rounded-lg text-sm text-yellow-700 flex items-start gap-2">
|
||||
<InfoCircleOutlined className="mt-0.5 shrink-0" />
|
||||
<Info className="mt-0.5 size-4 shrink-0" />
|
||||
<span>
|
||||
Set the <strong>Authentication Type</strong> below to specify how user keys are sent (e.g., Bearer
|
||||
Token, API Key header).
|
||||
|
|
@ -62,7 +62,7 @@ const OpenApiByokFields: React.FC = () => {
|
|||
<span className="text-sm font-medium text-gray-700">
|
||||
Access Description
|
||||
<Tooltip title="List of permissions shown to users in the connection modal (e.g. 'Create and manage Jira issues')">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ const OpenApiByokFields: React.FC = () => {
|
|||
<span className="text-sm font-medium text-gray-700">
|
||||
API Key Help URL
|
||||
<Tooltip title="Optional link shown to users to help them find their API key">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { antdRequired } from "@/components/common_components/antdFormRules";
|
||||
|
|
@ -37,7 +37,7 @@ const StdioConfiguration: React.FC<StdioConfigurationProps> = ({ isVisible, requ
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Stdio Configuration (JSON)
|
||||
<Tooltip title="Paste your stdio MCP server configuration in JSON format. You can use the full mcpServers structure from config.yaml or just the inner server configuration.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Select, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
import { selectControl } from "./mcpFieldRules";
|
||||
|
|
@ -20,7 +20,7 @@ const TokenEndpointAuthMethodField: React.FC<TokenEndpointAuthMethodFieldProps>
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Token Endpoint Auth Method (optional)
|
||||
<Tooltip title="How the proxy authenticates to the upstream OAuth token endpoint. Client Secret Basic sends the client credentials in an HTTP Basic Authorization header; leave blank to use the default, Client Secret Post, which sends them in the request body.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Input, Select, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { useWatch } from "react-hook-form";
|
||||
|
||||
import { MountedFormField } from "@/components/common_components/MountedFormField";
|
||||
|
|
@ -17,7 +17,7 @@ const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, toolt
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
{label}
|
||||
<Tooltip title={tooltip}>
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Select, Tooltip, Input, InputNumber } from "antd";
|
||||
import { TriangleAlert } from "lucide-react";
|
||||
import { Info, TriangleAlert } from "lucide-react";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import {
|
||||
|
|
@ -875,7 +874,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
OpenAPI Spec URL
|
||||
<Tooltip title="URL to an OpenAPI specification (JSON or YAML). MCP tools will be automatically generated from the API endpoints defined in the spec.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -898,7 +897,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Max Concurrent Requests (optional)
|
||||
<Tooltip title="Maximum number of tool calls LiteLLM will run against this server at the same time. Additional calls wait for a free slot. Leave blank for no limit.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1026,7 +1025,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
Authentication Value
|
||||
<Tooltip title="Token, password, or header value to send with each request for the selected auth type.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1091,7 +1090,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Region
|
||||
<Tooltip title="AWS region for SigV4 signing (e.g., us-east-1)">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1110,7 +1109,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Service Name
|
||||
<Tooltip title="AWS service name for SigV4 signing. Defaults to 'bedrock-agentcore'.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1129,7 +1128,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Access Key ID
|
||||
<Tooltip title="Optional. If not provided, falls back to the boto3 credential chain (IAM role, env vars, etc.).">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1148,7 +1147,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Secret Access Key
|
||||
<Tooltip title="Optional. Required if AWS Access Key ID is provided.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1167,7 +1166,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Session Token
|
||||
<Tooltip title="Optional. Only needed for temporary STS credentials.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1186,7 +1185,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Role ARN
|
||||
<Tooltip title="Optional. IAM role ARN to assume via STS before signing. If set, LiteLLM calls sts:AssumeRole to get temporary credentials.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1205,7 +1204,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<span className="text-sm font-medium text-gray-700 flex items-center">
|
||||
AWS Session Name
|
||||
<Tooltip title="Optional. Session name for the AssumeRole call — appears in CloudTrail logs. Auto-generated if omitted.">
|
||||
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
<Info className="ml-2 size-4 text-blue-400 hover:text-blue-600 cursor-help" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/in
|
|||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
||||
import { ClockCircleOutlined } from "@ant-design/icons";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { CircleHelp } from "lucide-react";
|
||||
import { CircleHelp, Clock } from "lucide-react";
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
|
|
@ -199,7 +198,7 @@ const LoggingSettingsForm: React.FC<LoggingSettingsFormProps> = ({
|
|||
placeholder={field.placeholder}
|
||||
/>
|
||||
<InputGroupAddon>
|
||||
<ClockCircleOutlined />
|
||||
<Clock />
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ describe("PluginSettings config payload", () => {
|
|||
render(<PluginSettings />);
|
||||
expect(await screen.findByText("Alpha")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "edit" }));
|
||||
await user.click(screen.getByRole("button", { name: "Edit alpha" }));
|
||||
expect(await screen.findByLabelText(/Plugin Key/)).toHaveValue("");
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Save" }));
|
||||
|
|
@ -88,7 +88,7 @@ describe("PluginSettings config payload", () => {
|
|||
render(<PluginSettings />);
|
||||
expect(await screen.findByText("Alpha")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "edit" }));
|
||||
await user.click(screen.getByRole("button", { name: "Edit alpha" }));
|
||||
fireEvent.change(await screen.findByLabelText(/Plugin Key/), { target: { value: "sk-brand-new" } });
|
||||
await user.click(screen.getByRole("button", { name: "Save" }));
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ describe("PluginSettings plugin key reveal (post-migration shadcn affordance)",
|
|||
render(<PluginSettings />);
|
||||
expect(await screen.findByText("Alpha")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "edit" }));
|
||||
await user.click(screen.getByRole("button", { name: "Edit alpha" }));
|
||||
const keyInput = await screen.findByLabelText(/Plugin Key/);
|
||||
expect(keyInput).toHaveAttribute("type", "password");
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { Card, Space, Table, Typography } from "antd";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { Eye, EyeOff } from "lucide-react";
|
||||
import { Eye, EyeOff, Pencil, Plus, Trash2 } from "lucide-react";
|
||||
import { getConfigFieldSetting, updateConfigFieldSetting } from "@/components/networking";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { FieldGroup } from "@/components/shared/form/field";
|
||||
|
|
@ -113,13 +112,18 @@ export default function PluginSettings() {
|
|||
{
|
||||
title: "Actions",
|
||||
key: "actions",
|
||||
render: (_: unknown, __: Plugin, idx: number) => (
|
||||
render: (_: unknown, plugin: Plugin, idx: number) => (
|
||||
<Space>
|
||||
<Button variant="outline" size="icon-sm" onClick={() => openEdit(idx)}>
|
||||
<EditOutlined />
|
||||
<Button variant="outline" size="icon-sm" aria-label={`Edit ${plugin.name}`} onClick={() => openEdit(idx)}>
|
||||
<Pencil />
|
||||
</Button>
|
||||
<Button variant="destructive" size="icon-sm" onClick={() => handleDelete(idx)}>
|
||||
<DeleteOutlined />
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="icon-sm"
|
||||
aria-label={`Delete ${plugin.name}`}
|
||||
onClick={() => handleDelete(idx)}
|
||||
>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
|
|
@ -138,7 +142,7 @@ export default function PluginSettings() {
|
|||
</Paragraph>
|
||||
|
||||
<Button className="mb-4" onClick={openAdd}>
|
||||
<PlusOutlined />
|
||||
<Plus />
|
||||
Add Plugin
|
||||
</Button>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
import { DataTableMultiSortHeader, DataTableSortHeader, type DataTableSortField } from "@/components/shared/DataTable";
|
||||
|
|
@ -119,7 +119,7 @@ const InfoHeader = ({ label, tooltip }: { label: string; tooltip: string }) => (
|
|||
<span className="flex items-center gap-1">
|
||||
{label}
|
||||
<HoverCard>
|
||||
<HoverCardTrigger render={<InfoCircleOutlined className="text-gray-400 text-xs cursor-help" />} />
|
||||
<HoverCardTrigger render={<Info className="size-3 text-gray-400 cursor-help" />} />
|
||||
<HoverCardContent className="w-auto">{tooltip}</HoverCardContent>
|
||||
</HoverCard>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { Select as AntdSelect, Card, InputNumber, Radio, Space, Switch, Typography } from "antd";
|
||||
import React from "react";
|
||||
|
|
@ -303,7 +303,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
|
|||
<div className="flex items-center gap-2 mb-1">
|
||||
<Text strong>Classification Rubric</Text>
|
||||
<SimpleTooltip content="Every rubric uses the same four tiers and the same tier definitions. They differ only in the worked examples that show the classifier where the boundary between tiers sits.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<SimpleTooltip
|
||||
|
|
@ -413,7 +413,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
|
|||
/>
|
||||
<Text strong>Include Assistant Turns</Text>
|
||||
<SimpleTooltip content="Off by default. Enabling it changes tier decisions, and therefore spend, for an existing router, and sends assistant text to the classifier model, which may be a different provider than the routed model.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
|
|
@ -431,7 +431,7 @@ const ClassificationMethodConfig: React.FC<ClassificationMethodConfigProps> = ({
|
|||
<div className="flex items-center gap-2 mb-1">
|
||||
<Text strong>Custom Technical Keywords</Text>
|
||||
<SimpleTooltip content="Domain-specific terms appended to the built-in technical keyword list. Prompts containing these terms score higher on the technical dimension and route to more capable models.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Text type="secondary" style={{ display: "block", marginBottom: 8, fontSize: 12 }}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { Select as AntdSelect, Card, Collapse, Divider, Input, Space, Switch, Typography } from "antd";
|
||||
import React from "react";
|
||||
|
|
@ -256,7 +256,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
|
|||
Complexity Tier Configuration
|
||||
</Typography.Title>
|
||||
<SimpleTooltip content="Map each complexity tier to one or more models. Simple queries use cheaper/faster models, complex queries use more capable models.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</Space>
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
|
|||
{label} Tier
|
||||
</Text>
|
||||
<SimpleTooltip content={tierInfo.description}>
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
Tier {index + 1} of {TIER_KEYS.length} · {tier}
|
||||
|
|
@ -336,7 +336,7 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
|
|||
Default Model
|
||||
</Text>
|
||||
<SimpleTooltip content="Leave empty to follow the tiers. A model chosen here is pinned: it stays the default however the tiers change.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<AntdSelect
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { Select as AntdSelect, Typography } from "antd";
|
||||
import React from "react";
|
||||
|
|
@ -20,7 +20,7 @@ const EscalationKeywords: React.FC<EscalationKeywordsProps> = ({ keywords, onCha
|
|||
Escalation Keywords
|
||||
</Typography.Title>
|
||||
<SimpleTooltip content="Case-sensitive phrases a user can include in their message to force a bump to the next-higher complexity tier when they aren't happy with results. They can force a stronger model, but not choose which one.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Text type="secondary" style={{ display: "block", marginBottom: 8, fontSize: 12 }}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DeleteOutlined, InfoCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { Info, Plus, Trash2 } from "lucide-react";
|
||||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { Card, Empty, Select as AntdSelect, Typography } from "antd";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -73,11 +73,11 @@ const KeywordTierRules: React.FC<KeywordTierRulesProps> = ({ rules, onChange, ti
|
|||
Keyword Tier Overrides
|
||||
</Typography.Title>
|
||||
<SimpleTooltip content="Match known terms and force the request straight to a chosen complexity tier, bypassing rule-based scoring.">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Button variant="outline" onClick={addRule}>
|
||||
<PlusOutlined />
|
||||
<Plus />
|
||||
Add keyword rule
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -139,7 +139,7 @@ const KeywordTierRules: React.FC<KeywordTierRulesProps> = ({ rules, onChange, ti
|
|||
aria-label={`Remove keyword rule ${index + 1}`}
|
||||
onClick={() => removeRule(rule.id)}
|
||||
>
|
||||
<DeleteOutlined />
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { InputNumber, Select as AntdSelect, Switch, Typography } from "antd";
|
||||
import React from "react";
|
||||
|
|
@ -43,7 +43,7 @@ const SemanticKeywordMatching: React.FC<SemanticKeywordMatchingProps> = ({
|
|||
<div className="flex items-center gap-2">
|
||||
<Text className="font-medium">Semantic keyword matching</Text>
|
||||
<SimpleTooltip content="Recognize related phrasing beyond exact keyword matches by comparing embeddings instead of plain text. Overrides direct keyword matching">
|
||||
<InfoCircleOutlined className="text-gray-400" />
|
||||
<Info className="size-4 text-gray-400" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Text className="text-gray-500 text-sm">
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import React from "react";
|
||||
import { Switch, Select, Tooltip, DatePicker } from "antd";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { ChevronDown, Info } from "lucide-react";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Row, Col, Typography } from "antd";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Team } from "../key_team_helpers/key_list";
|
||||
import { antdRules } from "../common_components/antdFormRules";
|
||||
import { labelWithHint } from "@/components/shared/form/LabelWithHint";
|
||||
|
|
@ -115,7 +114,7 @@ const AdvancedSettings: React.FC<AdvancedSettingsProps> = ({
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -145,7 +144,7 @@ const AdvancedSettings: React.FC<AdvancedSettingsProps> = ({
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useProviderFields } from "@/app/(dashboard)/hooks/providers/useProviderFields";
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Col, Input as AntdInput, Row, Select, Typography, Upload, UploadProps } from "antd";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Upload as UploadIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import { antdRequired } from "../common_components/antdFormRules";
|
||||
|
|
@ -257,7 +257,7 @@ const ProviderSpecificFields: React.FC<ProviderSpecificFieldsProps> = ({ selecte
|
|||
}}
|
||||
>
|
||||
<Button variant="outline">
|
||||
<UploadOutlined />
|
||||
<UploadIcon />
|
||||
Click to Upload
|
||||
</Button>
|
||||
</Upload>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import { ArrowLeftOutlined, CopyOutlined, CheckOutlined, LinkOutlined } from "@ant-design/icons";
|
||||
import { ArrowLeft, Check, Copy, Link2 } from "lucide-react";
|
||||
import { buildMarketplaceSettingsSnippet, formatInstallCommand } from "./helpers";
|
||||
import { Plugin } from "./types";
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ const SkillDetail: React.FC<SkillDetailProps> = ({ skill, onBack }) => {
|
|||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
<ArrowLeftOutlined style={{ fontSize: 11 }} />
|
||||
<ArrowLeft className="size-3" />
|
||||
<span>Skills</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ const SkillDetail: React.FC<SkillDetailProps> = ({ skill, onBack }) => {
|
|||
}}
|
||||
>
|
||||
{sourceUrl.replace("https://", "")}
|
||||
<LinkOutlined style={{ fontSize: 11, flexShrink: 0 }} />
|
||||
<Link2 className="size-3 shrink-0" />
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -243,7 +243,7 @@ const SkillDetail: React.FC<SkillDetailProps> = ({ skill, onBack }) => {
|
|||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{copiedKey === "install" ? <CheckOutlined /> : <CopyOutlined />}
|
||||
{copiedKey === "install" ? <Check className="size-3" /> : <Copy className="size-3" />}
|
||||
{copiedKey === "install" ? "Copied" : "Copy"}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -315,7 +315,7 @@ const SkillDetail: React.FC<SkillDetailProps> = ({ skill, onBack }) => {
|
|||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{copiedKey === "settings" ? <CheckOutlined /> : <CopyOutlined />}
|
||||
{copiedKey === "settings" ? <Check className="size-3" /> : <Copy className="size-3" />}
|
||||
{copiedKey === "settings" ? "Copied" : "Copy"}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Select, Skeleton } from "antd";
|
||||
import { TeamOutlined } from "@ant-design/icons";
|
||||
import { Users } from "lucide-react";
|
||||
import { useAccessGroups, AccessGroupResponse } from "@/app/(dashboard)/hooks/accessGroups/useAccessGroups";
|
||||
|
||||
export interface AccessGroupSelectorProps {
|
||||
|
|
@ -42,7 +42,7 @@ const AccessGroupSelector: React.FC<AccessGroupSelectorProps> = ({
|
|||
<div>
|
||||
{showLabel && (
|
||||
<p className="mb-2 flex items-center text-sm font-medium text-foreground">
|
||||
<TeamOutlined className="mr-2" /> {labelText}
|
||||
<Users className="mr-2 size-4" /> {labelText}
|
||||
</p>
|
||||
)}
|
||||
<Skeleton.Input active block style={{ height: 32, ...style }} />
|
||||
|
|
@ -68,7 +68,7 @@ const AccessGroupSelector: React.FC<AccessGroupSelectorProps> = ({
|
|||
<div>
|
||||
{showLabel && (
|
||||
<p className="mb-2 flex items-center text-sm font-medium text-foreground">
|
||||
<TeamOutlined className="mr-2" /> {labelText}
|
||||
<Users className="mr-2 size-4" /> {labelText}
|
||||
</p>
|
||||
)}
|
||||
<Select
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Input as AntdInput, InputNumber, Select } from "antd";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Info } from "lucide-react";
|
||||
import { Tooltip } from "antd";
|
||||
import type { UseFormSetValue } from "react-hook-form";
|
||||
import { getOpenAPISchema } from "../networking";
|
||||
|
|
@ -183,7 +183,7 @@ const SchemaFormFields: React.FC<SchemaFormFieldsProps> = ({
|
|||
<span>
|
||||
{label}{" "}
|
||||
<Tooltip title={tooltip}>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useRef, useState } from "react";
|
||||
import { Info } from "lucide-react";
|
||||
import { Info, UserPlus } from "lucide-react";
|
||||
import { Alert, AlertTitle } from "@/components/shared/Alert";
|
||||
import { UserAddOutlined } from "@ant-design/icons";
|
||||
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { userFilterUICall } from "@/components/networking";
|
||||
|
|
@ -266,7 +265,7 @@ const UserSearchModal: React.FC<UserSearchModalProps> = ({
|
|||
|
||||
<div className="mt-4 text-right">
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{isSubmitting ? <UiLoadingSpinner className="size-4" /> : <UserAddOutlined />}
|
||||
{isSubmitting ? <UiLoadingSpinner className="size-4" /> : <UserPlus />}
|
||||
{isSubmitting ? "Adding..." : "Add Member"}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,15 +5,7 @@ import { Input, Switch } from "antd";
|
|||
import { toast } from "@/lib/toast";
|
||||
import { fetchClient } from "@/lib/http/api";
|
||||
import { ApiError } from "@/lib/http/client";
|
||||
import {
|
||||
KeyOutlined,
|
||||
LockOutlined,
|
||||
CheckOutlined,
|
||||
ArrowRightOutlined,
|
||||
ArrowLeftOutlined,
|
||||
CloseOutlined,
|
||||
LinkOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { ArrowLeft, ArrowRight, Check, Key, Link2, Lock, X } from "lucide-react";
|
||||
import { MCPServer } from "./types";
|
||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||
|
||||
|
|
@ -84,7 +76,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
onClick={() => setStep(1)}
|
||||
className="flex items-center gap-1 text-gray-500 hover:text-gray-800 text-sm"
|
||||
>
|
||||
<ArrowLeftOutlined /> Back
|
||||
<ArrowLeft className="size-3.5" /> Back
|
||||
</button>
|
||||
) : (
|
||||
<div />
|
||||
|
|
@ -94,7 +86,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
<div className={`w-2 h-2 rounded-full ${step === 2 ? "bg-blue-500" : "bg-gray-300"}`} />
|
||||
</div>
|
||||
<button onClick={handleClose} className="text-gray-400 hover:text-gray-600">
|
||||
<CloseOutlined />
|
||||
<X className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -105,7 +97,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
<div className="w-14 h-14 rounded-xl bg-linear-to-br from-teal-400 to-cyan-600 flex items-center justify-center text-white font-bold text-xl shadow-sm">
|
||||
L
|
||||
</div>
|
||||
<ArrowRightOutlined className="text-gray-400 text-lg" />
|
||||
<ArrowRight className="size-4.5 text-gray-400" />
|
||||
<div className="w-14 h-14 rounded-xl bg-linear-to-br from-blue-600 to-indigo-800 flex items-center justify-center text-white font-bold text-xl shadow-sm">
|
||||
{firstLetter}
|
||||
</div>
|
||||
|
|
@ -148,7 +140,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
<ul className="space-y-2">
|
||||
{server.byok_description.map((item, i) => (
|
||||
<li key={i} className="flex items-center gap-2 text-sm text-gray-700">
|
||||
<CheckOutlined className="text-green-500 shrink-0" />
|
||||
<Check className="size-3.5 shrink-0 text-green-500" />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
|
|
@ -160,7 +152,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
onClick={() => setStep(2)}
|
||||
className="w-full bg-gray-900 hover:bg-gray-700 text-white font-medium py-3 px-6 rounded-xl flex items-center justify-center gap-2 transition-colors"
|
||||
>
|
||||
Continue to Authentication <ArrowRightOutlined />
|
||||
Continue to Authentication <ArrowRight className="size-4" />
|
||||
</button>
|
||||
<button onClick={handleClose} className="mt-3 w-full text-gray-400 hover:text-gray-600 text-sm py-2">
|
||||
Cancel
|
||||
|
|
@ -170,7 +162,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
<div>
|
||||
{/* Key icon */}
|
||||
<div className="w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center mb-4">
|
||||
<KeyOutlined className="text-blue-400 text-xl" />
|
||||
<Key className="size-5 text-blue-400" />
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Provide API Key</h2>
|
||||
|
|
@ -192,7 +184,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
rel="noopener noreferrer"
|
||||
className="text-blue-500 hover:text-blue-700 text-sm mt-2 flex items-center gap-1"
|
||||
>
|
||||
Where do I find my API key? <LinkOutlined />
|
||||
Where do I find my API key? <Link2 className="size-3.5" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -213,7 +205,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
|
||||
{/* Security note */}
|
||||
<div className="bg-blue-50 rounded-xl p-4 flex items-start gap-3 mb-6">
|
||||
<LockOutlined className="text-blue-400 mt-0.5 shrink-0" />
|
||||
<Lock className="mt-0.5 size-4 shrink-0 text-blue-400" />
|
||||
<p className="text-sm text-blue-700">
|
||||
Your key is stored securely and transmitted over HTTPS. It is never shared with third parties.
|
||||
</p>
|
||||
|
|
@ -224,7 +216,7 @@ export const ByokCredentialModal: React.FC<ByokCredentialModalProps> = ({ server
|
|||
disabled={loading}
|
||||
className="w-full bg-blue-500 hover:bg-blue-600 disabled:opacity-60 text-white font-medium py-3 px-6 rounded-xl flex items-center justify-center gap-2 transition-colors"
|
||||
>
|
||||
<LockOutlined /> Connect & Authorize
|
||||
<Lock className="size-4" /> Connect & Authorize
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { useModelCostMap } from "@/app/(dashboard)/hooks/models/useModelCostMap"
|
|||
import { useModelHub, useModelsInfo } from "@/app/(dashboard)/hooks/models/useModels";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { transformModelData } from "@/app/(dashboard)/models-and-endpoints/utils/modelDataTransformer";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { KeyIcon, RefreshIcon, TrashIcon } from "@heroicons/react/outline";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
|
@ -10,7 +9,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { applyPtuModelInfo } from "../utils/ptuModelInfo";
|
||||
import { usePtuCostAttributionEnabled } from "@/app/(dashboard)/hooks/uiSettings/usePtuCostAttributionEnabled";
|
||||
import { ArrowLeft, CheckIcon, CopyIcon } from "lucide-react";
|
||||
import { ArrowLeft, CheckIcon, CopyIcon, Info } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { copyToClipboard as utilCopyToClipboard } from "../utils/dataUtils";
|
||||
import { stripMaskedSecrets } from "../utils/maskedSecretUtils";
|
||||
|
|
@ -757,7 +756,7 @@ export default function ModelInfoView({
|
|||
)
|
||||
) : (
|
||||
<SimpleTooltip content="Only DB models can be edited. You must be an admin or the creator of the model to edit it.">
|
||||
<InfoCircleOutlined />
|
||||
<Info className="size-4 text-muted-foreground" />
|
||||
</SimpleTooltip>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { CheckOutlined, CopyOutlined, SyncOutlined } from "@ant-design/icons";
|
||||
import { Alert, AlertTitle } from "@/components/shared/Alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { CircleHelp, TriangleAlert } from "lucide-react";
|
||||
import { Check, CircleHelp, Copy, RefreshCw, TriangleAlert } from "lucide-react";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useWatch } from "react-hook-form";
|
||||
import { CopyToClipboard } from "react-copy-to-clipboard";
|
||||
|
|
@ -264,7 +263,7 @@ export function RegenerateKeyModal({ selectedToken, visible, onClose, onKeyUpdat
|
|||
</Button>
|
||||
<CopyToClipboard text={regeneratedKey} onCopy={handleCopyKey}>
|
||||
<Button>
|
||||
{copied ? <CheckOutlined /> : <CopyOutlined />}
|
||||
{copied ? <Check /> : <Copy />}
|
||||
{copied ? "Copied" : "Copy Key"}
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
|
|
@ -275,7 +274,7 @@ export function RegenerateKeyModal({ selectedToken, visible, onClose, onKeyUpdat
|
|||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleRegenerateKey} disabled={isRegenerating} aria-busy={isRegenerating}>
|
||||
<SyncOutlined />
|
||||
<RefreshCw />
|
||||
Regenerate
|
||||
</Button>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@ import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings"
|
|||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import useCan from "@/app/(dashboard)/hooks/useCan";
|
||||
import { formatNumberWithCommas } from "@/utils/dataUtils";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Field, FieldLabel } from "@/components/shared/form/field";
|
||||
import { Input as AntdInput, Radio, Select, Switch, Tag, Tooltip, Typography } from "antd";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { ChevronDown, Info } from "lucide-react";
|
||||
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
|
||||
import { DEBOUNCE_WAIT_MS } from "@/utils/debounceConstants";
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
|
@ -647,7 +646,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Owned By{" "}
|
||||
<Tooltip title="Select who will own this Virtual Key">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FieldLabel>
|
||||
|
|
@ -667,7 +666,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
User ID{" "}
|
||||
<Tooltip title="The user who will own this key and be responsible for its usage">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -740,7 +739,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Organization{" "}
|
||||
<Tooltip title="The organization this key belongs to. Selecting an organization filters the available teams.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -763,7 +762,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Team{" "}
|
||||
<Tooltip title="The team this key belongs to, which determines available models and budget limits">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -790,7 +789,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Project{" "}
|
||||
<Tooltip title="Assign this key to a project. Selecting a project will lock the team to the project's team.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -836,7 +835,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
: "Unique identifier for this service account"
|
||||
}
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -856,7 +855,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Models{" "}
|
||||
<Tooltip title="Select which models this key can access. Choose 'All Team Models' to grant access to all models available to the team. Leave empty to allow access to all models.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -909,7 +908,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Key Type{" "}
|
||||
<Tooltip title="Select the type of key to determine what routes and operations this key can access">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -972,7 +971,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Max Budget (USD){" "}
|
||||
<Tooltip title="Maximum amount in USD this key can spend. When reached, the key will be blocked from making further requests">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -999,7 +998,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Reset Budget{" "}
|
||||
<Tooltip title="How often the budget should reset. For example, setting 'daily' will reset the budget every 24 hours">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1021,7 +1020,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Budget Windows{" "}
|
||||
<Tooltip title="Set multiple independent budget windows (e.g., hourly $10 AND monthly $200). Each window tracks spend separately and resets on its own schedule.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FieldLabel>
|
||||
|
|
@ -1032,7 +1031,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Budget Fallbacks{" "}
|
||||
<Tooltip title="When a model exceeds its per-model budget (model_max_budget), requests automatically reroute to fallback models instead of failing. Configure per-model budgets in Advanced Settings.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FieldLabel>
|
||||
|
|
@ -1049,7 +1048,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Tokens per minute Limit (TPM){" "}
|
||||
<Tooltip title="Maximum number of tokens this key can process per minute. Helps control usage and costs">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1090,7 +1089,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Requests per minute Limit (RPM){" "}
|
||||
<Tooltip title="Maximum number of API requests this key can make per minute. Helps prevent abuse and manage load">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1130,7 +1129,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Per-Tag Rate Limits{" "}
|
||||
<Tooltip title="Scope rate limits to a request tag so each tag (e.g. a cell or group) gets its own RPM counter. Requests without a matching tag fall back to the key-level limit.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FieldLabel>
|
||||
|
|
@ -1142,7 +1141,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Throttle on budget exceeded{" "}
|
||||
<Tooltip title="When this key exceeds its max budget, throttle its TPM/RPM to the globally configured percentage instead of blocking access entirely. Requires budget_exceeded_throttle_percentage in litellm_settings and a TPM/RPM limit on the key.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1164,7 +1163,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Enable Prompt Caching{" "}
|
||||
<Tooltip title="Automatically add prompt caching breakpoints (cache_control markers) to requests made with this key, cutting input cost on repeated prompts. Applies to Anthropic and Bedrock Claude models; requests that already set their own cache_control markers are left untouched.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1191,7 +1190,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -1231,7 +1230,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -1267,7 +1266,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -1309,7 +1308,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -1344,7 +1343,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Access Groups{" "}
|
||||
<Tooltip title="Assign access groups to this key. Access groups control which models, MCP servers, and agents this key can use">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1371,7 +1370,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()} // Prevent accordion from collapsing when clicking link
|
||||
>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
|
@ -1404,7 +1403,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Allowed Vector Stores{" "}
|
||||
<Tooltip title="Select which vector stores this key can access. If none selected, the key will have access to all available vector stores">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1426,7 +1425,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Metadata{" "}
|
||||
<Tooltip title="JSON object with additional information about this key. Used for tracking or custom logic">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1447,7 +1446,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Tags{" "}
|
||||
<Tooltip title="Tags for tracking spend and/or doing tag-based routing. Used for analytics and filtering">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1478,7 +1477,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Allowed MCP Servers{" "}
|
||||
<Tooltip title="Select which MCP servers or access groups this key can access">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1521,7 +1520,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
<span>
|
||||
Allowed Agents{" "}
|
||||
<Tooltip title="Select which agents or access groups this key can access">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -1688,7 +1687,7 @@ const CreateKey: React.FC<CreateKeyProps> = ({ team, teams, data, addKey, autoOp
|
|||
</span>
|
||||
}
|
||||
>
|
||||
<InfoCircleOutlined className="text-muted-foreground hover:text-foreground cursor-help" />
|
||||
<Info className="size-4 text-muted-foreground hover:text-foreground cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<ChevronDown className={SECTION_CHEVRON_CLASS} />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import React, { useMemo, useState } from "react";
|
||||
import { Card, Flex, Input, Space, Typography } from "antd";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { PlusOutlined, ReloadOutlined, SearchOutlined } from "@ant-design/icons";
|
||||
import { Plus, RefreshCw, Search } from "lucide-react";
|
||||
import { useRoutingGroups, useSaveRoutingGroups } from "@/app/(dashboard)/hooks/routingGroups/useRoutingGroups";
|
||||
import { useRouterFields } from "@/app/(dashboard)/hooks/router/useRouterFields";
|
||||
import { useModelHub } from "@/app/(dashboard)/hooks/models/useModels";
|
||||
|
|
@ -107,7 +107,7 @@ const RoutingGroups: React.FC = () => {
|
|||
<Flex justify="space-between" align="center" gap={12} className="mb-4">
|
||||
<Input
|
||||
allowClear
|
||||
prefix={<SearchOutlined className="text-gray-400" />}
|
||||
prefix={<Search className="size-4 text-gray-400" />}
|
||||
placeholder="Search groups..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
|
|
@ -120,11 +120,11 @@ const RoutingGroups: React.FC = () => {
|
|||
disabled={isFetching && !isLoading}
|
||||
aria-busy={isFetching && !isLoading}
|
||||
>
|
||||
<ReloadOutlined />
|
||||
<RefreshCw />
|
||||
Refresh
|
||||
</Button>
|
||||
<Button onClick={openCreate}>
|
||||
<PlusOutlined />
|
||||
<Plus />
|
||||
Create Group
|
||||
</Button>
|
||||
<Text type="secondary" className="text-sm whitespace-nowrap">
|
||||
|
|
|
|||
|
|
@ -49,10 +49,8 @@ describe("AdvancedDatePicker", () => {
|
|||
});
|
||||
|
||||
it("should display formatted date range", () => {
|
||||
render(<AdvancedDatePicker value={defaultValue} onValueChange={mockOnValueChange} />);
|
||||
// The component displays date range in the format "D MMM, HH:mm - D MMM, HH:mm"
|
||||
// Just check that the clock icon is present
|
||||
expect(screen.getByLabelText("clock-circle")).toBeInTheDocument();
|
||||
const { container } = render(<AdvancedDatePicker value={defaultValue} onValueChange={mockOnValueChange} />);
|
||||
expect(getTrigger(container)).toHaveTextContent(/\d{1,2} \w{3}, \d{2}:\d{2} - \d{1,2} \w{3}, \d{2}:\d{2}/);
|
||||
});
|
||||
|
||||
it("should open dropdown when clicked", () => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { CalendarOutlined, ClockCircleOutlined } from "@ant-design/icons";
|
||||
import { Calendar, Clock } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/cva.config";
|
||||
import type { DateRangePickerValue } from "./date_picker_types";
|
||||
|
|
@ -291,7 +291,7 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
|
|||
>
|
||||
<span className="flex items-center justify-between">
|
||||
<span className="flex items-center gap-2">
|
||||
<ClockCircleOutlined className="text-gray-600" />
|
||||
<Clock className="size-4 text-gray-600" />
|
||||
<span className="text-gray-900">{formatDisplayRange(value.from, value.to)}</span>
|
||||
</span>
|
||||
<svg
|
||||
|
|
@ -355,7 +355,7 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
|
|||
<div className="w-1/2 relative">
|
||||
<div className="p-3.5 border-b border-gray-200">
|
||||
<div className="flex items-center gap-2">
|
||||
<CalendarOutlined className="text-gray-600" />
|
||||
<Calendar className="size-4 text-gray-600" />
|
||||
<span className="text-sm font-semibold text-gray-900">Start and end dates</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@ import React from "react";
|
|||
import { SimpleTooltip } from "@/components/ui/tooltip";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group";
|
||||
import { CogIcon, BanIcon } from "@heroicons/react/outline";
|
||||
import { Eye, EyeOff, Plus, Trash2 } from "lucide-react";
|
||||
import { Eye, EyeOff, Info, Plus, Trash2 } from "lucide-react";
|
||||
import { callbackInfo, callback_map, mapDisplayToInternalNames } from "../callback_info_helpers";
|
||||
import { Logo } from "@/components/molecules/logo/Logo";
|
||||
import NumericalInput from "../shared/numerical_input";
|
||||
|
|
@ -198,7 +197,7 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<BanIcon className="w-5 h-5 text-destructive" />
|
||||
<span className="text-base font-semibold text-foreground">Disabled Callbacks</span>
|
||||
<SimpleTooltip content="Select callbacks to disable for this key. Disabled callbacks will not receive any logging data.">
|
||||
<InfoCircleOutlined className="text-muted-foreground cursor-help" />
|
||||
<Info className="size-4 text-muted-foreground cursor-help" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
|
||||
|
|
@ -244,7 +243,7 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<CogIcon className="w-5 h-5 text-foreground" />
|
||||
<span className="text-base font-semibold text-foreground">Logging Integrations</span>
|
||||
<SimpleTooltip content="Configure callback logging integrations for this team.">
|
||||
<InfoCircleOutlined className="text-muted-foreground cursor-help" />
|
||||
<Info className="size-4 text-muted-foreground cursor-help" />
|
||||
</SimpleTooltip>
|
||||
</div>
|
||||
<Button variant="secondary" onClick={addLoggingConfig} size="sm" type="button">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import { formatNumberWithCommas } from "@/utils/dataUtils";
|
|||
import { mapEmptyStringToNull } from "@/utils/keyUpdateUtils";
|
||||
import type { ObjectPermission } from "@/components/object_permission_types";
|
||||
import { isProxyAdminRole } from "@/utils/roles";
|
||||
import { EditOutlined, InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { ArrowLeftIcon } from "@heroicons/react/outline";
|
||||
import { StatusBadge, type StatusTone } from "@/components/shared/table_cells/status_badge";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
|
@ -42,7 +41,7 @@ import { TagsInput } from "@/app/(dashboard)/guardrails/_components/content_filt
|
|||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { useVisitedTabs } from "@/hooks/useVisitedTabs";
|
||||
import { toast } from "@/lib/toast";
|
||||
import { CheckIcon, ChevronDown, CircleMinus, CopyIcon, Plus, Save } from "lucide-react";
|
||||
import { CheckIcon, ChevronDown, CircleMinus, CopyIcon, Info, Pencil, Plus, Save } from "lucide-react";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useFieldArray } from "react-hook-form";
|
||||
import { z } from "zod/v4";
|
||||
|
|
@ -1119,7 +1118,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
startEditing();
|
||||
}}
|
||||
>
|
||||
<EditOutlined className="h-4 w-4" />
|
||||
<Pencil />
|
||||
Edit Settings
|
||||
</Button>
|
||||
)}
|
||||
|
|
@ -1809,7 +1808,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<p className="font-medium">
|
||||
Team Member Settings{" "}
|
||||
<SimpleTooltip content="These are limits on individual team members">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</p>
|
||||
<div>Max Budget: {info.team_member_budget_table?.max_budget || "No Limit"}</div>
|
||||
|
|
@ -1970,7 +1969,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<span>
|
||||
Team Member Budget (USD){" "}
|
||||
<SimpleTooltip content="Maximum amount in USD this member can spend within this team. This is separate from any global user budget limits">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</span>
|
||||
),
|
||||
|
|
@ -1985,7 +1984,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<span>
|
||||
Budget Reset Period{" "}
|
||||
<SimpleTooltip content="How often this member's budget resets within the team. Leave unset and the budget never resets.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</span>
|
||||
),
|
||||
|
|
@ -1997,7 +1996,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<span>
|
||||
Team Member TPM Limit{" "}
|
||||
<SimpleTooltip content="Maximum tokens per minute this member can use within this team. This is separate from any global user TPM limit">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</span>
|
||||
),
|
||||
|
|
@ -2012,7 +2011,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<span>
|
||||
Team Member RPM Limit{" "}
|
||||
<SimpleTooltip content="Maximum requests per minute this member can make within this team. This is separate from any global user RPM limit">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</span>
|
||||
),
|
||||
|
|
@ -2027,7 +2026,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<span>
|
||||
Allowed Models{" "}
|
||||
<SimpleTooltip content="Models this member can access within this team. Leave empty to inherit all team models.">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
<Info className="ml-1 inline size-3.5 align-text-bottom" />
|
||||
</SimpleTooltip>
|
||||
</span>
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue