diff --git a/surfsense_backend/app/routes/composio_routes.py b/surfsense_backend/app/routes/composio_routes.py
index 5ad2266b7..9e9b59f82 100644
--- a/surfsense_backend/app/routes/composio_routes.py
+++ b/surfsense_backend/app/routes/composio_routes.py
@@ -344,13 +344,16 @@ async def composio_callback(
try:
# Generate a unique, user-friendly connector name
- connector_name = await generate_unique_connector_name(
+ # Pass just toolkit_name (without "(Composio)") to avoid redundancy
+ base_name = await generate_unique_connector_name(
session,
connector_type,
space_id,
user_id,
- f"{toolkit_name} (Composio)",
+ toolkit_name,
)
+ # Append "(Composio)" suffix for identification
+ connector_name = f"{base_name} (Composio)"
db_connector = SearchSourceConnector(
name=connector_name,
diff --git a/surfsense_web/components/assistant-ui/connector-popup.tsx b/surfsense_web/components/assistant-ui/connector-popup.tsx
index a04e2a9fd..1ec8fad73 100644
--- a/surfsense_web/components/assistant-ui/connector-popup.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup.tsx
@@ -7,7 +7,7 @@ import type { FC } from "react";
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
-import { Dialog, DialogContent } from "@/components/ui/dialog";
+import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
import { Tabs, TabsContent } from "@/components/ui/tabs";
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
import { useConnectorsElectric } from "@/hooks/use-connectors-electric";
@@ -185,6 +185,7 @@ export const ConnectorIndicator: FC = () => {
+ Manage Connectors
{/* YouTube Crawler View - shown when adding YouTube videos */}
{isYouTubeView && searchSpaceId ? (
diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-calendar-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-calendar-config.tsx
index 6e7a06073..ce5133a9d 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-calendar-config.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-calendar-config.tsx
@@ -1,17 +1,6 @@
"use client";
-import { Calendar, Clock } from "lucide-react";
import type { FC } from "react";
-import { useEffect, useState } from "react";
-import { Label } from "@/components/ui/label";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select";
-import { Switch } from "@/components/ui/switch";
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
interface ComposioCalendarConfigProps {
@@ -20,201 +9,7 @@ interface ComposioCalendarConfigProps {
onNameChange?: (name: string) => void;
}
-interface CalendarIndexingOptions {
- max_events: number;
- include_recurring: boolean;
- include_past_events: boolean;
- days_ahead: number;
-}
-
-const DEFAULT_CALENDAR_OPTIONS: CalendarIndexingOptions = {
- max_events: 500,
- include_recurring: true,
- include_past_events: true,
- days_ahead: 365,
-};
-
-export const ComposioCalendarConfig: FC = ({ connector, onConfigChange }) => {
- const isIndexable = connector.config?.is_indexable as boolean;
-
- // Initialize with existing options from connector config
- const existingOptions =
- (connector.config?.calendar_options as CalendarIndexingOptions | undefined) || DEFAULT_CALENDAR_OPTIONS;
-
- const [calendarOptions, setCalendarOptions] = useState(existingOptions);
-
- // Update options when connector config changes
- useEffect(() => {
- const options =
- (connector.config?.calendar_options as CalendarIndexingOptions | undefined) ||
- DEFAULT_CALENDAR_OPTIONS;
- setCalendarOptions(options);
- }, [connector.config]);
-
- const updateConfig = (options: CalendarIndexingOptions) => {
- if (onConfigChange) {
- onConfigChange({
- ...connector.config,
- calendar_options: options,
- });
- }
- };
-
- const handleOptionChange = (key: keyof CalendarIndexingOptions, value: number | boolean) => {
- const newOptions = { ...calendarOptions, [key]: value };
- setCalendarOptions(newOptions);
- updateConfig(newOptions);
- };
-
- // Only show configuration if the connector is indexable
- if (!isIndexable) {
- return ;
- }
-
- return (
-
- {/* Calendar Indexing Options */}
-
-
-
-
-
Calendar Indexing Options
-
-
- Configure how events are indexed from your Google Calendar.
-
-
-
- {/* Max events to index */}
-
-
-
-
-
- Maximum number of events to index per sync
-
-
-
-
-
-
- {/* Days ahead */}
-
-
-
-
-
-
-
-
- How far ahead to index future events
-
-
-
-
-
-
- {/* Include recurring events toggle */}
-
-
-
-
- Index individual instances of recurring events
-
-
-
- handleOptionChange("include_recurring", checked)
- }
- />
-
-
- {/* Include past events toggle */}
-
-
-
-
- Index events from before the selected date range
-
-
-
- handleOptionChange("include_past_events", checked)
- }
- />
-
-
-
- );
+export const ComposioCalendarConfig: FC = () => {
+ return ;
};
diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-drive-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-drive-config.tsx
index 755b91a5a..0ab0869ff 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-drive-config.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-drive-config.tsx
@@ -1,6 +1,6 @@
"use client";
-import { File, FileSpreadsheet, FileText, FolderClosed, Image, Presentation } from "lucide-react";
+import { File, FileSpreadsheet, FileText, FolderClosed, Image, Presentation, X } from "lucide-react";
import type { FC } from "react";
import { useEffect, useState } from "react";
import { ComposioDriveFolderTree } from "@/components/connectors/composio-drive-folder-tree";
@@ -143,6 +143,18 @@ export const ComposioDriveConfig: FC = ({ connector, o
updateConfig(selectedFolders, selectedFiles, newOptions);
};
+ const handleRemoveFolder = (folderId: string) => {
+ const newFolders = selectedFolders.filter((folder) => folder.id !== folderId);
+ setSelectedFolders(newFolders);
+ updateConfig(newFolders, selectedFiles, indexingOptions);
+ };
+
+ const handleRemoveFile = (fileId: string) => {
+ const newFiles = selectedFiles.filter((file) => file.id !== fileId);
+ setSelectedFiles(newFiles);
+ updateConfig(selectedFolders, newFiles, indexingOptions);
+ };
+
const totalSelected = selectedFolders.length + selectedFiles.length;
// Only show configuration if the connector is indexable
@@ -176,29 +188,45 @@ export const ComposioDriveConfig: FC = ({ connector, o
`${selectedFiles.length} file${selectedFiles.length > 1 ? "s" : ""}`
);
}
- return parts.length > 0 ? `(${parts.join(" ")})` : "";
+ return parts.length > 0 ? `(${parts.join(", ")})` : "";
})()}
{selectedFolders.map((folder) => (
-
- {folder.name}
-
+
{folder.name}
+
+
))}
{selectedFiles.map((file) => (
-
{getFileIconFromName(file.name)}
- {file.name}
-
+ {file.name}
+
+
))}
diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-gmail-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-gmail-config.tsx
index 963753ab3..4664e3e64 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-gmail-config.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/composio-gmail-config.tsx
@@ -1,17 +1,6 @@
"use client";
-import { Mail, Tag } from "lucide-react";
import type { FC } from "react";
-import { useEffect, useState } from "react";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select";
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
interface ComposioGmailConfigProps {
@@ -20,155 +9,7 @@ interface ComposioGmailConfigProps {
onNameChange?: (name: string) => void;
}
-interface GmailIndexingOptions {
- max_emails: number;
- label_filter: string;
- search_query: string;
-}
-
-const DEFAULT_GMAIL_OPTIONS: GmailIndexingOptions = {
- max_emails: 500,
- label_filter: "",
- search_query: "",
-};
-
-export const ComposioGmailConfig: FC = ({ connector, onConfigChange }) => {
- const isIndexable = connector.config?.is_indexable as boolean;
-
- // Initialize with existing options from connector config
- const existingOptions =
- (connector.config?.gmail_options as GmailIndexingOptions | undefined) || DEFAULT_GMAIL_OPTIONS;
-
- const [gmailOptions, setGmailOptions] = useState(existingOptions);
-
- // Update options when connector config changes
- useEffect(() => {
- const options =
- (connector.config?.gmail_options as GmailIndexingOptions | undefined) ||
- DEFAULT_GMAIL_OPTIONS;
- setGmailOptions(options);
- }, [connector.config]);
-
- const updateConfig = (options: GmailIndexingOptions) => {
- if (onConfigChange) {
- onConfigChange({
- ...connector.config,
- gmail_options: options,
- });
- }
- };
-
- const handleOptionChange = (key: keyof GmailIndexingOptions, value: number | string) => {
- const newOptions = { ...gmailOptions, [key]: value };
- setGmailOptions(newOptions);
- updateConfig(newOptions);
- };
-
- // Only show configuration if the connector is indexable
- if (!isIndexable) {
- return ;
- }
-
- return (
-
- {/* Gmail Indexing Options */}
-
-
-
-
-
Gmail Indexing Options
-
-
- Configure how emails are indexed from your Gmail account.
-
-
-
- {/* Max emails to index */}
-
-
-
-
-
- Maximum number of emails to index per sync
-
-
-
-
-
-
- {/* Label filter */}
-
-
-
-
-
-
-
- Only index emails with this label (e.g., "INBOX", "IMPORTANT", "work")
-
-
-
handleOptionChange("label_filter", e.target.value)}
- placeholder="Enter label name..."
- className="bg-slate-400/5 dark:bg-slate-400/5 border-slate-400/20 text-xs sm:text-sm"
- />
-
-
- {/* Search query */}
-
-
-
-
- Gmail search query to filter emails (e.g., "from:boss@company.com", "has:attachment")
-
-
-
handleOptionChange("search_query", e.target.value)}
- placeholder="Enter Gmail search query..."
- className="bg-slate-400/5 dark:bg-slate-400/5 border-slate-400/20 text-xs sm:text-sm"
- />
-
-
-
- );
+export const ComposioGmailConfig: FC = () => {
+ return ;
};
diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/google-drive-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/google-drive-config.tsx
index 17f4a49a5..b6cfb39ae 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/google-drive-config.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/google-drive-config.tsx
@@ -1,6 +1,6 @@
"use client";
-import { File, FileSpreadsheet, FileText, FolderClosed, Image, Presentation } from "lucide-react";
+import { File, FileSpreadsheet, FileText, FolderClosed, Image, Presentation, X } from "lucide-react";
import type { FC } from "react";
import { useEffect, useState } from "react";
import { GoogleDriveFolderTree } from "@/components/connectors/google-drive-folder-tree";
@@ -135,6 +135,18 @@ export const GoogleDriveConfig: FC = ({ connector, onConfi
updateConfig(selectedFolders, selectedFiles, newOptions);
};
+ const handleRemoveFolder = (folderId: string) => {
+ const newFolders = selectedFolders.filter((folder) => folder.id !== folderId);
+ setSelectedFolders(newFolders);
+ updateConfig(newFolders, selectedFiles, indexingOptions);
+ };
+
+ const handleRemoveFile = (fileId: string) => {
+ const newFiles = selectedFiles.filter((file) => file.id !== fileId);
+ setSelectedFiles(newFiles);
+ updateConfig(selectedFolders, newFiles, indexingOptions);
+ };
+
const totalSelected = selectedFolders.length + selectedFiles.length;
return (
@@ -161,29 +173,45 @@ export const GoogleDriveConfig: FC = ({ connector, onConfi
if (selectedFiles.length > 0) {
parts.push(`${selectedFiles.length} file${selectedFiles.length > 1 ? "s" : ""}`);
}
- return parts.length > 0 ? `(${parts.join(" ")})` : "";
+ return parts.length > 0 ? `(${parts.join(", ")})` : "";
})()}
{selectedFolders.map((folder) => (
-
- {folder.name}
-
+
{folder.name}
+
+
))}
{selectedFiles.map((file) => (
-
{getFileIconFromName(file.name)}
- {file.name}
-
+ {file.name}
+
+
))}
diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/views/connector-edit-view.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/views/connector-edit-view.tsx
index 6b1a8c92b..8951336c5 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/views/connector-edit-view.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/views/connector-edit-view.tsx
@@ -9,6 +9,7 @@ import { cn } from "@/lib/utils";
import { DateRangeSelector } from "../../components/date-range-selector";
import { PeriodicSyncConfig } from "../../components/periodic-sync-config";
import { getConnectorConfigComponent } from "../index";
+import { getConnectorDisplayName } from "../../tabs/all-connectors-tab";
interface ConnectorEditViewProps {
connector: SearchSourceConnector;
@@ -151,7 +152,7 @@ export const ConnectorEditView: FC = ({
- {connector.name}
+ {getConnectorDisplayName(connector.name)}
Manage your connector settings and sync configuration
diff --git a/surfsense_web/components/assistant-ui/connector-popup/tabs/active-connectors-tab.tsx b/surfsense_web/components/assistant-ui/connector-popup/tabs/active-connectors-tab.tsx
index e45888bb1..2067ca9ad 100644
--- a/surfsense_web/components/assistant-ui/connector-popup/tabs/active-connectors-tab.tsx
+++ b/surfsense_web/components/assistant-ui/connector-popup/tabs/active-connectors-tab.tsx
@@ -15,6 +15,7 @@ import { connectorsApiService } from "@/lib/apis/connectors-api.service";
import { cn } from "@/lib/utils";
import { COMPOSIO_CONNECTORS, OAUTH_CONNECTORS } from "../constants/connector-constants";
import { getDocumentCountForConnector } from "../utils/connector-document-mapping";
+import { getConnectorDisplayName } from "./all-connectors-tab";
interface ActiveConnectorsTabProps {
searchQuery: string;
@@ -263,8 +264,8 @@ export const ActiveConnectorsTab: FC = ({
-
- {connector.name}
+
+ {getConnectorDisplayName(connector.name)}
{isIndexing ? (