Spaces:
Runtime error
Runtime error
tech-envision
commited on
Commit
·
d39d8db
1
Parent(s):
1eafe79
Fix terminal tool to return output
Browse files- README.md +3 -3
- src/tools.py +13 -9
- src/vm.py +5 -5
README.md
CHANGED
@@ -9,9 +9,9 @@ conversations can be resumed with context. One example tool is included:
|
|
9 |
with network access. Use it to read uploaded documents under ``/data``, fetch
|
10 |
web content via tools like ``curl`` or run any other commands. The assistant
|
11 |
must invoke this tool to search online when unsure about a response. Output
|
12 |
-
from ``stdout`` and ``stderr`` is captured when
|
13 |
-
|
14 |
-
|
15 |
The VM is created when a chat session starts and reused for all subsequent
|
16 |
tool calls.
|
17 |
|
|
|
9 |
with network access. Use it to read uploaded documents under ``/data``, fetch
|
10 |
web content via tools like ``curl`` or run any other commands. The assistant
|
11 |
must invoke this tool to search online when unsure about a response. Output
|
12 |
+
from ``stdout`` and ``stderr`` is captured when each command finishes.
|
13 |
+
Execution happens asynchronously so the assistant can continue responding
|
14 |
+
while the command runs.
|
15 |
The VM is created when a chat session starts and reused for all subsequent
|
16 |
tool calls.
|
17 |
|
src/tools.py
CHANGED
@@ -27,29 +27,33 @@ def execute_terminal(command: str) -> str:
|
|
27 |
The assistant must call this tool to search the internet whenever unsure
|
28 |
about any detail.
|
29 |
|
30 |
-
The command is executed with network access enabled.
|
31 |
-
|
32 |
-
|
|
|
33 |
"""
|
34 |
if not command:
|
35 |
return "No command provided."
|
36 |
|
37 |
if _VM:
|
38 |
try:
|
39 |
-
return _VM.execute(command,
|
40 |
except Exception as exc: # pragma: no cover - unforeseen errors
|
41 |
return f"Failed to execute command in VM: {exc}"
|
42 |
|
43 |
try:
|
44 |
-
subprocess.
|
45 |
command,
|
46 |
shell=True,
|
47 |
-
|
48 |
-
|
49 |
-
start_new_session=True,
|
50 |
env=os.environ.copy(),
|
|
|
51 |
)
|
52 |
-
|
|
|
|
|
|
|
53 |
except Exception as exc: # pragma: no cover - unforeseen errors
|
54 |
return f"Failed to execute command: {exc}"
|
55 |
|
|
|
27 |
The assistant must call this tool to search the internet whenever unsure
|
28 |
about any detail.
|
29 |
|
30 |
+
The command is executed with network access enabled. Output from
|
31 |
+
``stdout`` and ``stderr`` is captured when the command completes.
|
32 |
+
Execution happens asynchronously so the assistant can continue
|
33 |
+
responding while the command runs.
|
34 |
"""
|
35 |
if not command:
|
36 |
return "No command provided."
|
37 |
|
38 |
if _VM:
|
39 |
try:
|
40 |
+
return _VM.execute(command, timeout=None)
|
41 |
except Exception as exc: # pragma: no cover - unforeseen errors
|
42 |
return f"Failed to execute command in VM: {exc}"
|
43 |
|
44 |
try:
|
45 |
+
completed = subprocess.run(
|
46 |
command,
|
47 |
shell=True,
|
48 |
+
capture_output=True,
|
49 |
+
text=True,
|
|
|
50 |
env=os.environ.copy(),
|
51 |
+
timeout=None,
|
52 |
)
|
53 |
+
output = completed.stdout
|
54 |
+
if completed.stderr:
|
55 |
+
output = f"{output}\n{completed.stderr}" if output else completed.stderr
|
56 |
+
return output.strip()
|
57 |
except Exception as exc: # pragma: no cover - unforeseen errors
|
58 |
return f"Failed to execute command: {exc}"
|
59 |
|
src/vm.py
CHANGED
@@ -68,7 +68,7 @@ class LinuxVM:
|
|
68 |
raise RuntimeError(f"Failed to start VM: {exc}") from exc
|
69 |
|
70 |
def execute(
|
71 |
-
self, command: str, *, timeout: int = 3, detach: bool = False
|
72 |
) -> str:
|
73 |
"""Execute a command inside the running VM.
|
74 |
|
@@ -77,8 +77,8 @@ class LinuxVM:
|
|
77 |
command:
|
78 |
The shell command to run inside the container.
|
79 |
timeout:
|
80 |
-
Maximum time in seconds to wait for completion.
|
81 |
-
``detach`` is ``True``.
|
82 |
detach:
|
83 |
Run the command in the background without waiting for it to finish.
|
84 |
"""
|
@@ -105,7 +105,7 @@ class LinuxVM:
|
|
105 |
cmd,
|
106 |
capture_output=True,
|
107 |
text=True,
|
108 |
-
timeout=None if detach else timeout,
|
109 |
)
|
110 |
except subprocess.TimeoutExpired as exc:
|
111 |
return f"Command timed out after {timeout}s: {exc.cmd}"
|
@@ -118,7 +118,7 @@ class LinuxVM:
|
|
118 |
return output.strip()
|
119 |
|
120 |
async def execute_async(
|
121 |
-
self, command: str, *, timeout: int = 3, detach: bool = False
|
122 |
) -> str:
|
123 |
"""Asynchronously execute ``command`` inside the running VM."""
|
124 |
loop = asyncio.get_running_loop()
|
|
|
68 |
raise RuntimeError(f"Failed to start VM: {exc}") from exc
|
69 |
|
70 |
def execute(
|
71 |
+
self, command: str, *, timeout: int | None = 3, detach: bool = False
|
72 |
) -> str:
|
73 |
"""Execute a command inside the running VM.
|
74 |
|
|
|
77 |
command:
|
78 |
The shell command to run inside the container.
|
79 |
timeout:
|
80 |
+
Maximum time in seconds to wait for completion. Set to ``None``
|
81 |
+
to wait indefinitely. Ignored when ``detach`` is ``True``.
|
82 |
detach:
|
83 |
Run the command in the background without waiting for it to finish.
|
84 |
"""
|
|
|
105 |
cmd,
|
106 |
capture_output=True,
|
107 |
text=True,
|
108 |
+
timeout=None if detach or timeout is None else timeout,
|
109 |
)
|
110 |
except subprocess.TimeoutExpired as exc:
|
111 |
return f"Command timed out after {timeout}s: {exc.cmd}"
|
|
|
118 |
return output.strip()
|
119 |
|
120 |
async def execute_async(
|
121 |
+
self, command: str, *, timeout: int | None = 3, detach: bool = False
|
122 |
) -> str:
|
123 |
"""Asynchronously execute ``command`` inside the running VM."""
|
124 |
loop = asyncio.get_running_loop()
|