| from __future__ import annotations |
|
|
| import os |
| import sys |
| import ast |
| from io import StringIO |
| from typing import Annotated |
| import importlib.metadata |
|
|
| import gradio as gr |
| from ._docstrings import autodoc |
| from .File_System import ROOT_DIR, File_System |
| from .Web_Fetch import Web_Fetch |
| from .Web_Search import Web_Search |
| from .Memory_Manager import Memory_Manager |
| from .Generate_Speech import Generate_Speech, List_Kokoro_Voices |
| from .Generate_Image import Generate_Image |
| from .Generate_Video import Generate_Video |
| from .Deep_Research import Deep_Research |
| from .Obsidian_Vault import Obsidian_Vault |
| from .Shell_Command import Shell_Command |
| from .Code_Interpreter import Code_Interpreter |
|
|
| from app import _log_call_end, _log_call_start, _truncate_for_log |
|
|
| def search_packages(query: str = "") -> str: |
| """Search for installed Python packages by name. If query is empty, lists all.""" |
| packages = [] |
| query = query.lower() |
| for dist in importlib.metadata.distributions(): |
| name = dist.metadata['Name'] |
| if query in name.lower(): |
| packages.append(f"{name} ({dist.version})") |
| packages.sort() |
| if not packages: |
| return f"No packages found matching '{query}'." |
| return "\n".join(packages) |
|
|
| def _get_tools_map(): |
| return { |
| "Web_Fetch": Web_Fetch, |
| "Web_Search": Web_Search, |
| "Memory_Manager": Memory_Manager, |
| "Generate_Speech": Generate_Speech, |
| "List_Kokoro_Voices": List_Kokoro_Voices, |
| "Generate_Image": Generate_Image, |
| "Generate_Video": Generate_Video, |
| "Deep_Research": Deep_Research, |
| "File_System": File_System, |
| "Obsidian_Vault": Obsidian_Vault, |
| "Shell_Command": Shell_Command, |
| "Code_Interpreter": Code_Interpreter, |
| } |
|
|
| def list_tools() -> list[str]: |
| """List all available tools in the Code Interpreter environment.""" |
| return list(_get_tools_map().keys()) |
|
|
| def search_tools(query: str) -> str: |
| """Search for tools by name or description. Returns usage info for matches.""" |
| query = query.lower() |
| matches = [] |
| tools = _get_tools_map() |
| for name, func in tools.items(): |
| doc = (func.__doc__ or "").lower() |
| if query in name.lower() or query in doc: |
| matches.append((name, func)) |
| |
| if not matches: |
| return f"No tools found matching '{query}'." |
| |
| output = [] |
| for name, func in matches: |
| output.append(f"--- {name} ---") |
| output.append(func.__doc__ or "No documentation available.") |
| output.append("") |
| return "\n".join(output) |
|
|
| def usage(tool_name: str) -> str: |
| """Get detailed usage information for a specific tool.""" |
| tools = _get_tools_map() |
| if tool_name not in tools: |
| return f"Tool '{tool_name}' not found. Available tools: {', '.join(tools.keys())}" |
| func = tools[tool_name] |
| return f"--- {tool_name} ---\n{func.__doc__ or 'No documentation available.'}" |
|
|
| |
| TOOL_SUMMARY = ( |
| "Executes Python code as the unified interface for the entire tools ecosystem. " |
| "All tool interactions must happen through this code-execution gateway. " |
| "Use Agent Terminal repeatedly whenever you need to chain or combine tool operations. " |
| "Available tools: `Web_Fetch`, `Web_Search`, `Code_Interpreter`, `Shell_Command`, `File_System`, `Obsidian_Vault`, `Memory_Manager`, `Generate_Speech`, `Generate_Image`, `Generate_Video`, `Deep_Research`." |
| ) |
|
|
|
|
|
|
| @autodoc( |
| summary=TOOL_SUMMARY, |
| ) |
| def Agent_Terminal(code: Annotated[str, ( |
| "Python source code to run; stdout is captured and returned. " |
| "Execute these commands: " |
| "`search_tools('query')` to search for tools by name or capability; " |
| "`list_tools()` to list all available tools; " |
| "`usage('ToolName')` to inspect a tool’s expected input parameters; " |
| "`search_packages('query')` to search for installed Python libraries." |
| )]) -> str: |
| _log_call_start("Agent_Terminal", code=_truncate_for_log(code or "", 300)) |
| if code is None: |
| result = "No code provided." |
| _log_call_end("Agent_Terminal", result) |
| return result |
| old_stdout = sys.stdout |
| old_cwd = os.getcwd() |
| redirected_output = sys.stdout = StringIO() |
| |
| |
| tools_env = { |
| "Web_Fetch": Web_Fetch, |
| "Web_Search": Web_Search, |
| "Memory_Manager": Memory_Manager, |
| "Generate_Speech": Generate_Speech, |
| "List_Kokoro_Voices": List_Kokoro_Voices, |
| "Generate_Image": Generate_Image, |
| "Generate_Video": Generate_Video, |
| "Deep_Research": Deep_Research, |
| "File_System": File_System, |
| "Obsidian_Vault": Obsidian_Vault, |
| "Shell_Command": Shell_Command, |
| "Code_Interpreter": Code_Interpreter, |
| "list_tools": list_tools, |
| "search_tools": search_tools, |
| "usage": usage, |
| "search_packages": search_packages, |
| "print": print, |
| "__builtins__": __builtins__, |
| } |
| |
| try: |
| os.chdir(ROOT_DIR) |
| |
| |
| tree = ast.parse(code) |
| if tree.body and isinstance(tree.body[-1], ast.Expr): |
| last_node = tree.body.pop() |
| |
| |
| if tree.body: |
| exec(compile(tree, filename="<string>", mode="exec"), tools_env) |
| |
| |
| expr = compile(ast.Expression(last_node.value), filename="<string>", mode="eval") |
| result_val = eval(expr, tools_env) |
| if result_val is not None: |
| print(result_val) |
| else: |
| exec(code, tools_env) |
| |
| result = redirected_output.getvalue() |
| except Exception as exc: |
| result = str(exc) |
| finally: |
| sys.stdout = old_stdout |
| try: |
| os.chdir(old_cwd) |
| except Exception: |
| pass |
| _log_call_end("Agent_Terminal", _truncate_for_log(result)) |
| return result |
|
|
|
|
| def build_interface() -> gr.Interface: |
| return gr.Interface( |
| fn=Agent_Terminal, |
| inputs=gr.Code(label="Python Code", language="python"), |
| outputs=gr.Textbox(label="Output", lines=5, max_lines=20), |
| title="Agent Terminal", |
| description="<div style=\"text-align:center\">Interact with all other tools via a Python API. Reduces token usage by 90%.</div>", |
| api_description=TOOL_SUMMARY, |
| flagging_mode="never", |
| ) |
|
|
|
|
| __all__ = ["Agent_Terminal", "build_interface"] |
|
|