From 77d2d04a030c729c1a71747cc827afd922317c9d Mon Sep 17 00:00:00 2001 From: marko-kraemer Date: Thu, 9 Oct 2025 17:17:17 +0200 Subject: [PATCH] fix granular tool --- backend/core/agentpress/tool.py | 6 +- backend/core/tools/paper_search_tool.py | 2 +- backend/core/utils/TOOL_AUTO_GENERATION.md | 4 +- backend/core/utils/tool_discovery.py | 2 +- .../tools/granular-tool-configuration.tsx | 11 +- .../components/agents/tools/tool-groups.ts | 11 +- .../components/dashboard/suna-modes-panel.tsx | 242 ++++++++---------- .../react-query/tools/use-tools-metadata.ts | 16 +- 8 files changed, 150 insertions(+), 144 deletions(-) diff --git a/backend/core/agentpress/tool.py b/backend/core/agentpress/tool.py index d661bed3..2ece23c0 100644 --- a/backend/core/agentpress/tool.py +++ b/backend/core/agentpress/tool.py @@ -71,12 +71,12 @@ class MethodMetadata: display_name (str): Human-readable method name description (str): Method description is_core (bool): Whether this is a core method (always enabled) - visible (bool): Whether method is visible in frontend UI (default False) + visible (bool): Whether method is visible in frontend UI (default True) """ display_name: str description: str is_core: bool = False - visible: bool = False + visible: bool = True class Tool(ABC): """Abstract base class for all tools. @@ -254,7 +254,7 @@ def method_metadata( display_name: str, description: str, is_core: bool = False, - visible: bool = False + visible: bool = True ): """Decorator to add metadata to a tool method. diff --git a/backend/core/tools/paper_search_tool.py b/backend/core/tools/paper_search_tool.py index 21992ef2..3b46b1a9 100644 --- a/backend/core/tools/paper_search_tool.py +++ b/backend/core/tools/paper_search_tool.py @@ -19,7 +19,7 @@ from core.services.supabase import DBConnection icon="FileText", color="bg-emerald-100 dark:bg-emerald-800/50", weight=270, - visible=True + visible=False ) class PaperSearchTool(Tool): def __init__(self, thread_manager: ThreadManager): diff --git a/backend/core/utils/TOOL_AUTO_GENERATION.md b/backend/core/utils/TOOL_AUTO_GENERATION.md index 2faf6f4b..09fad4f3 100644 --- a/backend/core/utils/TOOL_AUTO_GENERATION.md +++ b/backend/core/utils/TOOL_AUTO_GENERATION.md @@ -268,7 +268,9 @@ def ask(self, question: str): ## 👁️ Visible in UI -**Default:** `visible = True` (both tool and method level) +**Default:** +- **Tool level:** `visible = False` (tools hidden by default) +- **Method level:** `visible = True` (methods visible by default) Controls whether a tool/method is shown in the frontend UI. diff --git a/backend/core/utils/tool_discovery.py b/backend/core/utils/tool_discovery.py index edf8f7b8..e7142c31 100644 --- a/backend/core/utils/tool_discovery.py +++ b/backend/core/utils/tool_discovery.py @@ -222,7 +222,7 @@ def _extract_tool_metadata(tool_name: str, tool_class: Type[Tool]) -> Dict[str, method_info["description"] = f"{method_name} function" method_info["is_core"] = False - method_info["visible"] = False + method_info["visible"] = True metadata["methods"].append(method_info) except Exception as e: diff --git a/frontend/src/components/agents/tools/granular-tool-configuration.tsx b/frontend/src/components/agents/tools/granular-tool-configuration.tsx index a8db4928..c0b251b2 100644 --- a/frontend/src/components/agents/tools/granular-tool-configuration.tsx +++ b/frontend/src/components/agents/tools/granular-tool-configuration.tsx @@ -206,7 +206,10 @@ export const GranularToolConfiguration = ({ const toolGroup = getToolGroup(toolName, toolsData); if (!toolGroup) return 0; - return toolGroup.methods.filter(method => isMethodEnabled(toolName, method.name)).length; + // Only count visible methods + return toolGroup.methods + .filter(method => method.visible !== false) + .filter(method => isMethodEnabled(toolName, method.name)).length; }; const filteredGroups = getFilteredToolGroups(); @@ -251,7 +254,7 @@ export const GranularToolConfiguration = ({ const isGroupEnabled = isToolGroupEnabled(toolGroup.name); const isExpanded = expandedGroups.has(toolGroup.name); const enabledMethodsCount = getEnabledMethodsCount(toolGroup.name); - const totalMethodsCount = toolGroup.methods.length; + const totalMethodsCount = toolGroup.methods.filter(m => m.visible !== false).length; const IconComponent = getIconComponent(toolGroup.icon); const hasGranular = hasGranularControl(toolGroup.name, toolsData); @@ -323,7 +326,9 @@ export const GranularToolConfiguration = ({ - {toolGroup.methods.map((method) => { + {toolGroup.methods + .filter(method => method.visible !== false) // Only show visible methods + .map((method) => { const isMethodEnabledState = isMethodEnabled(toolGroup.name, method.name); return ( diff --git a/frontend/src/components/agents/tools/tool-groups.ts b/frontend/src/components/agents/tools/tool-groups.ts index 75a2e410..e7b0d15a 100644 --- a/frontend/src/components/agents/tools/tool-groups.ts +++ b/frontend/src/components/agents/tools/tool-groups.ts @@ -57,13 +57,13 @@ export function normalizeToolGroup(apiToolGroup: any): ToolGroup { enabled: m.enabled ?? true, isCore: m.is_core || m.isCore, is_core: m.is_core, - visible: m.visible ?? false, // Default false - tools must explicitly set visible=True + visible: m.visible, // Use API value directly - backend controls visibility })) || [], enabled: apiToolGroup.enabled ?? true, isCore: apiToolGroup.is_core || apiToolGroup.isCore, is_core: apiToolGroup.is_core, weight: apiToolGroup.weight ?? 100, - visible: apiToolGroup.visible ?? false, // Default false - tools must explicitly set visible=True + visible: apiToolGroup.visible, // Use API value directly - backend controls visibility }; } @@ -91,7 +91,12 @@ export function getAllToolGroups(toolsData?: Record): Record): boolean { const group = getToolGroup(toolName, toolsData); - return group ? group.methods.length > 1 : false; + if (!group) return false; + + // Only count visible methods for granular control (visible=true or visible=undefined counts as visible) + const visibleMethods = group.methods.filter(m => m.visible !== false); + console.log(`[hasGranularControl] ${toolName}: ${group.methods.length} total methods, ${visibleMethods.length} visible`, group.methods.map(m => ({ name: m.name, visible: m.visible }))); + return visibleMethods.length > 1; } export function getEnabledMethodsForTool( diff --git a/frontend/src/components/dashboard/suna-modes-panel.tsx b/frontend/src/components/dashboard/suna-modes-panel.tsx index 7422fd71..d9b4bf0c 100644 --- a/frontend/src/components/dashboard/suna-modes-panel.tsx +++ b/frontend/src/components/dashboard/suna-modes-panel.tsx @@ -11,7 +11,6 @@ import { FileText, Search, Users, - Code2, RefreshCw, } from 'lucide-react'; import { Button } from '@/components/ui/button'; @@ -25,7 +24,7 @@ interface SunaModesPanelProps { isMobile?: boolean; } -type ModeType = 'research' | 'people' | 'code' | 'docs' | 'data' | 'slides' | 'image'; +type ModeType = 'image' | 'slides' | 'data' | 'docs' | 'people' | 'research'; interface Mode { id: ModeType; @@ -53,83 +52,74 @@ interface Mode { const modes: Mode[] = [ { - id: 'research', - label: 'Research', - icon: , + id: 'image', + label: 'Image', + icon: , samplePrompts: [ - 'Analyze emerging trends in quantum computing and potential business applications', - 'Research top 10 competitors in the AI-powered CRM space with feature comparison', - 'Investigate regulatory requirements for launching a fintech app in the EU', - 'Compile market analysis on electric vehicle adoption rates across major markets', - 'Study the impact of remote work on commercial real estate demand in major cities', - 'Research Web3 adoption patterns among Fortune 500 companies', - 'Analyze consumer sentiment towards sustainable fashion brands', - 'Investigate the latest developments in gene therapy for rare diseases', - 'Study pricing strategies of successful D2C subscription box companies', - 'Research the competitive landscape of AI-powered cybersecurity solutions', + 'A majestic golden eagle soaring through misty mountain peaks at sunrise with dramatic lighting', + 'Close-up portrait of a fashion model with avant-garde makeup, studio lighting, high contrast shadows', + 'Cozy Scandinavian living room with natural wood furniture, indoor plants, and soft morning sunlight', + 'Futuristic cyberpunk street market at night with neon signs, rain-slicked pavement, and holographic displays', + 'Elegant product photography of luxury perfume bottle on marble surface with soft reflections', + 'Whimsical floating islands connected by rope bridges in a pastel sky with dreamy clouds', + 'Macro close-up of morning dew drops on vibrant flower petals with bokeh background', + 'Modern workspace desk setup with laptop, coffee, notebook, and succulent plants from above', + 'Mystical forest path with ancient trees, glowing fireflies, and ethereal light beams through fog', + 'Architectural detail of contemporary glass building facade with geometric patterns and reflections', + 'Vibrant street food vendor stall with colorful ingredients, steam rising, and warm lighting', + 'Serene Japanese zen garden with raked sand, moss-covered stones, and cherry blossom petals', + 'Dynamic action shot of athlete mid-jump against dramatic sunset sky, silhouette effect', + 'Rustic farmhouse kitchen with copper pots, fresh herbs, wooden cutting boards, and natural textures', + 'Abstract fluid art with swirling metallic gold, deep blue, and emerald green organic patterns', ], + options: { + title: 'Choose a style', + items: [ + { id: 'photorealistic', name: 'Photorealistic', image: '/images/image-styles/photorealistic_eagle-min.png' }, + { id: 'watercolor', name: 'Watercolor', image: '/images/image-styles/watercolor_garden-min.png' }, + { id: 'digital-art', name: 'Digital Art', image: '/images/image-styles/digital_art_cyberpunk-min.png' }, + { id: 'oil-painting', name: 'Oil Painting', image: '/images/image-styles/oil_painting_villa-min.png' }, + { id: 'minimalist', name: 'Minimalist', image: '/images/image-styles/minimalist_coffee-min.png' }, + { id: 'isometric', name: 'Isometric', image: '/images/image-styles/isometric_bedroom-min.png' }, + { id: 'vintage', name: 'Vintage', image: '/images/image-styles/vintage_diner-min.png' }, + { id: 'comic', name: 'Comic Book', image: '/images/image-styles/comic_book_robot-min.png' }, + { id: 'neon', name: 'Neon', image: '/images/image-styles/neon_jellyfish-min.png' }, + { id: 'pastel', name: 'Pastel', image: '/images/image-styles/pastel_landscape-min.png' }, + { id: 'geometric', name: 'Geometric', image: '/images/image-styles/geometric_crystal-min.png' }, + { id: 'abstract', name: 'Abstract', image: '/images/image-styles/abstract_organic-min.png' }, + { id: 'anime', name: 'Anime', image: '/images/image-styles/anime_forest-min.png' }, + { id: 'impressionist', name: 'Impressionist', image: '/images/image-styles/impressionist_garden-min.png' }, + { id: 'surreal', name: 'Surreal', image: '/images/image-styles/surreal_islands-min.png' }, + ], + }, }, { - id: 'people', - label: 'People', - icon: , + id: 'slides', + label: 'Slides', + icon: , samplePrompts: [ - 'Find VP of Engineering candidates at Series B+ AI companies in NYC', - 'Build lead list of CMOs at SaaS companies with 50-200 employees', - 'Research blockchain developers with Solidity experience open to relocation', - 'Generate prospect list of tech founders who raised funding in the last 6 months', - 'Identify Product Managers at fintech startups with 5+ years experience', - 'Find decision-makers at mid-market companies in healthcare IT', - 'Research sales leaders at B2B companies with recent ARR growth', - 'Build list of CTOs at enterprise companies adopting AI infrastructure', - 'Find UX designers with experience in mobile-first e-commerce', - 'Identify DevOps engineers at cloud-native startups in Austin', - ], - }, - { - id: 'code', - label: 'Code', - icon: , - samplePrompts: [ - 'Build a modern landing page with React, Tailwind CSS, and smooth animations', - 'Create a Python script to scrape product data and generate CSV reports', - 'Develop a REST API with authentication and rate limiting', - 'Build an interactive data dashboard with real-time charts and filters', - 'Create a Chrome extension to track time spent on websites', - 'Build a Node.js backend with PostgreSQL and Redis caching', - 'Develop a real-time chat application with WebSocket support', - 'Create an automated email campaign system with analytics', - 'Build a portfolio website with dark mode and CMS integration', - 'Develop a Python CLI tool for automating deployment workflows', - ], - }, - { - id: 'docs', - label: 'Docs', - icon: , - samplePrompts: [ - 'Write a comprehensive PRD for an AI-powered recommendation engine', - 'Draft a technical architecture document for a scalable microservices platform', - 'Create a go-to-market strategy document for our Q2 product launch', - 'Develop a 90-day onboarding playbook for engineering managers', - 'Write an API documentation guide with examples and best practices', - 'Create a company handbook covering culture, policies, and benefits', - 'Draft a data privacy policy compliant with GDPR and CCPA', - 'Develop a customer success playbook for SaaS enterprise accounts', - 'Write a security incident response plan with escalation procedures', - 'Create a comprehensive style guide for brand and content', + 'Create a Series A pitch deck with market size, traction, and financial projections', + 'Build a Q4 business review showcasing KPIs, wins, and strategic initiatives', + 'Design a product launch presentation with demo videos and customer testimonials', + 'Develop a sales enablement deck explaining our value prop and competitive advantages', + 'Create an investor update highlighting key metrics and upcoming milestones', + 'Build a customer case study presentation showing ROI and success metrics', + 'Design an all-hands presentation covering company updates and vision', + 'Develop a training deck for new product features and workflows', + 'Create a conference talk about scaling engineering teams', + 'Build a board meeting presentation with strategic recommendations', ], options: { title: 'Choose a template', items: [ - { id: 'prd', name: 'PRD', description: 'Product requirements document' }, - { id: 'technical', name: 'Technical', description: 'Technical documentation' }, - { id: 'proposal', name: 'Proposal', description: 'Business proposal' }, - { id: 'report', name: 'Report', description: 'Detailed report format' }, - { id: 'guide', name: 'Guide', description: 'Step-by-step guide' }, - { id: 'wiki', name: 'Wiki', description: 'Knowledge base article' }, - { id: 'policy', name: 'Policy', description: 'Policy document' }, - { id: 'meeting-notes', name: 'Meeting Notes', description: 'Meeting minutes' }, + { id: 'modern', name: 'Modern', description: 'Clean and professional' }, + { id: 'bold', name: 'Bold', description: 'High impact design' }, + { id: 'elegant', name: 'Elegant', description: 'Sophisticated style' }, + { id: 'tech', name: 'Tech', description: 'Technology focused' }, + { id: 'creative', name: 'Creative', description: 'Artistic and unique' }, + { id: 'minimal', name: 'Minimal', description: 'Simple and clear' }, + { id: 'corporate', name: 'Corporate', description: 'Business standard' }, + { id: 'vibrant', name: 'Vibrant', description: 'Colorful and energetic' }, ], }, }, @@ -175,76 +165,68 @@ const modes: Mode[] = [ }, }, { - id: 'slides', - label: 'Slides', - icon: , + id: 'docs', + label: 'Docs', + icon: , samplePrompts: [ - 'Create a Series A pitch deck with market size, traction, and financial projections', - 'Build a Q4 business review showcasing KPIs, wins, and strategic initiatives', - 'Design a product launch presentation with demo videos and customer testimonials', - 'Develop a sales enablement deck explaining our value prop and competitive advantages', - 'Create an investor update highlighting key metrics and upcoming milestones', - 'Build a customer case study presentation showing ROI and success metrics', - 'Design an all-hands presentation covering company updates and vision', - 'Develop a training deck for new product features and workflows', - 'Create a conference talk about scaling engineering teams', - 'Build a board meeting presentation with strategic recommendations', + 'Write a comprehensive PRD for an AI-powered recommendation engine', + 'Draft a technical architecture document for a scalable microservices platform', + 'Create a go-to-market strategy document for our Q2 product launch', + 'Develop a 90-day onboarding playbook for engineering managers', + 'Write an API documentation guide with examples and best practices', + 'Create a company handbook covering culture, policies, and benefits', + 'Draft a data privacy policy compliant with GDPR and CCPA', + 'Develop a customer success playbook for SaaS enterprise accounts', + 'Write a security incident response plan with escalation procedures', + 'Create a comprehensive style guide for brand and content', ], options: { title: 'Choose a template', items: [ - { id: 'modern', name: 'Modern', description: 'Clean and professional' }, - { id: 'bold', name: 'Bold', description: 'High impact design' }, - { id: 'elegant', name: 'Elegant', description: 'Sophisticated style' }, - { id: 'tech', name: 'Tech', description: 'Technology focused' }, - { id: 'creative', name: 'Creative', description: 'Artistic and unique' }, - { id: 'minimal', name: 'Minimal', description: 'Simple and clear' }, - { id: 'corporate', name: 'Corporate', description: 'Business standard' }, - { id: 'vibrant', name: 'Vibrant', description: 'Colorful and energetic' }, + { id: 'prd', name: 'PRD', description: 'Product requirements document' }, + { id: 'technical', name: 'Technical', description: 'Technical documentation' }, + { id: 'proposal', name: 'Proposal', description: 'Business proposal' }, + { id: 'report', name: 'Report', description: 'Detailed report format' }, + { id: 'guide', name: 'Guide', description: 'Step-by-step guide' }, + { id: 'wiki', name: 'Wiki', description: 'Knowledge base article' }, + { id: 'policy', name: 'Policy', description: 'Policy document' }, + { id: 'meeting-notes', name: 'Meeting Notes', description: 'Meeting minutes' }, ], }, }, { - id: 'image', - label: 'Image', - icon: , + id: 'people', + label: 'People', + icon: , samplePrompts: [ - 'A majestic golden eagle soaring through misty mountain peaks at sunrise with dramatic lighting', - 'Close-up portrait of a fashion model with avant-garde makeup, studio lighting, high contrast shadows', - 'Cozy Scandinavian living room with natural wood furniture, indoor plants, and soft morning sunlight', - 'Futuristic cyberpunk street market at night with neon signs, rain-slicked pavement, and holographic displays', - 'Elegant product photography of luxury perfume bottle on marble surface with soft reflections', - 'Whimsical floating islands connected by rope bridges in a pastel sky with dreamy clouds', - 'Macro close-up of morning dew drops on vibrant flower petals with bokeh background', - 'Modern workspace desk setup with laptop, coffee, notebook, and succulent plants from above', - 'Mystical forest path with ancient trees, glowing fireflies, and ethereal light beams through fog', - 'Architectural detail of contemporary glass building facade with geometric patterns and reflections', - 'Vibrant street food vendor stall with colorful ingredients, steam rising, and warm lighting', - 'Serene Japanese zen garden with raked sand, moss-covered stones, and cherry blossom petals', - 'Dynamic action shot of athlete mid-jump against dramatic sunset sky, silhouette effect', - 'Rustic farmhouse kitchen with copper pots, fresh herbs, wooden cutting boards, and natural textures', - 'Abstract fluid art with swirling metallic gold, deep blue, and emerald green organic patterns', + 'Find VP of Engineering candidates at Series B+ AI companies in NYC', + 'Build lead list of CMOs at SaaS companies with 50-200 employees', + 'Research blockchain developers with Solidity experience open to relocation', + 'Generate prospect list of tech founders who raised funding in the last 6 months', + 'Identify Product Managers at fintech startups with 5+ years experience', + 'Find decision-makers at mid-market companies in healthcare IT', + 'Research sales leaders at B2B companies with recent ARR growth', + 'Build list of CTOs at enterprise companies adopting AI infrastructure', + 'Find UX designers with experience in mobile-first e-commerce', + 'Identify DevOps engineers at cloud-native startups in Austin', + ], + }, + { + id: 'research', + label: 'Research', + icon: , + samplePrompts: [ + 'Analyze emerging trends in quantum computing and potential business applications', + 'Research top 10 competitors in the AI-powered CRM space with feature comparison', + 'Investigate regulatory requirements for launching a fintech app in the EU', + 'Compile market analysis on electric vehicle adoption rates across major markets', + 'Study the impact of remote work on commercial real estate demand in major cities', + 'Research Web3 adoption patterns among Fortune 500 companies', + 'Analyze consumer sentiment towards sustainable fashion brands', + 'Investigate the latest developments in gene therapy for rare diseases', + 'Study pricing strategies of successful D2C subscription box companies', + 'Research the competitive landscape of AI-powered cybersecurity solutions', ], - options: { - title: 'Choose a style', - items: [ - { id: 'photorealistic', name: 'Photorealistic', image: '/images/image-styles/photorealistic_eagle-min.png' }, - { id: 'watercolor', name: 'Watercolor', image: '/images/image-styles/watercolor_garden-min.png' }, - { id: 'digital-art', name: 'Digital Art', image: '/images/image-styles/digital_art_cyberpunk-min.png' }, - { id: 'oil-painting', name: 'Oil Painting', image: '/images/image-styles/oil_painting_villa-min.png' }, - { id: 'minimalist', name: 'Minimalist', image: '/images/image-styles/minimalist_coffee-min.png' }, - { id: 'isometric', name: 'Isometric', image: '/images/image-styles/isometric_bedroom-min.png' }, - { id: 'vintage', name: 'Vintage', image: '/images/image-styles/vintage_diner-min.png' }, - { id: 'comic', name: 'Comic Book', image: '/images/image-styles/comic_book_robot-min.png' }, - { id: 'neon', name: 'Neon', image: '/images/image-styles/neon_jellyfish-min.png' }, - { id: 'pastel', name: 'Pastel', image: '/images/image-styles/pastel_landscape-min.png' }, - { id: 'geometric', name: 'Geometric', image: '/images/image-styles/geometric_crystal-min.png' }, - { id: 'abstract', name: 'Abstract', image: '/images/image-styles/abstract_organic-min.png' }, - { id: 'anime', name: 'Anime', image: '/images/image-styles/anime_forest-min.png' }, - { id: 'impressionist', name: 'Impressionist', image: '/images/image-styles/impressionist_garden-min.png' }, - { id: 'surreal', name: 'Surreal', image: '/images/image-styles/surreal_islands-min.png' }, - ], - }, }, ]; @@ -347,7 +329,7 @@ export function SunaModesPanel({ selectedMode, onModeSelect, onSelectPrompt, isM )} - {/* Sample Prompts - Card Grid Style (for code, docs, data, slides, image) */} + {/* Sample Prompts - Card Grid Style (for image, slides, data, docs) */} {selectedMode && displayedPrompts && !['research', 'people'].includes(selectedMode) && (
diff --git a/frontend/src/hooks/react-query/tools/use-tools-metadata.ts b/frontend/src/hooks/react-query/tools/use-tools-metadata.ts index f04de4bf..7984bd06 100644 --- a/frontend/src/hooks/react-query/tools/use-tools-metadata.ts +++ b/frontend/src/hooks/react-query/tools/use-tools-metadata.ts @@ -37,11 +37,23 @@ export function useToolsMetadata() { return useQuery({ queryKey: ['tools', 'metadata'], queryFn: async () => { - const response = await backendApi.get('/tools'); + const response = await backendApi.get<{ success: boolean; tools: ToolMetadata[] }>('/tools'); if (!response.success || !response.data) { throw new Error('Failed to fetch tools metadata'); } - return response.data; + + // Backend returns array, convert to object keyed by tool name + const toolsArray = response.data.tools; + const toolsObject: Record = {}; + + for (const tool of toolsArray) { + toolsObject[tool.name] = tool; + } + + return { + success: response.data.success, + tools: toolsObject + }; }, staleTime: 1000 * 60 * 60, // Cache for 1 hour since tools don't change frequently gcTime: 1000 * 60 * 60 * 24, // Keep in cache for 24 hours