import { useCallback, useRef, useState } from "react"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Separator } from "@/components/ui/separator"; import type { ModelProviderRead } from "@/contracts/types/model-connections.types"; import { AzureConnectForm } from "./azure-connect-form"; import { BedrockConnectForm } from "./bedrock-connect-form"; import { ConnectFormFooter } from "./connect-fields"; import { DefaultConnectForm } from "./default-connect-form"; import type { SelectableModel } from "./model-utils"; import { ModelsSelectionPanel } from "./models-selection-panel"; import { type ConnectionDraft, type ProviderConnectFormProps, providerDefaultBaseUrl, providerDisplay, providerIcon, } from "./provider-metadata"; import { VertexConnectForm } from "./vertex-connect-form"; interface ProviderConnectDialogProps { open: boolean; onOpenChange: (open: boolean) => void; provider: string; selectedProvider?: ModelProviderRead; isPending: boolean; onSubmit: (draft: ConnectionDraft) => void; previewModels?: SelectableModel[]; isPreviewingModels?: boolean; onPreviewModels?: (draft: ConnectionDraft) => void; onAddPreviewModel?: (modelId: string) => void; onTogglePreviewModel?: (model: SelectableModel, enabled: boolean) => void; onBulkTogglePreviewModels?: (models: SelectableModel[], enabled: boolean) => void; } /** * Shared dialog shell for the "Add Provider" flow. It owns the header and routes * to the provider-specific connect form. Forms remount on open (Radix unmounts * closed content), so each gets fresh, prefilled state. */ export function ProviderConnectDialog({ open, onOpenChange, provider, selectedProvider, isPending, onSubmit, previewModels = [], isPreviewingModels = false, onPreviewModels, onAddPreviewModel, onTogglePreviewModel, onBulkTogglePreviewModels, }: ProviderConnectDialogProps) { const meta = providerDisplay(provider); const isAzure = provider === "azure"; const isBedrock = provider === "bedrock"; const isVertex = provider === "vertex_ai"; const titleRef = useRef(null); const [currentDraft, setCurrentDraft] = useState({ base_url: null, api_key: null, extra: {}, }); const [canSubmit, setCanSubmit] = useState(false); const handleDraftChange = useCallback((draft: ConnectionDraft, nextCanSubmit: boolean) => { setCurrentDraft(draft); setCanSubmit(nextCanSubmit); }, []); const formProps: ProviderConnectFormProps = { provider, defaultBaseUrl: providerDefaultBaseUrl(provider, selectedProvider?.default_base_url), baseUrlRequired: Boolean(selectedProvider?.base_url_required), onDraftChange: handleDraftChange, }; const modelDescription = (() => { if (isAzure) { return "Select the models to enable for Azure OpenAI"; } if (isBedrock) { return "Select the models to enable for Amazon Bedrock"; } if (isVertex) { return "Select the models to enable for Gemini"; } return "Select the models to enable for this provider"; })(); const canRefreshModels = !isAzure && !isVertex && (!isBedrock || canSubmit); const hasEnabledModel = previewModels.some((model) => model.enabled) || Boolean(currentDraft.seedModelId); const canConnect = canSubmit && hasEnabledModel; return ( { event.preventDefault(); titleRef.current?.focus(); }} >
{providerIcon(provider, "size-5")}
Connect {meta.name} {meta.subtitle}
{provider === "azure" ? ( ) : provider === "bedrock" ? ( ) : provider === "vertex_ai" ? ( ) : ( )} onPreviewModels?.(currentDraft) : undefined} onAddManual={onAddPreviewModel} onToggleModel={onTogglePreviewModel} onBulkToggle={onBulkTogglePreviewModels} />
onOpenChange(false)} onSubmit={() => onSubmit(currentDraft)} canSubmit={canConnect} isPending={isPending} />
); }