feat: integrate collapsible sections for connector management in ComposerAction, add new connector icons for Discord, Teams, and Luma

This commit is contained in:
Anish Sarkar 2026-05-19 16:45:16 +05:30
parent 78ad19dd6a
commit a5bd2bea9c
3 changed files with 300 additions and 85 deletions

View file

@ -12,7 +12,7 @@ import {
ArrowUpIcon, ArrowUpIcon,
Camera, Camera,
ChevronDown, ChevronDown,
ChevronUp, ChevronRight,
Clipboard, Clipboard,
Globe, Globe,
Plus, Plus,
@ -72,6 +72,11 @@ import {
import { PromptPicker, type PromptPickerRef } from "@/components/new-chat/prompt-picker"; import { PromptPicker, type PromptPickerRef } from "@/components/new-chat/prompt-picker";
import { Avatar, AvatarFallback, AvatarGroup } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarGroup } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { import {
Drawer, Drawer,
DrawerContent, DrawerContent,
@ -378,7 +383,7 @@ const ClipboardChip: FC<{ text: string; onDismiss: () => void }> = ({ text, onDi
size="icon" size="icon"
className="size-5 text-muted-foreground hover:bg-transparent hover:text-accent-foreground" className="size-5 text-muted-foreground hover:bg-transparent hover:text-accent-foreground"
> >
{expanded ? <ChevronUp className="size-3.5" /> : <ChevronDown className="size-3.5" />} <ChevronDown className={cn("size-3.5 transition-transform", expanded && "rotate-180")} />
</Button> </Button>
)} )}
<Button <Button
@ -799,6 +804,10 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
const mentionedDocuments = useAtomValue(mentionedDocumentsAtom); const mentionedDocuments = useAtomValue(mentionedDocumentsAtom);
const setConnectorDialogOpen = useSetAtom(connectorDialogOpenAtom); const setConnectorDialogOpen = useSetAtom(connectorDialogOpenAtom);
const [toolsPopoverOpen, setToolsPopoverOpen] = useState(false); const [toolsPopoverOpen, setToolsPopoverOpen] = useState(false);
const [openConnectorSubmenu, setOpenConnectorSubmenu] = useState<string | null>(null);
const [expandedConnectorGroups, setExpandedConnectorGroups] = useState<Set<string>>(
() => new Set()
);
const isDesktop = useMediaQuery("(min-width: 640px)"); const isDesktop = useMediaQuery("(min-width: 640px)");
const { openDialog: openUploadDialog } = useDocumentUploadDialog(); const { openDialog: openUploadDialog } = useDocumentUploadDialog();
const pendingScreenImages = useAtomValue(pendingUserImageDataUrlsAtom); const pendingScreenImages = useAtomValue(pendingUserImageDataUrlsAtom);
@ -847,6 +856,17 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
}, },
[disabledToolsSet, setDisabledTools] [disabledToolsSet, setDisabledTools]
); );
const setConnectorGroupExpanded = useCallback((label: string, expanded: boolean) => {
setExpandedConnectorGroups((prev) => {
const next = new Set(prev);
if (expanded) {
next.add(label);
} else {
next.delete(label);
}
return next;
});
}, []);
const hasWebSearchTool = agentTools?.some((t) => t.name === "web_search") ?? false; const hasWebSearchTool = agentTools?.some((t) => t.name === "web_search") ?? false;
const isWebSearchEnabled = hasWebSearchTool && !disabledToolsSet.has("web_search"); const isWebSearchEnabled = hasWebSearchTool && !disabledToolsSet.has("web_search");
@ -888,6 +908,9 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
return result; return result;
}, [filteredTools, connectedTypes]); }, [filteredTools, connectedTypes]);
const regularToolGroups = groupedTools.filter((g) => !g.connectorIcon && g.label !== "Other");
const connectorToolGroups = groupedTools.filter((g) => g.connectorIcon);
const otherToolGroup = groupedTools.find((g) => !g.connectorIcon && g.label === "Other");
useEffect(() => { useEffect(() => {
hydrateDisabled(); hydrateDisabled();
@ -917,17 +940,13 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
variant="ghost" variant="ghost"
size="icon" size="icon"
className="h-9 w-9 rounded-full p-0 font-semibold text-xs text-muted-foreground transition-colors dark:border-muted-foreground/15 hover:bg-foreground/10 hover:text-foreground" className="h-9 w-9 rounded-full p-0 font-semibold text-xs text-muted-foreground transition-colors dark:border-muted-foreground/15 hover:bg-foreground/10 hover:text-foreground"
aria-label="Upload files, connect tools and more" aria-label="Upload files, manage tools and more"
data-joyride="connector-icon" data-joyride="connector-icon"
> >
<Plus className="size-5" /> <Plus className="size-5" />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent side="bottom" align="start" sideOffset={8}> <DropdownMenuContent side="bottom" align="start" sideOffset={8}>
<DropdownMenuItem onSelect={() => setToolsPopoverOpen(true)}>
<Settings2 className="size-4" />
Manage Tools
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => openUploadDialog()}> <DropdownMenuItem onSelect={() => openUploadDialog()}>
<Upload className="size-4" /> <Upload className="size-4" />
Upload Files Upload Files
@ -952,6 +971,10 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
<Unplug className="size-4" /> <Unplug className="size-4" />
Manage Connectors Manage Connectors
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onSelect={() => setToolsPopoverOpen(true)}>
<Settings2 className="size-4" />
Manage Tools
</DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
<Drawer <Drawer
@ -967,9 +990,7 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
</DrawerTitle> </DrawerTitle>
</DrawerHeader> </DrawerHeader>
<div className="min-h-0 flex-1 overflow-y-auto scrollbar-thin pb-6"> <div className="min-h-0 flex-1 overflow-y-auto scrollbar-thin pb-6">
{groupedTools {regularToolGroups.map((group) => (
.filter((g) => !g.connectorIcon)
.map((group) => (
<div key={group.label}> <div key={group.label}>
<div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none"> <div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none">
{group.label} {group.label}
@ -996,22 +1017,30 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
})} })}
</div> </div>
))} ))}
{groupedTools.some((g) => g.connectorIcon) && ( {connectorToolGroups.length > 0 && (
<div> <div>
<div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none"> <div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none">
Connector Actions Connector Actions
</div> </div>
{groupedTools {connectorToolGroups.map((group) => {
.filter((g) => g.connectorIcon)
.map((group) => {
const iconKey = group.connectorIcon ?? ""; const iconKey = group.connectorIcon ?? "";
const iconInfo = CONNECTOR_TOOL_ICON_PATHS[iconKey]; const iconInfo = CONNECTOR_TOOL_ICON_PATHS[iconKey];
const toolNames = group.tools.map((t) => t.name); const toolNames = group.tools.map((t) => t.name);
const allDisabled = toolNames.every((n) => disabledToolsSet.has(n)); const allDisabled = toolNames.every((n) => disabledToolsSet.has(n));
const isExpanded = expandedConnectorGroups.has(group.label);
return ( return (
<div <Collapsible
key={group.label} key={group.label}
className="flex w-full items-center gap-3 px-4 py-2 hover:bg-accent hover:text-accent-foreground transition-colors" open={isExpanded}
onOpenChange={(open) =>
setConnectorGroupExpanded(group.label, open)
}
>
<div className="flex w-full items-center gap-3 px-4 py-2 hover:bg-accent hover:text-accent-foreground transition-colors">
<CollapsibleTrigger asChild>
<button
type="button"
className="flex min-w-0 flex-1 items-center gap-3 text-left"
> >
{iconInfo ? ( {iconInfo ? (
<Image <Image
@ -1025,15 +1054,74 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
) : ( ) : (
<Wrench className="size-4 shrink-0 text-muted-foreground" /> <Wrench className="size-4 shrink-0 text-muted-foreground" />
)} )}
<span className="flex-1 min-w-0 text-sm font-medium truncate"> <span className="min-w-0 flex-1 truncate text-sm font-medium">
{group.label} {group.label}
</span> </span>
{isExpanded ? (
<ChevronDown className="size-4 shrink-0 text-muted-foreground" />
) : (
<ChevronRight className="size-4 shrink-0 text-muted-foreground" />
)}
</button>
</CollapsibleTrigger>
<Switch <Switch
checked={!allDisabled} checked={!allDisabled}
onCheckedChange={() => toggleToolGroup(toolNames)} onCheckedChange={() => toggleToolGroup(toolNames)}
className="shrink-0" className="shrink-0"
/> />
</div> </div>
<CollapsibleContent className="pb-1">
{group.tools.map((tool) => {
const isDisabled = disabledToolsSet.has(tool.name);
return (
<div
key={tool.name}
className={cn(
"ml-8 flex items-center gap-3 px-4 py-1.5 rounded-md transition-colors",
"hover:bg-accent hover:text-accent-foreground",
!isDisabled && "text-primary"
)}
>
<span className="min-w-0 flex-1 truncate text-sm">
{formatToolName(tool.name)}
</span>
<Switch
checked={!isDisabled}
onCheckedChange={() => toggleTool(tool.name)}
className="shrink-0"
/>
</div>
);
})}
</CollapsibleContent>
</Collapsible>
);
})}
</div>
)}
{otherToolGroup && (
<div>
<div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none">
{otherToolGroup.label}
</div>
{otherToolGroup.tools.map((tool) => {
const isDisabled = disabledToolsSet.has(tool.name);
const ToolIcon = getToolIcon(tool.name);
return (
<div
key={tool.name}
className="flex w-full items-center gap-3 px-4 py-2 hover:bg-accent hover:text-accent-foreground transition-colors"
>
<ToolIcon className="size-4 shrink-0 text-muted-foreground" />
<span className="flex-1 min-w-0 text-sm font-medium truncate">
{formatToolName(tool.name)}
</span>
<Switch
checked={!isDisabled}
onCheckedChange={() => toggleTool(tool.name)}
className="shrink-0"
/>
</div>
); );
})} })}
</div> </div>
@ -1063,16 +1151,23 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
</Drawer> </Drawer>
</> </>
) : ( ) : (
<DropdownMenu onOpenChange={(open) => !open && setToolsPopoverOpen(false)}> <DropdownMenu
onOpenChange={(open) => {
if (!open) {
setToolsPopoverOpen(false);
setOpenConnectorSubmenu(null);
}
}}
>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<TooltipIconButton <TooltipIconButton
tooltip="Upload files, connect tools and more" tooltip="Upload files, manage tools and more"
side="bottom" side="bottom"
disableTooltip={toolsPopoverOpen} disableTooltip={toolsPopoverOpen}
variant="ghost" variant="ghost"
size="icon" size="icon"
className="h-9 w-9 rounded-full p-0 font-semibold text-xs text-muted-foreground transition-colors dark:border-muted-foreground/15 hover:bg-foreground/10 hover:text-foreground" className="h-9 w-9 rounded-full p-0 font-semibold text-xs text-muted-foreground transition-colors dark:border-muted-foreground/15 hover:bg-foreground/10 hover:text-foreground"
aria-label="Upload files, connect tools and more" aria-label="Upload files, manage tools and more"
data-joyride="connector-icon" data-joyride="connector-icon"
> >
<Plus className="size-5" /> <Plus className="size-5" />
@ -1113,7 +1208,13 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
/> />
</DropdownMenuItem> </DropdownMenuItem>
)} )}
<DropdownMenuSub open={toolsPopoverOpen} onOpenChange={setToolsPopoverOpen}> <DropdownMenuSub
open={toolsPopoverOpen}
onOpenChange={(open) => {
setToolsPopoverOpen(open);
if (!open) setOpenConnectorSubmenu(null);
}}
>
<DropdownMenuSubTrigger> <DropdownMenuSubTrigger>
<Settings2 className="h-4 w-4" /> <Settings2 className="h-4 w-4" />
Manage Tools Manage Tools
@ -1123,10 +1224,9 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
alignOffset={-192} alignOffset={-192}
collisionPadding={8} collisionPadding={8}
className="w-60 h-56 gap-1 overflow-y-auto overscroll-none" className="w-60 h-56 gap-1 overflow-y-auto overscroll-none"
onScroll={() => setOpenConnectorSubmenu(null)}
> >
{groupedTools {regularToolGroups.map((group) => (
.filter((g) => !g.connectorIcon)
.map((group) => (
<div key={group.label}> <div key={group.label}>
<div className="px-2 pt-1.5 pb-0.5 text-[10px] text-muted-foreground/80 font-normal select-none"> <div className="px-2 pt-1.5 pb-0.5 text-[10px] text-muted-foreground/80 font-normal select-none">
{group.label} {group.label}
@ -1161,28 +1261,29 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
})} })}
</div> </div>
))} ))}
{groupedTools.some((g) => g.connectorIcon) && ( {connectorToolGroups.length > 0 && (
<div> <div>
<div className="px-2 pt-1.5 pb-0.5 text-[10px] text-muted-foreground/80 font-normal select-none"> <div className="px-2 pt-1.5 pb-0.5 text-[10px] text-muted-foreground/80 font-normal select-none">
Connector Actions Connector Actions
</div> </div>
{groupedTools {connectorToolGroups.map((group) => {
.filter((g) => g.connectorIcon)
.map((group) => {
const iconKey = group.connectorIcon ?? ""; const iconKey = group.connectorIcon ?? "";
const iconInfo = CONNECTOR_TOOL_ICON_PATHS[iconKey]; const iconInfo = CONNECTOR_TOOL_ICON_PATHS[iconKey];
const toolNames = group.tools.map((t) => t.name); const toolNames = group.tools.map((t) => t.name);
const allDisabled = toolNames.every((n) => disabledToolsSet.has(n)); const allDisabled = toolNames.every((n) => disabledToolsSet.has(n));
return ( return (
<DropdownMenuItem <DropdownMenuSub
key={group.label} key={group.label}
onSelect={(e) => { open={openConnectorSubmenu === group.label}
e.preventDefault(); onOpenChange={(open) =>
toggleToolGroup(toolNames); setOpenConnectorSubmenu(open ? group.label : null)
}} }
>
<DropdownMenuSubTrigger
className={cn( className={cn(
"mb-1 last:mb-0 transition-all", "mb-1 last:mb-0 transition-all",
"hover:bg-accent hover:text-accent-foreground", "hover:bg-accent hover:text-accent-foreground",
"gap-1 [&>svg:last-child]:ml-0",
!allDisabled && "text-primary" !allDisabled && "text-primary"
)} )}
> >
@ -1198,10 +1299,82 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
) : ( ) : (
<Wrench className="h-4 w-4" /> <Wrench className="h-4 w-4" />
)} )}
<span className="flex-1 min-w-0 truncate">{group.label}</span> <span className="min-w-0 flex-1 truncate">{group.label}</span>
<Switch <Switch
checked={!allDisabled} checked={!allDisabled}
tabIndex={-1} tabIndex={-1}
onPointerDown={(event) => event.stopPropagation()}
onClick={(event) => event.stopPropagation()}
onCheckedChange={() => toggleToolGroup(toolNames)}
className="shrink-0 scale-[0.6]"
/>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent
collisionPadding={8}
className="w-60 max-h-56 overflow-y-auto overscroll-none"
>
{group.tools.map((tool) => {
const isDisabled = disabledToolsSet.has(tool.name);
return (
<DropdownMenuItem
key={tool.name}
onSelect={(e) => {
e.preventDefault();
toggleTool(tool.name);
}}
className={cn(
"mb-1 last:mb-0 transition-all",
"hover:bg-accent hover:text-accent-foreground",
!isDisabled && "text-primary"
)}
>
<span className="min-w-0 flex-1 truncate">
{formatToolName(tool.name)}
</span>
<Switch
checked={!isDisabled}
tabIndex={-1}
className="pointer-events-none shrink-0 scale-[0.6]"
/>
</DropdownMenuItem>
);
})}
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
);
})}
</div>
)}
{otherToolGroup && (
<div>
<div className="px-2 pt-1.5 pb-0.5 text-[10px] text-muted-foreground/80 font-normal select-none">
{otherToolGroup.label}
</div>
{otherToolGroup.tools.map((tool) => {
const isDisabled = disabledToolsSet.has(tool.name);
const ToolIcon = getToolIcon(tool.name);
return (
<DropdownMenuItem
key={tool.name}
onSelect={(e) => {
e.preventDefault();
toggleTool(tool.name);
}}
className={cn(
"mb-1 last:mb-0 transition-all",
"hover:bg-accent hover:text-accent-foreground",
!isDisabled && "text-primary"
)}
>
<ToolIcon className="h-4 w-4" />
<span className="flex-1 min-w-0 truncate">
{formatToolName(tool.name)}
</span>
<Switch
checked={!isDisabled}
tabIndex={-1}
className="pointer-events-none shrink-0 scale-[0.6]" className="pointer-events-none shrink-0 scale-[0.6]"
/> />
</DropdownMenuItem> </DropdownMenuItem>
@ -1300,7 +1473,13 @@ const TOOL_GROUPS: ToolGroup[] = [
}, },
{ {
label: "Generate", label: "Generate",
tools: ["generate_podcast", "generate_video_presentation", "generate_report", "generate_image"], tools: [
"generate_podcast",
"generate_video_presentation",
"generate_report",
"generate_resume",
"generate_image",
],
}, },
{ {
label: "Memory", label: "Memory",
@ -1308,15 +1487,27 @@ const TOOL_GROUPS: ToolGroup[] = [
}, },
{ {
label: "Gmail", label: "Gmail",
tools: ["create_gmail_draft", "update_gmail_draft", "send_gmail_email", "trash_gmail_email"], tools: [
"search_gmail",
"read_gmail_email",
"create_gmail_draft",
"update_gmail_draft",
"send_gmail_email",
"trash_gmail_email",
],
connectorIcon: "gmail", connectorIcon: "gmail",
tooltip: "Create drafts, update drafts, send emails, and trash emails in Gmail", tooltip: "Search, read, draft, update, send, and trash emails in Gmail",
}, },
{ {
label: "Google Calendar", label: "Google Calendar",
tools: ["create_calendar_event", "update_calendar_event", "delete_calendar_event"], tools: [
"search_calendar_events",
"create_calendar_event",
"update_calendar_event",
"delete_calendar_event",
],
connectorIcon: "google_calendar", connectorIcon: "google_calendar",
tooltip: "Create, update, and delete events in Google Calendar", tooltip: "Search, create, update, and delete events in Google Calendar",
}, },
{ {
label: "Google Drive", label: "Google Drive",
@ -1360,6 +1551,24 @@ const TOOL_GROUPS: ToolGroup[] = [
connectorIcon: "confluence", connectorIcon: "confluence",
tooltip: "Create, update, and delete pages in Confluence", tooltip: "Create, update, and delete pages in Confluence",
}, },
{
label: "Discord",
tools: ["list_discord_channels", "read_discord_messages", "send_discord_message"],
connectorIcon: "discord",
tooltip: "List channels, read messages, and send messages in Discord",
},
{
label: "Microsoft Teams",
tools: ["list_teams_channels", "read_teams_messages", "send_teams_message"],
connectorIcon: "teams",
tooltip: "List channels, read messages, and send messages in Microsoft Teams",
},
{
label: "Luma",
tools: ["list_luma_events", "read_luma_event", "create_luma_event"],
connectorIcon: "luma",
tooltip: "List, read, and create events in Luma",
},
]; ];
const EditComposer: FC = () => { const EditComposer: FC = () => {

View file

@ -33,7 +33,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content" data-slot="dropdown-menu-content"
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md p-1 shadow-md", "bg-popover text-popover-foreground border border-popover-border data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md p-1 shadow-md",
className className
)} )}
{...props} {...props}
@ -201,7 +201,7 @@ function DropdownMenuSubContent({
<DropdownMenuPrimitive.SubContent <DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content" data-slot="dropdown-menu-sub-content"
className={cn( className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md p-1 shadow-lg", "bg-popover text-popover-foreground border border-popover-border data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md p-1 shadow-lg",
className className
)} )}
{...props} {...props}

View file

@ -2,7 +2,6 @@ import {
BookOpen, BookOpen,
Brain, Brain,
Calendar, Calendar,
Check,
FileEdit, FileEdit,
FilePlus, FilePlus,
FileText, FileText,
@ -23,6 +22,7 @@ import {
Podcast, Podcast,
ScanLine, ScanLine,
Search, Search,
SearchCheck,
Send, Send,
Trash2, Trash2,
Wrench, Wrench,
@ -104,7 +104,7 @@ const TOOL_ICONS: Record<string, LucideIcon> = {
read_luma_event: Calendar, read_luma_event: Calendar,
create_luma_event: Calendar, create_luma_event: Calendar,
// Misc // Misc
get_connected_accounts: Check, get_connected_accounts: SearchCheck,
execute: Wrench, execute: Wrench,
execute_code: Wrench, execute_code: Wrench,
}; };
@ -200,7 +200,7 @@ const TOOL_DISPLAY_NAMES: Record<string, string> = {
read_luma_event: "Read Luma event", read_luma_event: "Read Luma event",
create_luma_event: "Create Luma event", create_luma_event: "Create Luma event",
// Misc // Misc
get_connected_accounts: "Check connected accounts", get_connected_accounts: "Discover connected accounts",
execute: "Run command", execute: "Run command",
execute_code: "Run code", execute_code: "Run code",
}; };
@ -228,6 +228,9 @@ export const CONNECTOR_TOOL_ICON_PATHS: Record<string, { src: string; alt: strin
linear: { src: "/connectors/linear.svg", alt: "Linear" }, linear: { src: "/connectors/linear.svg", alt: "Linear" },
jira: { src: "/connectors/jira.svg", alt: "Jira" }, jira: { src: "/connectors/jira.svg", alt: "Jira" },
confluence: { src: "/connectors/confluence.svg", alt: "Confluence" }, confluence: { src: "/connectors/confluence.svg", alt: "Confluence" },
discord: { src: "/connectors/discord.svg", alt: "Discord" },
teams: { src: "/connectors/microsoft-teams.svg", alt: "Microsoft Teams" },
luma: { src: "/connectors/luma.svg", alt: "Luma" },
}; };
export const CONNECTOR_ICON_TO_TYPES: Record<string, string[]> = { export const CONNECTOR_ICON_TO_TYPES: Record<string, string[]> = {
@ -240,4 +243,7 @@ export const CONNECTOR_ICON_TO_TYPES: Record<string, string[]> = {
linear: ["LINEAR_CONNECTOR"], linear: ["LINEAR_CONNECTOR"],
jira: ["JIRA_CONNECTOR"], jira: ["JIRA_CONNECTOR"],
confluence: ["CONFLUENCE_CONNECTOR"], confluence: ["CONFLUENCE_CONNECTOR"],
discord: ["DISCORD_CONNECTOR"],
teams: ["TEAMS_CONNECTOR"],
luma: ["LUMA_CONNECTOR"],
}; };