Rebase onto upstream (a4d95fd) #12

Closed
wylab wants to merge 144 commits from rebase-onto-upstream into main
Showing only changes of commit cf5360a346 - Show all commits
+45 -1
View File
@@ -21,6 +21,7 @@ from nanobot.agent.tools.message import MessageTool
from nanobot.agent.tools.spawn import SpawnTool from nanobot.agent.tools.spawn import SpawnTool
from nanobot.agent.tools.wait import WaitForSubagentsTool from nanobot.agent.tools.wait import WaitForSubagentsTool
from nanobot.agent.tools.cron import CronTool from nanobot.agent.tools.cron import CronTool
from nanobot.agent.tools.anthropic.base import ToolResult, CLIResult
from nanobot.agent.memory import MemoryStore from nanobot.agent.memory import MemoryStore
from nanobot.agent.subagent import SubagentManager from nanobot.agent.subagent import SubagentManager
from nanobot.agent.visibility import sign_content, has_forged_marker, strip_all_hidden_markers from nanobot.agent.visibility import sign_content, has_forged_marker, strip_all_hidden_markers
@@ -395,8 +396,51 @@ class AgentLoop:
args_str = json.dumps(tool_call.arguments, ensure_ascii=False) args_str = json.dumps(tool_call.arguments, ensure_ascii=False)
logger.info(f"Tool call: {tool_call.name}({args_str[:200]})") logger.info(f"Tool call: {tool_call.name}({args_str[:200]})")
result = await self.tools.execute(tool_call.name, tool_call.arguments) result = await self.tools.execute(tool_call.name, tool_call.arguments)
# Handle different result types
if isinstance(result, ToolResult):
# Native Anthropic tool result
content_parts = []
# Add text content
if result.output:
text_content = result.output
elif result.error:
text_content = f"Error: {result.error}"
else:
text_content = ""
# If both output and error, combine them
if result.output and result.error:
text_content = f"{result.output}\n\nError: {result.error}"
# If there's an image, use multipart content
if result.base64_image:
content_parts = [
{"type": "text", "text": text_content},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": result.base64_image,
}
}
]
tool_content = content_parts
else:
tool_content = text_content
elif isinstance(result, CLIResult):
# CLI-style tool result (text editor)
tool_content = result.output
else:
# Legacy string result from function tools
tool_content = result
messages = self.context.add_tool_result( messages = self.context.add_tool_result(
messages, tool_call.id, tool_call.name, result messages, tool_call.id, tool_call.name, tool_content
) )
# Interleaved CoT: reflect before next action (skip when thinking is active) # Interleaved CoT: reflect before next action (skip when thinking is active)
if not getattr(self.provider, 'thinking_budget', 0): if not getattr(self.provider, 'thinking_budget', 0):