mirror of https://github.com/kortix-ai/suna.git
refactor versioning & run.py
This commit is contained in:
parent
f848d5c10f
commit
8e1cce5cbd
File diff suppressed because it is too large
Load Diff
|
@ -194,16 +194,40 @@ class AgentConfigTool(AgentBuilderBaseTool):
|
||||||
if isinstance(configured_mcps, str):
|
if isinstance(configured_mcps, str):
|
||||||
configured_mcps = json.loads(configured_mcps)
|
configured_mcps = json.loads(configured_mcps)
|
||||||
|
|
||||||
existing_mcps_by_name = {mcp.get('qualifiedName', ''): mcp for mcp in current_configured_mcps}
|
def get_mcp_identifier(mcp):
|
||||||
|
if not isinstance(mcp, dict):
|
||||||
|
return None
|
||||||
|
return (
|
||||||
|
mcp.get('qualifiedName') or
|
||||||
|
mcp.get('name') or
|
||||||
|
f"{mcp.get('type', 'unknown')}_{mcp.get('config', {}).get('url', 'nourl')}" or
|
||||||
|
str(hash(json.dumps(mcp, sort_keys=True)))
|
||||||
|
)
|
||||||
|
|
||||||
|
merged_mcps = []
|
||||||
|
existing_identifiers = set()
|
||||||
|
|
||||||
|
for existing_mcp in current_configured_mcps:
|
||||||
|
identifier = get_mcp_identifier(existing_mcp)
|
||||||
|
if identifier:
|
||||||
|
existing_identifiers.add(identifier)
|
||||||
|
merged_mcps.append(existing_mcp)
|
||||||
|
|
||||||
for new_mcp in configured_mcps:
|
for new_mcp in configured_mcps:
|
||||||
qualified_name = new_mcp.get('qualifiedName', '')
|
identifier = get_mcp_identifier(new_mcp)
|
||||||
if qualified_name:
|
|
||||||
existing_mcps_by_name[qualified_name] = new_mcp
|
if identifier and identifier in existing_identifiers:
|
||||||
|
for i, existing_mcp in enumerate(merged_mcps):
|
||||||
|
if get_mcp_identifier(existing_mcp) == identifier:
|
||||||
|
merged_mcps[i] = new_mcp
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
current_configured_mcps.append(new_mcp)
|
merged_mcps.append(new_mcp)
|
||||||
|
if identifier:
|
||||||
|
existing_identifiers.add(identifier)
|
||||||
|
|
||||||
current_configured_mcps = list(existing_mcps_by_name.values())
|
current_configured_mcps = merged_mcps
|
||||||
|
logger.info(f"MCP merge result: {len(current_configured_mcps)} total MCPs (was {len(current_version.get('configured_mcps', []))}, adding {len(configured_mcps)})")
|
||||||
|
|
||||||
current_custom_mcps = current_version.get('custom_mcps', [])
|
current_custom_mcps = current_version.get('custom_mcps', [])
|
||||||
|
|
||||||
|
|
|
@ -278,13 +278,11 @@ class CredentialProfileTool(AgentBuilderBaseTool):
|
||||||
|
|
||||||
if profile.is_connected and connections:
|
if profile.is_connected and connections:
|
||||||
try:
|
try:
|
||||||
# directly discover MCP servers via the facade
|
|
||||||
from pipedream.domain.entities import ConnectionStatus
|
from pipedream.domain.entities import ConnectionStatus
|
||||||
servers = await self.pipedream_manager.discover_mcp_servers(
|
servers = await self.pipedream_manager.discover_mcp_servers(
|
||||||
external_user_id=profile.external_user_id.value if hasattr(profile.external_user_id, 'value') else str(profile.external_user_id),
|
external_user_id=profile.external_user_id.value if hasattr(profile.external_user_id, 'value') else str(profile.external_user_id),
|
||||||
app_slug=profile.app_slug.value if hasattr(profile.app_slug, 'value') else str(profile.app_slug)
|
app_slug=profile.app_slug.value if hasattr(profile.app_slug, 'value') else str(profile.app_slug)
|
||||||
)
|
)
|
||||||
# filter connected servers
|
|
||||||
connected_servers = [s for s in servers if s.status == ConnectionStatus.CONNECTED]
|
connected_servers = [s for s in servers if s.status == ConnectionStatus.CONNECTED]
|
||||||
if connected_servers:
|
if connected_servers:
|
||||||
tools = [t.name for t in connected_servers[0].available_tools]
|
tools = [t.name for t in connected_servers[0].available_tools]
|
||||||
|
@ -422,7 +420,6 @@ class CredentialProfileTool(AgentBuilderBaseTool):
|
||||||
if not profile:
|
if not profile:
|
||||||
return self.fail_response("Credential profile not found")
|
return self.fail_response("Credential profile not found")
|
||||||
|
|
||||||
# Get current version config
|
|
||||||
agent_result = await client.table('agents').select('current_version_id').eq('agent_id', self.agent_id).execute()
|
agent_result = await client.table('agents').select('current_version_id').eq('agent_id', self.agent_id).execute()
|
||||||
if agent_result.data and agent_result.data[0].get('current_version_id'):
|
if agent_result.data and agent_result.data[0].get('current_version_id'):
|
||||||
version_result = await client.table('agent_versions')\
|
version_result = await client.table('agent_versions')\
|
||||||
|
|
|
@ -145,10 +145,54 @@ class MCPSearchTool(AgentBuilderBaseTool):
|
||||||
"available_triggers": getattr(app_data, 'available_triggers', [])
|
"available_triggers": getattr(app_data, 'available_triggers', [])
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.success_response({
|
available_tools = []
|
||||||
|
try:
|
||||||
|
import httpx
|
||||||
|
import json
|
||||||
|
|
||||||
|
url = f"https://remote.mcp.pipedream.net/?app={app_slug}&externalUserId=tools_preview"
|
||||||
|
payload = {"jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1}
|
||||||
|
headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
|
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||||
|
async with client.stream("POST", url, json=payload, headers=headers) as resp:
|
||||||
|
resp.raise_for_status()
|
||||||
|
async for line in resp.aiter_lines():
|
||||||
|
if not line or not line.startswith("data:"):
|
||||||
|
continue
|
||||||
|
data_str = line[len("data:"):].strip()
|
||||||
|
try:
|
||||||
|
data_obj = json.loads(data_str)
|
||||||
|
tools = data_obj.get("result", {}).get("tools", [])
|
||||||
|
for tool in tools:
|
||||||
|
desc = tool.get("description", "") or ""
|
||||||
|
idx = desc.find("[")
|
||||||
|
if idx != -1:
|
||||||
|
desc = desc[:idx].strip()
|
||||||
|
|
||||||
|
available_tools.append({
|
||||||
|
"name": tool.get("name", ""),
|
||||||
|
"description": desc
|
||||||
|
})
|
||||||
|
break
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.warning(f"Failed to parse JSON data: {data_str}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
except Exception as tools_error:
|
||||||
|
logger.warning(f"Could not fetch MCP tools for {app_slug}: {tools_error}")
|
||||||
|
|
||||||
|
result = {
|
||||||
"message": f"Retrieved details for {formatted_app['name']}",
|
"message": f"Retrieved details for {formatted_app['name']}",
|
||||||
"app": formatted_app
|
"app": formatted_app,
|
||||||
})
|
"available_mcp_tools": available_tools,
|
||||||
|
"total_mcp_tools": len(available_tools)
|
||||||
|
}
|
||||||
|
|
||||||
|
if available_tools:
|
||||||
|
result["message"] += f" - {len(available_tools)} MCP tools available"
|
||||||
|
|
||||||
|
return self.success_response(result)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.fail_response(f"Error getting app details: {str(e)}")
|
return self.fail_response(f"Error getting app details: {str(e)}")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
from agentpress.tool import Tool, ToolResult, openapi_schema, xml_schema, ToolSchema, SchemaType
|
from agentpress.tool import Tool, ToolResult, ToolSchema, SchemaType
|
||||||
from mcp_module import mcp_manager
|
from mcp_module import mcp_manager
|
||||||
from utils.logger import logger
|
from utils.logger import logger
|
||||||
import inspect
|
import inspect
|
||||||
|
@ -77,33 +77,55 @@ class MCPToolWrapper(Tool):
|
||||||
|
|
||||||
logger.info(f"Created {len(self._dynamic_tools)} dynamic MCP tool methods")
|
logger.info(f"Created {len(self._dynamic_tools)} dynamic MCP tool methods")
|
||||||
|
|
||||||
|
# Re-register schemas to pick up the dynamic methods
|
||||||
|
self._register_schemas()
|
||||||
|
logger.info(f"Re-registered schemas after creating dynamic tools - total: {len(self._schemas)}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error creating dynamic MCP tools: {e}")
|
logger.error(f"Error creating dynamic MCP tools: {e}")
|
||||||
|
|
||||||
def _register_schemas(self):
|
def _register_schemas(self):
|
||||||
|
self._schemas.clear()
|
||||||
|
|
||||||
for name, method in inspect.getmembers(self, predicate=inspect.ismethod):
|
for name, method in inspect.getmembers(self, predicate=inspect.ismethod):
|
||||||
if hasattr(method, 'tool_schemas'):
|
if hasattr(method, 'tool_schemas'):
|
||||||
self._schemas[name] = method.tool_schemas
|
self._schemas[name] = method.tool_schemas
|
||||||
logger.debug(f"Registered schemas for method '{name}' in {self.__class__.__name__}")
|
logger.debug(f"Registered schemas for method '{name}' in {self.__class__.__name__}")
|
||||||
|
|
||||||
logger.debug(f"Initial registration complete for MCPToolWrapper")
|
if hasattr(self, '_dynamic_tools') and self._dynamic_tools:
|
||||||
|
for tool_name, tool_data in self._dynamic_tools.items():
|
||||||
|
method_name = tool_data.get('method_name')
|
||||||
|
if method_name and method_name in self._schemas:
|
||||||
|
continue
|
||||||
|
|
||||||
|
method = tool_data.get('method')
|
||||||
|
if method and hasattr(method, 'tool_schemas'):
|
||||||
|
self._schemas[method_name] = method.tool_schemas
|
||||||
|
logger.debug(f"Registered dynamic method schemas for '{method_name}'")
|
||||||
|
|
||||||
|
logger.debug(f"Registration complete for MCPToolWrapper - total schemas: {len(self._schemas)}")
|
||||||
|
|
||||||
def get_schemas(self) -> Dict[str, List[ToolSchema]]:
|
def get_schemas(self) -> Dict[str, List[ToolSchema]]:
|
||||||
|
logger.debug(f"get_schemas called - returning {len(self._schemas)} schemas")
|
||||||
|
for method_name in self._schemas:
|
||||||
|
logger.debug(f" - Schema available for: {method_name}")
|
||||||
return self._schemas
|
return self._schemas
|
||||||
|
|
||||||
def __getattr__(self, name: str):
|
def __getattr__(self, name: str):
|
||||||
method = self.tool_builder.find_method_by_name(name)
|
if hasattr(self, 'tool_builder') and self.tool_builder:
|
||||||
if method:
|
method = self.tool_builder.find_method_by_name(name)
|
||||||
return method
|
if method:
|
||||||
|
return method
|
||||||
|
|
||||||
for tool_data in self._dynamic_tools.values():
|
if hasattr(self, '_dynamic_tools') and self._dynamic_tools:
|
||||||
if tool_data.get('method_name') == name:
|
for tool_data in self._dynamic_tools.values():
|
||||||
return tool_data.get('method')
|
if tool_data.get('method_name') == name:
|
||||||
|
return tool_data.get('method')
|
||||||
name_with_hyphens = name.replace('_', '-')
|
|
||||||
for tool_name, tool_data in self._dynamic_tools.items():
|
name_with_hyphens = name.replace('_', '-')
|
||||||
if tool_data.get('method_name') == name or tool_name == name_with_hyphens:
|
for tool_name, tool_data in self._dynamic_tools.items():
|
||||||
return tool_data.get('method')
|
if tool_data.get('method_name') == name or tool_name == name_with_hyphens:
|
||||||
|
return tool_data.get('method')
|
||||||
|
|
||||||
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
|
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
|
||||||
|
|
||||||
|
@ -111,10 +133,7 @@ class MCPToolWrapper(Tool):
|
||||||
await self._ensure_initialized()
|
await self._ensure_initialized()
|
||||||
if tool_registry and self._dynamic_tools:
|
if tool_registry and self._dynamic_tools:
|
||||||
logger.info(f"Updating tool registry with {len(self._dynamic_tools)} MCP tools")
|
logger.info(f"Updating tool registry with {len(self._dynamic_tools)} MCP tools")
|
||||||
for method_name, schemas in self._schemas.items():
|
|
||||||
if method_name not in ['call_mcp_tool']:
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def get_available_tools(self) -> List[Dict[str, Any]]:
|
async def get_available_tools(self) -> List[Dict[str, Any]]:
|
||||||
await self._ensure_initialized()
|
await self._ensure_initialized()
|
||||||
return self.mcp_manager.get_all_tools_openapi()
|
return self.mcp_manager.get_all_tools_openapi()
|
||||||
|
@ -123,46 +142,6 @@ class MCPToolWrapper(Tool):
|
||||||
await self._ensure_initialized()
|
await self._ensure_initialized()
|
||||||
return await self.tool_executor.execute_tool(tool_name, arguments)
|
return await self.tool_executor.execute_tool(tool_name, arguments)
|
||||||
|
|
||||||
@openapi_schema({
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": "call_mcp_tool",
|
|
||||||
"description": "Execute a tool from any connected MCP server. This is a fallback wrapper that forwards calls to MCP tools. The tool_name should be in the format 'mcp_{server}_{tool}' where {server} is the MCP server's qualified name and {tool} is the specific tool name.",
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"tool_name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The full MCP tool name in format 'mcp_{server}_{tool}', e.g., 'mcp_exa_web_search_exa'"
|
|
||||||
},
|
|
||||||
"arguments": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "The arguments to pass to the MCP tool, as a JSON object. The required arguments depend on the specific tool being called.",
|
|
||||||
"additionalProperties": True
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["tool_name", "arguments"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@xml_schema(
|
|
||||||
tag_name="call-mcp-tool",
|
|
||||||
mappings=[
|
|
||||||
{"param_name": "tool_name", "node_type": "attribute", "path": "."},
|
|
||||||
{"param_name": "arguments", "node_type": "content", "path": "."}
|
|
||||||
],
|
|
||||||
example='''
|
|
||||||
<function_calls>
|
|
||||||
<invoke name="call_mcp_tool">
|
|
||||||
<parameter name="tool_name">mcp_exa_web_search_exa</parameter>
|
|
||||||
<parameter name="arguments">{"query": "latest developments in AI", "num_results": 10}</parameter>
|
|
||||||
</invoke>
|
|
||||||
</function_calls>
|
|
||||||
'''
|
|
||||||
)
|
|
||||||
async def call_mcp_tool(self, tool_name: str, arguments: Dict[str, Any]) -> ToolResult:
|
|
||||||
return await self._execute_mcp_tool(tool_name, arguments)
|
|
||||||
|
|
||||||
async def cleanup(self):
|
async def cleanup(self):
|
||||||
if self._initialized:
|
if self._initialized:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -337,6 +337,7 @@ class PipedreamManager:
|
||||||
user_id: str,
|
user_id: str,
|
||||||
enabled_tools: List[str]
|
enabled_tools: List[str]
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
|
|
||||||
from services.supabase import DBConnection
|
from services.supabase import DBConnection
|
||||||
from agent.versioning.version_service import get_version_service
|
from agent.versioning.version_service import get_version_service
|
||||||
import copy
|
import copy
|
||||||
|
@ -353,17 +354,24 @@ class PipedreamManager:
|
||||||
|
|
||||||
agent = agent_result.data[0]
|
agent = agent_result.data[0]
|
||||||
|
|
||||||
|
print(f"[DEBUG] Starting update_agent_profile_tools for agent {agent_id}, profile {profile_id}")
|
||||||
|
|
||||||
current_version_data = None
|
current_version_data = None
|
||||||
if agent.get('current_version_id'):
|
if agent.get('current_version_id'):
|
||||||
try:
|
try:
|
||||||
current_version_data = await get_version_service().get_version(
|
version_service = await get_version_service()
|
||||||
|
current_version_data = await version_service.get_version(
|
||||||
agent_id=agent_id,
|
agent_id=agent_id,
|
||||||
version_id=agent['current_version_id'],
|
version_id=agent['current_version_id'],
|
||||||
user_id=user_id
|
user_id=user_id
|
||||||
)
|
)
|
||||||
version_data = current_version_data.to_dict()
|
version_data = current_version_data.to_dict()
|
||||||
current_custom_mcps = version_data.get('custom_mcps', [])
|
current_custom_mcps = version_data.get('custom_mcps', [])
|
||||||
|
print(f"[DEBUG] Retrieved current version {agent['current_version_id']}")
|
||||||
|
print(f"[DEBUG] Current custom_mcps count: {len(current_custom_mcps)}")
|
||||||
|
print(f"[DEBUG] Current custom_mcps: {current_custom_mcps}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print(f"[DEBUG] Error getting current version: {e}")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -376,30 +384,40 @@ class PipedreamManager:
|
||||||
configured_mcps = current_version_data.configured_mcps
|
configured_mcps = current_version_data.configured_mcps
|
||||||
agentpress_tools = current_version_data.agentpress_tools
|
agentpress_tools = current_version_data.agentpress_tools
|
||||||
current_custom_mcps = current_version_data.custom_mcps
|
current_custom_mcps = current_version_data.custom_mcps
|
||||||
|
print(f"[DEBUG] Using version data - custom_mcps count: {len(current_custom_mcps)}")
|
||||||
else:
|
else:
|
||||||
system_prompt = ''
|
system_prompt = ''
|
||||||
configured_mcps = []
|
configured_mcps = []
|
||||||
agentpress_tools = {}
|
agentpress_tools = {}
|
||||||
current_custom_mcps = []
|
current_custom_mcps = []
|
||||||
|
print(f"[DEBUG] No version data - starting with empty custom_mcps")
|
||||||
|
|
||||||
|
|
||||||
updated_custom_mcps = copy.deepcopy(current_custom_mcps)
|
updated_custom_mcps = copy.deepcopy(current_custom_mcps)
|
||||||
|
print(f"[DEBUG] After deepcopy - updated_custom_mcps count: {len(updated_custom_mcps)}")
|
||||||
|
print(f"[DEBUG] After deepcopy - updated_custom_mcps: {updated_custom_mcps}")
|
||||||
|
|
||||||
|
# Normalize enabledTools vs enabled_tools
|
||||||
for mcp in updated_custom_mcps:
|
for mcp in updated_custom_mcps:
|
||||||
if 'enabled_tools' in mcp and 'enabledTools' not in mcp:
|
if 'enabled_tools' in mcp and 'enabledTools' not in mcp:
|
||||||
mcp['enabledTools'] = mcp['enabled_tools']
|
mcp['enabledTools'] = mcp['enabled_tools']
|
||||||
elif 'enabledTools' not in mcp and 'enabled_tools' not in mcp:
|
elif 'enabledTools' not in mcp and 'enabled_tools' not in mcp:
|
||||||
mcp['enabledTools'] = []
|
mcp['enabledTools'] = []
|
||||||
|
|
||||||
|
# Look for existing MCP with same profile_id
|
||||||
found_match = False
|
found_match = False
|
||||||
for mcp in updated_custom_mcps:
|
for i, mcp in enumerate(updated_custom_mcps):
|
||||||
|
print(f"[DEBUG] Checking MCP {i}: type={mcp.get('type')}, profile_id={mcp.get('config', {}).get('profile_id')}")
|
||||||
if (mcp.get('type') == 'pipedream' and
|
if (mcp.get('type') == 'pipedream' and
|
||||||
mcp.get('config', {}).get('profile_id') == profile_id):
|
mcp.get('config', {}).get('profile_id') == profile_id):
|
||||||
|
print(f"[DEBUG] Found existing MCP at index {i}, updating tools from {mcp.get('enabledTools', [])} to {enabled_tools}")
|
||||||
mcp['enabledTools'] = enabled_tools
|
mcp['enabledTools'] = enabled_tools
|
||||||
mcp['enabled_tools'] = enabled_tools
|
mcp['enabled_tools'] = enabled_tools
|
||||||
found_match = True
|
found_match = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if not found_match:
|
if not found_match:
|
||||||
|
print(f"[DEBUG] No existing MCP found, creating new one")
|
||||||
new_mcp_config = {
|
new_mcp_config = {
|
||||||
"name": profile.app_name,
|
"name": profile.app_name,
|
||||||
"type": "pipedream",
|
"type": "pipedream",
|
||||||
|
@ -413,7 +431,12 @@ class PipedreamManager:
|
||||||
"enabledTools": enabled_tools,
|
"enabledTools": enabled_tools,
|
||||||
"enabled_tools": enabled_tools
|
"enabled_tools": enabled_tools
|
||||||
}
|
}
|
||||||
|
print(f"[DEBUG] New MCP config: {new_mcp_config}")
|
||||||
updated_custom_mcps.append(new_mcp_config)
|
updated_custom_mcps.append(new_mcp_config)
|
||||||
|
print(f"[DEBUG] After append - updated_custom_mcps count: {len(updated_custom_mcps)}")
|
||||||
|
|
||||||
|
print(f"[DEBUG] Final updated_custom_mcps count: {len(updated_custom_mcps)}")
|
||||||
|
print(f"[DEBUG] Final updated_custom_mcps: {updated_custom_mcps}")
|
||||||
|
|
||||||
version_service = await get_version_service()
|
version_service = await get_version_service()
|
||||||
|
|
||||||
|
@ -428,6 +451,8 @@ class PipedreamManager:
|
||||||
change_description=f"Updated {profile.app_name} tools"
|
change_description=f"Updated {profile.app_name} tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(f"[DEBUG] Created new version {new_version.version_id} with {len(updated_custom_mcps)} custom MCPs")
|
||||||
|
|
||||||
update_result = await client.table('agents').update({
|
update_result = await client.table('agents').update({
|
||||||
'current_version_id': new_version.version_id
|
'current_version_id': new_version.version_id
|
||||||
}).eq('agent_id', agent_id).execute()
|
}).eq('agent_id', agent_id).execute()
|
||||||
|
@ -440,7 +465,7 @@ class PipedreamManager:
|
||||||
'enabled_tools': enabled_tools,
|
'enabled_tools': enabled_tools,
|
||||||
'total_tools': len(enabled_tools),
|
'total_tools': len(enabled_tools),
|
||||||
'version_id': new_version.version_id,
|
'version_id': new_version.version_id,
|
||||||
'version_name': new_version['version_name']
|
'version_name': new_version.version_name
|
||||||
}
|
}
|
||||||
|
|
||||||
async def close(self):
|
async def close(self):
|
||||||
|
|
|
@ -49,8 +49,6 @@ const HIDE_STREAMING_XML_TAGS = new Set([
|
||||||
'crawl-webpage',
|
'crawl-webpage',
|
||||||
'web-search',
|
'web-search',
|
||||||
'see-image',
|
'see-image',
|
||||||
'call-mcp-tool',
|
|
||||||
|
|
||||||
'execute_data_provider_call',
|
'execute_data_provider_call',
|
||||||
'execute_data_provider_endpoint',
|
'execute_data_provider_endpoint',
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export interface CustomMcp {
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
profile_id?: string;
|
profile_id?: string;
|
||||||
};
|
};
|
||||||
enabled_tools: string[];
|
enabledTools: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AgentConfiguration {
|
export interface AgentConfiguration {
|
||||||
|
|
|
@ -83,7 +83,10 @@ export function GetCurrentAgentConfigToolView({
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTotalMcpToolsCount = (mcps: CustomMcp[]) => {
|
const getTotalMcpToolsCount = (mcps: CustomMcp[]) => {
|
||||||
return mcps.reduce((total, mcp) => total + mcp.enabled_tools.length, 0);
|
return mcps.reduce((total, mcp) => {
|
||||||
|
const enabledTools = mcp.enabledTools || [];
|
||||||
|
return total + (Array.isArray(enabledTools) ? enabledTools.length : 0);
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -268,12 +271,12 @@ export function GetCurrentAgentConfigToolView({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge variant="outline" className="text-xs">
|
<Badge variant="outline" className="text-xs">
|
||||||
{mcp.enabled_tools.length} tools
|
{mcp.enabledTools.length} tools
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-2">
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-2">
|
||||||
{mcp.enabled_tools.map((tool, toolIndex) => (
|
{mcp.enabledTools.map((tool, toolIndex) => (
|
||||||
<div key={toolIndex} className="flex items-center gap-1 p-2 bg-zinc-50 dark:bg-zinc-800/50 rounded text-xs">
|
<div key={toolIndex} className="flex items-center gap-1 p-2 bg-zinc-50 dark:bg-zinc-800/50 rounded text-xs">
|
||||||
<Zap className="w-3 h-3 text-zinc-500 dark:text-zinc-400" />
|
<Zap className="w-3 h-3 text-zinc-500 dark:text-zinc-400" />
|
||||||
<span className="text-zinc-700 dark:text-zinc-300 truncate">
|
<span className="text-zinc-700 dark:text-zinc-300 truncate">
|
||||||
|
|
|
@ -387,8 +387,6 @@ const TOOL_DISPLAY_NAMES = new Map([
|
||||||
['web_search', 'Searching Web'],
|
['web_search', 'Searching Web'],
|
||||||
['see_image', 'Viewing Image'],
|
['see_image', 'Viewing Image'],
|
||||||
|
|
||||||
['call_mcp_tool', 'External Tool'],
|
|
||||||
|
|
||||||
['update_agent', 'Updating Agent'],
|
['update_agent', 'Updating Agent'],
|
||||||
['get_current_agent_config', 'Getting Agent Config'],
|
['get_current_agent_config', 'Getting Agent Config'],
|
||||||
['search_mcp_servers', 'Searching MCP Servers'],
|
['search_mcp_servers', 'Searching MCP Servers'],
|
||||||
|
|
Loading…
Reference in New Issue