refactor(kanban): unify attachment size cap on KANBAN_ATTACHMENT_MAX_BYTES

The salvaged attachment-toolset commit predated main centralizing the
25 MB cap as kanban_db.KANBAN_ATTACHMENT_MAX_BYTES and re-introduced a
private _MAX_ATTACHMENT_BYTES alias. Drop the duplicate: kanban_db's
store_attachment_bytes(), the dashboard upload endpoint, and the
kanban_attach_url tool all reference the one shared constant now, and
the tests monkeypatch that same name.
This commit is contained in:
Teknium 2026-07-16 06:40:36 -07:00
parent 3fccd698fd
commit f3cbe45605
4 changed files with 11 additions and 12 deletions

View file

@ -2963,11 +2963,10 @@ def list_comments(conn: sqlite3.Connection, task_id: str) -> list[Comment]:
# Attachments
# ---------------------------------------------------------------------------
# Cap a single attachment so a runaway upload can't fill the disk. 25 MB
# comfortably covers PDFs, images, and source docs — the kanban use case.
# Shared by the dashboard HTTP endpoint, the agent toolset, and the CLI so
# the limit cannot drift between surfaces.
_MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024
# The attachment size cap is the module-level ``KANBAN_ATTACHMENT_MAX_BYTES``
# (defined near the top of this file) — one constant shared by the dashboard
# HTTP endpoint, the agent toolset, and the CLI so the limit cannot drift
# between surfaces.
class AttachmentTooLarge(ValueError):
@ -3045,7 +3044,7 @@ def store_attachment_bytes(
is removed before re-raising.
"""
if max_bytes is None:
max_bytes = _MAX_ATTACHMENT_BYTES
max_bytes = KANBAN_ATTACHMENT_MAX_BYTES
if len(data) > max_bytes:
raise AttachmentTooLarge(
f"attachment exceeds {max_bytes // (1024 * 1024)} MB limit"

View file

@ -666,7 +666,7 @@ def create_task(payload: CreateTaskBody, board: Optional[str] = Query(None)):
# ``ValueError`` there; the upload handler's ``except ValueError`` below maps
# it to a 400, preserving the previous response.
from hermes_cli.kanban_db import ( # noqa: E402
_MAX_ATTACHMENT_BYTES,
KANBAN_ATTACHMENT_MAX_BYTES,
_collision_free_path,
_safe_attachment_name,
)
@ -726,13 +726,13 @@ async def upload_task_attachment(
if not chunk:
break
total += len(chunk)
if total > _MAX_ATTACHMENT_BYTES:
if total > KANBAN_ATTACHMENT_MAX_BYTES:
out.close()
dest_path.unlink(missing_ok=True)
raise HTTPException(
status_code=413,
detail=(
f"attachment exceeds {_MAX_ATTACHMENT_BYTES // (1024 * 1024)} MB limit"
f"attachment exceeds {KANBAN_ATTACHMENT_MAX_BYTES // (1024 * 1024)} MB limit"
),
)
out.write(chunk)

View file

@ -2302,7 +2302,7 @@ def test_attach_rejects_oversize(worker_env, monkeypatch):
from tools import kanban_tools as kt
# Shrink the cap so we don't have to build a 25 MB payload.
monkeypatch.setattr(kb, "_MAX_ATTACHMENT_BYTES", 8)
monkeypatch.setattr(kb, "KANBAN_ATTACHMENT_MAX_BYTES", 8)
out = kt._handle_attach({
"filename": "big.bin",
"content_base64": base64.b64encode(b"0123456789").decode(),
@ -2451,7 +2451,7 @@ def test_attach_url_rejects_oversize_stream(worker_env, monkeypatch):
def log_message(self, *a):
pass
monkeypatch.setattr(kb, "_MAX_ATTACHMENT_BYTES", 1024)
monkeypatch.setattr(kb, "KANBAN_ATTACHMENT_MAX_BYTES", 1024)
srv = http.server.HTTPServer(("127.0.0.1", 0), _Handler)
threading.Thread(target=srv.serve_forever, daemon=True).start()
try:

View file

@ -956,7 +956,7 @@ def _handle_attach_url(args: dict, **kw) -> str:
content_type = args.get("content_type")
board = args.get("board")
try:
data, fetched_ct = _download_url_with_cap(url, kb._MAX_ATTACHMENT_BYTES)
data, fetched_ct = _download_url_with_cap(url, kb.KANBAN_ATTACHMENT_MAX_BYTES)
except ValueError as e:
return tool_error(f"kanban_attach_url: {e}")
except Exception as e: