+
+
+
+
+
+
+
+
+
+
+
+ Configure which providers this virtual key can use
+ and their specific settings. Leave empty to block
+ all providers. Add providers to allow them.
+
+
+
+
+
+
+ {/* Add Provider Dropdown */}
+
+
+
+
+ {/* Provider Configurations Table */}
+ {providerConfigs.length > 0 && (
+
+
+ {providerConfigs.map((config, index) => {
+ const providerConfig = availableProviders.find(
+ (provider) => provider.name === config.provider,
+ );
+ return (
+
+
+
+
+
+ {providerConfig?.custom_provider_config
+ ? providerConfig.name
+ : ProviderLabels[
+ config.provider as ProviderName
+ ]}
+
+
+
+
+
+
+
+
+ handleUpdateProviderConfig(
+ index,
+ "weight",
+ value,
+ )
+ }
+ />
+
+
+
+ {(() => {
+ const hasWildcardModels = (
+ config.allowed_models || []
+ ).includes("*");
+ return (
+
{
+ const providerKeys =
+ availableKeys.filter(
+ (key) =>
+ key.provider ===
+ config.provider,
+ );
+ const configKeyIds =
+ config.key_ids || [];
+ return configKeyIds.includes("*")
+ ? providerKeys.map(
+ (key) => key.key_id,
+ )
+ : providerKeys
+ .filter((key) =>
+ configKeyIds.includes(
+ key.key_id,
+ ),
+ )
+ .map((key) => key.key_id);
+ })()}
+ allowAllOption={true}
+ value={
+ hasWildcardModels
+ ? ["*"]
+ : config.allowed_models || []
+ }
+ onChange={(models: string[]) => {
+ const hadStar = (
+ config.allowed_models || []
+ ).includes("*");
+ const hasStar =
+ models.includes("*");
+ if (!hadStar && hasStar) {
+ handleUpdateProviderConfig(
+ index,
+ "allowed_models",
+ ["*"],
+ );
+ } else if (
+ hadStar &&
+ hasStar &&
+ models.length > 1
+ ) {
+ handleUpdateProviderConfig(
+ index,
+ "allowed_models",
+ models.filter((m) => m !== "*"),
+ );
+ } else {
+ handleUpdateProviderConfig(
+ index,
+ "allowed_models",
+ models,
+ );
+ }
+ }}
+ placeholder={
+ hasWildcardModels
+ ? "All models allowed"
+ : (config.allowed_models || [])
+ .length === 0
+ ? "No models (deny all)"
+ : config.provider
+ ? ModelPlaceholders[
+ config.provider as keyof typeof ModelPlaceholders
+ ] ||
+ ModelPlaceholders.default
+ : ModelPlaceholders.default
+ }
+ className="min-h-10 max-w-[500px] min-w-[200px]"
+ />
+ );
+ })()}
+
+ Select specific models or choose "Allow
+ All Models" to allow all. Leave empty to
+ deny all.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Models this VK must never serve.
+ The denylist always wins - if a
+ model appears in both Allowed
+ Models and here, it is blocked.
+ Select "All Models" to block every
+ model on this VK.
+
+
+
+
+
+ {(() => {
+ const hasWildcardBlocked = (
+ config.blacklisted_models || []
+ ).includes("*");
+ return (
+
{
+ const providerKeys =
+ availableKeys.filter(
+ (key) =>
+ key.provider ===
+ config.provider,
+ );
+ const configKeyIds =
+ config.key_ids || [];
+ return configKeyIds.includes("*")
+ ? providerKeys.map(
+ (key) => key.key_id,
+ )
+ : providerKeys
+ .filter((key) =>
+ configKeyIds.includes(
+ key.key_id,
+ ),
+ )
+ .map((key) => key.key_id);
+ })()}
+ allowAllOption={true}
+ value={
+ hasWildcardBlocked
+ ? ["*"]
+ : config.blacklisted_models || []
+ }
+ onChange={(models: string[]) => {
+ const hadStar = (
+ config.blacklisted_models || []
+ ).includes("*");
+ const hasStar =
+ models.includes("*");
+ if (!hadStar && hasStar) {
+ handleUpdateProviderConfig(
+ index,
+ "blacklisted_models",
+ ["*"],
+ );
+ } else if (
+ hadStar &&
+ hasStar &&
+ models.length > 1
+ ) {
+ handleUpdateProviderConfig(
+ index,
+ "blacklisted_models",
+ models.filter((m) => m !== "*"),
+ );
+ } else {
+ handleUpdateProviderConfig(
+ index,
+ "blacklisted_models",
+ models,
+ );
+ }
+ }}
+ placeholder={
+ hasWildcardBlocked
+ ? "All models blocked"
+ : (
+ config.blacklisted_models ||
+ []
+ ).length === 0
+ ? "No models blocked"
+ : "Search models..."
+ }
+ className="min-h-10 max-w-[500px] min-w-[200px]"
+ />
+ );
+ })()}
+
+
+
+ {/* Allowed Keys for this provider */}
+ {(() => {
+ const providerKeys = availableKeys.filter(
+ (key) => key.provider === config.provider,
+ );
+ const configKeyIds = config.key_ids || [];
+ const hasWildcard =
+ configKeyIds.includes("*");
+ const allKeyOptions = [
+ {
+ label: "Allow All Keys",
+ value: "*",
+ description:
+ "Allow all current and future keys for this provider",
+ provider: "",
+ },
+ ...providerKeys.map((key) => ({
+ label: key.name,
+ value: key.key_id,
+ description:
+ key.models == null ||
+ key.models.includes("*")
+ ? "All models"
+ : key.models
+ .filter((m) => m !== "*")
+ .join(", ") ||
+ "No models (deny all)",
+ provider: key.provider,
+ })),
+ ];
+ const selectedProviderKeys = hasWildcard
+ ? [allKeyOptions[0]]
+ : providerKeys
+ .filter((key) =>
+ configKeyIds.includes(key.key_id),
+ )
+ .map((key) => ({
+ label: key.name,
+ value: key.key_id,
+ description:
+ key.models == null ||
+ key.models.includes("*")
+ ? "All models"
+ : key.models
+ .filter((m) => m !== "*")
+ .join(", ") ||
+ "No models (deny all)",
+ provider: key.provider,
+ }));
+
+ return (
+
+
+
+ Select specific keys or allow all. Leave
+ empty to block all keys for this
+ provider.
+
+
,
+ ) => {
+ return (
+
+ {multiValueProps.data.label}{" "}
+ {
+ e.stopPropagation();
+ multiValueProps.removeProps.onClick?.(
+ e as any,
+ );
+ }}
+ />
+
+ );
+ },
+ option: (
+ optionProps: OptionProps,
+ ) => {
+ const { Option } = components;
+ return (
+
+ );
+ },
+ }}
+ value={selectedProviderKeys}
+ onChange={(keys) => {
+ const hadStar = hasWildcard;
+ const hasStar = keys.some(
+ (k) => k.value === "*",
+ );
+ if (!hadStar && hasStar) {
+ // Just selected "Allow All Keys" — set to ["*"] only
+ handleUpdateProviderConfig(
+ index,
+ "key_ids",
+ ["*"],
+ );
+ } else if (
+ hadStar &&
+ hasStar &&
+ keys.length > 1
+ ) {
+ // Had "*", still has "*", but user also selected a specific key — drop "*"
+ handleUpdateProviderConfig(
+ index,
+ "key_ids",
+ keys
+ .filter((k) => k.value !== "*")
+ .map((k) => k.value as string),
+ );
+ } else {
+ handleUpdateProviderConfig(
+ index,
+ "key_ids",
+ keys.map(
+ (k) => k.value as string,
+ ),
+ );
+ }
+ }}
+ placeholder={
+ hasWildcard
+ ? "All keys allowed"
+ : configKeyIds.length === 0
+ ? "No keys selected"
+ : "Select keys..."
+ }
+ className="hover:bg-accent w-full"
+ menuClassName="z-[60] max-h-[300px] overflow-y-auto w-full cursor-pointer custom-scrollbar"
+ />
+
+ );
+ })()}
+
+
+
+ {/* Provider Budget Configuration */}
+ 0
+ ? config.budgets.map((b) => ({
+ id: b.id,
+ max_limit: b.max_limit,
+ reset_duration:
+ b.reset_duration || "1M",
+ }))
+ : []
+ }
+ onChange={(lines) => {
+ const updatedConfigs = [...providerConfigs];
+ updatedConfigs[index] = {
+ ...updatedConfigs[index],
+ budgets: lines.map((l) => ({
+ id: l.id,
+ max_limit: l.max_limit,
+ reset_duration: l.reset_duration,
+ })),
+ };
+ form.setValue(
+ "providerConfigs",
+ updatedConfigs,
+ { shouldDirty: true },
+ );
+ }}
+ />
+
+
+
+ {/* Provider Rate Limit Configuration */}
+
+
+
+ {
+ const currentRateLimit =
+ config.rate_limit || {};
+ handleUpdateProviderConfig(
+ index,
+ "rate_limit",
+ {
+ ...currentRateLimit,
+ token_max_limit: value,
+ },
+ );
+ }}
+ onChangeSelect={(value) => {
+ const currentRateLimit =
+ config.rate_limit || {};
+ handleUpdateProviderConfig(
+ index,
+ "rate_limit",
+ {
+ ...currentRateLimit,
+ token_reset_duration: value,
+ },
+ );
+ }}
+ options={resetDurationOptions}
+ />
+
+ {
+ const currentRateLimit =
+ config.rate_limit || {};
+ handleUpdateProviderConfig(
+ index,
+ "rate_limit",
+ {
+ ...currentRateLimit,
+ request_max_limit: value,
+ },
+ );
+ }}
+ onChangeSelect={(value) => {
+ const currentRateLimit =
+ config.rate_limit || {};
+ handleUpdateProviderConfig(
+ index,
+ "rate_limit",
+ {
+ ...currentRateLimit,
+ request_reset_duration: value,
+ },
+ );
+ }}
+ options={resetDurationOptions}
+ />
+
+
+
+ );
+ })}
+
+
+ )}
+ {/* Display validation errors for provider configurations */}
+ {form.formState.errors.providerConfigs && (
+
+ {form.formState.errors.providerConfigs.message}
+
+ )}
+
+ {/* MCP Client Configurations */}
+ {((mcpClientsData && mcpClientsData.length > 0) ||
+ (mcpConfigs && mcpConfigs.length > 0)) && (
+
+
+
+
+
+
+
+
+
+
+
+
+ Configure which MCP clients this virtual key can
+ use and their allowed tools. Leaving this section
+ empty blocks all MCP tools. After adding an MCP
+ client, you must select specific tools or choose{" "}
+
+ Allow All Tools
+ {" "}
+ to grant tool access.
+
+
+
+
+
+
+ {/* MCP servers available on all virtual keys by default, excluding explicitly overridden ones */}
+ {(() => {
+ const defaultMCPClients = mcpClientsData.filter(
+ (client) =>
+ client.config.allow_on_all_virtual_keys &&
+ !mcpConfigs.some(
+ (config) =>
+ config.mcp_client_name === client.config.name,
+ ),
+ );
+ return defaultMCPClients.length > 0 ? (
+
+
+
+
+ The following MCP servers are available to this
+ key by default with all tools enabled on that
+ client:{" "}
+
+ {defaultMCPClients
+ .map((c) => c.config.name)
+ .join(", ")}
+
+ . Adding an explicit config for any of them below
+ will override the all-tools default for this key.
+
+
+
+ ) : null;
+ })()}
+
+ {/* Add MCP Client Dropdown */}
+ {mcpClientsData && mcpClientsData.length > 0 && (
+
+
+
+ )}
+
+ {/* MCP Configurations Table */}
+ {mcpConfigs.length > 0 && (
+
+
+
+
+ MCP Client
+ Allowed Tools
+
+
+
+
+ {mcpConfigs.map((config, index) => {
+ const mcpClient = mcpClientsData?.find(
+ (client) =>
+ client.config.name === config.mcp_client_name,
+ );
+
+ // Handle new wildcard semantics for client-level filtering
+ const clientToolsToExecute =
+ mcpClient?.config?.tools_to_execute;
+ let availableTools: any[] = [];
+
+ if (
+ !clientToolsToExecute ||
+ clientToolsToExecute.length === 0
+ ) {
+ // nil/undefined or empty array - no tools available from client config
+ availableTools = [];
+ } else if (clientToolsToExecute.includes("*")) {
+ // Wildcard - all tools available
+ availableTools = mcpClient?.tools || [];
+ } else {
+ // Specific tools listed
+ availableTools =
+ (mcpClient?.tools || []).filter((tool) =>
+ clientToolsToExecute.includes(tool.name),
+ ) || [];
+ }
+
+ const enabledToolsByConfig =
+ (mcpClient?.tools || []).filter((tool) =>
+ config.tools_to_execute?.includes(tool.name),
+ ) || [];
+ const selectedTools =
+ config.tools_to_execute || [];
+
+ return (
+
+
+ {config.mcp_client_name}
+
+
+
+ arr.findIndex(
+ (t) => t.name === tool.name,
+ ) === index,
+ )
+ .map((tool) => ({
+ label: tool.name,
+ value: tool.name,
+ description: tool.description,
+ })),
+ ]}
+ defaultValue={selectedTools}
+ onValueChange={(tools: string[]) => {
+ const hadStar =
+ selectedTools.includes("*");
+ const hasStar = tools.includes("*");
+ if (!hadStar && hasStar) {
+ // Just selected "Allow All Tools" — set to ["*"] only
+ handleUpdateMCPConfig(
+ index,
+ "tools_to_execute",
+ ["*"],
+ );
+ } else if (
+ hadStar &&
+ hasStar &&
+ tools.length > 1
+ ) {
+ // Had "*", still has "*", but user also selected a specific tool — drop "*"
+ handleUpdateMCPConfig(
+ index,
+ "tools_to_execute",
+ tools.filter((t) => t !== "*"),
+ );
+ } else {
+ handleUpdateMCPConfig(
+ index,
+ "tools_to_execute",
+ tools,
+ );
+ }
+ }}
+ placeholder={
+ selectedTools.length === 0
+ ? "No tools selected"
+ : selectedTools.includes("*")
+ ? "All tools allowed"
+ : "Select tools..."
+ }
+ variant="inverted"
+ className="hover:bg-accent w-full bg-white dark:bg-zinc-800"
+ commandClassName="w-full max-w-96"
+ modalPopover={true}
+ animation={0}
+ />
+
+
+
+
+
+ );
+ })}
+
+
+
+ )}
+
+ )}
+
+
+
+
+ (
+
+
+ Assignment Type
+
+ 0
+ ? [
+ {
+ value: "team",
+ label: "Assign to Team",
+ },
+ ]
+ : []),
+ ...(customers?.length > 0
+ ? [
+ {
+ value: "customer",
+ label: "Assign to Customer",
+ },
+ ]
+ : []),
+ ...(accessProfiles?.length > 0 ||
+ virtualKey?.access_profile_id ||
+ defaultAccessProfileId
+ ? [
+ {
+ value: "access_profile",
+ label: "Assign to Access Profile",
+ },
+ ]
+ : []),
+ ]}
+ value={field.value}
+ onValueChange={async (value) => {
+ const val = value ?? "none";
+ const originalType = virtualKey?.team_id
+ ? "team"
+ : virtualKey?.customer_id
+ ? "customer"
+ : virtualKey?.access_profile_id
+ ? "access_profile"
+ : "none";
+ if (
+ isEditing &&
+ currentAssignmentLabel &&
+ val !== "none" &&
+ val !== originalType
+ ) {
+ setPendingEntityType(
+ val as
+ | "team"
+ | "customer"
+ | "access_profile",
+ );
+ setShowReassignTypeWarning(true);
+ return;
+ }
+ field.onChange(val);
+ if (val === "team" && teams?.length > 0) {
+ form.setValue("teamId", teams[0].id, {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("customerId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("accessProfileId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ await form.trigger([
+ "teamId",
+ "customerId",
+ "accessProfileId",
+ "entityType",
+ ]);
+ } else if (
+ val === "customer" &&
+ customers?.length > 0
+ ) {
+ form.setValue(
+ "customerId",
+ customers[0].id,
+ {
+ shouldDirty: true,
+ shouldValidate: true,
+ },
+ );
+ form.setValue("teamId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("accessProfileId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ await form.trigger([
+ "teamId",
+ "customerId",
+ "accessProfileId",
+ "entityType",
+ ]);
+ } else if (val === "access_profile") {
+ const apId =
+ accessProfiles?.length > 0
+ ? String(accessProfiles[0].id)
+ : virtualKey?.access_profile_id
+ ? String(virtualKey.access_profile_id)
+ : "";
+ form.setValue("accessProfileId", apId, {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("teamId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("customerId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ await form.trigger([
+ "teamId",
+ "customerId",
+ "accessProfileId",
+ "entityType",
+ ]);
+ } else {
+ form.setValue("teamId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("customerId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ form.setValue("accessProfileId", "", {
+ shouldDirty: true,
+ shouldValidate: true,
+ });
+ await form.trigger([
+ "teamId",
+ "customerId",
+ "accessProfileId",
+ "entityType",
+ ]);
+ }
+ }}
+ disabled={isTeamLocked || isAPLocked}
+ disableSearch
+ hideClear
+ className="h-9"
+ />
+
+
+ )}
+ />
+ {form.watch("entityType") === "team" &&
+ teams?.length > 0 && (
+ (
+
+
+ Select Team
+
+ ({
+ value: team.id,
+ label: team.customer
+ ? `${team.name} — ${team.customer.name}`
+ : team.name,
+ }))}
+ value={field.value || null}
+ onValueChange={(val) => {
+ const newVal = val ?? "";
+ if (
+ isEditing &&
+ virtualKey?.team_id &&
+ newVal &&
+ newVal !== virtualKey.team_id
+ ) {
+ setPendingTeamId(newVal);
+ setShowReassignTeamWarning(true);
+ } else {
+ field.onChange(newVal);
+ }
+ }}
+ placeholder="Select a team"
+ disabled={isTeamLocked}
+ emptyMessage="No teams found."
+ className="h-9"
+ />
+
+
+ )}
+ />
+ )}
+
+ {form.watch("entityType") === "customer" &&
+ customers?.length > 0 && (
+ (
+
+
+ Select Customer
+
+ ({
+ value: customer.id,
+ label: customer.name,
+ }))}
+ value={field.value || null}
+ onValueChange={(val) =>
+ field.onChange(val ?? "")
+ }
+ placeholder="Select a customer"
+ emptyMessage="No customers found."
+ className="h-9"
+ />
+
+
+ )}
+ />
+ )}
+
+ {form.watch("entityType") === "access_profile" &&
+ (accessProfiles?.length > 0 ||
+ virtualKey?.access_profile_id ||
+ defaultAccessProfileId) && (
+ (
+
+
+ Select Access Profile
+
+ ({
+ value: String(ap.id),
+ label: ap.name,
+ }))}
+ value={field.value || null}
+ onValueChange={(val) => {
+ const newVal = val ?? "";
+ if (
+ isEditing &&
+ virtualKey?.access_profile_id &&
+ newVal &&
+ newVal !==
+ String(virtualKey.access_profile_id)
+ ) {
+ setPendingAccessProfileId(newVal);
+ setShowReassignAPWarning(true);
+ } else {
+ field.onChange(newVal);
+ }
+ }}
+ placeholder="Select an access profile"
+ disabled={isAPLocked}
+ emptyMessage="No access profiles found."
+ className="h-9"
+ />
+
+
+ )}
+ />
+ )}
+
+
+ >
+ )}
+