feat: Add Circleback connector integration

- Implement CirclebackConnectForm for user input and configuration
- Update connector benefits to include Circleback features
- Add CirclebackConfig component for webhook configuration
- Integrate Circleback into connector selection and management UI
- Update connector constants and document mappings for Circleback
This commit is contained in:
Anish Sarkar 2026-01-01 02:59:49 +05:30
parent 2373421212
commit e2f4f6c8e0
23 changed files with 370 additions and 296 deletions

View file

@ -0,0 +1,121 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { Info, Webhook } from "lucide-react";
import type { FC } from "react";
import { useRef } from "react";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { EnumConnectorName } from "@/contracts/enums/connector";
import type { ConnectFormProps } from "../index";
import { getConnectorBenefits } from "../connector-benefits";
const circlebackFormSchema = z.object({
name: z.string().min(3, {
message: "Connector name must be at least 3 characters.",
}),
});
type CirclebackFormValues = z.infer<typeof circlebackFormSchema>;
export const CirclebackConnectForm: FC<ConnectFormProps> = ({
onSubmit,
isSubmitting,
}) => {
const isSubmittingRef = useRef(false);
const form = useForm<CirclebackFormValues>({
resolver: zodResolver(circlebackFormSchema),
defaultValues: {
name: "Circleback Connector",
},
});
const handleSubmit = async (values: CirclebackFormValues) => {
// Prevent multiple submissions
if (isSubmittingRef.current || isSubmitting) {
return;
}
isSubmittingRef.current = true;
try {
await onSubmit({
name: values.name,
connector_type: EnumConnectorName.CIRCLEBACK_CONNECTOR,
config: {},
is_indexable: false,
last_indexed_at: null,
periodic_indexing_enabled: false,
indexing_frequency_minutes: null,
next_scheduled_at: null,
});
} finally {
isSubmittingRef.current = false;
}
};
return (
<div className="space-y-6 pb-6">
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3 flex items-center [&>svg]:relative [&>svg]:left-0 [&>svg]:top-0 [&>svg+div]:translate-y-0">
<Webhook className="h-3 w-3 sm:h-4 sm:w-4 shrink-0 ml-1" />
<div className="-ml-1">
<AlertTitle className="text-xs sm:text-sm">Webhook-Based Integration</AlertTitle>
<AlertDescription className="text-[10px] sm:text-xs !pl-0">
Circleback uses webhooks to automatically send meeting data. After connecting, you'll receive a webhook URL to configure in your Circleback settings.
</AlertDescription>
</div>
</Alert>
<div className="rounded-xl border border-border bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6 space-y-3 sm:space-y-4">
<Form {...form}>
<form id="circleback-connect-form" onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4 sm:space-y-6">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel className="text-xs sm:text-sm">Connector Name</FormLabel>
<FormControl>
<Input
placeholder="My Circleback Connector"
className="border-slate-400/20 focus-visible:border-slate-400/40"
disabled={isSubmitting}
{...field}
/>
</FormControl>
<FormDescription className="text-[10px] sm:text-xs">
A friendly name to identify this connector.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</div>
{/* What you get section */}
{getConnectorBenefits(EnumConnectorName.CIRCLEBACK_CONNECTOR) && (
<div className="rounded-xl border border-border bg-slate-400/5 dark:bg-white/5 px-3 sm:px-6 py-4 space-y-2">
<h4 className="text-xs sm:text-sm font-medium">What you get with Circleback:</h4>
<ul className="list-disc pl-5 text-[10px] sm:text-xs text-muted-foreground space-y-1">
{getConnectorBenefits(EnumConnectorName.CIRCLEBACK_CONNECTOR)?.map((benefit) => (
<li key={benefit}>{benefit}</li>
))}
</ul>
</div>
)}
</div>
);
};

View file

@ -101,6 +101,13 @@ export function getConnectorBenefits(connectorType: string): string[] | null {
"Keep your search results up-to-date with latest Luma content",
"Index your Luma events for enhanced search capabilities",
],
CIRCLEBACK_CONNECTOR: [
"Automatically receive meeting notes, transcripts, and action items",
"Access meeting details, attendees, and insights",
"Search through all your Circleback meeting records",
"Real-time updates via webhook integration",
"No manual indexing required - meetings are added automatically",
],
};
return benefits[connectorType] || null;

View file

