Skip to content

Commit 5339cbb

Browse files
authored
Merge pull request #134 from XSpoonAi/feat/modify-cmd
the cli imports the custom agent
2 parents bfaacc2 + ad1bca6 commit 5339cbb

File tree

3 files changed

+104
-13
lines changed

3 files changed

+104
-13
lines changed

cli/commands.py

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from prompt_toolkit.styles import Style
1717

1818
from spoon_ai.agents import SpoonReactAI, SpoonReactMCP
19+
from spoon_ai.agents.my_agents import CUSTOM_AGENTS
1920
from spoon_ai.retrieval.document_loader import DocumentLoader
2021
from spoon_ai.schema import Message, Role
2122
from spoon_ai.trade.aggregator import Aggregator
@@ -302,6 +303,14 @@ def _init_commands(self):
302303
aliases=["sysinfo", "status", "info"]
303304
))
304305

306+
# Tool Status Command
307+
self.add_command(SpoonCommand(
308+
name="tool-status",
309+
description="Check tool loading status and diagnose issues",
310+
handler=self._handle_tool_status,
311+
aliases=["tools", "tool-check"]
312+
))
313+
305314
# Configuration Migration Commands
306315
self.add_command(SpoonCommand(
307316
name="migrate-config",
@@ -335,7 +344,9 @@ def _help(self, input_list: List[str]):
335344
if len(input_list) <= 1:
336345
# show all available commands
337346
logger.info("Available commands:")
338-
for command in self.commands.values():
347+
# Use set to deduplicate commands (since aliases point to same object)
348+
unique_commands = set(self.commands.values())
349+
for command in sorted(unique_commands, key=lambda x: x.name):
339350
logger.info(f" {command.name}: {command.description}")
340351
else:
341352
# show help for a specific command
@@ -437,8 +448,13 @@ async def _load_agent(self, name: str):
437448
elif agent_class == "SpoonReactMCP":
438449
# For MCP agents, the unified system handles MCP server lifecycle
439450
agent_instance = SpoonReactMCP(**agent_instance_config)
451+
elif agent_class in CUSTOM_AGENTS:
452+
# Handle custom agents
453+
custom_agent_class = CUSTOM_AGENTS[agent_class]
454+
agent_instance = custom_agent_class(**agent_instance_config)
440455
else:
441456
logger.error(f"Unknown agent class: {agent_class}")
457+
logger.error(f"Available custom agents: {list(CUSTOM_AGENTS.keys())}")
442458
return
443459

444460
# Load tools using the unified system
@@ -1659,7 +1675,14 @@ def _handle_system_info(self, input_list: List[str]):
16591675
print_formatted_text(f" Agent type: {type(self.current_agent).__name__}")
16601676
if hasattr(self.current_agent, 'avaliable_tools'):
16611677
tool_count = len(self.current_agent.avaliable_tools.tools)
1662-
print_formatted_text(f" Available tools: {tool_count}")
1678+
if tool_count > 0:
1679+
print_formatted_text(PromptHTML(f" <ansigreen>Available tools: {tool_count}</ansigreen>"))
1680+
# Show tool names for debugging
1681+
tool_names = [tool.name for tool in self.current_agent.avaliable_tools.tools]
1682+
print_formatted_text(f" Tools: {', '.join(tool_names)}")
1683+
else:
1684+
print_formatted_text(PromptHTML(" <ansired>Available tools: 0</ansired>"))
1685+
print_formatted_text(" ⚠️ No tools loaded - check configuration and network connectivity")
16631686
if hasattr(self.current_agent, 'llm') and self.current_agent.llm:
16641687
llm_info = f"{getattr(self.current_agent.llm, 'llm_provider', 'unknown')}"
16651688
model_name = getattr(self.current_agent.llm, 'model_name', 'unknown')
@@ -1986,4 +2009,55 @@ def _show_migrate_help(self):
19862009
print_formatted_text("Examples:")
19872010
print_formatted_text(" migrate-config # Interactive migration")
19882011
print_formatted_text(" migrate-config -f my_config.json # Migrate specific file")
1989-
print_formatted_text(" migrate-config --dry-run # Preview migration")
2012+
print_formatted_text(" migrate-config --dry-run # Preview migration")
2013+
2014+
async def _handle_tool_status(self, input_list: List[str]):
2015+
"""Check tool loading status and diagnose issues"""
2016+
print("🔧 Tool Status Check")
2017+
print("=" * 50)
2018+
2019+
if not self.current_agent:
2020+
print("❌ No agent loaded")
2021+
print(" Please load an agent first with: load-agent <agent_name>")
2022+
return
2023+
2024+
print(f"✓ Agent: {self.current_agent.name}")
2025+
print(f" Agent type: {type(self.current_agent).__name__}")
2026+
2027+
# Check tools in agent
2028+
if hasattr(self.current_agent, 'avaliable_tools'):
2029+
tool_count = len(self.current_agent.avaliable_tools.tools)
2030+
print(f"✓ Tools loaded: {tool_count}")
2031+
2032+
if tool_count > 0:
2033+
print(" Tool details:")
2034+
for i, tool in enumerate(self.current_agent.avaliable_tools.tools, 1):
2035+
print(f" {i}. {tool.name}")
2036+
print(f" Description: {tool.description}")
2037+
if hasattr(tool, 'mcp_transport'):
2038+
print(f" Type: MCP tool")
2039+
else:
2040+
print(f" Type: Built-in tool")
2041+
else:
2042+
print("❌ No tools loaded")
2043+
print(" Possible causes:")
2044+
print(" • MCP server connection timeout")
2045+
print(" • Network connectivity issues")
2046+
print(" • Configuration errors")
2047+
print(" • Missing dependencies")
2048+
2049+
# Try to reload tools
2050+
print(" Attempting to reload tools...")
2051+
try:
2052+
tools = await self.config_manager.load_agent_tools(self.current_agent.name)
2053+
if tools:
2054+
self.current_agent.avaliable_tools.add_tools(*tools)
2055+
print(f"✓ Successfully reloaded {len(tools)} tools")
2056+
else:
2057+
print("❌ Still no tools after reload")
2058+
except Exception as e:
2059+
print(f"❌ Failed to reload tools: {e}")
2060+
else:
2061+
print("❌ Agent doesn't have tool manager")
2062+
2063+
print("=" * 50)

spoon_ai/config/manager.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Configuration manager for unified tool configuration."""
22

3+
import asyncio
34
import json
45
import logging
56
import os
@@ -82,17 +83,33 @@ async def load_agent_tools(self, agent_name: str) -> List[BaseTool]:
8283

8384
try:
8485
for tool_config in agent_config.tools:
85-
try:
86-
tool = await self.tool_factory.create_tool(tool_config)
87-
if tool: # Skip disabled tools
88-
tools.append(tool)
89-
logger.info(f"Created tool: {tool_config.name}")
90-
except Exception as e:
91-
logger.error(f"Failed to create tool {tool_config.name}: {e}")
92-
# Continue with other tools instead of failing completely
93-
continue
86+
tool_created = False
87+
max_retries = 2 if tool_config.type == "mcp" else 1
88+
89+
for attempt in range(max_retries):
90+
try:
91+
tool = await self.tool_factory.create_tool(tool_config)
92+
if tool: # Skip disabled tools
93+
tools.append(tool)
94+
logger.info(f"Created tool: {tool_config.name}")
95+
tool_created = True
96+
break
97+
except Exception as e:
98+
if attempt < max_retries - 1:
99+
logger.warning(f"Failed to create tool {tool_config.name} (attempt {attempt + 1}/{max_retries}): {e}")
100+
logger.info(f"Retrying tool {tool_config.name}...")
101+
await asyncio.sleep(1) # Wait 1 second before retry
102+
else:
103+
logger.error(f"Failed to create tool {tool_config.name} after {max_retries} attempts: {e}")
104+
# Continue with other tools instead of failing completely
105+
continue
106+
107+
if not tool_created:
108+
logger.warning(f"Skipping tool {tool_config.name} due to creation failure")
94109

95110
logger.info(f"Loaded {len(tools)} tools for agent {agent_name}")
111+
if len(tools) == 0:
112+
logger.warning(f"No tools were successfully loaded for agent {agent_name}")
96113
return tools
97114

98115
except Exception as e:

spoon_ai/config/mcp_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ async def _start_server_internal(self, server: MCPServerInstance) -> None:
285285
}
286286
}
287287

288-
stdout, stderr = test_process.communicate(input=json.dumps(init_request), timeout=10)
288+
stdout, stderr = test_process.communicate(input=json.dumps(init_request), timeout=30)
289289

290290
if test_process.returncode != 0:
291291
raise Exception(f"Process failed with return code {test_process.returncode}: {stderr}")

0 commit comments

Comments
 (0)