import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks"; import { useT } from "@agent-native/core/client/i18n"; import { IconAlertTriangle, IconArchive, IconBrandGithub, IconBrandSlack, IconChecks, IconChevronDown, IconCircleCheck, IconCircleDashed, IconClock, IconCopy, IconDatabaseImport, IconDotsVertical, IconExternalLink, IconFileSearch, IconFileText, IconLoader2, IconNotes, IconPlayerPlay, IconRefresh, IconReportAnalytics, IconSend, IconSettings2, IconShieldCheck, IconVideo, IconWebhook, } from "@tabler/icons-react"; import { useEffect, useMemo, useState, type ReactNode } from "react"; import { useSearchParams } from "react-router"; import { EmptyActionState, LoadingRows, PageHeader, StatusBadge, } from "@/components/brain/Surface"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Progress } from "@/components/ui/progress"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { type BrainConnectionProvider, type BrainHealthResponse, type BrainCaptureReviewStatus, type BrainCaptureReviewItem, type EnqueueCapturesDistillationResponse, type CapturesResponse, type CreateSourceResponse, type BrainSource, type BrainWorkspaceConnectionGrantState, type BrainWorkspaceConnectionStatus, type BrainWorkspaceCredentialRef, type ConnectionProvidersResponse, type SourcesResponse, formatPercent, sourceAutoSync, sourceDescription, sourceEnabled, sourceHealth, sourceLastSync, sourceName, sourceRetryAfter, sourceReviewRequired, sourceType, } from "@/lib/brain"; import { createOneTimeIngestHandoff, type OneTimeIngestHandoff, } from "@/lib/ingest-handoff"; import { cn } from "@/lib/utils"; type Provider = "manual" | "generic" | "clips" | "slack" | "granola" | "github"; type CaptureStatusFilter = BrainCaptureReviewStatus | "all"; type BrainT = ReturnType; interface SourceFormState { title: string; provider: Provider; channelRefs: string; historyLimit: string; granolaPageSize: string; granolaUpdatedAfter: string; githubRepos: string; githubLimit: string; githubState: "open" | "closed" | "all"; githubIncludeIssues: boolean; githubIncludePullRequests: boolean; workspaceConnectionId: string; pollMinutes: string; sourceKey: string; autoSync: boolean; reviewRequired: boolean; includePublicChannels: boolean; } const providers: Array<{ value: Provider; label: string; detail: string; icon: typeof IconDatabaseImport; }> = [ { value: "slack", label: "Slack", detail: "Approved public/private channels only", icon: IconBrandSlack, }, { value: "granola", label: "Granola", detail: "Enterprise API Team-space notes", icon: IconNotes, }, { value: "github", label: "GitHub", detail: "Approved repository issues and PRs", icon: IconBrandGithub, }, { value: "clips", label: "Clips", detail: "Recordings exported into Brain", icon: IconVideo, }, { value: "generic", label: "Webhook", detail: "Signed transcript and capture imports", icon: IconWebhook, }, { value: "manual", label: "Manual", detail: "Agent/UI imports without remote sync", icon: IconFileText, }, ]; function defaultTitle(provider: Provider, t?: ReturnType) { switch (provider) { case "slack": return t?.("sources.defaultTitle.slack") ?? "Slack knowledge channels"; case "granola": return t?.("sources.defaultTitle.granola") ?? "Granola team notes"; case "github": return t?.("sources.defaultTitle.github") ?? "GitHub product repos"; case "clips": return t?.("sources.defaultTitle.clips") ?? "Clips exports"; case "generic": return ( t?.("sources.defaultTitle.generic") ?? "Generic transcript webhook" ); case "manual": default: return t?.("sources.defaultTitle.manual") ?? "Manual imports"; } } function defaultForm( provider: Provider, t?: ReturnType, ): SourceFormState { return { title: defaultTitle(provider, t), provider, channelRefs: "", historyLimit: "15", granolaPageSize: "10", granolaUpdatedAfter: "", githubRepos: "", githubLimit: "25", githubState: "all", githubIncludeIssues: true, githubIncludePullRequests: true, workspaceConnectionId: "", pollMinutes: "60", sourceKey: provider === "generic" || provider === "clips" ? provider : "", autoSync: provider === "slack" || provider === "granola" || provider === "github", reviewRequired: true, includePublicChannels: false, }; } function listValue(value: unknown) { if (Array.isArray(value)) return value.filter(Boolean).join("\n"); return typeof value === "string" ? value : ""; } function formFromSource(source: BrainSource): SourceFormState { const provider = (source.provider ?? "generic") as Provider; const config = source.config ?? {}; return { ...defaultForm(provider), title: sourceName(source), channelRefs: listValue( config.channelIds ?? config.channels ?? config.allowedChannels, ), historyLimit: typeof config.historyLimit === "number" || typeof config.historyLimit === "string" ? String(config.historyLimit) : "15", granolaPageSize: typeof config.pageSize === "number" || typeof config.pageSize === "string" ? String(config.pageSize) : "10", granolaUpdatedAfter: typeof config.updatedAfter === "string" ? config.updatedAfter : "", githubRepos: listValue(config.repositories ?? config.repos), githubLimit: typeof config.limit === "number" || typeof config.limit === "string" ? String(config.limit) : "25", githubState: config.state === "open" || config.state === "closed" ? config.state : "all", githubIncludeIssues: config.includeIssues !== false, githubIncludePullRequests: config.includePullRequests !== false, workspaceConnectionId: typeof config.workspaceConnectionId === "string" ? config.workspaceConnectionId : "", pollMinutes: typeof config.pollMinutes === "number" || typeof config.pollMinutes === "string" ? String(config.pollMinutes) : "60", sourceKey: "", autoSync: sourceAutoSync(source), reviewRequired: sourceReviewRequired(source), includePublicChannels: config.includePublicChannels === true, }; } function splitLines(value: string) { return value .split(/[\n,]/g) .map((item) => item.trim().replace(/^#/, "")) .filter(Boolean); } function numberValue( value: string, fallback: number, min: number, max: number, ) { const parsed = Number(value); if (!Number.isFinite(parsed)) return fallback; return Math.max(min, Math.min(max, Math.floor(parsed))); } function buildConfig(form: SourceFormState) { const config: Record = { reviewRequired: form.reviewRequired, autoSync: form.autoSync, pollMinutes: numberValue(form.pollMinutes, 60, 5, 1440), }; if (form.provider === "slack") { config.channelIds = splitLines(form.channelRefs); config.historyLimit = numberValue(form.historyLimit, 15, 1, 15); config.includePublicChannels = form.includePublicChannels; } if (form.provider === "granola") { config.pageSize = numberValue(form.granolaPageSize, 10, 1, 30); if (form.granolaUpdatedAfter.trim()) { config.updatedAfter = form.granolaUpdatedAfter.trim(); } } if (form.provider === "github") { config.repositories = splitLines(form.githubRepos); config.state = form.githubState; config.limit = numberValue(form.githubLimit, 25, 1, 100); config.includeIssues = form.githubIncludeIssues; config.includePullRequests = form.githubIncludePullRequests; } config.workspaceConnectionId = form.workspaceConnectionId.trim(); if (form.sourceKey.trim()) config.sourceKey = form.sourceKey.trim(); return config; } function sourceProviderIcon(provider?: string) { return ( providers.find((item) => item.value === provider)?.icon ?? IconFileText ); } function shortDate(value?: string | null) { if (!value) return null; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; return date.toLocaleString(undefined, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", }); } function syncDetail(source: BrainSource, t: BrainT) { const retry = sourceRetryAfter(source); if (retry) return t("sources.retryAfter", { date: shortDate(retry) ?? retry }); if (source.lastError) return source.lastError; if (source.latestRun?.status === "error") { return source.latestRun.error ?? t("sources.lastSyncFailed"); } if (source.nextSyncAt) return t("sources.nextSync", { date: shortDate(source.nextSyncAt) ?? source.nextSyncAt, }); return sourceAutoSync(source) ? t("sources.waitingForFirstSync") : t("sources.manualSync"); } const captureStatusOptions: CaptureStatusFilter[] = [ "queued", "distilling", "distilled", "ignored", "all", ]; function captureStatusLabel(status: CaptureStatusFilter, t: BrainT) { switch (status) { case "queued": return t("sources.captureStatus.queued"); case "distilling": return t("sources.captureStatus.distilling"); case "distilled": return t("sources.captureStatus.distilled"); case "ignored": return t("sources.captureStatus.ignored"); case "all": default: return t("sources.captureStatus.all"); } } function queueStatusLabel(status: string, t: BrainT) { switch (status) { case "processing": return t("sources.queueStatus.processing"); case "done": return t("sources.queueStatus.done"); case "failed": return t("sources.queueStatus.failed"); case "queued": default: return t("sources.queueStatus.queued"); } } function queueActionLabel( queue: NonNullable[number]["distillationQueue"], t: BrainT, ) { if (!queue) return t("sources.queueDistill"); if (queue.status === "failed") return t("sources.retryDistill"); if (queue.status === "done") return t("sources.captureStatus.distilled"); return t("sources.queueStatus.queued"); } function captureCanQueue(capture: BrainCaptureReviewItem) { const queue = capture.distillationQueue; const terminal = capture.status === "distilled" || capture.status === "ignored"; return !terminal && (!queue || queue.status === "failed"); } function isSourceProvider(providerId: string): providerId is Provider { return providers.some((provider) => provider.value === providerId); } function dispatchIntegrationsHref(providerId: string) { const params = new URLSearchParams({ provider: providerId, appId: "brain" }); return `/dispatch/integrations?${params.toString()}`; } function grantStateLabel(state: BrainWorkspaceConnectionGrantState, t: BrainT) { switch (state) { case "connected": return t("sources.grantState.connected"); case "granted": return t("sources.grantState.granted"); case "needs_grant": return t("sources.grantState.needsGrant"); case "not_connected": default: return t("sources.grantState.notConnected"); } } function grantStateDetail( provider: BrainConnectionProvider, state: BrainWorkspaceConnectionGrantState, t: BrainT, ) { const workspace = provider.workspaceConnection; if (workspace?.grantAvailabilityMessage) { return workspace.grantAvailabilityMessage; } const sourceCount = provider.configuredSourceCount.toLocaleString(); switch (state) { case "connected": return t("sources.grantDetail.connected", { count: (workspace?.activeConnectionCount ?? 0).toLocaleString(), }); case "granted": return t("sources.grantDetail.granted", { count: (workspace?.grantedConnectionCount ?? 0).toLocaleString(), }); case "needs_grant": return t("sources.grantDetail.needsGrant"); case "not_connected": default: return provider.hasConfiguredSources ? t("sources.grantDetail.configuredSources", { count: sourceCount, }) : t("sources.grantDetail.noSharedConnection"); } } type ReadinessTone = "ready" | "attention" | "danger" | "muted"; type ProviderReadinessItem = { label: string; value: string; detail: string; tone: ReadinessTone; icon: typeof IconDatabaseImport; }; function readinessToneClass(tone: ReadinessTone) { switch (tone) { case "ready": return "border-border bg-secondary text-secondary-foreground"; case "attention": return "border-border bg-accent text-accent-foreground"; case "danger": return "border-destructive/25 bg-destructive/10 text-destructive"; case "muted": default: return "border-border bg-muted text-muted-foreground"; } } function providerHealthLabel(provider: BrainConnectionProvider, t: BrainT) { switch (provider.providerHealth?.status) { case "ready": return t("sources.providerHealth.ready"); case "needs_grant": return t("sources.providerHealth.grantNeeded"); case "unhealthy": return t("sources.providerHealth.needsRepair"); case "missing_credentials": return t("sources.providerHealth.missingKeys"); case "unsupported": return t("sources.providerHealth.metadataOnly"); default: return t("sources.providerHealth.unknown"); } } function providerHealthClass(provider: BrainConnectionProvider) { switch (provider.providerHealth?.status) { case "ready": return readinessToneClass("ready"); case "needs_grant": case "unhealthy": return readinessToneClass("attention"); case "missing_credentials": return readinessToneClass("danger"); case "unsupported": default: return readinessToneClass("muted"); } } function grantStateClass(state: BrainWorkspaceConnectionGrantState) { switch (state) { case "connected": return readinessToneClass("ready"); case "granted": return readinessToneClass("attention"); case "needs_grant": return readinessToneClass("attention"); case "not_connected": default: return readinessToneClass("muted"); } } type BrainWorkspaceSummaryConnection = NonNullable< BrainConnectionProvider["workspaceConnection"] >["connections"][number]; function appAccessLabel( access: BrainWorkspaceSummaryConnection["appAccess"], t: BrainT, ) { switch (access?.mode) { case "all-apps": return t("sources.appAccess.allApps"); case "allowed-app": return t("sources.appAccess.brainAllowList"); case "explicit-grant": return t("sources.appAccess.brainGrant"); case "unavailable": default: return t("sources.appAccess.needsBrainGrant"); } } function appAccessClass(access: BrainWorkspaceSummaryConnection["appAccess"]) { return access?.available ? readinessToneClass("muted") : grantStateClass("needs_grant"); } function workspaceStatusLabel( status: BrainWorkspaceConnectionStatus, t: BrainT, ) { switch (status) { case "connected": return t("sources.workspaceStatus.connected"); case "checking": return t("sources.workspaceStatus.checking"); case "needs_reauth": return t("sources.workspaceStatus.needsReauth"); case "error": return t("sources.workspaceStatus.error"); case "disabled": default: return t("sources.workspaceStatus.disabled"); } } function workspaceStatusClass(status: BrainWorkspaceConnectionStatus) { switch (status) { case "connected": return readinessToneClass("ready"); case "checking": return readinessToneClass("attention"); case "needs_reauth": return readinessToneClass("attention"); case "error": return readinessToneClass("danger"); case "disabled": default: return readinessToneClass("muted"); } } function supportsWorkspaceConnectionBinding(provider: Provider) { return ( provider === "slack" || provider === "granola" || provider === "github" ); } function providerMetadataForSource( providers: BrainConnectionProvider[], provider: Provider, ) { return providers.find((entry) => entry.id === provider); } function grantedWorkspaceConnections(provider?: BrainConnectionProvider) { return (provider?.workspaceConnection?.connections ?? []).filter( (connection) => connection.appAccess?.available, ); } function grantStateIcon(state: BrainWorkspaceConnectionGrantState) { switch (state) { case "connected": return IconCircleCheck; case "granted": return IconShieldCheck; case "needs_grant": return IconAlertTriangle; case "not_connected": default: return IconCircleDashed; } } function refLabel(ref: BrainWorkspaceCredentialRef) { return `${ref.key}${ref.scope ? `:${ref.scope}` : ""}`; } function providerWorkspaceCredentialRefs(provider: BrainConnectionProvider) { const refs = new Map(); for (const connection of provider.workspaceConnection?.connections ?? []) { for (const ref of connection.credentialRefs) { refs.set(`${connection.id}:connection:${refLabel(ref)}`, ref); } for (const ref of connection.explicitGrant?.credentialRefs ?? []) { refs.set(`${connection.id}:grant:${refLabel(ref)}`, ref); } } return Array.from(refs.values()); } function availableCredentialDetails(provider: BrainConnectionProvider) { return ( provider.credentialHealth?.details.filter((detail) => detail.available) ?? [] ); } function credentialCount( provider: BrainConnectionProvider, source: "workspace_connection" | "brain_local" | "registered_secret", ) { return availableCredentialDetails(provider).filter( (detail) => detail.provenance?.source === source, ).length; } function scopedCredentialCount(provider: BrainConnectionProvider) { return ( credentialCount(provider, "brain_local") + credentialCount(provider, "registered_secret") ); } function countLabel(count: number, singular: string, plural = `${singular}s`) { return `${count.toLocaleString()} ${count === 1 ? singular : plural}`; } function sharedConnectionReadiness( provider: BrainConnectionProvider, t: BrainT, ): ProviderReadinessItem { const workspace = provider.workspaceConnection; if (!workspace) { return { label: t("sources.sharedConnection"), value: t("sources.workspaceStatus.checking"), detail: t("sources.readiness.workspaceNotLoaded"), tone: "muted", icon: IconCircleDashed, }; } if (workspace.hasActiveWorkspaceConnection) { return { label: t("sources.sharedConnection"), value: t("sources.workspaceStatus.connected"), detail: t("sources.readiness.activeConnections", { count: workspace.activeConnectionCount.toLocaleString(), }), tone: "ready", icon: IconCircleCheck, }; } if (workspace.hasGrantedWorkspaceConnection) { return { label: t("sources.sharedConnection"), value: t("sources.readiness.repair"), detail: t("sources.readiness.grantNeedsAttention"), tone: "attention", icon: IconAlertTriangle, }; } if (workspace.hasWorkspaceConnection) { return { label: t("sources.sharedConnection"), value: t("sources.readiness.grantable"), detail: t("sources.readiness.workspaceConnectionGrantable"), tone: "attention", icon: IconShieldCheck, }; } return { label: t("sources.sharedConnection"), value: t("sources.grantState.notConnected"), detail: scopedCredentialCount(provider) ? t("sources.readiness.scopedLocalCredentialRefs") : t("sources.readiness.addReusableConnection"), tone: "muted", icon: IconCircleDashed, }; } function appGrantReadiness( provider: BrainConnectionProvider, t: BrainT, ): ProviderReadinessItem { const workspace = provider.workspaceConnection; const grantState = workspace?.grantState ?? "not_connected"; if (grantState === "connected" || grantState === "granted") { return { label: t("sources.brainAppGrant"), value: grantState === "connected" ? t("sources.grantState.granted") : t("sources.readiness.grantedRepair"), detail: grantState === "connected" ? t("sources.readiness.brainCanUseSharedConnection") : t("sources.readiness.accessGrantedConnectionInactive"), tone: grantState === "connected" ? "ready" : "attention", icon: grantStateIcon(grantState), }; } if (grantState === "needs_grant") { return { label: t("sources.brainAppGrant"), value: t("sources.readiness.needed"), detail: t("sources.readiness.grantExistingConnection"), tone: "attention", icon: IconAlertTriangle, }; } return { label: t("sources.brainAppGrant"), value: scopedCredentialCount(provider) ? t("sources.readiness.notNeeded") : t("sources.readiness.noGrant"), detail: scopedCredentialCount(provider) ? t("sources.readiness.scopedCredentialsAvailable") : t("sources.readiness.grantAppearsAfterConnection"), tone: "muted", icon: IconCircleDashed, }; } function credentialPathReadiness( provider: BrainConnectionProvider, t: BrainT, ): ProviderReadinessItem { const health = provider.credentialHealth; if (!health) { return { label: t("sources.credentialPath"), value: t("sources.workspaceStatus.checking"), detail: t("sources.readiness.credentialNotLoaded"), tone: "muted", icon: IconCircleDashed, }; } if (health.status === "not_required") { return { label: t("sources.credentialPath"), value: t("sources.notRequired"), detail: t("sources.readiness.noCredentialKeyRequired"), tone: "ready", icon: IconCircleCheck, }; } const available = availableCredentialDetails(provider)[0]; if (available?.provenance?.source === "workspace_connection") { return { label: t("sources.credentialPath"), value: t("sources.readiness.shared"), detail: t("sources.readiness.usingWorkspaceCredentialRefs"), tone: "ready", icon: IconShieldCheck, }; } if (available?.provenance?.source === "brain_local") { return { label: t("sources.credentialPath"), value: t("sources.readiness.brainLocal"), detail: t("sources.readiness.scopedCredentialRefsConfigured"), tone: "ready", icon: IconShieldCheck, }; } if (available?.provenance?.source === "registered_secret") { return { label: t("sources.credentialPath"), value: t("sources.readiness.vault"), detail: t("sources.readiness.registeredCredentialRefAvailable"), tone: "ready", icon: IconShieldCheck, }; } if (health.available) { return { label: t("sources.credentialPath"), value: t("sources.readiness.available"), detail: t("sources.readiness.requiredCredentialRefsAvailable"), tone: "ready", icon: IconShieldCheck, }; } return { label: t("sources.credentialPath"), value: t("sources.readiness.missing"), detail: health.missingMessages[0] ?? t("sources.readiness.addSharedOrScopedCredential"), tone: "danger", icon: IconAlertTriangle, }; } function providerConnectionReadiness( provider: BrainConnectionProvider, t: BrainT, ): ProviderReadinessItem { const workspace = provider.workspaceConnection; const health = provider.providerHealth?.status; if (!provider.sourceProviderSupported) { return { label: t("sources.providerConnection"), value: t("sources.providerHealth.metadataOnly"), detail: t("sources.readiness.sourceSetupNotImplemented"), tone: "muted", icon: IconCircleDashed, }; } if (health === "ready") { return { label: t("sources.providerConnection"), value: t("sources.providerHealth.ready"), detail: workspace?.hasActiveWorkspaceConnection ? t("sources.readiness.readyThroughSharedConnection") : scopedCredentialCount(provider) ? t("sources.readiness.readyThroughScopedRefs") : t("sources.readiness.readyForSourceSetup"), tone: "ready", icon: IconCircleCheck, }; } if (health === "needs_grant") { return { label: t("sources.providerConnection"), value: t("sources.providerHealth.grantNeeded"), detail: t("sources.readiness.providerNeedsAppAccess"), tone: "attention", icon: IconAlertTriangle, }; } if (health === "unhealthy") { return { label: t("sources.providerConnection"), value: t("sources.readiness.repair"), detail: t("sources.readiness.reauthorizeProviderConnection"), tone: "attention", icon: IconAlertTriangle, }; } if (health === "missing_credentials" && !workspace?.hasWorkspaceConnection) { return { label: t("sources.providerConnection"), value: t("sources.connectProvider"), detail: t("sources.readiness.addSharedOrScopedCredential"), tone: "danger", icon: IconAlertTriangle, }; } return { label: t("sources.providerConnection"), value: providerHealthLabel(provider, t), detail: provider.providerHealth?.message ?? t("sources.readiness.providerUnknown"), tone: health === "missing_credentials" ? "danger" : "muted", icon: health === "missing_credentials" ? IconAlertTriangle : IconCircleDashed, }; } function providerReadinessItems(provider: BrainConnectionProvider, t: BrainT) { return [ sharedConnectionReadiness(provider, t), appGrantReadiness(provider, t), providerConnectionReadiness(provider, t), credentialPathReadiness(provider, t), ]; } function providerReadinessCallout( provider: BrainConnectionProvider, t: BrainT, ): ProviderReadinessItem & { title: string } { const workspace = provider.workspaceConnection; if (!provider.sourceProviderSupported) { return { ...providerConnectionReadiness(provider, t), title: t("sources.connectionMetadataOnly"), }; } if (workspace?.hasActiveWorkspaceConnection) { return { label: t("sources.readinessLabel"), value: t("sources.readiness.shared"), title: t("sources.sharedWorkspaceConnectionReady"), detail: t("sources.readiness.reuseProviderConnection"), tone: "ready", icon: IconCircleCheck, }; } if (workspace?.grantState === "needs_grant") { return { label: t("sources.readinessLabel"), value: t("sources.providerHealth.grantNeeded"), title: t("sources.grantBrainAccess"), detail: t("sources.readiness.approveBrainAccess"), tone: "attention", icon: IconAlertTriangle, }; } if (scopedCredentialCount(provider)) { return { label: t("sources.readinessLabel"), value: t("sources.readiness.local"), title: t("sources.scopedCredentialsReady"), detail: t("sources.readiness.localCredentialRefsAvailable"), tone: "ready", icon: IconShieldCheck, }; } if (provider.credentialHealth?.status === "not_required") { return { label: t("sources.readinessLabel"), value: t("sources.providerHealth.ready"), title: t("sources.noCredentialRequired"), detail: t("sources.readiness.providerNoCredential"), tone: "ready", icon: IconCircleCheck, }; } return { label: t("sources.readinessLabel"), value: t("sources.readiness.connect"), title: t("sources.connectTheProvider"), detail: t("sources.readiness.addSharedOrScopedCredential"), tone: "danger", icon: IconAlertTriangle, }; } function ProviderReadinessCell({ item }: { item: ProviderReadinessItem }) { const Icon = item.icon; return (

{item.label}

{item.detail}

{item.value}
); } function provenanceLabel( provenance: NonNullable< NonNullable< BrainConnectionProvider["credentialHealth"] >["details"][number]["provenance"] >, t: BrainT, ) { switch (provenance.source) { case "workspace_connection": return [ provenance.connectionLabel ?? t("sources.workspaceConnection"), provenance.appAccessMode === "explicit-grant" ? t("sources.provenance.explicitBrainGrant") : provenance.appAccessMode === "all-apps" ? t("sources.appAccess.allApps") : provenance.appAccessMode === "allowed-app" ? t("sources.appAccess.brainAllowList") : null, ] .filter(Boolean) .join(" - "); case "brain_local": return t("sources.provenance.brainLocalCredential"); case "registered_secret": return t("sources.provenance.credentialVault"); default: return t("sources.provenance.credentialSource"); } } function ProviderCatalog({ providers: connectionProviders, loading, workspaceError, onAddSource, }: { providers: BrainConnectionProvider[]; loading: boolean; workspaceError?: string | null; onAddSource: (provider: Provider) => void; }) { const t = useT(); const [expandedProviderId, setExpandedProviderId] = useState( null, ); return (

{t("sources.connectionProviders")}

{t("sources.connectionProvidersDescription")}

{loading ? t("sources.loading") : t("sources.providerCount", { count: connectionProviders.length.toLocaleString(), })}
{loading ? (
{t("sources.loadingProviderCatalog")}
) : connectionProviders.length ? (
{connectionProviders.map((provider) => { const workspace = provider.workspaceConnection; const grantState = workspace?.grantState ?? "not_connected"; const GrantIcon = grantStateIcon(grantState); const credentialRefs = providerWorkspaceCredentialRefs(provider); const missingCredentialMessage = provider.credentialHealth?.missingMessages[0] ?? null; const credentialBadges = credentialRefs.length ? credentialRefs.map((ref, index) => ({ key: `${refLabel(ref)}-${index}`, label: refLabel(ref), })) : provider.credentialKeys.map((credential) => ({ key: credential.key, label: credential.key, })); const sourceProvider = isSourceProvider(provider.id) ? provider.id : null; const Icon = sourceProvider ? sourceProviderIcon(sourceProvider) : IconDatabaseImport; const expanded = expandedProviderId === provider.id; const readinessCallout = providerReadinessCallout(provider, t); const ReadinessIcon = readinessCallout.icon; const readinessItems = providerReadinessItems(provider, t); return (

{provider.label}

{provider.hasConfiguredSources ? `${provider.configuredSourceCount.toLocaleString()} configured` : t("sources.noBrainSourcesYet")}

{grantStateLabel(grantState, t)} {providerHealthLabel(provider, t)}

{provider.providerHealth?.message ?? grantStateDetail(provider, grantState, t)}

{readinessCallout.title}

{readinessCallout.detail}

{readinessCallout.value}
{provider.capabilities.map((capability) => ( {capability} ))}
{expanded ? (

{provider.description}

{t("sources.connectionReadiness")}

{t("sources.valuesHidden")}
{readinessItems.map((item) => ( ))}

{credentialRefs.length ? t("sources.credentialRefs") : t("sources.catalogKeys")}

{credentialBadges.length ? ( credentialBadges.map((credential) => ( {credential.label} )) ) : ( {t("sources.noCredentialKeysRequired")} )}
{missingCredentialMessage ? (

{missingCredentialMessage}

) : null}
{provider.id === "slack" ? (
{t("sources.slackSetupGuide")}

{t("sources.slackSetupAllowList")}

{t("sources.slackSetupScopes")}

{t("sources.slackSetupPrivateChannels")}

) : null} {provider.credentialKeys.length ? (
{provider.credentialKeys.map((credential) => (

{credential.label} {credential.required ? ( {" "} {t("sources.required")} ) : null}

{credential.description ? (

{credential.description}

) : null}
))}
) : null} {provider.credentialHealth?.details.length ? (

{t("sources.credentialProvenance")}

{provider.credentialHealth.details.map((detail) => (

{detail.key}

{detail.available ? t("sources.readiness.available") : t("sources.readiness.missing")}

{detail.provenance ? provenanceLabel(detail.provenance, t) : detail.missingMessage}

))}
) : null} {workspace?.connections.length ? (

{t("sources.workspaceConnections")}

{workspace.connections.map((connection) => { const refs = [ ...connection.credentialRefs, ...(connection.explicitGrant?.credentialRefs ?? []), ]; return (

{connection.label}

{connection.accountLabel ?? connection.accountId ?? provider.label}

{workspaceStatusLabel(connection.status, t)} {appAccessLabel(connection.appAccess, t)}
{refs.length ? (
{refs.map((ref, index) => ( {refLabel(ref)} ))}
) : (

{t("sources.noCredentialRefs")}

)} {connection.lastError ? (

{connection.lastError}

) : null}
); })}
) : (

{t("sources.noSharedWorkspaceConnection")}

)} {!provider.sourceProviderSupported ? (

{t("sources.connectionMetadataOnlyDetail")}

) : null}
) : null}
{grantState === "needs_grant" ? ( ) : null} {sourceProvider ? ( ) : null}
); })}
) : (
{t("sources.noConnectionProviders")}
)} {workspaceError ? (
{t("sources.workspaceStatusUnavailable", { error: workspaceError })}
) : null}
); } function BrainHealthStrip({ health, loading, }: { health?: BrainHealthResponse; loading: boolean; }) { const t = useT(); const attention = (health?.sources.needsSetup ?? 0) + (health?.sources.needsSync ?? 0) + (health?.sources.stale ?? 0) + (health?.sources.error ?? 0); const lastEval = health?.retrieval.lastEval; const nextStep = health?.setup.nextSteps[0]; return (

{t("sources.brainHealth")}

{loading ? ( {t("sources.workspaceStatus.checking")} ) : null}

{nextStep ?? t("sources.healthReady")}

{t("sources.healthHealthy", { healthy: (health?.sources.healthy ?? 0).toLocaleString(), total: (health?.sources.total ?? 0).toLocaleString(), })} {attention ? ( {t("sources.healthAttention", { count: attention.toLocaleString(), })} ) : null} {health?.sources.lastSyncedAt ? t("sources.lastSyncWithDate", { date: shortDate(health.sources.lastSyncedAt), }) : t("sources.noSyncYet")} {lastEval ? ( {t("sources.evalScore", { score: Math.round(lastEval.score * 100).toLocaleString(), })} ) : null}
); } function SourceFact({ label, value }: { label: string; value: ReactNode }) { return (

{label}

{value}

); } function ingestSourceKey(source: BrainSource) { const sourceKey = source.config?.sourceKey; return typeof sourceKey === "string" && sourceKey.trim() ? sourceKey.trim() : null; } function SourceListItem({ source, syncPending, onReview, onRotateIngestToken, onSync, onTune, }: { source: BrainSource; syncPending: boolean; onReview: () => void; onRotateIngestToken?: () => void; onSync: () => void; onTune: () => void; }) { const t = useT(); const [expanded, setExpanded] = useState(false); const Icon = sourceProviderIcon(source.provider); const retry = sourceRetryAfter(source); const hasSyncNotice = Boolean( source.lastError || retry || source.latestRun?.status === "error", ); const nextSync = source.nextSyncAt ? (shortDate(source.nextSyncAt) ?? source.nextSyncAt) : null; const coverage = typeof source.coverage === "number" ? formatPercent(source.coverage) : null; const captureCount = (source.recordCount ?? 0).toLocaleString(); const lastSync = shortDate(sourceLastSync(source)) ?? t("sources.never"); return (

{sourceName(source)}

{sourceType(source)} {captureCount} {t("sources.captures").toLocaleLowerCase()} {t("sources.lastSyncWithDate", { date: lastSync })} {hasSyncNotice ? ( {t("sources.actionFailedTitle")} ) : null}
{t("sources.captures")} {t("sources.syncNow")} {t("sources.tuneSource")} {onRotateIngestToken ? ( {t("sources.rotateIngestToken")} ) : null} {expanded ? t("sources.hideDetails") : t("sources.details")}
{expanded ? (

{sourceDescription(source)}

{hasSyncNotice ? (

{syncDetail(source, t)}

) : null}
{coverage ? ( ) : null}
{coverage ? ( ) : null} {nextSync ? (

{t("sources.nextSync", { date: nextSync })}

) : null}
) : null}
); } export default function SourcesRoute() { const t = useT(); const [params, setParams] = useSearchParams(); const type = params.get("type") ?? "all"; const [advancedOpen, setAdvancedOpen] = useState(false); const [setupOpen, setSetupOpen] = useState(false); const [ingestHandoff, setIngestHandoff] = useState(null); const [copiedHandoffField, setCopiedHandoffField] = useState( null, ); const [editingSource, setEditingSource] = useState(null); const [reviewSource, setReviewSource] = useState(null); const [captureStatus, setCaptureStatus] = useState("queued"); const [showCapturePreview, setShowCapturePreview] = useState(false); const [selectedCaptureIds, setSelectedCaptureIds] = useState>( () => new Set(), ); const [bulkResult, setBulkResult] = useState(null); const [form, setForm] = useState(() => defaultForm("slack", t), ); const sourcesQuery = useActionQuery( "list-sources" as any, { provider: type === "all" ? undefined : type, includeArchived: false, } as any, ); const connectionProvidersQuery = useActionQuery( "list-connection-providers" as any, {} as any, ); const healthQuery = useActionQuery( "get-brain-health" as any, {} as any, ); const updateSource = useActionMutation< unknown, { id: string; title?: string; status?: "active" | "paused"; config?: Record; } >("update-source" as any); const createSource = useActionMutation< CreateSourceResponse, { title: string; provider: Provider; visibility: "org"; config: Record; sourceKey?: string; } >("create-source" as any); const rotateSourceIngestToken = useActionMutation< CreateSourceResponse, { sourceId: string } >("rotate-source-ingest-token" as any); const syncSource = useActionMutation( "sync-source" as any, ); const syncDueSources = useActionMutation( "sync-due-sources" as any, ); const capturesQuery = useActionQuery( "list-captures" as any, { sourceId: reviewSource?.id, status: captureStatus === "all" ? undefined : captureStatus, includePreview: showCapturePreview, limit: 25, } as any, { enabled: Boolean(reviewSource?.id), retry: false }, ); const enqueueDistillation = useActionMutation< unknown, { captureId: string; priority?: number } >("enqueue-distillation" as any); const enqueueCapturesDistillation = useActionMutation< EnqueueCapturesDistillationResponse, { captureIds: string[]; priority?: number } >("enqueue-captures-distillation" as any); const markCaptureDistilled = useActionMutation< unknown, { captureId: string; status: "ignored" } >("mark-capture-distilled" as any); const sources = sourcesQuery.data?.sources ?? []; const connectionProviders = connectionProvidersQuery.data?.providers ?? []; const formProviderMetadata = providerMetadataForSource( connectionProviders, form.provider, ); const formWorkspaceConnections = [ ...new Map( [ ...grantedWorkspaceConnections(formProviderMetadata), ...( formProviderMetadata?.workspaceConnection?.connections ?? [] ).filter((connection) => connection.id === form.workspaceConnectionId), ].map((connection) => [connection.id, connection]), ).values(), ]; const selectedWorkspaceConnection = formWorkspaceConnections.find( (connection) => connection.id === form.workspaceConnectionId, ); const captures = capturesQuery.data?.captures ?? []; const queueableCaptures = captures.filter(captureCanQueue); const queueableCaptureIds = new Set( queueableCaptures.map((capture) => capture.id), ); const selectedQueueableIds = Array.from(selectedCaptureIds).filter((id) => queueableCaptureIds.has(id), ); const allQueueableSelected = queueableCaptures.length > 0 && queueableCaptures.every((capture) => selectedCaptureIds.has(capture.id)); const selectedSourceId = params.get("sourceId"); const sourceTypes = useMemo( () => [ "all", ...Array.from( new Set([ ...providers.map((provider) => provider.value), ...sources.map((source) => sourceType(source)), ]), ), ], [sources], ); const visibleSources = sources.filter((source) => type === "all" ? true : sourceType(source) === type, ); useEffect(() => { if (!selectedSourceId) { setReviewSource(null); return; } const selected = sources.find((source) => source.id === selectedSourceId); if (selected) setReviewSource(selected); }, [selectedSourceId, sources]); function updateType(value: string) { const next = new URLSearchParams(params); if (value === "all") next.delete("type"); else next.set("type", value); setParams(next, { replace: true }); } function openCreate(provider?: Provider) { const selected = provider ?? (type === "slack" || type === "granola" || type === "github" || type === "clips" || type === "manual" || type === "generic" ? (type as Provider) : "slack"); setEditingSource(null); setForm(defaultForm(selected, t)); setSetupOpen(true); } function openEdit(source: BrainSource) { setEditingSource(source); setForm(formFromSource(source)); setSetupOpen(true); } function openCaptureReview(source: BrainSource) { setCaptureStatus("queued"); setShowCapturePreview(false); setSelectedCaptureIds(new Set()); setBulkResult(null); const next = new URLSearchParams(params); next.set("sourceId", source.id); setParams(next, { replace: true }); } function closeCaptureReview() { const next = new URLSearchParams(params); next.delete("sourceId"); setParams(next, { replace: true }); setReviewSource(null); setSelectedCaptureIds(new Set()); setBulkResult(null); } function updateForm(patch: Partial) { setForm((current) => ({ ...current, ...patch })); } function closeIngestHandoff() { setIngestHandoff(null); setCopiedHandoffField(null); } async function copyIngestHandoffValue(value: string, field: string) { await navigator.clipboard.writeText(value); setCopiedHandoffField(field); } async function submitSource() { const config = buildConfig(form); if (editingSource) { await updateSource.mutateAsync({ id: editingSource.id, title: form.title.trim() || defaultTitle(form.provider, t), status: form.autoSync || sourceEnabled(editingSource) ? "active" : "paused", config, }); } else { const result = await createSource.mutateAsync({ title: form.title.trim() || defaultTitle(form.provider, t), provider: form.provider, visibility: "org", config, sourceKey: form.sourceKey.trim() || undefined, }); const handoff = createOneTimeIngestHandoff({ origin: window.location.origin, provider: form.provider, result, sourceKey: form.sourceKey, }); if (handoff) setIngestHandoff(handoff); } setSetupOpen(false); } async function rotateIngestToken(source: BrainSource) { const sourceKey = ingestSourceKey(source); if (!sourceKey) return; const result = await rotateSourceIngestToken.mutateAsync({ sourceId: source.id, }); const handoff = createOneTimeIngestHandoff({ origin: window.location.origin, provider: source.provider ?? "", result, sourceKey, }); if (handoff) setIngestHandoff(handoff); } function toggleCaptureSelection(captureId: string, checked: boolean) { setSelectedCaptureIds((current) => { const next = new Set(current); if (checked) next.add(captureId); else next.delete(captureId); return next; }); } function toggleAllQueueableCaptures() { setSelectedCaptureIds((current) => { const next = new Set(current); if (allQueueableSelected) { queueableCaptures.forEach((capture) => next.delete(capture.id)); } else { queueableCaptures.forEach((capture) => next.add(capture.id)); } return next; }); } async function queueSelectedCaptures() { if (!selectedQueueableIds.length) return; const result = await enqueueCapturesDistillation.mutateAsync({ captureIds: selectedQueueableIds, priority: 60, }); setBulkResult(result); setSelectedCaptureIds(new Set()); } return (
} />
{sourcesQuery.isLoading ? (
) : visibleSources.length ? (
{visibleSources.map((source) => ( openCaptureReview(source)} onRotateIngestToken={ (source.provider === "clips" || source.provider === "generic") && ingestSourceKey(source) ? () => void rotateIngestToken(source) : undefined } onSync={() => syncSource.mutate({ sourceId: source.id })} onTune={() => openEdit(source)} /> ))}
) : (
)} {sourcesQuery.isError || connectionProvidersQuery.isError || updateSource.isError || createSource.isError || rotateSourceIngestToken.isError || syncSource.isError || syncDueSources.isError || enqueueCapturesDistillation.isError ? (
) : null}
{t("sources.advancedTitle")} {t("sources.advancedDescription")}
{ setAdvancedOpen(false); openCreate(provider); }} />
{ if (!open) closeCaptureReview(); }} > {t("sources.reviewRawCaptures")} {reviewSource ? t("sources.captureInventoryDescription", { source: sourceName(reviewSource), }) : t("sources.reviewRawCapturesDescription")}
{(captures.length || bulkResult) && (

{t("sources.batchDistillation")}

{t("sources.batchDistillationDescription")}

{selectedCaptureIds.size ? ( ) : null}
{t("sources.selectedCount", { count: selectedQueueableIds.length.toLocaleString(), })} {t("sources.queueableCount", { count: queueableCaptures.length.toLocaleString(), })} {bulkResult ? ( {t("sources.bulkResult", { queued: bulkResult.queued.toLocaleString(), existing: bulkResult.existing.toLocaleString(), errors: bulkResult.errors.toLocaleString(), })} ) : null}
)} {capturesQuery.isLoading ? ( ) : capturesQuery.isError ? ( ) : (capturesQuery.data?.captures ?? []).length ? (
{captures.map((capture) => { const queue = capture.distillationQueue; const queueIsActive = queue?.status === "queued" || queue?.status === "processing"; const canQueue = captureCanQueue(capture); const isMutating = enqueueDistillation.isPending || enqueueCapturesDistillation.isPending || markCaptureDistilled.isPending; const selected = selectedCaptureIds.has(capture.id); return (
toggleCaptureSelection( capture.id, event.target.checked, ) } />
{capture.kind} {shortDate(capture.capturedAt) ?? capture.capturedAt}

{capture.title}

{capture.preview ? (

{capture.preview}

) : (

{t("sources.rawContentHidden")}

)} {queue ? (
{t("sources.distillation")}{" "} {queueStatusLabel(queue.status, t)} {queue.attempts ? ( {queue.attempts}{" "} {queue.attempts === 1 ? t("sources.attempt") : t("sources.attempts")} ) : null} {queue.runAfter ? ( {t("sources.nextCheck")}{" "} {shortDate(queue.runAfter) ?? queue.runAfter} ) : null}
{queue.error ? (

{queue.error}

) : queueIsActive ? (

{t("sources.waitingForWorker")}

) : null}
) : null}
{capture.sourceUrl ? ( ) : null}
); })}
) : ( )}
{ if (!open) closeIngestHandoff(); }} > {ingestHandoff ? ( {t("sources.connectIngestSource", { source: ingestHandoff.source.title, })} {t("sources.ingestHandoffDescription")}
{[ [t("sources.endpoint"), ingestHandoff.endpoint, "endpoint"], [t("sources.sourceKey"), ingestHandoff.sourceKey, "source-key"], [ t("sources.ingestToken"), ingestHandoff.ingestToken, "ingest-token", ], ].map(([label, value, field]) => (
))}
{t("sources.ingestTokenSecurity")}
) : null}
{editingSource ? t("sources.tuneSource") : t("sources.addSource")} {t("sources.setupDescription")}
updateForm({ title: event.target.value })} />
{supportsWorkspaceConnectionBinding(form.provider) && (

{selectedWorkspaceConnection ? t("sources.boundConnectionDescription", { connection: selectedWorkspaceConnection.label, }) : formWorkspaceConnections.length ? t("sources.pickGrantedConnection") : t("sources.grantConnectionBeforePinning")}

)} {form.provider === "slack" && (

{t("sources.slackDiscoveryMode")} {" "} — {t("sources.slackDiscoveryModeDescription")}

{t("sources.slackExclusions")}

{t("sources.slackManualInvite")}

{t("sources.sensitivityPreviewDescription")}

{t("sources.slackAccessRules")}

{t("sources.slackAccessRuleIds")}

{t("sources.slackAccessRuleScopes")}