@ -1,6 +1,7 @@
import type { FC } from "react";
import { BaiduSearchApiConnectForm } from "./components/baidu-search-api-connect-form";
import { BookStackConnectForm } from "./components/bookstack-connect-form";
import { CirclebackConnectForm } from "./components/circleback-connect-form";
import { ClickUpConnectForm } from "./components/clickup-connect-form";
import { ConfluenceConnectForm } from "./components/confluence-connect-form";
import { DiscordConnectForm } from "./components/discord-connect-form";
@ -74,6 +75,8 @@ export function getConnectFormComponent(
return ClickUpConnectForm;
case "LUMA_CONNECTOR":
return LumaConnectForm;
case "CIRCLEBACK_CONNECTOR":
return CirclebackConnectForm;
// Add other connector types here as needed
default:
return null;

View file

@ -0,0 +1,156 @@
"use client";
import { Copy, Webhook, Check } from "lucide-react";
import { useState, useEffect } from "react";
import type { FC } from "react";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import type { ConnectorConfigProps } from "../index";
import { authenticatedFetch } from "@/lib/auth-utils";
export interface CirclebackConfigProps extends ConnectorConfigProps {
onNameChange?: (name: string) => void;
}
export const CirclebackConfig: FC<CirclebackConfigProps> = ({
connector,
onNameChange,
}) => {
const [name, setName] = useState<string>(connector.name || "");
const [webhookUrl, setWebhookUrl] = useState<string>("");
const [webhookInfo, setWebhookInfo] = useState<{ webhook_url: string; search_space_id: number; method: string; content_type: string; description: string; note: string } | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [copied, setCopied] = useState(false);
// Update name when connector changes
useEffect(() => {
setName(connector.name || "");
}, [connector.name]);
// Fetch webhook info
useEffect(() => {
const fetchWebhookInfo = async () => {
if (!connector.search_space_id) return;
setIsLoading(true);
try {
const response = await authenticatedFetch(
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/webhooks/circleback/${connector.search_space_id}/info`
);
if (response.ok) {
const data = await response.json();
setWebhookInfo(data);
setWebhookUrl(data.webhook_url || "");
}
} catch (error) {
console.error("Failed to fetch webhook info:", error);
} finally {
setIsLoading(false);
}
};
fetchWebhookInfo();
}, [connector.search_space_id]);
const handleNameChange = (value: string) => {
setName(value);
if (onNameChange) {
onNameChange(value);
}
};
const handleCopyWebhookUrl = async () => {
if (webhookUrl) {
await navigator.clipboard.writeText(webhookUrl);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
return (
<div className="space-y-6">
{/* Connector Name */}
<div className="rounded-xl border border-border bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6 space-y-3 sm:space-y-4">
<div className="space-y-2">
<Label className="text-xs sm:text-sm">Connector Name</Label>
<Input
value={name}
onChange={(e) => handleNameChange(e.target.value)}
placeholder="My Circleback Connector"
className="border-slate-400/20 focus-visible:border-slate-400/40"
/>
<p className="text-[10px] sm:text-xs text-muted-foreground">
A friendly name to identify this connector.
</p>
</div>
</div>
{/* Webhook Configuration */}
<div className="rounded-xl border border-border bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6 space-y-3 sm:space-y-4">
<div className="space-y-1 sm:space-y-2">
<h3 className="font-medium text-sm sm:text-base flex items-center gap-2">
<Webhook className="h-4 w-4" />
Webhook Configuration
</h3>
</div>
{isLoading ? (
<p className="text-[10px] sm:text-xs text-muted-foreground">
Loading webhook information...
</p>
) : webhookUrl ? (
<div className="space-y-2">
<Label className="text-xs sm:text-sm">Webhook URL</Label>
<div className="flex gap-2">
<Input
value={webhookUrl}
readOnly
className="border-slate-400/20 focus-visible:border-slate-400/40 font-mono text-xs"
/>
<Button
type="button"
variant="outline"
size="sm"
onClick={handleCopyWebhookUrl}
className="shrink-0"
>
{copied ? (
<>
<Check className="h-4 w-4 mr-2" />
Copied!
</>
) : (
<>
<Copy className="h-4 w-4 mr-2" />
Copy
</>
)}
</Button>
</div>
<p className="text-[10px] sm:text-xs text-muted-foreground">
Use this URL in your Circleback automation settings to send meeting data to SurfSense.
</p>
</div>
) : (
<p className="text-[10px] sm:text-xs text-muted-foreground">
Unable to load webhook URL. Please try refreshing the page.
</p>
)}
{webhookInfo && (
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20">
<Webhook className="h-3 w-3 sm:h-4 sm:w-4" />
<AlertTitle className="text-xs sm:text-sm">Configuration Instructions</AlertTitle>
<AlertDescription className="text-[10px] sm:text-xs !pl-0 mt-1">
Configure this URL in Circleback Settings Automations Create automation Send webhook request.
The webhook will automatically send meeting notes, transcripts, and action items to this search space.
</AlertDescription>
</Alert>
)}
</div>
</div>
);
};

View file

@ -4,6 +4,7 @@ import type { FC } from "react";
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
import { BaiduSearchApiConfig } from "./components/baidu-search-api-config";
import { BookStackConfig } from "./components/bookstack-config";
import { CirclebackConfig } from "./components/circleback-config";
import { ClickUpConfig } from "./components/clickup-config";
import { ConfluenceConfig } from "./components/confluence-config";
import { DiscordConfig } from "./components/discord-config";
@ -69,6 +70,8 @@ export function getConnectorConfigComponent(
return ClickUpConfig;
case "LUMA_CONNECTOR":
return LumaConfig;
case "CIRCLEBACK_CONNECTOR":
return CirclebackConfig;
// OAuth connectors (Gmail, Calendar, Airtable) and others don't need special config UI
default:
return null;

View file

@ -62,6 +62,7 @@ export const ConnectorConnectView: FC<ConnectorConnectViewProps> = ({
JIRA_CONNECTOR: "jira-connect-form",
CLICKUP_CONNECTOR: "clickup-connect-form",
LUMA_CONNECTOR: "luma-connect-form",
CIRCLEBACK_CONNECTOR: "circleback-connect-form",
};
const formId = formIdMap[connectorType];
if (formId) {

View file

@ -38,7 +38,7 @@ export const CRAWLERS = [
id: "youtube-crawler",
title: "YouTube",
description: "Crawl YouTube channels and playlists",
connectorType: null, // Not a connector, handled separately
connectorType: EnumConnectorName.YOUTUBE_CONNECTOR,
},
{
id: "webcrawler-connector",
@ -140,6 +140,12 @@ export const OTHER_CONNECTORS = [
description: "Search with Baidu",
connectorType: EnumConnectorName.BAIDU_SEARCH_API,
},
{
id: "circleback-connector",
title: "Circleback",
description: "Receive meeting notes via webhook",
connectorType: EnumConnectorName.CIRCLEBACK_CONNECTOR,
},
] as const;
// Re-export IndexingConfigState from schemas for backward compatibility

View file

@ -183,23 +183,24 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{filteredOther.map((connector) => {
// Special handling for connectors that can be created in popup
const isWebcrawler = connector.id === "webcrawler-connector";
const isTavily = connector.id === "tavily-api";
const isSearxng = connector.id === "searxng";
const isLinkup = connector.id === "linkup-api";
const isBaidu = connector.id === "baidu-search-api";
const isLinear = connector.id === "linear-connector";
const isElasticsearch = connector.id === "elasticsearch-connector";
const isSlack = connector.id === "slack-connector";
const isDiscord = connector.id === "discord-connector";
const isNotion = connector.id === "notion-connector";
const isConfluence = connector.id === "confluence-connector";
const isBookStack = connector.id === "bookstack-connector";
const isGithub = connector.id === "github-connector";
const isJira = connector.id === "jira-connector";
const isClickUp = connector.id === "clickup-connector";
const isLuma = connector.id === "luma-connector";
// Special handling for connectors that can be created in popup
const isWebcrawler = connector.id === "webcrawler-connector";
const isTavily = connector.id === "tavily-api";
const isSearxng = connector.id === "searxng";
const isLinkup = connector.id === "linkup-api";
const isBaidu = connector.id === "baidu-search-api";
const isLinear = connector.id === "linear-connector";
const isElasticsearch = connector.id === "elasticsearch-connector";
const isSlack = connector.id === "slack-connector";
const isDiscord = connector.id === "discord-connector";
const isNotion = connector.id === "notion-connector";
const isConfluence = connector.id === "confluence-connector";
const isBookStack = connector.id === "bookstack-connector";
const isGithub = connector.id === "github-connector";
const isJira = connector.id === "jira-connector";
const isClickUp = connector.id === "clickup-connector";
const isLuma = connector.id === "luma-connector";
const isCircleback = connector.id === "circleback-connector";
const isConnected = connectedTypes.has(connector.connectorType);
const isConnecting = connectingId === connector.id;
@ -215,7 +216,7 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
const handleConnect = isWebcrawler && onCreateWebcrawler
? onCreateWebcrawler
: (isTavily || isSearxng || isLinkup || isBaidu || isLinear || isElasticsearch || isSlack || isDiscord || isNotion || isConfluence || isBookStack || isGithub || isJira || isClickUp || isLuma) && onConnectNonOAuth
: (isTavily || isSearxng || isLinkup || isBaidu || isLinear || isElasticsearch || isSlack || isDiscord || isNotion || isConfluence || isBookStack || isGithub || isJira || isClickUp || isLuma || isCircleback) && onConnectNonOAuth
? () => onConnectNonOAuth(connector.connectorType)
: () => router.push(`/dashboard/${searchSpaceId}/connectors/add/${connector.id}`);

View file

@ -24,6 +24,7 @@ export const CONNECTOR_TO_DOCUMENT_TYPE: Record<string, string> = {
LUMA_CONNECTOR: "LUMA_CONNECTOR",
ELASTICSEARCH_CONNECTOR: "ELASTICSEARCH_CONNECTOR",
BOOKSTACK_CONNECTOR: "BOOKSTACK_CONNECTOR",
CIRCLEBACK_CONNECTOR: "CIRCLEBACK",
// Special mappings (connector type differs from document type)
GOOGLE_DRIVE_CONNECTOR: "GOOGLE_DRIVE_FILE",

View file

@ -1,6 +1,5 @@
"use client";
import { IconBrandYoutube } from "@tabler/icons-react";
import { ArrowLeft } from "lucide-react";
import { TagInput, type Tag as TagType } from "emblor";
import { useAtom } from "jotai";
@ -12,6 +11,8 @@ import { toast } from "sonner";
import { createDocumentMutationAtom } from "@/atoms/documents/document-mutation.atoms";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { EnumConnectorName } from "@/contracts/enums/connector";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
const youtubeRegex =
/^(https:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})$/;
@ -129,7 +130,7 @@ export const YouTubeCrawlerView: FC<YouTubeCrawlerViewProps> = ({
<div className="flex items-center gap-4 mb-6">
<div className="flex h-14 w-14 items-center justify-center rounded-xl border border-slate-400/30">
<IconBrandYoutube className="h-7 w-7" />
{getConnectorIcon(EnumConnectorName.YOUTUBE_CONNECTOR, "h-7 w-7")}
</div>
<div>
<h2 className="text-xl sm:text-2xl font-semibold tracking-tight">
@ -236,10 +237,7 @@ export const YouTubeCrawlerView: FC<YouTubeCrawlerViewProps> = ({
{t("processing")}
</>
) : (
<>
<IconBrandYoutube className="mr-2 h-4 w-4" />
{t("submit")}
</>
t("submit")
)}
</Button>
</div>

View file

@ -1,215 +0,0 @@
import { EnumConnectorName } from "@/contracts/enums/connector";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
import type { ConnectorCategory } from "./types";
export const connectorCategories: ConnectorCategory[] = [
{
id: "web-crawling",
title: "web_crawling",
connectors: [
{
id: "webcrawler-connector",
title: "Web Pages",
description: "webcrawler_desc",
icon: getConnectorIcon(EnumConnectorName.WEBCRAWLER_CONNECTOR, "h-6 w-6"),
status: "available",
},
],
},
{
id: "web-search",
title: "web_search",
connectors: [
{
id: "tavily-api",
title: "Tavily API",
description: "tavily_desc",
icon: getConnectorIcon(EnumConnectorName.TAVILY_API, "h-6 w-6"),
status: "available",
},
{
id: "searxng",
title: "SearxNG",
description: "searxng_desc",
icon: getConnectorIcon(EnumConnectorName.SEARXNG_API, "h-6 w-6"),
status: "available",
},
{
id: "linkup-api",
title: "Linkup API",
description: "linkup_desc",
icon: getConnectorIcon(EnumConnectorName.LINKUP_API, "h-6 w-6"),
status: "available",
},
{
id: "baidu-search-api",
title: "Baidu Search",
description: "baidu_desc",
icon: getConnectorIcon(EnumConnectorName.BAIDU_SEARCH_API, "h-6 w-6"),
status: "available",
},
],
},
{
id: "messaging",
title: "messaging",
connectors: [
{
id: "slack-connector",
title: "Slack",
description: "slack_desc",
icon: getConnectorIcon(EnumConnectorName.SLACK_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "discord-connector",
title: "Discord",
description: "discord_desc",
icon: getConnectorIcon(EnumConnectorName.DISCORD_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "ms-teams",
title: "Microsoft Teams",
description: "teams_desc",
icon: getConnectorIcon("ms-teams", "h-6 w-6"),
status: "coming-soon",
},
],
},
{
id: "project-management",
title: "project_management",
connectors: [
{
id: "linear-connector",
title: "Linear",
description: "linear_desc",
icon: getConnectorIcon(EnumConnectorName.LINEAR_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "jira-connector",
title: "Jira",
description: "jira_desc",
icon: getConnectorIcon(EnumConnectorName.JIRA_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "clickup-connector",
title: "ClickUp",
description: "clickup_desc",
icon: getConnectorIcon(EnumConnectorName.CLICKUP_CONNECTOR, "h-6 w-6"),
status: "available",
},
],
},
{
id: "documentation",
title: "documentation",
connectors: [
{
id: "notion-connector",
title: "Notion",
description: "notion_desc",
icon: getConnectorIcon(EnumConnectorName.NOTION_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "confluence-connector",
title: "Confluence",
description: "confluence_desc",
icon: getConnectorIcon(EnumConnectorName.CONFLUENCE_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "bookstack-connector",
title: "BookStack",
description: "bookstack_desc",
icon: getConnectorIcon(EnumConnectorName.BOOKSTACK_CONNECTOR, "h-6 w-6"),
status: "available",
},
],
},
{
id: "development",
title: "development",
connectors: [
{
id: "github-connector",
title: "GitHub",
description: "github_desc",
icon: getConnectorIcon(EnumConnectorName.GITHUB_CONNECTOR, "h-6 w-6"),
status: "available",
},
],
},
{
id: "databases",
title: "databases",
connectors: [
{
id: "elasticsearch-connector",
title: "Elasticsearch",
description: "elasticsearch_desc",
icon: getConnectorIcon(EnumConnectorName.ELASTICSEARCH_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "airtable-connector",
title: "Airtable",
description: "airtable_desc",
icon: getConnectorIcon(EnumConnectorName.AIRTABLE_CONNECTOR, "h-6 w-6"),
status: "available",
},
],
},
{
id: "productivity",
title: "productivity",
connectors: [
{
id: "google-calendar-connector",
title: "Google Calendar",
description: "calendar_desc",
icon: getConnectorIcon(EnumConnectorName.GOOGLE_CALENDAR_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "google-gmail-connector",
title: "Gmail",
description: "gmail_desc",
icon: getConnectorIcon(EnumConnectorName.GOOGLE_GMAIL_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "google-drive-connector",
title: "Google Drive",
description: "google_drive_desc",
icon: getConnectorIcon(EnumConnectorName.GOOGLE_DRIVE_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "luma-connector",
title: "Luma",
description: "luma_desc",
icon: getConnectorIcon(EnumConnectorName.LUMA_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "circleback-connector",
title: "Circleback",
description: "circleback_desc",
icon: getConnectorIcon(EnumConnectorName.CIRCLEBACK_CONNECTOR, "h-6 w-6"),
status: "available",
},
{
id: "zoom",
title: "Zoom",
description: "zoom_desc",
icon: getConnectorIcon("zoom", "h-6 w-6"),
status: "coming-soon",
},
],
},
];

View file

@ -19,5 +19,6 @@ export enum EnumConnectorName {
LUMA_CONNECTOR = "LUMA_CONNECTOR",
ELASTICSEARCH_CONNECTOR = "ELASTICSEARCH_CONNECTOR",
WEBCRAWLER_CONNECTOR = "WEBCRAWLER_CONNECTOR",
YOUTUBE_CONNECTOR = "YOUTUBE_CONNECTOR",
CIRCLEBACK_CONNECTOR = "CIRCLEBACK_CONNECTOR",
}

View file

@ -2,7 +2,6 @@ import {
IconLinkPlus,
IconSparkles,
IconUsersGroup,
IconWorldWww,
} from "@tabler/icons-react";
import {
File,
@ -20,16 +19,30 @@ import { EnumConnectorName } from "./connector";
export const getConnectorIcon = (connectorType: EnumConnectorName | string, className?: string) => {
const iconProps = { className: className || "h-4 w-4" };
const imgProps = { className: className || "h-5 w-5", width: 20, height: 20 };
// Larger props for specific services (Google services, GitHub, Linear) - scale up from size-6 to size-8
const getLargeClassName = () => {
if (!className) return "h-8 w-8";
// Replace size-6 with size-8, or h-6/w-6 with h-8/w-8
return className
.replace(/size-6/g, "size-8")
.replace(/\bh-6\b/g, "h-8")
.replace(/\bw-6\b/g, "w-8");
};
const largeImgProps = {
className: getLargeClassName(),
width: 32,
height: 32
};
switch (connectorType) {
case EnumConnectorName.LINKUP_API:
return <IconLinkPlus {...iconProps} />;
case EnumConnectorName.LINEAR_CONNECTOR:
return <Image src="/connectors/linear.svg" alt="Linear" {...imgProps} />;
return <Image src="/connectors/linear.svg" alt="Linear" {...largeImgProps} />;
case EnumConnectorName.GITHUB_CONNECTOR:
return <Image src="/connectors/github.svg" alt="GitHub" {...imgProps} />;
return <Image src="/connectors/github.svg" alt="GitHub" {...largeImgProps} />;
case EnumConnectorName.TAVILY_API:
return <IconWorldWww {...iconProps} />;
return <Image src="/connectors/tavily.svg" alt="Tavily" {...imgProps} />;
case EnumConnectorName.SEARXNG_API:
return <Globe {...iconProps} />;
case EnumConnectorName.BAIDU_SEARCH_API:
@ -43,11 +56,11 @@ export const getConnectorIcon = (connectorType: EnumConnectorName | string, clas
case EnumConnectorName.JIRA_CONNECTOR:
return <Image src="/connectors/jira.svg" alt="Jira" {...imgProps} />;
case EnumConnectorName.GOOGLE_CALENDAR_CONNECTOR:
return <Image src="/connectors/google-calendar.svg" alt="Google Calendar" {...imgProps} />;
return <Image src="/connectors/google-calendar.svg" alt="Google Calendar" {...largeImgProps} />;
case EnumConnectorName.GOOGLE_GMAIL_CONNECTOR:
return <Image src="/connectors/google-gmail.svg" alt="Gmail" {...imgProps} />;
return <Image src="/connectors/google-gmail.svg" alt="Gmail" {...largeImgProps} />;
case EnumConnectorName.GOOGLE_DRIVE_CONNECTOR:
return <Image src="/connectors/google-drive.svg" alt="Google Drive" {...imgProps} />;
return <Image src="/connectors/google-drive.svg" alt="Google Drive" {...largeImgProps} />;
case EnumConnectorName.AIRTABLE_CONNECTOR:
return <Image src="/connectors/airtable.svg" alt="Airtable" {...imgProps} />;
case EnumConnectorName.CONFLUENCE_CONNECTOR:
@ -62,9 +75,13 @@ export const getConnectorIcon = (connectorType: EnumConnectorName | string, clas
return <Image src="/connectors/elasticsearch.svg" alt="Elasticsearch" {...imgProps} />;
case EnumConnectorName.WEBCRAWLER_CONNECTOR:
return <Globe {...iconProps} />;
case EnumConnectorName.YOUTUBE_CONNECTOR:
return <Image src="/connectors/youtube.svg" alt="YouTube" {...imgProps} />;
case EnumConnectorName.CIRCLEBACK_CONNECTOR:
return <IconUsersGroup {...iconProps} />;
// Additional cases for non-enum connector types
case "YOUTUBE_CONNECTOR":
return <Image src="/connectors/youtube.svg" alt="YouTube" {...imgProps} />;
case "CIRCLEBACK":
return <IconUsersGroup {...iconProps} />;
case "CRAWLED_URL":

View file

@ -19,6 +19,7 @@ export const getConnectorTypeDisplay = (type: string): string => {
LUMA_CONNECTOR: "Luma",
ELASTICSEARCH_CONNECTOR: "Elasticsearch",
WEBCRAWLER_CONNECTOR: "Web Pages",
CIRCLEBACK_CONNECTOR: "Circleback",
};
return typeMap[type] || type;
};

View file

@ -1,6 +1 @@
<svg xmlns="http://www.w3.org/2000/svg"
aria-label="Baidu" role="img"
viewBox="0 0 512 512"><rect
width="512" height="512"
rx="15%"
fill="#fff"/><path d="m131 251c41-9 35-58 34-68-2-17-21-45-48-43-33 3-37 50-37 50-5 22 10 70 51 61m76-82c22 0 40-26 40-58s-18-58-40-58c-23 0-41 26-41 58s18 58 41 58m96 4c31 4 50-28 54-53 4-24-16-52-37-57s-48 29-50 52c-3 27 3 54 33 58m120 41c0-12-10-47-46-47s-41 33-41 57c0 22 2 53 47 52s40-51 40-62m-46 102s-46-36-74-75c-36-57-89-34-106-5-18 29-45 48-49 53-4 4-56 33-44 84 11 52 52 51 52 51s30 3 65-5 65 2 65 2 81 27 104-25c22-53-13-80-13-80" fill="#2319dc"/><path d="m214 266v34h-28s-29 3-39 35c-3 21 4 34 5 36 1 3 10 19 33 23h53v-128zm-1 107h-21s-15-1-19-18c-3-7 0-16 1-20 1-3 6-11 17-14h22zm38-70v68s1 17 24 23h61v-91h-26v68h-25s-8-1-10-7v-61z" fill="#fff"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#1565c0" d="M36.094 31.35c-1.695-1.5-3.754-3.225-6.66-7.35-1.865-2.647-3.512-4-5.934-4-2.664 0-4.117 1.25-5.552 3.279-2.1 2.971-2.925 3.971-5.088 5.675-.786.619-4.861 3.172-4.86 7.671C8.001 41.875 11.753 44 15.155 44c4.469 0 5.439-1 8.345-1 3.633 0 5.57 1 8.476 1C37.789 44 39 39.625 39 36.872 39 34.25 37.789 32.85 36.094 31.35zM11.389 24.885c3.124-.694 3.616-3.739 3.611-5.732-.002-.696-.064-1.263-.096-1.558-.198-1.678-2.027-4.55-4.551-4.594-.12-.002-.242.002-.365.013-3.412.314-3.911 5.412-3.911 5.412-.056.287-.082.613-.078.963.031 2.263 1.356 5.527 4.274 5.61C10.623 25.008 10.994 24.973 11.389 24.885M19.503 16C21.99 16 24 13.315 24 9.998 24 6.681 21.99 4 19.503 4 17.015 4 15 6.681 15 9.998 15 13.315 17.015 16 19.503 16M29.522 16.964c.221.031.436.041.645.033 2.696-.103 4.416-3.276 4.781-5.723.037-.241.054-.486.052-.733-.015-2.441-1.831-5.012-3.799-5.49-2.177-.532-4.893 3.173-5.138 5.59-.037.37-.059.739-.063 1.103C25.975 14.296 26.841 16.599 29.522 16.964M41.984 21.142c0-1.281-1.004-5.142-4.742-5.142C33.496 16 33 19.644 33 22.219c0 2.41.187 5.752 4.578 5.781.087.001.176 0 .267-.002 4.027-.094 4.183-4.203 4.152-6.138C41.993 21.561 41.984 21.315 41.984 21.142"/><path fill="#fff" d="M24 31v7.5c0 0 0 1.875 2.625 2.5H33V31h-2.625v7.5h-2.75c0 0-.875-.125-1-.75V31H24zM20 27v4h-3c-2.125.375-4 2.25-3.999 4.875C13.001 35.917 13 35.958 13 36c0 2.75 1.875 4.625 4 5h5.625V27H20zM20 38.75h-2.375c-.75 0-2-1.125-2-2.75s1.25-2.75 2-2.75H20V38.75z"/></svg>

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -1 +1,14 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>ClickUp</title><path d="M2 18.439l3.69-2.828c1.961 2.56 4.044 3.739 6.363 3.739 2.307 0 4.33-1.166 6.203-3.704L22 18.405C19.298 22.065 15.941 24 12.053 24 8.178 24 4.788 22.078 2 18.439zM12.04 6.15l-6.568 5.66-3.036-3.52L12.055 0l9.543 8.296-3.05 3.509z"/></svg>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.43828 50.2095C5.81176 49.4456 5.94882 48.3212 6.71918 47.7027L14.0169 41.8433C14.6535 41.3322 15.5841 41.4476 16.1032 42.0777C21.06 48.0956 26.32 50.8815 32.142 50.8815C37.9238 50.8815 43.0403 48.135 47.7801 42.1839C48.2888 41.5452 49.2172 41.4131 49.8629 41.9129L57.2604 47.6377C58.0415 48.2422 58.1989 49.3637 57.5855 50.1379C50.5775 58.9839 41.9971 63.6446 32.142 63.6446C22.3156 63.6446 13.6586 59.013 6.43828 50.2095Z" fill="url(#paint0_linear_8_569)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.4953 17.1804C32.2202 16.9368 31.8067 16.9367 31.5314 17.1801L15.663 31.2116C15.0564 31.748 14.1285 31.6857 13.599 31.0731L7.40986 23.9122C6.88774 23.3082 6.95019 22.3961 7.54979 21.8688L31.0527 1.20062C31.6021 0.717503 32.4248 0.717611 32.9741 1.20088L56.4822 21.8847C57.0822 22.4125 57.1439 23.3256 56.6205 23.9294L50.4164 31.0866C49.8862 31.6982 48.9589 31.7594 48.353 31.2229L32.4953 17.1804Z" fill="url(#paint1_linear_8_569)"/>
<defs>
<linearGradient id="paint0_linear_8_569" x1="5.3335" y1="32.1624" x2="58.6653" y2="32.1624" gradientUnits="userSpaceOnUse">
<stop offset="0.225962" stop-color="#6647F0"/>
<stop offset="0.793269" stop-color="#0091FF"/>
</linearGradient>
<linearGradient id="paint1_linear_8_569" x1="5.3335" y1="31.6447" x2="58.6653" y2="31.6447" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF02F0"/>
<stop offset="0.778846" stop-color="#F76808"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 340 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -1,15 +1 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 24C0 10.7452 10.7452 0 24 0C37.2548 0 48 10.7452 48 24C48 37.2548 37.2548 48 24 48C10.7452 48 0 37.2548 0 24Z" fill="white"/>
<path d="M12.8682 29.5623C12.6206 29.9661 12.3425 30.4347 12.1063 30.808C11.8949 31.1653 12.0084 31.626 12.3615 31.8442L17.3139 34.8919C17.4878 34.9992 17.6974 35.0322 17.8958 34.9835C18.0943 34.9348 18.2648 34.8084 18.3692 34.6328C18.5673 34.3014 18.8225 33.8709 19.1006 33.4099C21.0625 30.1719 23.0358 30.568 26.5939 32.2671L31.5044 34.6023C31.6904 34.6908 31.9043 34.7003 32.0973 34.6285C32.2904 34.5568 32.4462 34.4099 32.5292 34.2214L34.8873 28.888C35.0539 28.5071 34.8843 28.063 34.5063 27.8899C33.4701 27.4023 31.4092 26.4309 29.5539 25.5357C22.8796 22.2938 17.2073 22.5033 12.8682 29.5623Z" fill="url(#paint0_linear)"/>
<path d="M35.0739 17.4595C35.3215 17.0557 35.5996 16.5871 35.8358 16.2138C36.0472 15.8565 35.9338 15.3958 35.5806 15.1776L30.6282 12.13C30.453 12.0119 30.2366 11.972 30.0307 12.0196C29.8248 12.0673 29.648 12.1983 29.5425 12.3814C29.3444 12.7128 29.0892 13.1433 28.8111 13.6043C26.8492 16.8424 24.8758 16.4462 21.3177 14.7471L16.4225 12.4233C16.2365 12.3348 16.0226 12.3253 15.8296 12.3971C15.6365 12.4689 15.4807 12.6158 15.3977 12.8043L13.0396 18.1376C12.873 18.5185 13.0426 18.9627 13.4206 19.1357C14.4568 19.6233 16.5177 20.5947 18.373 21.49C25.0625 24.7281 30.7349 24.5109 35.0739 17.4595Z" fill="url(#paint1_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="43.3553" y1="32.7159" x2="37.8094" y2="19.9929" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="1892.63" y1="-18635.3" x2="1828.06" y2="-18930.7" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
</defs>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="246" viewBox="0 0 256 246"><defs><linearGradient id="SVGYOXHRc2U" x1="99.14%" x2="33.859%" y1="112.708%" y2="37.755%"><stop offset="18%" stop-color="#0052cc"/><stop offset="100%" stop-color="#2684ff"/></linearGradient><linearGradient id="SVGvLBXDeEz" x1=".926%" x2="66.18%" y1="-12.582%" y2="62.306%"><stop offset="18%" stop-color="#0052cc"/><stop offset="100%" stop-color="#2684ff"/></linearGradient></defs><path fill="url(#SVGYOXHRc2U)" d="M9.26 187.33c-2.64 4.307-5.607 9.305-8.126 13.287a8.127 8.127 0 0 0 2.722 11.052l52.823 32.507a8.127 8.127 0 0 0 11.256-2.763c2.113-3.536 4.835-8.127 7.801-13.044c20.926-34.538 41.974-30.312 79.925-12.19l52.376 24.908a8.127 8.127 0 0 0 10.93-4.063l25.152-56.886a8.127 8.127 0 0 0-4.063-10.646c-11.052-5.201-33.034-15.562-52.823-25.111c-71.189-34.579-131.691-32.344-177.972 42.949"/><path fill="url(#SVGvLBXDeEz)" d="M246.115 58.232c2.641-4.307 5.607-9.305 8.127-13.287a8.127 8.127 0 0 0-2.723-11.052L198.696 1.386a8.127 8.127 0 0 0-11.58 2.682c-2.113 3.535-4.835 8.127-7.802 13.043c-20.926 34.538-41.974 30.313-79.925 12.19L47.176 4.515a8.127 8.127 0 0 0-10.93 4.063L11.093 65.465a8.127 8.127 0 0 0 4.063 10.645c11.052 5.202 33.035 15.563 52.823 25.112c71.351 34.538 131.854 32.222 178.135-42.99"/></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

@ -1,16 +1 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 24C0 10.7452 10.7452 0 24 0C37.2548 0 48 10.7452 48 24C48 37.2548 37.2548 48 24 48C10.7452 48 0 37.2548 0 24Z" fill="white"/>
<path d="M34.9367 12H23.41C23.41 13.38 23.9582 14.7035 24.934 15.6793C25.9098 16.6551 27.2333 17.2033 28.6133 17.2033H30.7367V19.2533C30.7385 22.1245 33.0656 24.4515 35.9367 24.4533V13C35.9367 12.4477 35.489 12 34.9367 12Z" fill="#2684FF"/>
<path d="M29.2333 17.7433H17.7067C17.7085 20.6144 20.0355 22.9414 22.9067 22.9433H25.03V25C25.0337 27.8711 27.3622 30.1966 30.2333 30.1966V18.7433C30.2333 18.191 29.7856 17.7433 29.2333 17.7433Z" fill="url(#paint0_linear)"/>
<path d="M23.5267 23.4833H12C12 26.357 14.3296 28.6866 17.2033 28.6866H19.3333V30.7366C19.3352 33.6051 21.6582 35.9311 24.5267 35.9366V24.4833C24.5267 23.931 24.079 23.4833 23.5267 23.4833Z" fill="url(#paint1_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="27.4434" y1="15.326" x2="22.5699" y2="20.4112" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="376.829" y1="349.939" x2="167.455" y2="557.146" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
</defs>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256"><defs><linearGradient id="SVGGI8CDGYT" x1="98.031%" x2="58.888%" y1=".161%" y2="40.766%"><stop offset="18%" stop-color="#0052cc"/><stop offset="100%" stop-color="#2684ff"/></linearGradient><linearGradient id="SVGIFnRCene" x1="100.665%" x2="55.402%" y1=".455%" y2="44.727%"><stop offset="18%" stop-color="#0052cc"/><stop offset="100%" stop-color="#2684ff"/></linearGradient></defs><path fill="#2684ff" d="M244.658 0H121.707a55.5 55.5 0 0 0 55.502 55.502h22.649V77.37c.02 30.625 24.841 55.447 55.466 55.467V10.666C255.324 4.777 250.55 0 244.658 0"/><path fill="url(#SVGGI8CDGYT)" d="M183.822 61.262H60.872c.019 30.625 24.84 55.447 55.466 55.467h22.649v21.938c.039 30.625 24.877 55.43 55.502 55.43V71.93c0-5.891-4.776-10.667-10.667-10.667"/><path fill="url(#SVGIFnRCene)" d="M122.951 122.489H0c0 30.653 24.85 55.502 55.502 55.502h22.72v21.867c.02 30.597 24.798 55.408 55.396 55.466V133.156c0-5.891-4.776-10.667-10.667-10.667"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1,017 B

Before After
Before After

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M21.996 12.018a10.65 10.65 0 0 0-9.98 9.98h-.04c-.32-5.364-4.613-9.656-9.976-9.98v-.04c5.363-.32 9.656-4.613 9.98-9.976h.04c.324 5.363 4.617 9.656 9.98 9.98v.036z"/></svg>

After

Width:  |  Height:  |  Size: 283 B

View file

@ -1,4 +1 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24 48C37.2548 48 48 37.2548 48 24C48 10.7452 37.2548 0 24 0C10.7452 0 0 10.7452 0 24C0 37.2548 10.7452 48 24 48Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.4602 9.06842L11.8104 10.2936C10.4679 10.4098 10 11.285 10 12.3342V30.5316C10 31.3492 10.2916 32.048 10.993 32.982L14.9069 38.0563C15.5498 38.8734 16.134 39.0482 17.3616 38.9897L36.6969 37.823C38.3322 37.7069 38.8 36.9481 38.8 35.665V15.1925C38.8 14.5292 38.5374 14.3376 37.7632 13.7728C37.7206 13.7418 37.6764 13.7096 37.6307 13.6761L32.3159 9.94338C31.0308 9.01056 30.5048 8.89318 28.4602 9.06842ZM17.8 14.8567C16.2214 14.9632 15.8627 14.9874 14.9662 14.2596L12.6865 12.4516C12.454 12.2178 12.5706 11.9262 13.1544 11.8683L29.1613 10.7017C30.5045 10.5848 31.2054 11.0522 31.7314 11.4602L34.4769 13.4435C34.5938 13.5016 34.8854 13.8511 34.5347 13.8511L18.0038 14.843L17.8 14.8567ZM15.9587 35.4897V18.1093C15.9587 17.3512 16.1924 17.001 16.893 16.9421L35.8782 15.8343C36.5222 15.776 36.8138 16.1846 36.8138 16.9421V34.206C36.8138 34.9648 36.6966 35.6072 35.6447 35.665L17.4773 36.7155C16.4259 36.7733 15.9587 36.4238 15.9587 35.4897ZM33.8936 19.0416C34.0101 19.5671 33.8936 20.092 33.3668 20.1511L32.4914 20.3254V33.1567C31.7314 33.5649 31.0306 33.7983 30.4466 33.7983C29.5116 33.7983 29.2774 33.5064 28.5771 32.632L22.8513 23.65V32.3404L24.6631 32.7489C24.6631 32.7489 24.6631 33.7983 23.2014 33.7983L19.1716 34.0319C19.0545 33.7983 19.1716 33.2155 19.5803 33.0987L20.6319 32.8075V21.3172L19.1718 21.2003C19.0547 20.6749 19.3463 19.9173 20.1648 19.8585L24.4879 19.5673L30.4466 28.6662V20.617L28.9274 20.4428C28.8107 19.8004 29.2774 19.334 29.8617 19.2761L33.8936 19.0416Z" fill="black"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="268" viewBox="0 0 256 268"><path fill="#fff" d="M16.092 11.538L164.09.608c18.179-1.56 22.85-.508 34.28 7.801l47.243 33.282C253.406 47.414 256 48.975 256 55.207v182.527c0 11.439-4.155 18.205-18.696 19.24L65.44 267.378c-10.913.517-16.11-1.043-21.825-8.327L8.826 213.814C2.586 205.487 0 199.254 0 191.97V29.726c0-9.352 4.155-17.153 16.092-18.188"/><path d="M164.09.608L16.092 11.538C4.155 12.573 0 20.374 0 29.726v162.245c0 7.284 2.585 13.516 8.826 21.843l34.789 45.237c5.715 7.284 10.912 8.844 21.825 8.327l171.864-10.404c14.532-1.035 18.696-7.801 18.696-19.24V55.207c0-5.911-2.336-7.614-9.21-12.66l-1.185-.856L198.37 8.409C186.94.1 182.27-.952 164.09.608M69.327 52.22c-14.033.945-17.216 1.159-25.186-5.323L23.876 30.778c-2.06-2.086-1.026-4.69 4.163-5.207l142.274-10.395c11.947-1.043 18.17 3.12 22.842 6.758l24.401 17.68c1.043.525 3.638 3.637.517 3.637L71.146 52.095zm-16.36 183.954V81.222c0-6.767 2.077-9.887 8.3-10.413L230.02 60.93c5.724-.517 8.31 3.12 8.31 9.879v153.917c0 6.767-1.044 12.49-10.387 13.008l-161.487 9.361c-9.343.517-13.489-2.594-13.489-10.921M212.377 89.53c1.034 4.681 0 9.362-4.681 9.897l-7.783 1.542v114.404c-6.758 3.637-12.981 5.715-18.18 5.715c-8.308 0-10.386-2.604-16.609-10.396l-50.898-80.079v77.476l16.1 3.646s0 9.362-12.989 9.362l-35.814 2.077c-1.043-2.086 0-7.284 3.63-8.318l9.351-2.595V109.823l-12.98-1.052c-1.044-4.68 1.55-11.439 8.826-11.965l38.426-2.585l52.958 81.113v-71.76l-13.498-1.552c-1.043-5.733 3.111-9.896 8.3-10.404z"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -1,6 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
aria-label="Slack" role="img"
viewBox="0 0 512 512"><rect
width="512" height="512"
rx="15%"
fill="#fff"/><g fill="#e01e5a"><path id="a" d="M149 305a39 39 0 0 1-78 0c0-22 17-39 39-39h39zM168 305a39 39 0 0 1 78 0v97a39 39 0 0 1-78 0z"/></g><use xlink:href="#a" fill="#36c5f0" transform="rotate(90,256,256)"/><use xlink:href="#a" fill="#2eb67d" transform="rotate(180,256,256)"/><use xlink:href="#a" fill="#ecb22e" transform="rotate(270,256,256)"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128"><path fill="#de1c59" d="M27.255 80.719c0 7.33-5.978 13.317-13.309 13.317S.63 88.049.63 80.719s5.987-13.317 13.317-13.317h13.309zm6.709 0c0-7.33 5.987-13.317 13.317-13.317s13.317 5.986 13.317 13.317v33.335c0 7.33-5.986 13.317-13.317 13.317c-7.33 0-13.317-5.987-13.317-13.317zm0 0"/><path fill="#35c5f0" d="M47.281 27.255c-7.33 0-13.317-5.978-13.317-13.309S39.951.63 47.281.63s13.317 5.987 13.317 13.317v13.309zm0 6.709c7.33 0 13.317 5.987 13.317 13.317s-5.986 13.317-13.317 13.317H13.946C6.616 60.598.63 54.612.63 47.281c0-7.33 5.987-13.317 13.317-13.317zm0 0"/><path fill="#2eb57d" d="M100.745 47.281c0-7.33 5.978-13.317 13.309-13.317s13.317 5.987 13.317 13.317s-5.987 13.317-13.317 13.317h-13.309zm-6.709 0c0 7.33-5.987 13.317-13.317 13.317s-13.317-5.986-13.317-13.317V13.946C67.402 6.616 73.388.63 80.719.63c7.33 0 13.317 5.987 13.317 13.317zm0 0"/><path fill="#ebb02e" d="M80.719 100.745c7.33 0 13.317 5.978 13.317 13.309s-5.987 13.317-13.317 13.317s-13.317-5.987-13.317-13.317v-13.309zm0-6.709c-7.33 0-13.317-5.987-13.317-13.317s5.986-13.317 13.317-13.317h33.335c7.33 0 13.317 5.986 13.317 13.317c0 7.33-5.987 13.317-13.317 13.317zm0 0"/></svg>

Before

Width:  |  Height:  |  Size: 533 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

View file

@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Tavily</title><path d="M9.1.503l2.824 4.47a1.078 1.078 0 01-.911 1.655H9.858v6.692h-1.67V0c.35 0 .7.168.912.503z" fill="#8FBCFA"></path><path d="M4.453 4.974L7.277.503A1.07 1.07 0 018.189 0v13.32a2.633 2.633 0 00-1.67.48V6.628H5.364c-.85 0-1.366-.936-.912-1.654z" fill="#468BFF"></path><path d="M17.041 17.74h-7.028c.423-.457.67-1.049.7-1.67h12.956c0 .35-.168.7-.502.912l-4.472 2.823a1.078 1.078 0 01-1.654-.911v-1.155z" fill="#FDBB11"></path><path d="M18.695 12.334l4.47 2.824c.336.212.503.562.503.912H10.713a2.65 2.65 0 00-.493-1.67h6.822v-1.154c0-.85.935-1.366 1.653-.912z" fill="#F6D785"></path><path d="M4.394 19.605L.316 23.683a1.07 1.07 0 001 .29l5.158-1.165A1.078 1.078 0 007 20.994l-.816-.816 3.073-3.074a1.61 1.61 0 000-2.276l-.042-.043-4.82 4.82z" fill="#FF9A9D"></path><path d="M3.822 17.817l3.073-3.074a1.61 1.61 0 012.277 0l.042.043-4.818 4.819-4.08 4.079a1.07 1.07 0 01-.289-1l1.165-5.158A1.078 1.078 0 013.006 17l.816.817z" fill="#FE363B"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="100%" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;" version="1.1" viewBox="0 0 24 24" width="100%" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:serif="http://www.serif.com/" xmlns:xlink="http://www.w3.org/1999/xlink"><rect height="24" id="Artboard15" style="fill:none;" width="24" x="0" y="0"/><g><path d="M2.093,9.075c0.125,-1.941 1.629,-3.509 3.562,-3.716c2.005,-0.202 4.136,-0.311 6.345,-0.311c2.209,0 4.34,0.109 6.345,0.312c1.933,0.206 3.437,1.774 3.562,3.715c0.061,0.956 0.093,1.933 0.093,2.925c0,0.992 -0.032,1.969 -0.093,2.925c-0.125,1.941 -1.629,3.509 -3.562,3.716c-2.005,0.202 -4.136,0.311 -6.345,0.311c-2.209,0 -4.34,-0.109 -6.345,-0.312c-1.933,-0.206 -3.437,-1.774 -3.562,-3.715c-0.061,-0.956 -0.093,-1.933 -0.093,-2.925c0,-0.992 0.032,-1.969 0.093,-2.925Z" style="fill:#f00;"/><path d="M15.055,12l-4.909,2.995l0,-5.99l4.909,2.995Z" style="fill:#fff;"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="180" viewBox="0 0 256 180"><path fill="#f00" d="M250.346 28.075A32.18 32.18 0 0 0 227.69 5.418C207.824 0 127.87 0 127.87 0S47.912.164 28.046 5.582A32.18 32.18 0 0 0 5.39 28.24c-6.009 35.298-8.34 89.084.165 122.97a32.18 32.18 0 0 0 22.656 22.657c19.866 5.418 99.822 5.418 99.822 5.418s79.955 0 99.82-5.418a32.18 32.18 0 0 0 22.657-22.657c6.338-35.348 8.291-89.1-.164-123.134"/><path fill="#fff" d="m102.421 128.06l66.328-38.418l-66.328-38.418z"/></svg>

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 511 B

Before After
Before After