chore: show all tools in config

This commit is contained in:
Saumya 2025-09-25 13:29:03 +05:30
parent b6aef872c7
commit d226e38809
8 changed files with 165 additions and 56 deletions

View File

@ -5,6 +5,7 @@ from core.utils.auth_utils import verify_and_get_user_id_from_jwt
from core.utils.logger import logger
from core.utils.config import config, EnvMode
from core.utils.pagination import PaginationParams
from core.utils.core_tools_helper import ensure_core_tools_enabled
from core.ai_models import model_manager
from .api_models import (
@ -261,6 +262,7 @@ async def update_agent(
current_custom_mcps = current_version_data.get('custom_mcps', [])
current_agentpress_tools = agent_data.agentpress_tools if agent_data.agentpress_tools is not None else current_version_data.get('agentpress_tools', {})
current_agentpress_tools = ensure_core_tools_enabled(current_agentpress_tools)
new_version_id = None
if needs_new_version:
try:
@ -736,6 +738,7 @@ async def create_agent(
system_prompt = SUNA_CONFIG["system_prompt"]
agentpress_tools = agent_data.agentpress_tools if agent_data.agentpress_tools else _get_default_agentpress_tools()
agentpress_tools = ensure_core_tools_enabled(agentpress_tools)
default_model = await model_manager.get_default_model_for_user(client, user_id)

View File

@ -4,6 +4,7 @@ from core.agentpress.tool import ToolResult, openapi_schema, usage_example
from core.agentpress.thread_manager import ThreadManager
from .base_tool import AgentBuilderBaseTool
from core.utils.logger import logger
from core.utils.core_tools_helper import ensure_core_tools_enabled, is_core_tool
@ -158,9 +159,9 @@ class AgentConfigTool(AgentBuilderBaseTool):
formatted_tools[tool_name] = tool_config.get("enabled", False)
else:
formatted_tools[tool_name] = bool(tool_config)
current_agentpress_tools = formatted_tools
current_agentpress_tools = ensure_core_tools_enabled(formatted_tools)
else:
current_agentpress_tools = current_version.get('agentpress_tools', {})
current_agentpress_tools = ensure_core_tools_enabled(current_version.get('agentpress_tools', {}))
current_configured_mcps = current_version.get('configured_mcps', [])
if configured_mcps is not None:

View File

@ -4,6 +4,7 @@ from uuid import uuid4
from core.agentpress.tool import Tool, ToolResult, openapi_schema, usage_example
from core.agentpress.thread_manager import ThreadManager
from core.utils.logger import logger
from core.utils.core_tools_helper import ensure_core_tools_enabled
from core.utils.config import config
@ -222,6 +223,8 @@ Approach each research task methodically, starting with broad searches and then
if tool_name not in agentpress_tools:
agentpress_tools[tool_name] = enabled
agentpress_tools = ensure_core_tools_enabled(agentpress_tools)
if configured_mcps is None:
configured_mcps = []

View File

@ -0,0 +1,27 @@
from typing import Dict, Any
from core.utils.logger import logger
CORE_TOOLS = {
'ask_tool': True,
'task_list_tool': True,
'expand_message_tool': True,
}
def ensure_core_tools_enabled(agentpress_tools: Dict[str, Any]) -> Dict[str, Any]:
if agentpress_tools is None:
agentpress_tools = {}
updated_tools = dict(agentpress_tools)
for tool_name, enabled in CORE_TOOLS.items():
updated_tools[tool_name] = enabled
logger.debug(f"Ensured core tools are enabled: {list(CORE_TOOLS.keys())}")
return updated_tools
def is_core_tool(tool_name: str) -> bool:
return tool_name in CORE_TOOLS
def get_core_tools() -> Dict[str, bool]:
return CORE_TOOLS.copy()

View File

@ -54,7 +54,7 @@ import { AgentTriggersConfiguration } from './triggers/agent-triggers-configurat
import { ProfilePictureDialog } from './config/profile-picture-dialog';
import { AgentIconAvatar } from './config/agent-icon-avatar';
import { AgentVersionSwitcher } from './agent-version-switcher';
import { DEFAULT_AGENTPRESS_TOOLS } from './tools';
import { DEFAULT_AGENTPRESS_TOOLS, ensureCoreToolsEnabled } from './tools';
interface AgentConfigurationDialogProps {
open: boolean;
@ -129,7 +129,7 @@ export function AgentConfigurationDialog({
description: configSource.description || '',
system_prompt: configSource.system_prompt || '',
model: configSource.model,
agentpress_tools: configSource.agentpress_tools || DEFAULT_AGENTPRESS_TOOLS,
agentpress_tools: ensureCoreToolsEnabled(configSource.agentpress_tools || DEFAULT_AGENTPRESS_TOOLS),
configured_mcps: configSource.configured_mcps || [],
custom_mcps: configSource.custom_mcps || [],
is_default: configSource.is_default || false,
@ -258,7 +258,8 @@ export function AgentConfigurationDialog({
return;
}
setFormData(prev => ({ ...prev, agentpress_tools: tools }));
const toolsWithCoreEnabled = ensureCoreToolsEnabled(tools);
setFormData(prev => ({ ...prev, agentpress_tools: toolsWithCoreEnabled }));
};
const handleMCPChange = (updates: { configured_mcps: any[]; custom_mcps: any[] }) => {

View File

@ -3,6 +3,7 @@ import { Switch } from '@/components/ui/switch';
import { Input } from '@/components/ui/input';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Search } from 'lucide-react';
import { icons } from 'lucide-react';
import { AGENTPRESS_TOOL_DEFINITIONS, getToolDisplayName } from './tools';
import { toast } from 'sonner';
@ -17,6 +18,15 @@ interface AgentToolsConfigurationProps {
export const AgentToolsConfiguration = ({ tools, onToolsChange, disabled = false, isSunaAgent = false, isLoading = false }: AgentToolsConfigurationProps) => {
const [searchQuery, setSearchQuery] = useState<string>('');
const getIconComponent = (iconName: string) => {
const IconComponent = (icons as any)[iconName];
return IconComponent || icons.Wrench;
};
const isCoreTool = (toolName: string): boolean => {
return AGENTPRESS_TOOL_DEFINITIONS[toolName]?.isCore === true;
};
const isToolEnabled = (tool: boolean | { enabled: boolean; description: string } | undefined): boolean => {
if (tool === undefined) return false;
if (typeof tool === 'boolean') return tool;
@ -31,6 +41,13 @@ export const AgentToolsConfiguration = ({ tools, onToolsChange, disabled = false
};
const handleToolToggle = (toolName: string, enabled: boolean) => {
if (isCoreTool(toolName)) {
toast.error("Core tool cannot be modified", {
description: "This tool is essential for agent functionality and cannot be disabled.",
});
return;
}
if (disabled && isSunaAgent) {
toast.error("Tools cannot be modified", {
description: "Suna's default tools are managed centrally and cannot be changed.",
@ -79,34 +96,45 @@ export const AgentToolsConfiguration = ({ tools, onToolsChange, disabled = false
</div>
<ScrollArea className="flex-1 pr-1">
<div className="space-y-3">
{getFilteredTools().map(([toolName, toolInfo]) => (
<div
key={toolName}
className="group border bg-card rounded-2xl p-4 transition-all duration-200 hover:bg-muted/50"
>
<div className="flex items-start gap-3 mb-3">
<div className={`w-10 h-10 rounded-xl ${toolInfo.color} border flex items-center justify-center flex-shrink-0`}>
<span className="text-lg">{toolInfo.icon}</span>
{getFilteredTools().map(([toolName, toolInfo]) => {
const isCoreToolItem = isCoreTool(toolName);
return (
<div
key={toolName}
className={`group border bg-card rounded-2xl p-4 transition-all duration-200`}
>
<div className="flex items-start gap-3 mb-3">
<div className={`w-10 h-10 rounded-xl ${toolInfo.color} border flex items-center justify-center flex-shrink-0`}>
{React.createElement(getIconComponent(toolInfo.icon), { className: "h-5 w-5" })}
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<h3 className="font-medium text-sm leading-tight truncate">
{getToolDisplayName(toolName)}
</h3>
{isCoreToolItem && (
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">
Core
</span>
)}
</div>
<p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">
{toolInfo.description}
</p>
</div>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-medium text-sm leading-tight truncate mb-1">
{getToolDisplayName(toolName)}
</h3>
<p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">
{toolInfo.description}
</p>
</div>
</div>
<div className="flex justify-end items-center">
<Switch
checked={isToolEnabled(tools[toolName])}
onCheckedChange={(checked) => handleToolToggle(toolName, checked)}
disabled={disabled || isLoading}
/>
<div className="flex justify-end items-center">
<Switch
checked={isCoreToolItem ? true : isToolEnabled(tools[toolName])}
onCheckedChange={(checked) => handleToolToggle(toolName, checked)}
disabled={disabled || isLoading || isCoreToolItem}
className={isCoreToolItem ? 'opacity-60 cursor-not-allowed' : ''}
/>
</div>
</div>
</div>
))}
);
})}
{getFilteredTools().length === 0 && (
<div className="text-center py-12 px-6 bg-muted/30 rounded-xl border-2 border-dashed border-border">

View File

@ -1,34 +1,39 @@
export const AGENTPRESS_TOOL_DEFINITIONS: Record<string, { enabled: boolean; description: string; icon: string; color: string }> = {
export const AGENTPRESS_TOOL_DEFINITIONS: Record<string, { enabled: boolean; description: string; icon: string; color: string; isCore?: boolean }> = {
// Core tools (always enabled)
'ask_tool': { enabled: true, description: 'Ask users questions and wait for responses during task execution', icon: 'MessageCircleQuestion', color: 'bg-blue-100 dark:bg-blue-800/50', isCore: true },
'task_list_tool': { enabled: true, description: 'Create and manage task lists to organize work and track progress', icon: 'ListTodo', color: 'bg-green-100 dark:bg-green-800/50', isCore: true },
'expand_message_tool': { enabled: true, description: 'Expand truncated messages from previous conversations', icon: 'Expand', color: 'bg-purple-100 dark:bg-purple-800/50', isCore: true },
// Core sandbox tools
'sb_shell_tool': { enabled: true, description: 'Execute shell commands in tmux sessions for terminal operations, CLI tools, and system management', icon: '💻', color: 'bg-slate-100 dark:bg-slate-800' },
'sb_files_tool': { enabled: true, description: 'Create, read, update, and delete files in the workspace with comprehensive file management', icon: '📁', color: 'bg-blue-100 dark:bg-blue-800/50' },
'sb_deploy_tool': { enabled: true, description: 'Deploy applications and services with automated deployment capabilities', icon: '🚀', color: 'bg-green-100 dark:bg-green-800/50' },
'sb_expose_tool': { enabled: true, description: 'Expose services and manage ports for application accessibility', icon: '🔌', color: 'bg-orange-100 dark:bg-orange-800/20' },
'web_search_tool': { enabled: true, description: 'Search the web using Tavily API and scrape webpages with Firecrawl for research', icon: '🔍', color: 'bg-yellow-100 dark:bg-yellow-800/50' },
'image_search_tool': { enabled: true, description: 'Search for images using SERPER API with support for single and batch searches', icon: '🖼️', color: 'bg-indigo-100 dark:bg-indigo-800/50' },
'sb_vision_tool': { enabled: true, description: 'Vision and image processing capabilities for visual content analysis', icon: '👁️', color: 'bg-pink-100 dark:bg-pink-800/50' },
'sb_image_edit_tool': { enabled: true, description: 'Generate new images or edit existing images using OpenAI GPT Image 1', icon: '🎨', color: 'bg-purple-100 dark:bg-purple-800/50' },
'sb_presentation_outline_tool': { enabled: false, description: 'Create structured presentation outlines with slide descriptions and speaker notes', icon: '📋', color: 'bg-purple-100 dark:bg-purple-800/50' },
'sb_presentation_tool': { enabled: false, description: 'Create professional presentations with HTML slides, preview, and export capabilities', icon: '📊', color: 'bg-violet-100 dark:bg-violet-800/50' },
'sb_shell_tool': { enabled: true, description: 'Execute shell commands in tmux sessions for terminal operations, CLI tools, and system management', icon: 'Terminal', color: 'bg-slate-100 dark:bg-slate-800' },
'sb_files_tool': { enabled: true, description: 'Create, read, update, and delete files in the workspace with comprehensive file management', icon: 'FolderOpen', color: 'bg-blue-100 dark:bg-blue-800/50' },
'sb_deploy_tool': { enabled: true, description: 'Deploy applications and services with automated deployment capabilities', icon: 'Rocket', color: 'bg-green-100 dark:bg-green-800/50' },
'sb_expose_tool': { enabled: true, description: 'Expose services and manage ports for application accessibility', icon: 'Plug', color: 'bg-orange-100 dark:bg-orange-800/20' },
'web_search_tool': { enabled: true, description: 'Search the web using Tavily API and scrape webpages with Firecrawl for research', icon: 'Search', color: 'bg-yellow-100 dark:bg-yellow-800/50' },
'image_search_tool': { enabled: true, description: 'Search for images using SERPER API with support for single and batch searches', icon: 'Image', color: 'bg-indigo-100 dark:bg-indigo-800/50' },
'sb_vision_tool': { enabled: true, description: 'Vision and image processing capabilities for visual content analysis', icon: 'Eye', color: 'bg-pink-100 dark:bg-pink-800/50' },
'sb_image_edit_tool': { enabled: true, description: 'Generate new images or edit existing images using OpenAI GPT Image 1', icon: 'Palette', color: 'bg-purple-100 dark:bg-purple-800/50' },
'sb_presentation_outline_tool': { enabled: false, description: 'Create structured presentation outlines with slide descriptions and speaker notes', icon: 'ClipboardList', color: 'bg-purple-100 dark:bg-purple-800/50' },
'sb_presentation_tool': { enabled: false, description: 'Create professional presentations with HTML slides, preview, and export capabilities', icon: 'Presentation', color: 'bg-violet-100 dark:bg-violet-800/50' },
'sb_docs_tool': { enabled: false, description: 'Create, read, update, and delete documents with TipTap editor', icon: '📄', color: 'bg-gray-100 dark:bg-gray-800/50' },
'sb_design_tool': { enabled: false, description: 'Create, read, update, and delete documents with TipTap editor', icon: '🎨', color: 'bg-gray-100 dark:bg-gray-800/50' },
'sb_docs_tool': { enabled: false, description: 'Create, read, update, and delete documents with TipTap editor', icon: 'FileText', color: 'bg-gray-100 dark:bg-gray-800/50' },
'sb_design_tool': { enabled: false, description: 'Create, read, update, and delete documents with TipTap editor', icon: 'Paintbrush', color: 'bg-gray-100 dark:bg-gray-800/50' },
'sb_sheets_tool': { enabled: false, description: 'Create, view, update, analyze, visualize, and format spreadsheets (XLSX/CSV) with Luckysheet viewer', icon: '📊', color: 'bg-purple-100 dark:bg-purple-800/50' },
// 'sb_web_dev_tool': { enabled: false, description: 'Create Next.js projects with shadcn/ui pre-installed, manage dependencies, build and deploy modern web applications', icon: '⚛️', color: 'bg-cyan-100 dark:bg-cyan-800/50' },
'sb_sheets_tool': { enabled: false, description: 'Create, view, update, analyze, visualize, and format spreadsheets (XLSX/CSV) with Luckysheet viewer', icon: 'Sheet', color: 'bg-purple-100 dark:bg-purple-800/50' },
// 'sb_web_dev_tool': { enabled: false, description: 'Create Next.js projects with shadcn/ui pre-installed, manage dependencies, build and deploy modern web applications', icon: 'Code', color: 'bg-cyan-100 dark:bg-cyan-800/50' },
// Browser and interaction tools
'browser_tool': { enabled: true, description: 'Browser automation for web navigation, clicking, form filling, and page interaction', icon: '🌐', color: 'bg-indigo-100 dark:bg-indigo-800/50' },
'browser_tool': { enabled: true, description: 'Browser automation for web navigation, clicking, form filling, and page interaction', icon: 'Globe', color: 'bg-indigo-100 dark:bg-indigo-800/50' },
// Data provider tools
'data_providers_tool': { enabled: true, description: 'Access to data providers and external APIs', icon: '🔗', color: 'bg-cyan-100 dark:bg-cyan-800/50' },
'data_providers_tool': { enabled: true, description: 'Access to data providers and external APIs', icon: 'Link', color: 'bg-cyan-100 dark:bg-cyan-800/50' },
// Agent self-configuration tools
'agent_config_tool': { enabled: true, description: 'Configure agent settings, tools, and integrations', icon: '⚙️', color: 'bg-gray-100 dark:bg-gray-800/50' },
'mcp_search_tool': { enabled: true, description: 'Search and discover MCP servers and integrations for external services', icon: '🔍', color: 'bg-teal-100 dark:bg-teal-800/50' },
'credential_profile_tool': { enabled: true, description: 'Manage credential profiles for secure integration authentication', icon: '🔐', color: 'bg-red-100 dark:bg-red-800/50' },
'workflow_tool': { enabled: true, description: 'Create and manage automated workflows and task sequences', icon: '🔄', color: 'bg-emerald-100 dark:bg-emerald-800/50' },
'trigger_tool': { enabled: true, description: 'Set up event triggers and scheduled automation', icon: '', color: 'bg-amber-100 dark:bg-amber-800/50' },
'agent_config_tool': { enabled: true, description: 'Configure agent settings, tools, and integrations', icon: 'Settings', color: 'bg-gray-100 dark:bg-gray-800/50' },
'mcp_search_tool': { enabled: true, description: 'Search and discover MCP servers and integrations for external services', icon: 'Search', color: 'bg-teal-100 dark:bg-teal-800/50' },
'credential_profile_tool': { enabled: true, description: 'Manage credential profiles for secure integration authentication', icon: 'KeyRound', color: 'bg-red-100 dark:bg-red-800/50' },
'workflow_tool': { enabled: true, description: 'Create and manage automated workflows and task sequences', icon: 'Workflow', color: 'bg-emerald-100 dark:bg-emerald-800/50' },
'trigger_tool': { enabled: true, description: 'Set up event triggers and scheduled automation', icon: 'Clock', color: 'bg-amber-100 dark:bg-amber-800/50' },
};
export const DEFAULT_AGENTPRESS_TOOLS: Record<string, boolean> = Object.entries(AGENTPRESS_TOOL_DEFINITIONS).reduce((acc, [key, value]) => {
@ -36,8 +41,28 @@ export const DEFAULT_AGENTPRESS_TOOLS: Record<string, boolean> = Object.entries(
return acc;
}, {} as Record<string, boolean>);
// Helper function to ensure core tools are always enabled
export const ensureCoreToolsEnabled = (tools: Record<string, any>): Record<string, any> => {
const coreTools = Object.entries(AGENTPRESS_TOOL_DEFINITIONS)
.filter(([_, toolInfo]) => toolInfo.isCore)
.map(([toolName]) => toolName);
const updatedTools = { ...tools };
coreTools.forEach(toolName => {
updatedTools[toolName] = true;
});
return updatedTools;
};
export const getToolDisplayName = (toolName: string): string => {
const displayNames: Record<string, string> = {
// Core tools
'ask_tool': 'User Communication',
'task_list_tool': 'Task Management',
'expand_message_tool': 'Message Expansion',
// Core sandbox tools
'sb_shell_tool': 'Terminal',
'sb_files_tool': 'File Manager',

View File

@ -9,7 +9,9 @@ import {
Check,
MoreHorizontal
} from 'lucide-react';
import { icons } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { AGENTPRESS_TOOL_DEFINITIONS } from '../tools';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
@ -75,6 +77,15 @@ export function ConditionalWorkflowBuilder({
agentTools,
isLoadingTools
}: ConditionalWorkflowBuilderProps) {
const getIconComponent = (iconName: string) => {
const IconComponent = (icons as any)[iconName];
return IconComponent || icons.Wrench;
};
const isCoreTool = (toolName: string): boolean => {
return AGENTPRESS_TOOL_DEFINITIONS[toolName]?.isCore === true;
};
const [toolSearchOpen, setToolSearchOpen] = useState<{ [key: string]: boolean }>({});
const [activeConditionTab, setActiveConditionTab] = useState<{ [key: string]: string }>({});
@ -496,8 +507,13 @@ export function ConditionalWorkflowBuilder({
if (agentpressTool) {
return (
<>
<span>{agentpressTool.icon || '🔧'}</span>
{React.createElement(getIconComponent(agentpressTool.icon || 'Wrench'), { className: "h-4 w-4" })}
<span>{normalizeToolName(agentpressTool.name, 'agentpress')}</span>
{isCoreTool(agentpressTool.name) && (
<span className="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">
Core
</span>
)}
</>
);
}
@ -505,7 +521,7 @@ export function ConditionalWorkflowBuilder({
if (mcpTool) {
return (
<>
<span>{mcpTool.icon || '🔧'}</span>
{React.createElement(getIconComponent(mcpTool.icon || 'Wrench'), { className: "h-4 w-4" })}
<span>{normalizeToolName(mcpTool.name, 'mcp')}</span>
</>
);
@ -540,8 +556,13 @@ export function ConditionalWorkflowBuilder({
}}
>
<div className="flex items-center gap-2">
<span>{tool.icon || '🔧'}</span>
{React.createElement(getIconComponent(tool.icon || 'Wrench'), { className: "h-4 w-4" })}
<span>{normalizeToolName(tool.name, 'agentpress')}</span>
{isCoreTool(tool.name) && (
<span className="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">
Core
</span>
)}
</div>
<Check
className={cn(
@ -565,7 +586,7 @@ export function ConditionalWorkflowBuilder({
}}
>
<div className="flex items-center gap-2">
<span>{tool.icon || '🔧'}</span>
{React.createElement(getIconComponent(tool.icon || 'Wrench'), { className: "h-4 w-4" })}
<span>{normalizeToolName(tool.name, 'mcp')}</span>
</div>
<Check