Add MCP delegation bridge and diagram tools
**Features Added**: 1. **Agent Registry (agent_registry.py)** - Thread-safe global singleton for MCP tool access to Agent instance - Enables MCP tools to call Agent.delegate() without circular imports - Registered at bot startup in bot_runner.py 2. **Sub-Agent Manager (sub_agent_manager.py)** - Watchdog system monitoring sub-agent lifecycle - Detects hung agents (5min timeout, 30s check interval) - Auto-cleanup and status tracking 3. **delegate_task MCP Tool (mcp_tools.py)** - Exposes Agent.delegate() to Claude via MCP protocol - Enables parallel sub-agent execution via tool calls - Supports specialist prompts and agent ID caching 4. **Memory Write Locks (memory_system.py)** - Thread-safe writes to prevent file corruption - Protects write_memory(), update_soul(), update_user() 5. **Diagram Tools** - Mermaid MCP server (flowcharts, sequence diagrams, etc.) - Excalidraw MCP server (hand-drawn style diagrams) - Config files in config/ directory 6. **Adapter Improvements** - Enhanced error handling across all adapters - Unified logging patterns **Testing**: Ready for parallel sub-agent testing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,61 @@ class AdapterRuntime:
|
||||
print("[Runtime] Warning: No event loop for message dispatch")
|
||||
self._message_queue.put_nowait(message)
|
||||
|
||||
async def _detect_and_send_diagrams(
|
||||
self,
|
||||
response: str,
|
||||
adapter: BaseAdapter,
|
||||
channel_id: str,
|
||||
thread_id: Optional[str]
|
||||
) -> None:
|
||||
"""Detect diagram file paths in response and auto-send them.
|
||||
|
||||
Args:
|
||||
response: Agent's text response
|
||||
adapter: Platform adapter to send files with
|
||||
channel_id: Channel/chat ID
|
||||
thread_id: Thread/message ID for replies
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# Match diagram file paths: "Saved to: path/to/diagram.png"
|
||||
# Pattern matches common phrases followed by file path with image/diagram extensions
|
||||
pattern = r"(?:Saved|Created|Generated|Exported|File saved|Output file)\s*(?:to|at)?[:\s]+([^\s]+\.(?:png|svg|pdf|jpg|jpeg))"
|
||||
matches = re.findall(pattern, response, re.IGNORECASE)
|
||||
|
||||
if not matches:
|
||||
return
|
||||
|
||||
sent_files = []
|
||||
for file_path_str in matches:
|
||||
try:
|
||||
file_path = Path(file_path_str)
|
||||
|
||||
# Check if file exists
|
||||
if not file_path.exists():
|
||||
print(f"[Runtime] Diagram file not found: {file_path}")
|
||||
continue
|
||||
|
||||
# Send file via adapter
|
||||
result = await adapter.send_file(
|
||||
channel_id=channel_id,
|
||||
file_path=str(file_path.absolute()),
|
||||
caption=f"Diagram: {file_path.name}",
|
||||
thread_id=thread_id,
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
sent_files.append(file_path.name)
|
||||
print(f"[Runtime] Sent diagram file: {file_path.name}")
|
||||
else:
|
||||
print(f"[Runtime] Failed to send diagram: {result.get('error')}")
|
||||
except Exception as e:
|
||||
print(f"[Runtime] Error sending diagram file: {e}")
|
||||
|
||||
if sent_files:
|
||||
print(f"[Runtime] Successfully sent {len(sent_files)} diagram file(s)")
|
||||
|
||||
async def _process_message_queue(self) -> None:
|
||||
"""Background task to process incoming messages."""
|
||||
print("[Runtime] Message processing loop started")
|
||||
@@ -169,12 +224,22 @@ class AdapterRuntime:
|
||||
user_message=processed_message.text,
|
||||
username=username,
|
||||
progress_callback=progress_callback,
|
||||
inbound_message=processed_message,
|
||||
)
|
||||
|
||||
# Apply postprocessors
|
||||
for postprocessor in self._postprocessors:
|
||||
response = postprocessor(response, processed_message)
|
||||
|
||||
# NEW: Detect and send diagram files mentioned in response
|
||||
if adapter:
|
||||
await self._detect_and_send_diagrams(
|
||||
response,
|
||||
adapter,
|
||||
message.channel_id,
|
||||
message.thread_id,
|
||||
)
|
||||
|
||||
# Send response back
|
||||
if adapter:
|
||||
reply_to = (
|
||||
|
||||
Reference in New Issue
Block a user