mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-29 02:46:25 +02:00
feat: implement tool grouping in ComposerAction for improved UI organization
This commit is contained in:
parent
591bd6bb46
commit
e5180aa0a3
1 changed files with 113 additions and 57 deletions
|
|
@ -614,6 +614,32 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
);
|
);
|
||||||
}, [filteredTools, disabledTools]);
|
}, [filteredTools, disabledTools]);
|
||||||
|
|
||||||
|
const groupedTools = useMemo(() => {
|
||||||
|
if (!filteredTools) return [];
|
||||||
|
const toolsByName = new Map(filteredTools.map((t) => [t.name, t]));
|
||||||
|
const result: { label: string; tools: typeof filteredTools }[] = [];
|
||||||
|
const placed = new Set<string>();
|
||||||
|
|
||||||
|
for (const group of TOOL_GROUPS) {
|
||||||
|
const matched = group.tools.flatMap((name) => {
|
||||||
|
const tool = toolsByName.get(name);
|
||||||
|
if (!tool) return [];
|
||||||
|
placed.add(name);
|
||||||
|
return [tool];
|
||||||
|
});
|
||||||
|
if (matched.length > 0) {
|
||||||
|
result.push({ label: group.label, tools: matched });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ungrouped = filteredTools.filter((t) => !placed.has(t.name));
|
||||||
|
if (ungrouped.length > 0) {
|
||||||
|
result.push({ label: "Other", tools: ungrouped });
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [filteredTools]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
hydrateDisabled();
|
hydrateDisabled();
|
||||||
}, [hydrateDisabled]);
|
}, [hydrateDisabled]);
|
||||||
|
|
@ -669,7 +695,12 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-y-auto pb-6" onScroll={handleToolsScroll}>
|
<div className="overflow-y-auto pb-6" onScroll={handleToolsScroll}>
|
||||||
{filteredTools?.map((tool) => {
|
{groupedTools.map((group) => (
|
||||||
|
<div key={group.label}>
|
||||||
|
<div className="px-4 pt-3 pb-1 text-xs text-muted-foreground/80 font-medium select-none">
|
||||||
|
{group.label}
|
||||||
|
</div>
|
||||||
|
{group.tools.map((tool) => {
|
||||||
const isDisabled = disabledTools.includes(tool.name);
|
const isDisabled = disabledTools.includes(tool.name);
|
||||||
const ToolIcon = getToolIcon(tool.name);
|
const ToolIcon = getToolIcon(tool.name);
|
||||||
return (
|
return (
|
||||||
|
|
@ -689,6 +720,8 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
{!filteredTools?.length && (
|
{!filteredTools?.length && (
|
||||||
<div className="px-4 py-6 text-center text-sm text-muted-foreground">
|
<div className="px-4 py-6 text-center text-sm text-muted-foreground">
|
||||||
Loading tools...
|
Loading tools...
|
||||||
|
|
@ -744,7 +777,12 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
WebkitMaskImage: `linear-gradient(to bottom, ${toolsScrollPos === "top" ? "black" : "transparent"}, black 16px, black calc(100% - 16px), ${toolsScrollPos === "bottom" ? "black" : "transparent"})`,
|
WebkitMaskImage: `linear-gradient(to bottom, ${toolsScrollPos === "top" ? "black" : "transparent"}, black 16px, black calc(100% - 16px), ${toolsScrollPos === "bottom" ? "black" : "transparent"})`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{filteredTools?.map((tool) => {
|
{groupedTools.map((group) => (
|
||||||
|
<div key={group.label}>
|
||||||
|
<div className="px-2.5 sm:px-3 pt-2 pb-0.5 text-[10px] sm:text-xs text-muted-foreground/80 font-normal select-none">
|
||||||
|
{group.label}
|
||||||
|
</div>
|
||||||
|
{group.tools.map((tool) => {
|
||||||
const isDisabled = disabledTools.includes(tool.name);
|
const isDisabled = disabledTools.includes(tool.name);
|
||||||
const ToolIcon = getToolIcon(tool.name);
|
const ToolIcon = getToolIcon(tool.name);
|
||||||
const row = (
|
const row = (
|
||||||
|
|
@ -769,6 +807,8 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
{!filteredTools?.length && (
|
{!filteredTools?.length && (
|
||||||
<div className="px-3 py-4 text-center text-xs text-muted-foreground">
|
<div className="px-3 py-4 text-center text-xs text-muted-foreground">
|
||||||
Loading tools...
|
Loading tools...
|
||||||
|
|
@ -783,7 +823,7 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => toggleTool("web_search")}
|
onClick={() => toggleTool("web_search")}
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-full transition-all flex items-center gap-1 px-2 py-1 border h-8",
|
"rounded-full transition-all flex items-center gap-1 px-2 py-1 border h-8 select-none",
|
||||||
isWebSearchEnabled
|
isWebSearchEnabled
|
||||||
? "bg-sky-500/15 border-sky-500/60 text-sky-500"
|
? "bg-sky-500/15 border-sky-500/60 text-sky-500"
|
||||||
: "bg-transparent border-transparent text-muted-foreground hover:text-foreground"
|
: "bg-transparent border-transparent text-muted-foreground hover:text-foreground"
|
||||||
|
|
@ -891,6 +931,22 @@ function formatToolName(name: string): string {
|
||||||
.join(" ");
|
.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TOOL_GROUPS: { label: string; tools: string[] }[] = [
|
||||||
|
{
|
||||||
|
label: "Research",
|
||||||
|
tools: ["search_knowledge_base", "search_surfsense_docs", "scrape_webpage", "link_preview"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Generate",
|
||||||
|
tools: ["generate_podcast", "generate_report", "generate_image", "display_image"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Memory",
|
||||||
|
tools: ["save_memory", "recall_memory"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
const MessageError: FC = () => {
|
const MessageError: FC = () => {
|
||||||
return (
|
return (
|
||||||
<MessagePrimitive.Error>
|
<MessagePrimitive.Error>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue