Research: add configurable run timeout

Surfaces the research_run_timeout_seconds setting (added in #783) in
Settings → Research as a "Max Time" field, and lets 0 disable the
wall-clock cap entirely for long deep-research runs.

- settings.py: document that 0 disables the cap; default stays 1800s.
- research_handler.py: resolve 0 (or negative) to no timeout
  (asyncio.wait_for timeout=None); other values stay bounded to
  [60, 86400] as before.
- index.html / settings.js: "Max Time" input bound to
  research_run_timeout_seconds, validated to {0} ∪ [60, 86400], with
  copy making explicit that 0 = no limit (unbounded model/API cost).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nikita Rozanov
2026-06-02 13:57:57 +02:00
committed by GitHub
parent c3228f8b59
commit 119075f368
4 changed files with 43 additions and 8 deletions
+17 -7
View File
@@ -216,15 +216,25 @@ class ResearchHandler:
"""
# Resolve the hard wall-clock timeout from settings when the caller
# didn't pin one. Local / edge models routinely need more than the
# old 600s default to finish a deep-research synthesis.
# old 600s default to finish a deep-research synthesis. A setting of
# 0 disables the cap entirely (unlimited run); any other value is
# bounded to [60, 86400] so a misconfigured settings.json can't
# explode into a multi-day hang.
if hard_timeout is None:
from src.settings import get_setting
hard_timeout = _bounded_int(
get_setting("research_run_timeout_seconds", 1800),
default=1800,
minimum=60,
maximum=86400,
)
try:
raw_timeout = int(get_setting("research_run_timeout_seconds", 1800))
except (TypeError, ValueError):
raw_timeout = 1800
if raw_timeout <= 0:
hard_timeout = None # 0 = no wall-clock cap (asyncio.wait_for timeout=None)
else:
hard_timeout = _bounded_int(
raw_timeout,
default=1800,
minimum=60,
maximum=86400,
)
# Cancel any existing research for this session
if session_id in self._active_tasks: