[loop-cycle-46] refactor: break up oversized functions in tools.py (#151) (#154)
All checks were successful
Tests / lint (push) Successful in 3s
Tests / test (push) Successful in 1m20s

This commit was merged in pull request #154.
This commit is contained in:
2026-03-15 10:56:33 -04:00
parent 466db7aed2
commit 717dba9816

View File

@@ -472,26 +472,8 @@ def consult_grok(query: str) -> str:
return response
def create_full_toolkit(base_dir: str | Path | None = None):
"""Create a full toolkit with all available tools (for the orchestrator).
Includes: web search, file read/write, shell commands, python execution,
memory search for contextual recall, and Grok consultation.
"""
if not _AGNO_TOOLS_AVAILABLE:
# Return None when tools aren't available (tests)
return None
from timmy.tool_safety import DANGEROUS_TOOLS
toolkit = Toolkit(
name="full",
)
# Set requires_confirmation_tools AFTER construction (avoids agno WARNING
# about tools not yet registered) but BEFORE register() calls (so each
# Function gets requires_confirmation=True). Fixes #79.
toolkit.requires_confirmation_tools = list(DANGEROUS_TOOLS)
def _register_core_tools(toolkit: Toolkit, base_path: Path) -> None:
"""Register core execution and file tools."""
# Python execution
python_tools = PythonTools()
toolkit.register(python_tools.run_python_code, name="python")
@@ -500,10 +482,7 @@ def create_full_toolkit(base_dir: str | Path | None = None):
shell_tools = ShellTools()
toolkit.register(shell_tools.run_shell_command, name="shell")
# File operations - use repo_root from settings
from config import settings
base_path = Path(base_dir) if base_dir else Path(settings.repo_root)
# File operations
file_tools = FileTools(base_dir=base_path)
toolkit.register(_make_smart_read_file(file_tools), name="read_file")
toolkit.register(file_tools.save_file, name="write_file")
@@ -512,7 +491,9 @@ def create_full_toolkit(base_dir: str | Path | None = None):
# Calculator — exact arithmetic (never let the LLM guess)
toolkit.register(calculator, name="calculator")
# Grok consultation — premium frontier reasoning (opt-in)
def _register_grok_tool(toolkit: Toolkit) -> None:
"""Register Grok consultation tool if available."""
try:
from timmy.backends import grok_available
@@ -523,7 +504,9 @@ def create_full_toolkit(base_dir: str | Path | None = None):
logger.warning("Tool execution failed (Grok registration): %s", exc)
logger.debug("Grok tool not available")
# Memory search, write, and forget — persistent recall across all channels
def _register_memory_tools(toolkit: Toolkit) -> None:
"""Register memory search, write, and forget tools."""
try:
from timmy.semantic_memory import memory_forget, memory_read, memory_search, memory_write
@@ -535,7 +518,9 @@ def create_full_toolkit(base_dir: str | Path | None = None):
logger.warning("Tool execution failed (Memory tools registration): %s", exc)
logger.debug("Memory tools not available")
# Agentic loop — background multi-step task execution
def _register_agentic_loop_tool(toolkit: Toolkit) -> None:
"""Register agentic loop tool for background multi-step task execution."""
try:
from timmy.agentic_loop import run_agentic_loop
@@ -582,7 +567,9 @@ def create_full_toolkit(base_dir: str | Path | None = None):
logger.warning("Tool execution failed (plan_and_execute registration): %s", exc)
logger.debug("plan_and_execute tool not available")
# System introspection - query runtime environment (sovereign self-knowledge)
def _register_introspection_tools(toolkit: Toolkit) -> None:
"""Register system introspection tools for runtime environment queries."""
try:
from timmy.tools_intro import (
check_ollama_health,
@@ -599,7 +586,9 @@ def create_full_toolkit(base_dir: str | Path | None = None):
logger.warning("Tool execution failed (Introspection tools registration): %s", exc)
logger.debug("Introspection tools not available")
# Inter-agent delegation - dispatch tasks to swarm agents
def _register_delegation_tools(toolkit: Toolkit) -> None:
"""Register inter-agent delegation tools."""
try:
from timmy.tools_delegation import delegate_task, delegate_to_kimi, list_swarm_agents
@@ -610,6 +599,34 @@ def create_full_toolkit(base_dir: str | Path | None = None):
logger.warning("Tool execution failed (Delegation tools registration): %s", exc)
logger.debug("Delegation tools not available")
def create_full_toolkit(base_dir: str | Path | None = None):
"""Create a full toolkit with all available tools (for the orchestrator).
Includes: web search, file read/write, shell commands, python execution,
memory search for contextual recall, and Grok consultation.
"""
if not _AGNO_TOOLS_AVAILABLE:
# Return None when tools aren't available (tests)
return None
from timmy.tool_safety import DANGEROUS_TOOLS
toolkit = Toolkit(name="full")
# Set requires_confirmation_tools AFTER construction (avoids agno WARNING
# about tools not yet registered) but BEFORE register() calls (so each
# Function gets requires_confirmation=True). Fixes #79.
toolkit.requires_confirmation_tools = list(DANGEROUS_TOOLS)
base_path = Path(base_dir) if base_dir else Path(settings.repo_root)
_register_core_tools(toolkit, base_path)
_register_grok_tool(toolkit)
_register_memory_tools(toolkit)
_register_agentic_loop_tool(toolkit)
_register_introspection_tools(toolkit)
_register_delegation_tools(toolkit)
# Gitea issue management is now provided by the gitea-mcp server
# (wired in as MCPTools in agent.py, not registered here)
@@ -719,13 +736,9 @@ get_tools_for_persona = get_tools_for_agent
PERSONA_TOOLKITS = AGENT_TOOLKITS
def get_all_available_tools() -> dict[str, dict]:
"""Get a catalog of all available tools and their descriptions.
Returns:
Dict mapping tool categories to their tools and descriptions.
"""
catalog = {
def _core_tool_catalog() -> dict:
"""Return core file and execution tools catalog entries."""
return {
"shell": {
"name": "Shell Commands",
"description": "Execute shell commands (sandboxed)",
@@ -751,16 +764,39 @@ def get_all_available_tools() -> dict[str, dict]:
"description": "List files in a directory",
"available_in": ["echo", "seer", "forge", "quill", "mace", "helm", "orchestrator"],
},
}
def _analysis_tool_catalog() -> dict:
"""Return analysis and calculation tools catalog entries."""
return {
"calculator": {
"name": "Calculator",
"description": "Evaluate mathematical expressions with exact results",
"available_in": ["orchestrator"],
},
}
def _ai_tool_catalog() -> dict:
"""Return AI assistant and frontier reasoning tools catalog entries."""
return {
"consult_grok": {
"name": "Consult Grok",
"description": "Premium frontier reasoning via xAI Grok (opt-in, Lightning-payable)",
"available_in": ["orchestrator"],
},
"aider": {
"name": "Aider AI Assistant",
"description": "Local AI coding assistant using Ollama (qwen3.5:latest or deepseek-coder)",
"available_in": ["forge", "orchestrator"],
},
}
def _introspection_tool_catalog() -> dict:
"""Return system introspection tools catalog entries."""
return {
"get_system_info": {
"name": "System Info",
"description": "Introspect runtime environment - discover model, Python version, config",
@@ -776,11 +812,12 @@ def get_all_available_tools() -> dict[str, dict]:
"description": "Check status of memory tiers (hot memory, vault)",
"available_in": ["orchestrator"],
},
"aider": {
"name": "Aider AI Assistant",
"description": "Local AI coding assistant using Ollama (qwen3.5:latest or deepseek-coder)",
"available_in": ["forge", "orchestrator"],
},
}
def _experiment_tool_catalog() -> dict:
"""Return ML experiment tools catalog entries."""
return {
"prepare_experiment": {
"name": "Prepare Experiment",
"description": "Clone autoresearch repo and run data preparation for ML experiments",
@@ -798,6 +835,9 @@ def get_all_available_tools() -> dict[str, dict]:
},
}
def _import_creative_catalogs(catalog: dict) -> None:
"""Import and merge creative tool catalogs from creative module."""
# ── Git tools ─────────────────────────────────────────────────────────────
try:
from creative.tools.git_tools import GIT_TOOL_CATALOG
@@ -876,4 +916,18 @@ def get_all_available_tools() -> dict[str, dict]:
except ImportError:
pass
def get_all_available_tools() -> dict[str, dict]:
"""Get a catalog of all available tools and their descriptions.
Returns:
Dict mapping tool categories to their tools and descriptions.
"""
catalog = {}
catalog.update(_core_tool_catalog())
catalog.update(_analysis_tool_catalog())
catalog.update(_ai_tool_catalog())
catalog.update(_introspection_tool_catalog())
catalog.update(_experiment_tool_catalog())
_import_creative_catalogs(catalog)
return catalog