Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/tools/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
_SESSION_MAX_COOKIES = 50
_SESSION_MAX_HEADERS = 30

# HTTP 响应体读取硬上限(字节):防异常超大响应塞爆内存;超限截断响应并提示。
# _read_limited_response 曾引用此名却无定义,会走到截断分支时抛 NameError。
_HTTP_MAX_BYTES = int(os.environ.get("WORKER_HTTP_MAX_BYTES", str(1024 * 1024)))
# 单目标工作目录落地日志体积上限(字节)。24x7 防撞盘:超限后停止写新日志文件,
# 仍把截断输出回传给 LLM,不影响挖掘,只是不再落地完整证据。
_WORKDIR_MAX_BYTES = int(os.environ.get("WORKER_WORKDIR_MAX_BYTES", str(50 * 1024 * 1024)))
Expand Down
33 changes: 33 additions & 0 deletions tests/test_executor_http_limit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""覆盖 _HTTP_MAX_BYTES 常量及响应截断逻辑。

历史背景:_read_limited_response 曾引用 _HTTP_MAX_BYTES 但全库无定义,走到截断分支会抛 NameError。
本用例断言该常量已定义,并验证大响应被截断、小响应原样放行。
"""
import unittest

import httpx

from app.tools.executor import ToolExecutor, _HTTP_MAX_BYTES


class TestHttpResponseLimit(unittest.TestCase):
def test_limit_constant_defined_and_positive(self):
self.assertIsInstance(_HTTP_MAX_BYTES, int)
self.assertGreater(_HTTP_MAX_BYTES, 0)

def test_large_response_truncated(self):
big = b"x" * (_HTTP_MAX_BYTES * 2)
resp = httpx.Response(200, content=big, headers={"Content-Type": "text/plain"})
body, truncated = ToolExecutor._read_limited_response(resp)
self.assertTrue(truncated)
self.assertLessEqual(len(body), _HTTP_MAX_BYTES + 200)

def test_small_response_passes_through(self):
resp = httpx.Response(200, content=b"hello", headers={"Content-Type": "text/plain"})
body, truncated = ToolExecutor._read_limited_response(resp)
self.assertFalse(truncated)
self.assertIn("hello", body)


if __name__ == "__main__":
unittest.main()