import { useState } from "react"; import type { CredentialSummary } from "@shared/contracts/schemas-credentials"; import type { ConnectorCatalogEntry } from "@shared/connector-catalog"; import { ApiKeyForm } from "../forms/ApiKeyForm"; import { AzureForm } from "../forms/AzureForm"; import { AwsForm } from "../forms/AwsForm"; import { VertexForm } from "../forms/VertexForm"; import { LocalForm } from "../forms/LocalForm"; import { ActionButton } from "../../ui"; import { useT, type TranslationFn } from "../../../i18n"; interface Props { entry: ConnectorCatalogEntry; credential: CredentialSummary | null; } function kindLabel( auth: ConnectorCatalogEntry["auth"]["type"], t: TranslationFn, ): string { switch (auth) { case "oauth": return t("providers.kindOAuth"); case "api_key": return t("providers.kindApiKey"); case "azure": return t("providers.kindAzure"); case "aws": return t("providers.kindAws"); case "gcp_adc": return t("providers.kindGcp"); case "local": return t("providers.kindLocal"); } } const STATUS_STYLE: Record = { active: { dot: "bg-success", text: "text-success" }, expired: { dot: "bg-warning", text: "text-warning" }, error: { dot: "bg-destructive", text: "text-destructive" }, not_configured: { dot: "bg-muted-foreground/30", text: "text-muted-foreground" }, revoked: { dot: "bg-muted-foreground/30", text: "text-muted-foreground" }, }; function statusLabel(status: string, t: TranslationFn): string { switch (status) { case "active": return t("providers.statusConnected"); case "expired": return t("providers.statusExpired"); case "error": return t("providers.statusError"); case "not_configured": return t("providers.statusNotConfigured"); case "revoked": return t("providers.statusRevoked"); default: return status; } } export function ProviderRow({ entry, credential }: Props) { const t = useT(); const [busy, setBusy] = useState<"login" | "remove" | "test" | null>(null); const [feedback, setFeedback] = useState(null); const [editing, setEditing] = useState(false); const status = credential?.status ?? "not_configured"; const statusStyle = STATUS_STYLE[status] ?? STATUS_STYLE.not_configured; const statusLabelText = statusLabel(status, t); const hasCredential = credential !== null; const handleOAuthLogin = async () => { const desktop = window.agentCompany; if (!desktop) return; setBusy("login"); setFeedback(null); const result = await desktop.startOAuth({ connectorId: entry.id }); setBusy(null); if (!result.ok) setFeedback(result.error.message); }; const handleRemove = async () => { const desktop = window.agentCompany; if (!desktop) return; setBusy("remove"); const result = await desktop.removeCredential({ connectorId: entry.id }); setBusy(null); if (!result.ok) setFeedback(result.error.message); }; const handleTest = async () => { const desktop = window.agentCompany; if (!desktop) return; setBusy("test"); setFeedback(null); const result = await desktop.testCredential({ connectorId: entry.id }); setBusy(null); if (!result.ok) { setFeedback(result.error.message); return; } setFeedback( result.data.ok ? t("providers.testOk").replace("{message}", result.data.message) : t("providers.testFailed").replace("{message}", result.data.message), ); }; const renderForm = () => { if (!editing || entry.auth.type === "oauth") return null; const onSaved = () => { setEditing(false); setFeedback(t("providers.saved")); }; const apiKeyEnv = entry.auth.type === "api_key" ? entry.auth.envKey : undefined; if (entry.auth.type === "api_key") return ; if (entry.auth.type === "azure") return ; if (entry.auth.type === "aws") return ; if (entry.auth.type === "gcp_adc") return ; if (entry.auth.type === "local") return ; return null; }; const disabled = busy !== null; const isOAuth = entry.auth.type === "oauth"; return (
  • {entry.label}
    {kindLabel(entry.auth.type, t)}
    {hasCredential && credential.displayHint ? credential.displayHint : statusLabelText} {hasCredential && status !== "active" ? ( ยท {statusLabelText} ) : null}
    {isOAuth ? ( void handleOAuthLogin()} tone={hasCredential ? "default" : "accent"} /> ) : ( setEditing((current) => !current)} tone={hasCredential || editing ? "default" : "accent"} /> )} {hasCredential ? ( void handleTest()} /> ) : null} {hasCredential ? ( void handleRemove()} /> ) : null}
    {feedback ? (
    {feedback}
    ) : null} {editing && !isOAuth ? (
    {renderForm()}
    ) : null}
  • ); }