diff --git a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py index 42e0273b0..9ee0e6123 100644 --- a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +++ b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py @@ -36,14 +36,12 @@ from .....astr_agent_tool_exec import FunctionToolExecutor from ....context import PipelineContext, call_event_hook from ...stage import Stage from ...utils import ( - CREATE_FILE_TOOL, EXECUTE_SHELL_TOOL, FILE_DOWNLOAD_TOOL, FILE_UPLOAD_TOOL, KNOWLEDGE_BASE_QUERY_TOOL, LLM_SAFETY_MODE_SYSTEM_PROMPT, PYTHON_TOOL, - READ_FILE_TOOL, decoded_blocked, retrieve_knowledge_base, ) @@ -488,12 +486,11 @@ class InternalAgentSubStage(Stage): return os.environ["SHIPYARD_ENDPOINT"] = ep os.environ["SHIPYARD_ACCESS_TOKEN"] = at - req.func_tool.add_tool(CREATE_FILE_TOOL) - req.func_tool.add_tool(READ_FILE_TOOL) req.func_tool.add_tool(EXECUTE_SHELL_TOOL) req.func_tool.add_tool(PYTHON_TOOL) req.func_tool.add_tool(FILE_UPLOAD_TOOL) req.func_tool.add_tool(FILE_DOWNLOAD_TOOL) + req.system_prompt += "\nYou have access to a sandboxed environment and can execute shell commands and Python code securely.\n" async def process( self, event: AstrMessageEvent, provider_wake_prefix: str @@ -576,6 +573,16 @@ class InternalAgentSubStage(Stage): req.extra_user_content_parts.append( TextPart(text=f"[Image Attachment: path {image_path}]") ) + elif isinstance(comp, File) and self.sandbox_cfg.get( + "enable", False + ): + file_path = await comp.get_file() + file_name = comp.name or os.path.basename(file_path) + req.extra_user_content_parts.append( + TextPart( + text=f"[File Attachment: name {file_name}, path {file_path}]" + ) + ) conversation = await self._get_session_conv(event) req.conversation = conversation diff --git a/astrbot/core/pipeline/process_stage/utils.py b/astrbot/core/pipeline/process_stage/utils.py index dc60c8025..7aee88c2b 100644 --- a/astrbot/core/pipeline/process_stage/utils.py +++ b/astrbot/core/pipeline/process_stage/utils.py @@ -8,12 +8,10 @@ from astrbot.core.agent.run_context import ContextWrapper from astrbot.core.agent.tool import FunctionTool, ToolExecResult from astrbot.core.astr_agent_context import AstrAgentContext from astrbot.core.sandbox.tools import ( - CreateFileTool, ExecuteShellTool, FileDownloadTool, FileUploadTool, PythonTool, - ReadFileTool, ) from astrbot.core.star.context import Context @@ -146,8 +144,6 @@ async def retrieve_knowledge_base( KNOWLEDGE_BASE_QUERY_TOOL = KnowledgeBaseQueryTool() -CREATE_FILE_TOOL = CreateFileTool() -READ_FILE_TOOL = ReadFileTool() EXECUTE_SHELL_TOOL = ExecuteShellTool() PYTHON_TOOL = PythonTool() FILE_UPLOAD_TOOL = FileUploadTool() diff --git a/astrbot/core/sandbox/tools/__init__.py b/astrbot/core/sandbox/tools/__init__.py index 2b22479be..8dacab79f 100644 --- a/astrbot/core/sandbox/tools/__init__.py +++ b/astrbot/core/sandbox/tools/__init__.py @@ -1,10 +1,8 @@ -from .fs import CreateFileTool, FileDownloadTool, FileUploadTool, ReadFileTool +from .fs import FileDownloadTool, FileUploadTool from .python import PythonTool from .shell import ExecuteShellTool __all__ = [ - "CreateFileTool", - "ReadFileTool", "FileUploadTool", "PythonTool", "ExecuteShellTool", diff --git a/astrbot/core/sandbox/tools/fs.py b/astrbot/core/sandbox/tools/fs.py index 3214abfe7..8f12a2f78 100644 --- a/astrbot/core/sandbox/tools/fs.py +++ b/astrbot/core/sandbox/tools/fs.py @@ -1,4 +1,3 @@ -import json import os from dataclasses import dataclass, field @@ -12,69 +11,68 @@ from astrbot.core.utils.astrbot_path import get_astrbot_temp_path from ..sandbox_client import get_booter +# @dataclass +# class CreateFileTool(FunctionTool): +# name: str = "astrbot_create_file" +# description: str = "Create a new file in the sandbox." +# parameters: dict = field( +# default_factory=lambda: { +# "type": "object", +# "properties": { +# "path": { +# "path": "string", +# "description": "The path where the file should be created, relative to the sandbox root. Must not use absolute paths or traverse outside the sandbox.", +# }, +# "content": { +# "type": "string", +# "description": "The content to write into the file.", +# }, +# }, +# "required": ["path", "content"], +# } +# ) -@dataclass -class CreateFileTool(FunctionTool): - name: str = "astrbot_create_file" - description: str = "Create a new file in the sandbox." - parameters: dict = field( - default_factory=lambda: { - "type": "object", - "properties": { - "path": { - "path": "string", - "description": "The path where the file should be created, relative to the sandbox root. Must not use absolute paths or traverse outside the sandbox.", - }, - "content": { - "type": "string", - "description": "The content to write into the file.", - }, - }, - "required": ["path", "content"], - } - ) - - async def call( - self, context: ContextWrapper[AstrAgentContext], path: str, content: str - ) -> ToolExecResult: - sb = await get_booter( - context.context.context, - context.context.event.unified_msg_origin, - ) - try: - result = await sb.fs.create_file(path, content) - return json.dumps(result) - except Exception as e: - return f"Error creating file: {str(e)}" +# async def call( +# self, context: ContextWrapper[AstrAgentContext], path: str, content: str +# ) -> ToolExecResult: +# sb = await get_booter( +# context.context.context, +# context.context.event.unified_msg_origin, +# ) +# try: +# result = await sb.fs.create_file(path, content) +# return json.dumps(result) +# except Exception as e: +# return f"Error creating file: {str(e)}" -@dataclass -class ReadFileTool(FunctionTool): - name: str = "astrbot_read_file" - description: str = "Read the content of a file in the sandbox." - parameters: dict = field( - default_factory=lambda: { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "The path of the file to read, relative to the sandbox root. Must not use absolute paths or traverse outside the sandbox.", - }, - }, - "required": ["path"], - } - ) +# @dataclass +# class ReadFileTool(FunctionTool): +# name: str = "astrbot_read_file" +# description: str = "Read the content of a file in the sandbox." +# parameters: dict = field( +# default_factory=lambda: { +# "type": "object", +# "properties": { +# "path": { +# "type": "string", +# "description": "The path of the file to read, relative to the sandbox root. Must not use absolute paths or traverse outside the sandbox.", +# }, +# }, +# "required": ["path"], +# } +# ) - async def call(self, context: ContextWrapper[AstrAgentContext], path: str): - sb = await get_booter( - context.context.context, - context.context.event.unified_msg_origin, - ) - try: - result = await sb.fs.read_file(path) - return result - except Exception as e: - return f"Error reading file: {str(e)}" +# async def call(self, context: ContextWrapper[AstrAgentContext], path: str): +# sb = await get_booter( +# context.context.context, +# context.context.event.unified_msg_origin, +# ) +# try: +# result = await sb.fs.read_file(path) +# return result +# except Exception as e: +# return f"Error reading file: {str(e)}" @dataclass diff --git a/astrbot/core/sandbox/tools/python.py b/astrbot/core/sandbox/tools/python.py index 791a7e691..fd45d797c 100644 --- a/astrbot/core/sandbox/tools/python.py +++ b/astrbot/core/sandbox/tools/python.py @@ -40,8 +40,9 @@ class PythonTool(FunctionTool): ) try: result = await sb.python.exec(code, silent=silent) - output = result.get("output", {}) - error = result.get("error", "") + data = result.get("data", {}) + output = data.get("output", {}) + error = data.get("error", "") images: list[dict] = output.get("images", []) text: str = output.get("text", "")