5eea508296
* stage * fix: update tool call logging to include tool call IDs and enhance sandbox ship creation parameters * feat: file upload * fix * update * fix: remove 'boxlite' option from booter and handle error in PythonTool execution * feat: implement singleton pattern for ShipyardSandboxClient and add FileUploadTool for file uploads * feat: sandbox * fix * beta * uv lock * remove * chore: makes world better * feat: implement localStorage persistence for showReservedPlugins state * docs: refine EULA * fix * feat: add availability check for sandbox in Shipyard and base booters * feat: add shipyard session configuration options and update related tools * feat: add file download functionality and update shipyard SDK version * fix: sending OpenAI-style image_url causes Anthropic 400 invalid tag error (#4444) * feat: chatui project (#4477) * feat: chatui-project * fix: remove console log from getProjects function * fix: title saving logic and update project sessions on changes * docs: standardize Context class documentation formatting (#4436) * docs: standardize Context class documentation formatting - Unified all method docstrings to standard format - Fixed mixed language and formatting issues - Added complete parameter and return descriptions - Enhanced developer experience for plugin creators - Fixes #4429 * docs: fix Context class documentation issues per review - Restored Sphinx directives for versionadded notes - Fixed MessageSesion typo to MessageSession throughout file - Added clarification for kwargs propagation in tool_loop_agent - Unified deprecation marker format - Fixes #4429 * Convert developer API comments to English * chore: revise comments --------- Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com> * fix: handle empty output case in PythonTool execution * fix: update description for command parameter in ExecuteShellTool * refactor: remove unused file tools and update PythonTool output handling * project list * fix: ensure message stream order (#4487) * feat: enhance iPython tool rendering with Shiki syntax highlighting * bugfixes * feat: add sandbox mode prompt for enhanced user guidance in executing commands * chore: remove skills prompt --------- Co-authored-by: 時壹 <137363396+KBVsent@users.noreply.github.com> Co-authored-by: Li-shi-ling <114913764+Li-shi-ling@users.noreply.github.com>
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
from dataclasses import dataclass, field
|
|
|
|
import mcp
|
|
|
|
from astrbot.api import FunctionTool
|
|
from astrbot.core.agent.run_context import ContextWrapper
|
|
from astrbot.core.agent.tool import ToolExecResult
|
|
from astrbot.core.astr_agent_context import AstrAgentContext
|
|
from astrbot.core.sandbox.sandbox_client import get_booter
|
|
|
|
|
|
@dataclass
|
|
class PythonTool(FunctionTool):
|
|
name: str = "astrbot_execute_ipython"
|
|
description: str = "Execute a command in an IPython shell."
|
|
parameters: dict = field(
|
|
default_factory=lambda: {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": {
|
|
"type": "string",
|
|
"description": "The Python code to execute.",
|
|
},
|
|
"silent": {
|
|
"type": "boolean",
|
|
"description": "Whether to suppress the output of the code execution.",
|
|
"default": False,
|
|
},
|
|
},
|
|
"required": ["code"],
|
|
}
|
|
)
|
|
|
|
async def call(
|
|
self, context: ContextWrapper[AstrAgentContext], code: str, silent: bool = False
|
|
) -> ToolExecResult:
|
|
sb = await get_booter(
|
|
context.context.context,
|
|
context.context.event.unified_msg_origin,
|
|
)
|
|
try:
|
|
result = await sb.python.exec(code, silent=silent)
|
|
data = result.get("data", {})
|
|
output = data.get("output", {})
|
|
error = data.get("error", "")
|
|
images: list[dict] = output.get("images", [])
|
|
text: str = output.get("text", "")
|
|
|
|
resp = mcp.types.CallToolResult(content=[])
|
|
|
|
if error:
|
|
resp.content.append(
|
|
mcp.types.TextContent(type="text", text=f"error: {error}")
|
|
)
|
|
|
|
if images:
|
|
for img in images:
|
|
resp.content.append(
|
|
mcp.types.ImageContent(
|
|
type="image", data=img["image/png"], mimeType="image/png"
|
|
)
|
|
)
|
|
if text:
|
|
resp.content.append(mcp.types.TextContent(type="text", text=text))
|
|
|
|
if not resp.content:
|
|
resp.content.append(
|
|
mcp.types.TextContent(type="text", text="No output.")
|
|
)
|
|
|
|
return resp
|
|
|
|
except Exception as e:
|
|
return f"Error executing code: {str(e)}"
|