From c2017fa089e4b4ad9cecae57505681f474a8ad8c Mon Sep 17 00:00:00 2001 From: Mateus Oliveira <34245751+moliveiracn@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:05:02 -0300 Subject: [PATCH] Phase 1: consolidate tool output constants into src/constants.py (#2989) MAX_OUTPUT_CHARS, MAX_READ_CHARS, and MAX_DIFF_LINES are now defined once in src/constants.py and imported by the three files that previously duplicated them (tool_execution.py, tool_implementations.py, agent_tools.py). agent_tools.py re-exports them for backward compatibility. Co-authored-by: mcnoliveira --- src/agent_tools.py | 7 ++++--- src/constants.py | 8 +++++++- src/tool_execution.py | 5 +---- src/tool_implementations.py | 3 +-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/agent_tools.py b/src/agent_tools.py index 41f0411ce..a953853b2 100644 --- a/src/agent_tools.py +++ b/src/agent_tools.py @@ -14,16 +14,17 @@ Sub-modules: import logging from collections import namedtuple +from src.constants import MAX_OUTPUT_CHARS, MAX_READ_CHARS + logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- -# Constants (kept here — sub-modules import from here) +# Constants (re-exported for backward compatibility — single source of truth +# is src.constants; always prefer importing from there for new code) # --------------------------------------------------------------------------- MAX_AGENT_ROUNDS = 50 SHELL_TIMEOUT = 60 PYTHON_TIMEOUT = 30 -MAX_OUTPUT_CHARS = 10_000 -MAX_READ_CHARS = 20_000 # Tool types that trigger execution TOOL_TAGS = {"bash", "python", "web_search", "web_fetch", "read_file", "write_file", "edit_file", diff --git a/src/constants.py b/src/constants.py index e44c6c4af..afe9db88a 100644 --- a/src/constants.py +++ b/src/constants.py @@ -19,6 +19,12 @@ UPLOAD_DIR = os.path.join(DATA_DIR, "uploads") FEATURES_FILE = os.path.join(DATA_DIR, "features.json") SETTINGS_FILE = os.path.join(DATA_DIR, "settings.json") +# Agent tool output limits (single source of truth — imported by tool_execution.py, +# tool_implementations.py, agent_tools.py, and any other module that needs them) +MAX_OUTPUT_CHARS = 10_000 # cap for bash/python/web_search/web_fetch output +MAX_READ_CHARS = 20_000 # cap for read_file / document preview +MAX_DIFF_LINES = 400 # cap for edit_file unified-diff display + # API Configuration MAX_CONTEXT_MESSAGES = 90 REQUEST_TIMEOUT = 20 @@ -28,7 +34,7 @@ OPENAI_COMPAT_PATH = "/v1/chat/completions" DEFAULT_HOST = os.getenv("LLM_HOST", "localhost") LLM_HOSTS = [h.strip() for h in os.getenv("LLM_HOSTS", "").split(",") if h.strip()] OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") -SEARXNG_INSTANCE = os.getenv('SEARXNG_INSTANCE', 'http://localhost:8080') +SEARXNG_INSTANCE = os.getenv("SEARXNG_INSTANCE", "http://localhost:8080") # Cleanup configuration diff --git a/src/tool_execution.py b/src/tool_execution.py index 3aef285d8..f4dc9ae0d 100644 --- a/src/tool_execution.py +++ b/src/tool_execution.py @@ -19,6 +19,7 @@ import time from typing import Any, Awaitable, Callable, Dict, Optional, Tuple from src.tool_security import is_public_blocked_tool, owner_is_admin_or_single_user +from src.constants import MAX_OUTPUT_CHARS, MAX_READ_CHARS, MAX_DIFF_LINES # Persistent working directory for agent subprocesses. # Resolves to /data, which is the bind-mounted volume in Docker @@ -27,10 +28,6 @@ from src.tool_security import is_public_blocked_tool, owner_is_admin_or_single_u # in ephemeral container layers that are lost on the next rebuild. _AGENT_WORKDIR = str(pathlib.Path(__file__).parent.parent / "data") -MAX_OUTPUT_CHARS = 10_000 -MAX_READ_CHARS = 20_000 -MAX_DIFF_LINES = 400 # cap unified-diff size returned to the UI - def _unified_diff(old: str, new: str, path: str) -> Optional[Dict[str, Any]]: """Build a unified diff of a file write for display in the chat. diff --git a/src/tool_implementations.py b/src/tool_implementations.py index 6a0999068..13c332461 100644 --- a/src/tool_implementations.py +++ b/src/tool_implementations.py @@ -12,8 +12,7 @@ import os import re from typing import Any, Dict, List, Optional -MAX_OUTPUT_CHARS = 10_000 -MAX_READ_CHARS = 20_000 +from src.constants import MAX_OUTPUT_CHARS, MAX_READ_CHARS def get_mcp_manager():