import { Result, useAtomValue } from "@effect-atom/atom-react"; import { connectionsAtom, sourceAtom } from "@executor/react/api/atoms"; import { Badge } from "@executor/react/components/badge"; import { Button } from "@executor/react/components/button"; import { useScope, useScopeStack, useUserScope } from "@executor/react/api/scope-context"; import { ScopeId } from "@executor/sdk"; import { openApiSourceAtom, openApiSourceBindingsAtom } from "./atoms"; import { effectiveBindingForScope, missingCredentialLabels, } from "../sdk/credential-status"; function ConnectedBadge() { return ( Connected ); } function OAuthBadge() { return OAuth; } function NeedsCredentialsBadge() { return ( Needs credentials ); } function CheckingCredentialsBadge() { return ( Checking credentials ); } // The entry row already renders name + id + kind, so this summary // component only contributes extras — specifically, an OAuth status // badge when the source has OAuth2 configured. Non-OAuth sources // render nothing. export default function OpenApiSourceSummary(props: { sourceId: string; variant?: "badge" | "panel"; onAction?: () => void; }) { const displayScope = useScope(); const userScope = useUserScope(); const scopeStack = useScopeStack(); const summaryResult = useAtomValue(sourceAtom(props.sourceId, displayScope)); const sourceScopeId = Result.isSuccess(summaryResult) && summaryResult.value?.scopeId ? summaryResult.value.scopeId : displayScope; const sourceResult = useAtomValue( openApiSourceAtom(ScopeId.make(sourceScopeId), props.sourceId), ); const bindingsResult = useAtomValue( openApiSourceBindingsAtom(displayScope, props.sourceId, ScopeId.make(sourceScopeId)), ); const connectionsResult = useAtomValue(connectionsAtom(displayScope)); const source = Result.isSuccess(sourceResult) && sourceResult.value ? sourceResult.value : null; if (!source) return null; const oauth2 = source.config.oauth2; const bindingsLoaded = Result.isSuccess(bindingsResult); const connectionsLoaded = Result.isSuccess(connectionsResult); if (!bindingsLoaded) { return props.variant === "panel" ? null : ; } const bindings = Result.isSuccess(bindingsResult) ? bindingsResult.value : []; const scopeRanks = new Map( scopeStack.map((scope, index) => [scope.id as string, index] as const), ); const credentialTargetScope = userScope; const missing = missingCredentialLabels( source, bindings, credentialTargetScope, scopeRanks, ); if (props.variant === "panel") { if (missing.length === 0) return null; return (
This source needs your credentials before tools can run.
Missing: {missing.join(", ")}
{props.onAction && ( )}
); } if (missing.length > 0) return ; if (!oauth2) return null; if (!connectionsLoaded) return ; const connections = connectionsResult.value; const connectionBinding = effectiveBindingForScope( bindings, oauth2.connectionSlot, credentialTargetScope, scopeRanks, ); const connectionId = connectionBinding && connectionBinding.value.kind === "connection" ? connectionBinding.value.connectionId : null; if ( connectionId && connections.some((connection) => connection.id === connectionId) ) { return ; } return ; }