tech-envision commited on
Commit
26ff0b4
·
1 Parent(s): 01aff11

Limit tool output to last 10k characters

Browse files
Files changed (5) hide show
  1. README.md +2 -0
  2. src/__init__.py +3 -0
  3. src/tools.py +6 -2
  4. src/utils.py +18 -0
  5. src/vm.py +2 -1
README.md CHANGED
@@ -10,6 +10,8 @@ conversations can be resumed with context. One example tool is included:
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
 
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
+ The output string is capped at the last 10,000 characters so very long
14
+ results are truncated. A short notice is prepended whenever data is hidden.
15
  Execution happens asynchronously so the assistant can continue responding
16
  while the command runs.
17
  The VM is created when a chat session starts and reused for all subsequent
src/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
  from .chat import ChatSession
2
  from .tools import execute_terminal, execute_terminal_async, set_vm
 
3
  from .vm import LinuxVM
4
 
5
  __all__ = [
@@ -8,4 +9,6 @@ __all__ = [
8
  "execute_terminal_async",
9
  "set_vm",
10
  "LinuxVM",
 
11
  ]
 
 
1
  from .chat import ChatSession
2
  from .tools import execute_terminal, execute_terminal_async, set_vm
3
+ from .utils import limit_chars
4
  from .vm import LinuxVM
5
 
6
  __all__ = [
 
9
  "execute_terminal_async",
10
  "set_vm",
11
  "LinuxVM",
12
+ "limit_chars",
13
  ]
14
+
src/tools.py CHANGED
@@ -7,6 +7,8 @@ import os
7
  from typing import Optional
8
  import asyncio
9
 
 
 
10
  from .vm import LinuxVM
11
 
12
  _VM: Optional[LinuxVM] = None
@@ -37,7 +39,8 @@ def execute_terminal(command: str) -> str:
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
 
@@ -53,7 +56,7 @@ def execute_terminal(command: str) -> str:
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
 
@@ -62,3 +65,4 @@ async def execute_terminal_async(command: str) -> str:
62
  """Asynchronously execute a shell command."""
63
  loop = asyncio.get_running_loop()
64
  return await loop.run_in_executor(None, execute_terminal, command)
 
 
7
  from typing import Optional
8
  import asyncio
9
 
10
+ from .utils import limit_chars
11
+
12
  from .vm import LinuxVM
13
 
14
  _VM: Optional[LinuxVM] = None
 
39
 
40
  if _VM:
41
  try:
42
+ output = _VM.execute(command, timeout=None)
43
+ return limit_chars(output)
44
  except Exception as exc: # pragma: no cover - unforeseen errors
45
  return f"Failed to execute command in VM: {exc}"
46
 
 
56
  output = completed.stdout
57
  if completed.stderr:
58
  output = f"{output}\n{completed.stderr}" if output else completed.stderr
59
+ return limit_chars(output)
60
  except Exception as exc: # pragma: no cover - unforeseen errors
61
  return f"Failed to execute command: {exc}"
62
 
 
65
  """Asynchronously execute a shell command."""
66
  loop = asyncio.get_running_loop()
67
  return await loop.run_in_executor(None, execute_terminal, command)
68
+
src/utils.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ __all__ = ["limit_chars"]
4
+
5
+
6
+ def limit_chars(text: str, limit: int = 10_000) -> str:
7
+ """Return at most ``limit`` characters from ``text``.
8
+
9
+ Earlier characters are stripped when the text exceeds the limit.
10
+ A short notice is prepended indicating the amount removed.
11
+ """
12
+ text = text.strip()
13
+ if len(text) <= limit:
14
+ return text
15
+
16
+ truncated = len(text) - limit
17
+ return f"(output truncated, {truncated} characters hidden)\n{text[-limit:]}"
18
+
src/vm.py CHANGED
@@ -9,6 +9,7 @@ from pathlib import Path
9
  from threading import Lock
10
 
11
  from .config import UPLOAD_DIR, VM_IMAGE, PERSIST_VMS, VM_STATE_DIR
 
12
 
13
  from .log import get_logger
14
 
@@ -147,7 +148,7 @@ class LinuxVM:
147
  output = completed.stdout
148
  if completed.stderr:
149
  output = f"{output}\n{completed.stderr}" if output else completed.stderr
150
- return output.strip()
151
 
152
  async def execute_async(
153
  self, command: str, *, timeout: int | None = 3, detach: bool = False
 
9
  from threading import Lock
10
 
11
  from .config import UPLOAD_DIR, VM_IMAGE, PERSIST_VMS, VM_STATE_DIR
12
+ from .utils import limit_chars
13
 
14
  from .log import get_logger
15
 
 
148
  output = completed.stdout
149
  if completed.stderr:
150
  output = f"{output}\n{completed.stderr}" if output else completed.stderr
151
+ return limit_chars(output)
152
 
153
  async def execute_async(
154
  self, command: str, *, timeout: int | None = 3, detach: bool = False