debug sb_files_tool & sb_vision_tool

This commit is contained in:
cyb1278588254
2025-07-20 17:26:15 +08:00
parent c94422748a
commit 0246513495
6 changed files with 109 additions and 18 deletions
+13 -2
View File
@@ -14,6 +14,9 @@ from app.tool.ask_human import AskHuman
from app.tool.browser_use_tool import BrowserUseTool
from app.tool.mcp import MCPClients, MCPClientTool
from app.tool.python_execute import PythonExecute
from app.tool.sb_files_tool import SandboxFilesTool
from app.tool.sb_shell_tool import SandboxShellTool
from app.tool.sb_vision_tool import SandboxVisionTool
from app.tool.str_replace_editor import StrReplaceEditor
from app.tool.sb_browser_tool import SandboxBrowserTool
@@ -122,8 +125,16 @@ class SandboxManus(ToolCallAgent):
}
logger.info(f"VNC URL: {vnc_url}")
logger.info(f"Website URL: {website_url}")
computer_tool = SandboxBrowserTool.create_with_sandbox(sandbox)
self.available_tools.add_tools(computer_tool)
sb_tools = [
SandboxBrowserTool(sandbox),
SandboxFilesTool(sandbox),
SandboxShellTool(sandbox),
SandboxVisionTool(sandbox)
]
# for sb_tool in sb_tools:
# self.available_tools.add_tool(sb_tool)
self.available_tools.add_tools(*sb_tools)
except Exception as e:
logger.error(f"Error initializing sandbox tools: {e}")
+2 -2
View File
@@ -16,8 +16,8 @@ import json
import asyncio
from openai import OpenAIError
import litellm
from utils.logger import logger
from utils.config import config
# from utils.logger import logger
# from utils.config import config
# litellm.set_verbose=True
litellm.modify_params=True
+10 -9
View File
@@ -1,9 +1,9 @@
from dataclasses import Field
from pydantic import Field
from typing import Optional, TypeVar
from app.tool.base import ToolResult
from app.daytona.tool_base import SandboxToolsBase, Sandbox
from app.utils.files_utils import should_exclude_file, clean_path
from app.agentpress.thread_manager import ThreadManager
# from app.agentpress.thread_manager import ThreadManager
from app.utils.logger import logger
import os
import asyncio
@@ -70,13 +70,14 @@ class SandboxFilesTool(SandboxToolsBase):
},
}
SNIPPET_LINES: int = Field(default=4, exclude=True)
workspace_path: str = Field(default="/workspace", exclude=True)
sandbox: Optional[Sandbox] = Field(default=None, exclude=True)
# workspace_path: str = Field(default="/workspace", exclude=True)
# sandbox: Optional[Sandbox] = Field(default=None, exclude=True)
def __init__(self, project_id: str, thread_manager: ThreadManager):
super().__init__(project_id, thread_manager)
self.SNIPPET_LINES = 4 # Number of context lines to show around edits
self.workspace_path = "/workspace" # Ensure we're always operating in /workspace
def __init__(self, sandbox: Optional[Sandbox] = None, thread_id: Optional[str] = None, **data):
"""Initialize with optional sandbox and thread_id."""
super().__init__(**data)
if sandbox is not None:
self._sandbox = sandbox
def clean_path(self, path: str) -> str:
"""Clean and normalize a path to be relative to /workspace"""
@@ -151,7 +152,7 @@ class SandboxFilesTool(SandboxToolsBase):
Returns:
ToolResult with the operation's output or error
"""
async with self.lock:
async with asyncio.Lock():
try:
# File creation
if action == "create_file":
+13 -5
View File
@@ -1,3 +1,4 @@
from pydantic import Field
import os
import base64
import mimetypes
@@ -7,8 +8,7 @@ from io import BytesIO
from PIL import Image
from app.tool.base import ToolResult
from app.agentpress.thread_manager import ThreadManager
from app.daytona.tool_base import SandboxToolsBase
from app.daytona.tool_base import SandboxToolsBase, Sandbox, ThreadMessage
# 最大文件大小(原图10MB,压缩后5MB)
MAX_IMAGE_SIZE = 10 * 1024 * 1024
@@ -54,6 +54,13 @@ class SandboxVisionTool(SandboxToolsBase):
# self.thread_id = thread_id
# self.thread_manager = thread_manager
vision_message: Optional[ThreadMessage] = Field(default=None, exclude=True)
def __init__(self, sandbox: Optional[Sandbox] = None, thread_id: Optional[str] = None, **data):
"""Initialize with optional sandbox and thread_id."""
super().__init__(**data)
if sandbox is not None:
self._sandbox = sandbox
def compress_image(self, image_bytes: bytes, mime_type: str, file_path: str):
"""压缩图片,保持合理质量。"""
try:
@@ -132,12 +139,13 @@ class SandboxVisionTool(SandboxToolsBase):
"original_size": file_info.size,
"compressed_size": len(compressed_bytes)
}
await self.thread_manager.add_message(
thread_id=self.thread_id,
message = ThreadMessage(
type="image_context",
content=image_context_data,
is_llm_message=False
)
return self.success_response(f"成功加载并压缩图片 '{cleaned_path}' (由 {file_info.size / 1024:.1f}KB 压缩到 {len(compressed_bytes) / 1024:.1f}KB)。")
self.vision_message = message
# return self.success_response(f"成功加载并压缩图片 '{cleaned_path}' (由 {file_info.size / 1024:.1f}KB 压缩到 {len(compressed_bytes) / 1024:.1f}KB)。")
return self.success_response(f"成功加载并压缩图片 '{cleaned_path}',压缩后的内容为:{base64_image}")
except Exception as e:
return self.fail_response(f"see_image 执行异常: {str(e)}")
+37
View File
@@ -0,0 +1,37 @@
from app.tool.sb_files_tool import SandboxFilesTool
from app.daytona.sandbox import create_sandbox
import asyncio
async def main():
# 创建沙箱和工具
sandbox = create_sandbox(password="123456")
# base_url=sandbox.get_preview_link(8000)
# print(f"Sandbox base URL: {base_url}")
print(f"Sandbox ID: {sandbox.id}")
vnc_link = sandbox.get_preview_link(6080)
website_link = sandbox.get_preview_link(8080)
print(f"VNC Link: {vnc_link}")
print(f"Website Link: {website_link}")
sb_files_tool = SandboxFilesTool(sandbox)
# 执行创建文件操作
result = await sb_files_tool.execute(action="create_file", file_path="src/a.txt", file_contents="aaaaa1111")
print(result)
# 执行字符串替换操作
# result = await sb_files_tool.execute(action="str_replace", file_path="src/a.txt", old_str="aaaaa", new_str="bbbbb")
# print(result)
# 执行全文件重写操作
result = await sb_files_tool.execute(action="full_file_rewrite", file_path="src/a.txt", file_contents="1234567")
print(result)
# 执行删除文件操作
# result = await sb_files_tool.execute(action="delete_file", file_path="src/a.txt")
# print(result)
# 清理资源(可选)
# await sb_shell_tool.cleanup()
if __name__ == "__main__":
asyncio.run(main())
+34
View File
@@ -0,0 +1,34 @@
from app.tool.sb_shell_tool import SandboxShellTool
from app.tool.sb_vision_tool import SandboxVisionTool
from app.daytona.sandbox import create_sandbox
import asyncio
async def main():
# 创建沙箱和工具
sandbox = create_sandbox(password="123456")
# base_url=sandbox.get_preview_link(8000)
# print(f"Sandbox base URL: {base_url}")
print(f"Sandbox ID: {sandbox.id}")
vnc_link = sandbox.get_preview_link(6080)
website_link = sandbox.get_preview_link(8080)
print(f"VNC Link: {vnc_link}")
print(f"Website Link: {website_link}")
sb_shell_tool = SandboxShellTool(sandbox)
sb_vision_tool = SandboxVisionTool(sandbox)
# 执行终端命令
result = await sb_shell_tool.execute(action="execute_command", command="curl -O http://img.netbian.com/file/2025/0716/091412RIFD9.jpg")
print(result)
# 执行see_image操作
result = await sb_vision_tool.execute(action="see_image", file_path="091412RIFD9.jpg")
print(result)
# 清理资源(可选)
# await sb_shell_tool.cleanup()
if __name__ == "__main__":
asyncio.run(main())