mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-01 20:03:30 +02:00
feat: add Composio connector types and enhance integration
- Introduced new enum values for Composio connectors: COMPOSIO_GOOGLE_DRIVE_CONNECTOR, COMPOSIO_GMAIL_CONNECTOR, and COMPOSIO_GOOGLE_CALENDAR_CONNECTOR. - Updated database migration to add these new enum values to the relevant types. - Refactored Composio integration logic to handle specific connector types, improving the management of connected accounts and indexing processes. - Enhanced frontend components to support the new Composio connector types, including updated UI elements and connector configuration handling. - Improved backend services to manage Composio connected accounts more effectively, including deletion and indexing tasks.
This commit is contained in:
parent
3a1fa25a6f
commit
be5715cfeb
19 changed files with 437 additions and 277 deletions
|
|
@ -188,8 +188,18 @@ export const ConnectorIndicator: FC = () => {
|
|||
searchSpaceId={searchSpaceId}
|
||||
connectedToolkits={
|
||||
(connectors || [])
|
||||
.filter((c: SearchSourceConnector) => c.connector_type === "COMPOSIO_CONNECTOR")
|
||||
.map((c: SearchSourceConnector) => c.config?.toolkit_id as string)
|
||||
.filter((c: SearchSourceConnector) =>
|
||||
c.connector_type === "COMPOSIO_GOOGLE_DRIVE_CONNECTOR" ||
|
||||
c.connector_type === "COMPOSIO_GMAIL_CONNECTOR" ||
|
||||
c.connector_type === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR"
|
||||
)
|
||||
.map((c: SearchSourceConnector) => {
|
||||
// Map connector type back to toolkit_id
|
||||
if (c.connector_type === "COMPOSIO_GOOGLE_DRIVE_CONNECTOR") return "googledrive";
|
||||
if (c.connector_type === "COMPOSIO_GMAIL_CONNECTOR") return "gmail";
|
||||
if (c.connector_type === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR") return "googlecalendar";
|
||||
return c.config?.toolkit_id as string;
|
||||
})
|
||||
.filter(Boolean)
|
||||
}
|
||||
onBack={handleBackFromComposio}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { ExternalLink, Info, Zap } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import type { FC } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
||||
|
|
@ -13,92 +11,13 @@ interface ComposioConfigProps {
|
|||
onNameChange?: (name: string) => void;
|
||||
}
|
||||
|
||||
// Get toolkit display info
|
||||
const getToolkitInfo = (toolkitId: string): { name: string; icon: string; description: string } => {
|
||||
switch (toolkitId) {
|
||||
case "googledrive":
|
||||
return {
|
||||
name: "Google Drive",
|
||||
icon: "/connectors/google-drive.svg",
|
||||
description: "Files and documents from Google Drive",
|
||||
};
|
||||
case "gmail":
|
||||
return {
|
||||
name: "Gmail",
|
||||
icon: "/connectors/google-gmail.svg",
|
||||
description: "Emails from Gmail",
|
||||
};
|
||||
case "googlecalendar":
|
||||
return {
|
||||
name: "Google Calendar",
|
||||
icon: "/connectors/google-calendar.svg",
|
||||
description: "Events from Google Calendar",
|
||||
};
|
||||
case "slack":
|
||||
return {
|
||||
name: "Slack",
|
||||
icon: "/connectors/slack.svg",
|
||||
description: "Messages from Slack",
|
||||
};
|
||||
case "notion":
|
||||
return {
|
||||
name: "Notion",
|
||||
icon: "/connectors/notion.svg",
|
||||
description: "Pages from Notion",
|
||||
};
|
||||
case "github":
|
||||
return {
|
||||
name: "GitHub",
|
||||
icon: "/connectors/github.svg",
|
||||
description: "Repositories from GitHub",
|
||||
};
|
||||
default:
|
||||
return {
|
||||
name: toolkitId,
|
||||
icon: "/connectors/composio.svg",
|
||||
description: "Connected via Composio",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const ComposioConfig: FC<ComposioConfigProps> = ({ connector }) => {
|
||||
const toolkitId = connector.config?.toolkit_id as string;
|
||||
const toolkitName = connector.config?.toolkit_name as string;
|
||||
const isIndexable = connector.config?.is_indexable as boolean;
|
||||
const composioAccountId = connector.config?.composio_connected_account_id as string;
|
||||
|
||||
const toolkitInfo = getToolkitInfo(toolkitId);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Toolkit Info Card */}
|
||||
<div className="rounded-xl border border-violet-500/20 bg-gradient-to-br from-violet-500/5 to-purple-500/5 p-4">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-gradient-to-br from-violet-500/10 to-purple-500/10 border border-violet-500/20 shrink-0">
|
||||
<Image
|
||||
src={toolkitInfo.icon}
|
||||
alt={toolkitInfo.name}
|
||||
width={24}
|
||||
height={24}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<h3 className="text-sm font-semibold">{toolkitName || toolkitInfo.name}</h3>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-[10px] px-1.5 py-0 h-5 bg-violet-500/10 text-violet-600 dark:text-violet-400 border-violet-500/20"
|
||||
>
|
||||
<Zap className="size-3 mr-0.5" />
|
||||
Composio
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">{toolkitInfo.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Connection Details */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||
|
|
@ -133,28 +52,6 @@ export const ComposioConfig: FC<ComposioConfigProps> = ({ connector }) => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Info Banner */}
|
||||
<div className="rounded-lg border border-border/50 bg-muted/30 p-3">
|
||||
<div className="flex items-start gap-2.5">
|
||||
<Info className="size-4 text-muted-foreground shrink-0 mt-0.5" />
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||
This connection uses Composio's managed OAuth, which means you don't need to
|
||||
wait for app verification. Your data is securely accessed through Composio.
|
||||
</p>
|
||||
<a
|
||||
href="https://composio.dev"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-xs text-violet-600 dark:text-violet-400 hover:underline"
|
||||
>
|
||||
Learn more about Composio
|
||||
<ExternalLink className="size-3" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -74,7 +74,9 @@ export function getConnectorConfigComponent(
|
|||
return CirclebackConfig;
|
||||
case "MCP_CONNECTOR":
|
||||
return MCPConfig;
|
||||
case "COMPOSIO_CONNECTOR":
|
||||
case "COMPOSIO_GOOGLE_DRIVE_CONNECTOR":
|
||||
case "COMPOSIO_GMAIL_CONNECTOR":
|
||||
case "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR":
|
||||
return ComposioConfig;
|
||||
// OAuth connectors (Gmail, Calendar, Airtable, Notion) and others don't need special config UI
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -168,14 +168,28 @@ export const OTHER_CONNECTORS = [
|
|||
},
|
||||
] as const;
|
||||
|
||||
// Composio Connector (Single entry that opens toolkit selector)
|
||||
// Composio Connectors - Individual entries for each supported toolkit
|
||||
export const COMPOSIO_CONNECTORS = [
|
||||
{
|
||||
id: "composio-connector",
|
||||
title: "Composio",
|
||||
description: "Connect 100+ apps via Composio (Google, Slack, Notion, etc.)",
|
||||
connectorType: EnumConnectorName.COMPOSIO_CONNECTOR,
|
||||
// No authEndpoint - handled via toolkit selector view
|
||||
id: "composio-googledrive",
|
||||
title: "Google Drive",
|
||||
description: "Search your Drive files via Composio",
|
||||
connectorType: EnumConnectorName.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
|
||||
authEndpoint: "/api/v1/auth/composio/connector/add/?toolkit_id=googledrive",
|
||||
},
|
||||
{
|
||||
id: "composio-gmail",
|
||||
title: "Gmail",
|
||||
description: "Search through your emails via Composio",
|
||||
connectorType: EnumConnectorName.COMPOSIO_GMAIL_CONNECTOR,
|
||||
authEndpoint: "/api/v1/auth/composio/connector/add/?toolkit_id=gmail",
|
||||
},
|
||||
{
|
||||
id: "composio-googlecalendar",
|
||||
title: "Google Calendar",
|
||||
description: "Search through your events via Composio",
|
||||
connectorType: EnumConnectorName.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
|
||||
authEndpoint: "/api/v1/auth/composio/connector/add/?toolkit_id=googlecalendar",
|
||||
},
|
||||
] as const;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { searchSourceConnectorTypeEnum } from "@/contracts/types/connector.types
|
|||
export const connectorPopupQueryParamsSchema = z.object({
|
||||
modal: z.enum(["connectors"]).optional(),
|
||||
tab: z.enum(["all", "active"]).optional(),
|
||||
view: z.enum(["configure", "edit", "connect", "youtube", "accounts", "mcp-list"]).optional(),
|
||||
view: z.enum(["configure", "edit", "connect", "youtube", "accounts", "mcp-list", "composio"]).optional(),
|
||||
connector: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
connectorType: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
import type { IndexingConfigState } from "../constants/connector-constants";
|
||||
import { OAUTH_CONNECTORS, OTHER_CONNECTORS } from "../constants/connector-constants";
|
||||
import { COMPOSIO_CONNECTORS, OAUTH_CONNECTORS, OTHER_CONNECTORS } from "../constants/connector-constants";
|
||||
import {
|
||||
dateRangeSchema,
|
||||
frequencyMinutesSchema,
|
||||
|
|
@ -176,15 +176,24 @@ export const useConnectorDialog = () => {
|
|||
}
|
||||
|
||||
// Handle accounts view
|
||||
if (params.view === "accounts" && params.connectorType && !viewingAccountsType) {
|
||||
const oauthConnector = OAUTH_CONNECTORS.find(
|
||||
(c) => c.connectorType === params.connectorType
|
||||
);
|
||||
if (oauthConnector) {
|
||||
setViewingAccountsType({
|
||||
connectorType: oauthConnector.connectorType,
|
||||
connectorTitle: oauthConnector.title,
|
||||
});
|
||||
if (params.view === "accounts" && params.connectorType) {
|
||||
// Update state if not set, or if connectorType has changed
|
||||
const needsUpdate = !viewingAccountsType ||
|
||||
viewingAccountsType.connectorType !== params.connectorType;
|
||||
|
||||
if (needsUpdate) {
|
||||
// Check both OAUTH_CONNECTORS and COMPOSIO_CONNECTORS
|
||||
const oauthConnector = OAUTH_CONNECTORS.find(
|
||||
(c) => c.connectorType === params.connectorType
|
||||
) || COMPOSIO_CONNECTORS.find(
|
||||
(c) => c.connectorType === params.connectorType
|
||||
);
|
||||
if (oauthConnector) {
|
||||
setViewingAccountsType({
|
||||
connectorType: oauthConnector.connectorType,
|
||||
connectorTitle: oauthConnector.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +302,8 @@ export const useConnectorDialog = () => {
|
|||
indexingConfig,
|
||||
connectingConnectorType,
|
||||
viewingAccountsType,
|
||||
viewingMCPList,
|
||||
viewingComposio,
|
||||
]);
|
||||
|
||||
// Detect OAuth success / Failure and transition to config view
|
||||
|
|
@ -389,15 +400,19 @@ export const useConnectorDialog = () => {
|
|||
|
||||
// Handle OAuth connection
|
||||
const handleConnectOAuth = useCallback(
|
||||
async (connector: (typeof OAUTH_CONNECTORS)[number]) => {
|
||||
async (connector: (typeof OAUTH_CONNECTORS)[number] | (typeof COMPOSIO_CONNECTORS)[number]) => {
|
||||
if (!searchSpaceId || !connector.authEndpoint) return;
|
||||
|
||||
// Set connecting state immediately to disable button and show spinner
|
||||
setConnectingId(connector.id);
|
||||
|
||||
try {
|
||||
// Check if authEndpoint already has query parameters
|
||||
const separator = connector.authEndpoint.includes("?") ? "&" : "?";
|
||||
const url = `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${connector.authEndpoint}${separator}space_id=${searchSpaceId}`;
|
||||
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${connector.authEndpoint}?space_id=${searchSpaceId}`,
|
||||
url,
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
|
|
@ -799,23 +814,19 @@ export const useConnectorDialog = () => {
|
|||
|
||||
// Handle viewing accounts list for OAuth connector type
|
||||
const handleViewAccountsList = useCallback(
|
||||
(connectorType: string, connectorTitle: string) => {
|
||||
(connectorType: string, _connectorTitle?: string) => {
|
||||
if (!searchSpaceId) return;
|
||||
|
||||
setViewingAccountsType({
|
||||
connectorType,
|
||||
connectorTitle,
|
||||
});
|
||||
|
||||
// Update URL to show accounts view, preserving current tab
|
||||
// The useEffect will handle setting viewingAccountsType based on URL params
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("modal", "connectors");
|
||||
url.searchParams.set("view", "accounts");
|
||||
url.searchParams.set("connectorType", connectorType);
|
||||
// Keep the current tab in URL so we can go back to it
|
||||
window.history.pushState({ modal: true }, "", url.toString());
|
||||
router.replace(url.pathname + url.search, { scroll: false });
|
||||
},
|
||||
[searchSpaceId]
|
||||
[searchSpaceId, router]
|
||||
);
|
||||
|
||||
// Handle going back from accounts list view
|
||||
|
|
@ -839,8 +850,8 @@ export const useConnectorDialog = () => {
|
|||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("modal", "connectors");
|
||||
url.searchParams.set("view", "mcp-list");
|
||||
window.history.pushState({ modal: true }, "", url.toString());
|
||||
}, [searchSpaceId]);
|
||||
router.replace(url.pathname + url.search, { scroll: false });
|
||||
}, [searchSpaceId, router]);
|
||||
|
||||
// Handle going back from MCP list view
|
||||
const handleBackFromMCPList = useCallback(() => {
|
||||
|
|
@ -871,8 +882,8 @@ export const useConnectorDialog = () => {
|
|||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("modal", "connectors");
|
||||
url.searchParams.set("view", "composio");
|
||||
window.history.pushState({ modal: true }, "", url.toString());
|
||||
}, [searchSpaceId]);
|
||||
router.replace(url.pathname + url.search, { scroll: false });
|
||||
}, [searchSpaceId, router]);
|
||||
|
||||
// Handle going back from Composio view
|
||||
const handleBackFromComposio = useCallback(() => {
|
||||
|
|
@ -1423,7 +1434,7 @@ export const useConnectorDialog = () => {
|
|||
setIsDisconnecting(false);
|
||||
}
|
||||
},
|
||||
[editingConnector, searchSpaceId, deleteConnector, router]
|
||||
[editingConnector, searchSpaceId, deleteConnector, router, cameFromMCPList]
|
||||
);
|
||||
|
||||
// Handle quick index (index without date picker, uses backend defaults)
|
||||
|
|
@ -1579,6 +1590,7 @@ export const useConnectorDialog = () => {
|
|||
viewingAccountsType,
|
||||
viewingMCPList,
|
||||
viewingComposio,
|
||||
connectingComposioToolkit,
|
||||
|
||||
// Setters
|
||||
setSearchQuery,
|
||||
|
|
@ -1616,8 +1628,6 @@ export const useConnectorDialog = () => {
|
|||
setIndexingConnectorConfig,
|
||||
|
||||
// Composio
|
||||
viewingComposio,
|
||||
connectingComposioToolkit,
|
||||
handleOpenComposio,
|
||||
handleBackFromComposio,
|
||||
handleConnectComposioToolkit,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import type { FC } from "react";
|
|||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
||||
import { ConnectorCard } from "../components/connector-card";
|
||||
import { ComposioConnectorCard } from "../components/composio-connector-card";
|
||||
import { CRAWLERS, OAUTH_CONNECTORS, OTHER_CONNECTORS, COMPOSIO_CONNECTORS } from "../constants/connector-constants";
|
||||
import { getDocumentCountForConnector } from "../utils/connector-document-mapping";
|
||||
|
||||
|
|
@ -29,13 +28,12 @@ interface AllConnectorsTabProps {
|
|||
allConnectors: SearchSourceConnector[] | undefined;
|
||||
documentTypeCounts?: Record<string, number>;
|
||||
indexingConnectorIds?: Set<number>;
|
||||
onConnectOAuth: (connector: (typeof OAUTH_CONNECTORS)[number]) => void;
|
||||
onConnectOAuth: (connector: (typeof OAUTH_CONNECTORS)[number] | (typeof COMPOSIO_CONNECTORS)[number]) => void;
|
||||
onConnectNonOAuth?: (connectorType: string) => void;
|
||||
onCreateWebcrawler?: () => void;
|
||||
onCreateYouTubeCrawler?: () => void;
|
||||
onManage?: (connector: SearchSourceConnector) => void;
|
||||
onViewAccountsList?: (connectorType: string, connectorTitle: string) => void;
|
||||
onOpenComposio?: () => void;
|
||||
}
|
||||
|
||||
export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
||||
|
|
@ -51,7 +49,6 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
|||
onCreateYouTubeCrawler,
|
||||
onManage,
|
||||
onViewAccountsList,
|
||||
onOpenComposio,
|
||||
}) => {
|
||||
// Filter connectors based on search
|
||||
const filteredOAuth = OAUTH_CONNECTORS.filter(
|
||||
|
|
@ -79,23 +76,16 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
|||
c.description.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// Count Composio connectors
|
||||
const composioConnectorCount = allConnectors
|
||||
? allConnectors.filter(
|
||||
(c: SearchSourceConnector) => c.connector_type === EnumConnectorName.COMPOSIO_CONNECTOR
|
||||
).length
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
{/* Quick Connect */}
|
||||
{filteredOAuth.length > 0 && (
|
||||
{/* Managed OAuth (Composio Integrations) */}
|
||||
{filteredComposio.length > 0 && (
|
||||
<section>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<h3 className="text-sm font-semibold text-muted-foreground">Quick Connect</h3>
|
||||
<h3 className="text-sm font-semibold text-muted-foreground">Managed OAuth</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{filteredOAuth.map((connector) => {
|
||||
{filteredComposio.map((connector) => {
|
||||
const isConnected = connectedTypes.has(connector.connectorType);
|
||||
const isConnecting = connectingId === connector.id;
|
||||
|
||||
|
|
@ -109,17 +99,6 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
|||
|
||||
const accountCount = typeConnectors.length;
|
||||
|
||||
// Get the most recent last_indexed_at across all accounts
|
||||
const mostRecentLastIndexed = typeConnectors.reduce<string | undefined>(
|
||||
(latest, c) => {
|
||||
if (!c.last_indexed_at) return latest;
|
||||
if (!latest) return c.last_indexed_at;
|
||||
return new Date(c.last_indexed_at) > new Date(latest)
|
||||
? c.last_indexed_at
|
||||
: latest;
|
||||
},
|
||||
undefined
|
||||
);
|
||||
|
||||
const documentCount = getDocumentCountForConnector(
|
||||
connector.connectorType,
|
||||
|
|
@ -154,26 +133,57 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
|||
</section>
|
||||
)}
|
||||
|
||||
{/* Composio Integrations */}
|
||||
{filteredComposio.length > 0 && onOpenComposio && (
|
||||
{/* Quick Connect */}
|
||||
{filteredOAuth.length > 0 && (
|
||||
<section>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<h3 className="text-sm font-semibold text-muted-foreground">Managed OAuth</h3>
|
||||
<span className="text-[10px] px-1.5 py-0.5 rounded-full bg-violet-500/10 text-violet-600 dark:text-violet-400 border border-violet-500/20 font-medium">
|
||||
No verification needed
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold text-muted-foreground">Quick Connect</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{filteredComposio.map((connector) => (
|
||||
<ComposioConnectorCard
|
||||
key={connector.id}
|
||||
id={connector.id}
|
||||
title={connector.title}
|
||||
description={connector.description}
|
||||
connectorCount={composioConnectorCount}
|
||||
onConnect={onOpenComposio}
|
||||
/>
|
||||
))}
|
||||
{filteredOAuth.map((connector) => {
|
||||
const isConnected = connectedTypes.has(connector.connectorType);
|
||||
const isConnecting = connectingId === connector.id;
|
||||
|
||||
// Find all connectors of this type
|
||||
const typeConnectors =
|
||||
isConnected && allConnectors
|
||||
? allConnectors.filter(
|
||||
(c: SearchSourceConnector) => c.connector_type === connector.connectorType
|
||||
)
|
||||
: [];
|
||||
|
||||
const accountCount = typeConnectors.length;
|
||||
|
||||
|
||||
const documentCount = getDocumentCountForConnector(
|
||||
connector.connectorType,
|
||||
documentTypeCounts
|
||||
);
|
||||
|
||||
// Check if any account is currently indexing
|
||||
const isIndexing = typeConnectors.some((c) => indexingConnectorIds?.has(c.id));
|
||||
|
||||
return (
|
||||
<ConnectorCard
|
||||
key={connector.id}
|
||||
id={connector.id}
|
||||
title={connector.title}
|
||||
description={connector.description}
|
||||
connectorType={connector.connectorType}
|
||||
isConnected={isConnected}
|
||||
isConnecting={isConnecting}
|
||||
documentCount={documentCount}
|
||||
accountCount={accountCount}
|
||||
isIndexing={isIndexing}
|
||||
onConnect={() => onConnectOAuth(connector)}
|
||||
onManage={
|
||||
isConnected && onViewAccountsList
|
||||
? () => onViewAccountsList(connector.connectorType, connector.title)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ export const CONNECTOR_TO_DOCUMENT_TYPE: Record<string, string> = {
|
|||
// Special mappings (connector type differs from document type)
|
||||
GOOGLE_DRIVE_CONNECTOR: "GOOGLE_DRIVE_FILE",
|
||||
WEBCRAWLER_CONNECTOR: "CRAWLED_URL",
|
||||
COMPOSIO_CONNECTOR: "COMPOSIO_CONNECTOR",
|
||||
// Composio connectors map to their own document types
|
||||
COMPOSIO_GOOGLE_DRIVE_CONNECTOR: "COMPOSIO_GOOGLE_DRIVE_CONNECTOR",
|
||||
COMPOSIO_GMAIL_CONNECTOR: "COMPOSIO_GMAIL_CONNECTOR",
|
||||
COMPOSIO_GOOGLE_CALENDAR_CONNECTOR: "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue