llmOS-Agent / src /tools.py
tech-envision
Fix terminal tool to return output
d39d8db
raw
history blame
1.98 kB
from __future__ import annotations
__all__ = ["execute_terminal", "execute_terminal_async", "set_vm"]
import subprocess
import os
from typing import Optional
import asyncio
from .vm import LinuxVM
_VM: Optional[LinuxVM] = None
def set_vm(vm: LinuxVM | None) -> None:
"""Register the VM instance used for command execution."""
global _VM
_VM = vm
def execute_terminal(command: str) -> str:
"""
Execute a shell command in a Ubuntu terminal.
Use this tool to inspect uploaded documents under ``/data``, fetch web
content with utilities like ``curl`` or ``wget`` and run other commands.
The assistant must call this tool to search the internet whenever unsure
about any detail.
The command is executed with network access enabled. Output from
``stdout`` and ``stderr`` is captured when the command completes.
Execution happens asynchronously so the assistant can continue
responding while the command runs.
"""
if not command:
return "No command provided."
if _VM:
try:
return _VM.execute(command, timeout=None)
except Exception as exc: # pragma: no cover - unforeseen errors
return f"Failed to execute command in VM: {exc}"
try:
completed = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
env=os.environ.copy(),
timeout=None,
)
output = completed.stdout
if completed.stderr:
output = f"{output}\n{completed.stderr}" if output else completed.stderr
return output.strip()
except Exception as exc: # pragma: no cover - unforeseen errors
return f"Failed to execute command: {exc}"
async def execute_terminal_async(command: str) -> str:
"""Asynchronously execute a shell command."""
loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, execute_terminal, command)