refactor: remove unused COMPOSIO_CONNECTOR migration and linting

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-01-22 16:43:08 -08:00
parent eb509810f1
commit 8b81507739
24 changed files with 401 additions and 251 deletions

View file

@ -33,7 +33,9 @@ import { DisplayImageToolUI } from "@/components/tool-ui/display-image";
import { GeneratePodcastToolUI } from "@/components/tool-ui/generate-podcast";
import { LinkPreviewToolUI } from "@/components/tool-ui/link-preview";
import { ScrapeWebpageToolUI } from "@/components/tool-ui/scrape-webpage";
import { SaveMemoryToolUI, RecallMemoryToolUI } from "@/components/tool-ui/user-memory";
import { RecallMemoryToolUI, SaveMemoryToolUI } from "@/components/tool-ui/user-memory";
import { useChatSessionStateSync } from "@/hooks/use-chat-session-state";
import { useMessagesElectric } from "@/hooks/use-messages-electric";
// import { WriteTodosToolUI } from "@/components/tool-ui/write-todos";
import { getBearerToken } from "@/lib/auth-utils";
import { createAttachmentAdapter, extractAttachmentContent } from "@/lib/chat/attachment-adapter";
@ -51,8 +53,6 @@ import {
type MessageRecord,
type ThreadRecord,
} from "@/lib/chat/thread-persistence";
import { useChatSessionStateSync } from "@/hooks/use-chat-session-state";
import { useMessagesElectric } from "@/hooks/use-messages-electric";
import {
trackChatCreated,
trackChatError,
@ -266,7 +266,16 @@ export default function NewChatPage() {
const { data: membersData } = useAtomValue(membersAtom);
const handleElectricMessagesUpdate = useCallback(
(electricMessages: { id: number; thread_id: number; role: string; content: unknown; author_id: string | null; created_at: string }[]) => {
(
electricMessages: {
id: number;
thread_id: number;
role: string;
content: unknown;
author_id: string | null;
created_at: string;
}[]
) => {
if (isRunning) {
return;
}

View file

@ -1,7 +1,7 @@
"use client";
import type { FC } from "react";
import { Loader2 } from "lucide-react";
import type { FC } from "react";
import { cn } from "@/lib/utils";
interface ChatSessionStatusProps {
@ -32,7 +32,8 @@ export const ChatSessionStatus: FC<ChatSessionStatusProps> = ({
}
const respondingUser = members.find((m) => m.user_id === respondingToUserId);
const displayName = respondingUser?.user_display_name || respondingUser?.user_email || "another user";
const displayName =
respondingUser?.user_display_name || respondingUser?.user_email || "another user";
return (
<div

View file

@ -186,12 +186,10 @@ export const ConnectorIndicator: FC = () => {
) : viewingComposio && searchSpaceId ? (
<ComposioToolkitView
searchSpaceId={searchSpaceId}
connectedToolkits={
(connectors || [])
.filter((c: SearchSourceConnector) => c.connector_type === "COMPOSIO_CONNECTOR")
.map((c: SearchSourceConnector) => c.config?.toolkit_id as string)
.filter(Boolean)
}
connectedToolkits={(connectors || [])
.filter((c: SearchSourceConnector) => c.connector_type === "COMPOSIO_CONNECTOR")
.map((c: SearchSourceConnector) => c.config?.toolkit_id as string)
.filter(Boolean)}
onBack={handleBackFromComposio}
onConnectToolkit={handleConnectComposioToolkit}
isConnecting={connectingComposioToolkit !== null}

View file

@ -5,8 +5,8 @@ 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 { ComposioConfig } from "./components/composio-config";
import { ClickUpConfig } from "./components/clickup-config";
import { ComposioConfig } from "./components/composio-config";
import { ConfluenceConfig } from "./components/confluence-config";
import { DiscordConfig } from "./components/discord-config";
import { ElasticsearchConfig } from "./components/elasticsearch-config";

View file

@ -3,9 +3,14 @@
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 { ConnectorCard } from "../components/connector-card";
import {
COMPOSIO_CONNECTORS,
CRAWLERS,
OAUTH_CONNECTORS,
OTHER_CONNECTORS,
} from "../constants/connector-constants";
import { getDocumentCountForConnector } from "../utils/connector-document-mapping";
/**

View file

@ -5,12 +5,12 @@ import {
Calendar,
Check,
ExternalLink,
FileText,
Github,
HardDrive,
Loader2,
Mail,
HardDrive,
MessageSquare,
FileText,
Zap,
} from "lucide-react";
import Image from "next/image";
@ -82,17 +82,65 @@ const getToolkitIcon = (toolkitId: string, className?: string) => {
switch (toolkitId) {
case "googledrive":
return <Image src="/connectors/google-drive.svg" alt="Google Drive" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/google-drive.svg"
alt="Google Drive"
width={20}
height={20}
className={iconClass}
/>
);
case "gmail":
return <Image src="/connectors/google-gmail.svg" alt="Gmail" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/google-gmail.svg"
alt="Gmail"
width={20}
height={20}
className={iconClass}
/>
);
case "googlecalendar":
return <Image src="/connectors/google-calendar.svg" alt="Google Calendar" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/google-calendar.svg"
alt="Google Calendar"
width={20}
height={20}
className={iconClass}
/>
);
case "slack":
return <Image src="/connectors/slack.svg" alt="Slack" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/slack.svg"
alt="Slack"
width={20}
height={20}
className={iconClass}
/>
);
case "notion":
return <Image src="/connectors/notion.svg" alt="Notion" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/notion.svg"
alt="Notion"
width={20}
height={20}
className={iconClass}
/>
);
case "github":
return <Image src="/connectors/github.svg" alt="GitHub" width={20} height={20} className={iconClass} />;
return (
<Image
src="/connectors/github.svg"
alt="GitHub"
width={20}
height={20}
className={iconClass}
/>
);
default:
return <Zap className={iconClass} />;
}
@ -139,9 +187,7 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
/>
</div>
<div className="flex-1 min-w-0">
<h2 className="text-xl sm:text-2xl font-semibold tracking-tight">
Composio
</h2>
<h2 className="text-xl sm:text-2xl font-semibold tracking-tight">Composio</h2>
<p className="text-xs sm:text-sm text-muted-foreground mt-1">
Connect 100+ apps with managed OAuth - no verification needed
</p>
@ -165,12 +211,16 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
<section className="mb-8">
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-foreground">Google Services</h3>
<Badge variant="secondary" className="text-[10px] px-1.5 py-0 h-5 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20">
<Badge
variant="secondary"
className="text-[10px] px-1.5 py-0 h-5 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20"
>
Indexable
</Badge>
</div>
<p className="text-xs text-muted-foreground mb-4">
Connect Google services via Composio&apos;s verified OAuth app. Your data will be indexed and searchable.
Connect Google services via Composio&apos;s verified OAuth app. Your data will be
indexed and searchable.
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
{indexableToolkits.map((toolkit) => {
@ -201,16 +251,17 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
{getToolkitIcon(toolkit.id, "size-5")}
</div>
{isConnected && (
<Badge variant="secondary" className="text-[10px] px-1.5 py-0 h-5 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20">
<Badge
variant="secondary"
className="text-[10px] px-1.5 py-0 h-5 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20"
>
<Check className="size-3 mr-0.5" />
Connected
</Badge>
)}
</div>
<h4 className="text-sm font-medium mb-1">{toolkit.name}</h4>
<p className="text-xs text-muted-foreground mb-4 flex-1">
{toolkit.description}
</p>
<p className="text-xs text-muted-foreground mb-4 flex-1">{toolkit.description}</p>
<Button
size="sm"
variant={isConnected ? "secondary" : "default"}
@ -242,12 +293,16 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-foreground">More Integrations</h3>
<Badge variant="secondary" className="text-[10px] px-1.5 py-0 h-5 bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20">
<Badge
variant="secondary"
className="text-[10px] px-1.5 py-0 h-5 bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20"
>
Coming Soon
</Badge>
</div>
<p className="text-xs text-muted-foreground mb-4">
Connect these services for future indexing support. Currently available for connection only.
Connect these services for future indexing support. Currently available for connection
only.
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 opacity-60">
{nonIndexableToolkits.map((toolkit) => (
@ -264,9 +319,7 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
</Badge>
</div>
<h4 className="text-sm font-medium mb-1">{toolkit.name}</h4>
<p className="text-xs text-muted-foreground mb-4 flex-1">
{toolkit.description}
</p>
<p className="text-xs text-muted-foreground mb-4 flex-1">{toolkit.description}</p>
<Button
size="sm"
variant="outline"
@ -289,8 +342,9 @@ export const ComposioToolkitView: FC<ComposioToolkitViewProps> = ({
<div>
<h4 className="text-sm font-medium mb-1">Why use Composio?</h4>
<p className="text-xs text-muted-foreground leading-relaxed">
Composio provides pre-verified OAuth apps, so you don&apos;t need to wait for Google app verification.
Your data is securely processed through Composio&apos;s managed authentication.
Composio provides pre-verified OAuth apps, so you don&apos;t need to wait for Google
app verification. Your data is securely processed through Composio&apos;s managed
authentication.
</p>
</div>
</div>

View file

@ -26,6 +26,7 @@ import {
import { useParams } from "next/navigation";
import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { chatSessionStateAtom } from "@/atoms/chat/chat-session-state.atom";
import { showCommentsGutterAtom } from "@/atoms/chat/current-thread.atom";
import {
mentionedDocumentIdsAtom,
@ -61,7 +62,6 @@ import {
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
import { Button } from "@/components/ui/button";
import type { Document } from "@/contracts/types/document.types";
import { chatSessionStateAtom } from "@/atoms/chat/chat-session-state.atom";
import { useCommentsElectric } from "@/hooks/use-comments-electric";
import { cn } from "@/lib/utils";

View file

@ -41,14 +41,14 @@ import { Spinner } from "@/components/ui/spinner";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
import type { InboxItem } from "@/hooks/use-inbox";
import { useMediaQuery } from "@/hooks/use-media-query";
import {
type ConnectorIndexingMetadata,
type NewMentionMetadata,
isConnectorIndexingMetadata,
isNewMentionMetadata,
type NewMentionMetadata,
} from "@/contracts/types/inbox.types";
import type { InboxItem } from "@/hooks/use-inbox";
import { useMediaQuery } from "@/hooks/use-media-query";
import { cn } from "@/lib/utils";
/**

View file

@ -1,6 +1,6 @@
"use client";
import { ChevronUp, Laptop, Languages, LogOut, Moon, Settings, Sun } from "lucide-react";
import { ChevronUp, Languages, Laptop, LogOut, Moon, Settings, Sun } from "lucide-react";
import { useTranslations } from "next-intl";
import {
DropdownMenu,

View file

@ -1,6 +1,6 @@
"use client";
import * as React from "react";
import type * as React from "react";
import { Drawer as DrawerPrimitive } from "vaul";
import { cn } from "@/lib/utils";

View file

@ -5,11 +5,7 @@ import { useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { membersAtom, myAccessAtom } from "@/atoms/members/members-query.atoms";
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
import type {
Comment,
CommentReply,
Author,
} from "@/contracts/types/chat-comments.types";
import type { Author, Comment, CommentReply } from "@/contracts/types/chat-comments.types";
import type { Membership } from "@/contracts/types/members.types";
import type { SyncHandle } from "@/lib/electric/client";
import { useElectricClient } from "@/lib/electric/context";
@ -123,7 +119,10 @@ function transformComments(
isOwner: boolean
): Map<number, Comment[]> {
// Group comments by message_id
const byMessage = new Map<number, { topLevel: RawCommentRow[]; replies: Map<number, RawCommentRow[]> }>();
const byMessage = new Map<
number,
{ topLevel: RawCommentRow[]; replies: Map<number, RawCommentRow[]> }
>();
for (const raw of rawComments) {
if (!byMessage.has(raw.message_id)) {
@ -176,10 +175,10 @@ function transformComments(
/**
* Hook for syncing comments with Electric SQL real-time sync.
*
*
* Syncs ALL comments for a thread in ONE subscription, then updates
* React Query cache for each message. This avoids N subscriptions for N messages.
*
*
* @param threadId - The thread ID to sync comments for
*/
export function useCommentsElectric(threadId: number | null) {
@ -247,12 +246,21 @@ export function useCommentsElectric(threadId: number | null) {
let mounted = true;
syncKeyRef.current = syncKey;
async function startSync() {
async function startSync() {
try {
const handle = await client.syncShape({
table: "chat_comments",
where: `thread_id = ${threadId}`,
columns: ["id", "message_id", "thread_id", "parent_id", "author_id", "content", "created_at", "updated_at"],
columns: [
"id",
"message_id",
"thread_id",
"parent_id",
"author_id",
"content",
"created_at",
"updated_at",
],
primaryKey: ["id"],
});
@ -283,7 +291,9 @@ export function useCommentsElectric(threadId: number | null) {
// Subscribe to the sync stream for real-time updates from Electric SQL
// This ensures we catch updates even if PGlite live query misses them
if (handle.stream) {
const stream = handle.stream as { subscribe?: (callback: (messages: unknown[]) => void) => void };
const stream = handle.stream as {
subscribe?: (callback: (messages: unknown[]) => void) => void;
};
if (typeof stream.subscribe === "function") {
stream.subscribe((messages: unknown[]) => {
if (!mounted) return;

View file

@ -2,12 +2,12 @@ import {
type GetNotificationsRequest,
type GetNotificationsResponse,
type GetUnreadCountResponse,
type MarkAllNotificationsReadResponse,
type MarkNotificationReadRequest,
type MarkNotificationReadResponse,
getNotificationsRequest,
getNotificationsResponse,
getUnreadCountResponse,
type MarkAllNotificationsReadResponse,
type MarkNotificationReadRequest,
type MarkNotificationReadResponse,
markAllNotificationsReadResponse,
markNotificationReadRequest,
markNotificationReadResponse,