first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,244 @@
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Switch } from "@/components/ui/switch";
import { getErrorMessage, useCreateProviderMutation } from "@/lib/store";
import { BaseProvider, ModelProviderName } from "@/lib/types/config";
import { allowedRequestsSchema } from "@/lib/types/schemas";
import { cleanPathOverrides } from "@/lib/utils/validation";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { AllowedRequestsFields } from "../fragments/allowedRequestsFields";
const formSchema = z.object({
name: z.string().min(1),
baseFormat: z.string().min(1),
base_url: z.string().min(1, "Base URL is required").url("Must be a valid URL"),
allowed_requests: allowedRequestsSchema,
request_path_overrides: z.record(z.string(), z.string().optional()).optional(),
is_key_less: z.boolean().optional(),
});
type FormData = z.infer<typeof formSchema>;
export interface AddCustomProviderSheetContentProps {
show?: boolean;
onSave: (id: string) => void;
onClose: () => void;
}
interface Props extends AddCustomProviderSheetContentProps {
show: boolean;
}
export function AddCustomProviderSheetContent({ show = true, onClose, onSave }: AddCustomProviderSheetContentProps) {
const [addProvider, { isLoading: isAddingProvider }] = useCreateProviderMutation();
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
baseFormat: "",
base_url: "",
allowed_requests: {
text_completion: true,
text_completion_stream: true,
chat_completion: true,
chat_completion_stream: true,
responses: true,
responses_stream: true,
embedding: true,
speech: true,
speech_stream: true,
transcription: true,
transcription_stream: true,
image_generation: true,
image_generation_stream: true,
image_edit: true,
image_edit_stream: true,
image_variation: true,
rerank: true,
ocr: true,
ocr_stream: true,
video_generation: true,
video_retrieve: true,
video_download: true,
video_delete: true,
video_list: true,
video_remix: true,
count_tokens: true,
list_models: true,
websocket_responses: true,
realtime: false,
},
request_path_overrides: undefined,
is_key_less: false,
},
});
useEffect(() => {
if (show) {
form.clearErrors();
}
}, [show]);
const onSubmit = (data: FormData) => {
const payload = {
provider: data.name as ModelProviderName,
custom_provider_config: {
base_provider_type: data.baseFormat as BaseProvider,
allowed_requests: data.allowed_requests,
request_path_overrides: cleanPathOverrides(data.request_path_overrides),
is_key_less: data.is_key_less ?? false,
},
network_config: {
base_url: data.base_url,
default_request_timeout_in_seconds: 30,
max_retries: 0,
retry_backoff_initial: 500,
retry_backoff_max: 5000,
},
};
addProvider(payload)
.unwrap()
.then((provider) => {
onSave(provider.name);
form.reset();
})
.catch((err) => {
toast.error("Failed to add provider", {
description: getErrorMessage(err),
});
});
};
const baseFormat = form.watch("baseFormat") as BaseProvider;
const isKeyLessDisabled = baseFormat === "bedrock";
return (
<>
<SheetHeader className="flex shrink-0 flex-col items-start">
<SheetTitle>Add Custom Provider</SheetTitle>
<SheetDescription>Enter the details of your custom provider.</SheetDescription>
</SheetHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex min-h-0 flex-1 flex-col overflow-hidden">
<div className="custom-scrollbar min-h-0 flex-1 space-y-4 overflow-y-auto">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem className="flex flex-col gap-3">
<FormLabel className="text-right">Name</FormLabel>
<div className="col-span-3">
<FormControl>
<Input placeholder="Name" data-testid="custom-provider-name" {...field} />
</FormControl>
<FormMessage />
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="baseFormat"
render={({ field }) => (
<FormItem className="flex flex-col gap-3">
<FormLabel>Base Format</FormLabel>
<div>
<FormControl>
<Select onValueChange={field.onChange} value={field.value}>
<SelectTrigger className="w-full" data-testid="base-provider-select">
<SelectValue placeholder="Select base format" />
</SelectTrigger>
<SelectContent>
<SelectItem value="openai">OpenAI</SelectItem>
<SelectItem value="anthropic">Anthropic</SelectItem>
<SelectItem value="gemini">Gemini</SelectItem>
<SelectItem value="cohere">Cohere</SelectItem>
<SelectItem value="bedrock">AWS Bedrock</SelectItem>
<SelectItem value="replicate">Replicate</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="base_url"
render={({ field }) => (
<FormItem className="flex flex-col gap-3">
<FormLabel>Base URL</FormLabel>
<div>
<FormControl>
<Input
placeholder={"https://api.your-provider.com"}
data-testid="base-url-input"
{...field}
value={field.value || ""}
/>
</FormControl>
<FormMessage />
</div>
</FormItem>
)}
/>
{!isKeyLessDisabled && (
<FormField
control={form.control}
name="is_key_less"
render={({ field }) => (
<FormItem>
<div className="flex items-center justify-between space-x-2 rounded-lg border p-3">
<div className="space-y-0.5">
<label htmlFor="drop-excess-requests" className="text-sm font-medium">
Is Keyless?
</label>
<p className="text-muted-foreground text-sm">Whether the custom provider requires a key</p>
</div>
<Switch
id="drop-excess-requests"
size="md"
checked={field.value}
onCheckedChange={field.onChange}
data-testid="custom-provider-keyless-switch"
/>
</div>
</FormItem>
)}
/>
)}
{/* Allowed Requests Configuration */}
<AllowedRequestsFields control={form.control} providerType={form.watch("baseFormat") as BaseProvider} />
<div className="align-end mt-10 ml-auto flex flex-row gap-2 border-t pt-4">
<Button type="button" variant="outline" onClick={onClose} className="ml-auto" data-testid="custom-provider-cancel-btn">
Cancel
</Button>
<Button type="submit" isLoading={isAddingProvider} data-testid="custom-provider-save-btn">
Add
</Button>
</div>
</div>
</form>
</Form>
</>
);
}
export default function AddCustomProviderSheet(props: Props) {
return (
<Sheet open={props.show} onOpenChange={(open) => !open && props.onClose()}>
<SheetContent className="custom-scrollbar flex flex-col p-8 sm:max-w-3xl" data-testid="custom-provider-sheet">
<AddCustomProviderSheetContent {...props} />
</SheetContent>
</Sheet>
);
}

View File

@@ -0,0 +1,57 @@
import Provider from "@/components/provider";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { ModelProvider } from "@/lib/types/config";
import { toast } from "sonner";
import ProviderKeyForm from "../views/providerKeyForm";
interface Props {
show: boolean;
onCancel: () => void;
provider: ModelProvider;
keyId: string | null;
providerName?: string;
}
export default function AddNewKeySheet({ show, onCancel, provider, keyId, providerName }: Props) {
const isEditing = keyId !== null;
const resolvedProviderName = (providerName ?? provider.name).toLowerCase();
const isVLLM = resolvedProviderName === "vllm";
const isOllamaOrSGL = resolvedProviderName === "ollama" || resolvedProviderName === "sgl";
const entityLabel = isVLLM ? "model" : isOllamaOrSGL ? "server" : "key";
const EntityLabel = entityLabel.charAt(0).toUpperCase() + entityLabel.slice(1);
const dialogTitle = isEditing ? `Edit ${entityLabel}` : `Add new ${entityLabel}`;
const successMessage = isEditing ? `${EntityLabel} updated successfully` : `${EntityLabel} added successfully`;
return (
<Sheet
open={show}
onOpenChange={(open) => {
if (!open) onCancel();
}}
>
<SheetContent className="custom-scrollbar p-8" data-testid="key-form" onInteractOutside={(e) => e.preventDefault()}>
<SheetHeader className="flex flex-col items-start">
<SheetTitle>
<div className="font-lg flex items-center gap-2">
<div className={"flex items-center"}>
<Provider provider={provider.name} size={24} />:
</div>
{dialogTitle}
</div>
</SheetTitle>
</SheetHeader>
<div>
<ProviderKeyForm
provider={provider}
keyId={keyId}
onCancel={onCancel}
onSave={() => {
toast.success(successMessage);
onCancel();
}}
/>
</div>
</SheetContent>
</Sheet>
);
}

View File

@@ -0,0 +1,56 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
} from "@/components/ui/alertDialog";
import { getErrorMessage, useDeleteProviderMutation } from "@/lib/store";
import { ModelProvider } from "@/lib/types/config";
import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib";
import { AlertDialogTitle } from "@radix-ui/react-alert-dialog";
import { toast } from "sonner";
interface Props {
show: boolean;
onCancel: () => void;
onDelete: () => void;
provider: ModelProvider;
}
export default function ConfirmDeleteProviderDialog({ show, onCancel, onDelete, provider }: Props) {
const [deleteProvider, { isLoading: isDeletingProvider }] = useDeleteProviderMutation();
const hasDeleteAccess = useRbac(RbacResource.ModelProvider, RbacOperation.Delete);
const onDeleteHandler = () => {
deleteProvider(provider.name)
.unwrap()
.then(() => {
onDelete();
})
.catch((err) => {
toast.error("Failed to delete provider", {
description: getErrorMessage(err),
});
});
};
return (
<AlertDialog open={show}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Provider</AlertDialogTitle>
<AlertDialogDescription>Are you sure you want to delete this provider? This action cannot be undone.</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={onCancel}>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={onDeleteHandler} disabled={isDeletingProvider || !hasDeleteAccess}>
{isDeletingProvider ? "Deleting..." : "Delete"}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

View File

@@ -0,0 +1,39 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alertDialog";
interface Props {
show: boolean;
onContinue: () => void;
onCancel: () => void;
}
export default function ConfirmRedirectionDialog({ show, onContinue, onCancel }: Props) {
return (
<AlertDialog open={show}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Confirm Redirection</AlertDialogTitle>
<AlertDialogDescription>You have unsaved data. Are you sure you want to continue?</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter className="mt-4">
<AlertDialogCancel onClick={onCancel}>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={() => {
onContinue();
}}
>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

View File

@@ -0,0 +1,155 @@
import Provider from "@/components/provider";
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ModelProvider } from "@/lib/types/config";
import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib";
import { useEffect, useMemo, useState } from "react";
import {
ApiStructureFormFragment,
BetaHeadersFormFragment,
GovernanceFormFragment,
OpenAIConfigFormFragment,
ProxyFormFragment,
} from "../fragments";
import { DebuggingFormFragment } from "../fragments/debuggingFormFragment";
import { NetworkFormFragment } from "../fragments/networkFormFragment";
import { PerformanceFormFragment } from "../fragments/performanceFormFragment";
interface Props {
show: boolean;
onCancel: () => void;
provider: ModelProvider;
}
const ANTHROPIC_FAMILY_PROVIDERS = ["anthropic", "vertex", "bedrock", "azure"];
const availableTabs = (hasCustomProviderConfig: boolean, hasGovernanceAccess: boolean, isOpenAI: boolean, isAnthropicFamily: boolean) => {
const tabs = [];
if (hasCustomProviderConfig) {
tabs.push({
id: "api-structure",
label: "API Structure",
});
}
tabs.push({
id: "network",
label: "Network",
});
tabs.push({
id: "proxy",
label: "Proxy",
});
tabs.push({
id: "performance",
label: "Performance",
});
if (hasGovernanceAccess) {
tabs.push({
id: "governance",
label: "Governance",
});
}
if (isAnthropicFamily) {
tabs.push({
id: "beta-headers",
label: "Beta Headers",
});
}
tabs.push({
id: "debugging",
label: "Debugging",
});
if (isOpenAI) {
tabs.push({
id: "openai-config",
label: "OpenAI Config",
});
}
return tabs;
};
export default function ProviderConfigSheet({ show, onCancel, provider }: Props) {
const [selectedTab, setSelectedTab] = useState<string | undefined>(undefined);
const hasGovernanceAccess = useRbac(RbacResource.Governance, RbacOperation.View);
const hasCustomProviderConfig = !!provider.custom_provider_config;
const isOpenAI = provider.name === "openai";
const isAnthropicFamily = ANTHROPIC_FAMILY_PROVIDERS.includes(provider.name.toLowerCase());
const tabs = useMemo(() => {
return availableTabs(hasCustomProviderConfig, hasGovernanceAccess, isOpenAI, isAnthropicFamily);
}, [hasCustomProviderConfig, hasGovernanceAccess, isOpenAI, isAnthropicFamily]);
useEffect(() => {
setSelectedTab((previousTab) => {
if (previousTab && tabs.some((tab) => tab.id === previousTab)) {
return previousTab;
}
return tabs[0]?.id;
});
}, [tabs]);
return (
<Sheet
open={show}
onOpenChange={(open) => {
if (!open) onCancel();
}}
>
<SheetContent className="custom-scrollbar p-8 sm:max-w-[50%]">
<SheetHeader className="flex flex-col items-start">
<SheetTitle>
<div className="font-lg flex items-center gap-2">
<div className="flex items-center">
<Provider provider={provider.name} size={24} />
</div>
Provider configuration
</div>
</SheetTitle>
</SheetHeader>
<div className="w-full rounded-sm border">
<Tabs defaultValue={tabs[0]?.id} value={selectedTab} onValueChange={setSelectedTab} className="space-y-6">
<div className="custom-scrollbar mb-4 w-full overflow-x-auto">
<TabsList className="h-10 w-max min-w-full justify-start rounded-tl-sm rounded-tr-sm rounded-br-none rounded-bl-none">
{tabs.map((tab) => (
<TabsTrigger
key={tab.id}
value={tab.id}
data-testid={`provider-tab-${tab.id}`}
className="flex-none px-3 whitespace-nowrap"
>
{tab.label}
</TabsTrigger>
))}
</TabsList>
</div>
<TabsContent value="api-structure">
<ApiStructureFormFragment provider={provider} />
</TabsContent>
<TabsContent value="openai-config">
<OpenAIConfigFormFragment provider={provider} />
</TabsContent>
<TabsContent value="network">
<NetworkFormFragment provider={provider} />
</TabsContent>
<TabsContent value="proxy">
<ProxyFormFragment provider={provider} />
</TabsContent>
<TabsContent value="performance">
<PerformanceFormFragment provider={provider} />
</TabsContent>
<TabsContent value="governance">
<GovernanceFormFragment provider={provider} />
</TabsContent>
<TabsContent value="beta-headers">
<BetaHeadersFormFragment provider={provider} />
</TabsContent>
<TabsContent value="debugging">
<DebuggingFormFragment provider={provider} />
</TabsContent>
</Tabs>
</div>
</SheetContent>
</Sheet>
);
}