From 2d69f73d9da4e5949789d6ad436bc91501859bb0 Mon Sep 17 00:00:00 2001 From: Kimi Agent Date: Thu, 19 Mar 2026 20:18:31 -0400 Subject: [PATCH] fix: add timeout to thinking/loop-QA schedulers (#530) Co-authored-by: Kimi Agent Co-committed-by: Kimi Agent --- src/config.py | 1 + src/dashboard/app.py | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/config.py b/src/config.py index 550743b..e5f580e 100644 --- a/src/config.py +++ b/src/config.py @@ -254,6 +254,7 @@ class Settings(BaseSettings): # When enabled, the agent starts an internal thought loop on server start. thinking_enabled: bool = True thinking_interval_seconds: int = 300 # 5 minutes between thoughts + thinking_timeout_seconds: int = 120 # max wall-clock time per thinking cycle thinking_distill_every: int = 10 # distill facts from thoughts every Nth thought thinking_issue_every: int = 20 # file Gitea issues from thoughts every Nth thought thinking_memory_check_every: int = 50 # check memory status every Nth thought diff --git a/src/dashboard/app.py b/src/dashboard/app.py index 137ded5..49c291e 100644 --- a/src/dashboard/app.py +++ b/src/dashboard/app.py @@ -155,7 +155,17 @@ async def _thinking_scheduler() -> None: while True: try: if settings.thinking_enabled: - await thinking_engine.think_once() + await asyncio.wait_for( + thinking_engine.think_once(), + timeout=settings.thinking_timeout_seconds, + ) + except TimeoutError: + logger.warning( + "Thinking cycle timed out after %ds — Ollama may be unresponsive", + settings.thinking_timeout_seconds, + ) + except asyncio.CancelledError: + raise except Exception as exc: logger.error("Thinking scheduler error: %s", exc) @@ -175,7 +185,10 @@ async def _loop_qa_scheduler() -> None: while True: try: if settings.loop_qa_enabled: - result = await loop_qa_orchestrator.run_next_test() + result = await asyncio.wait_for( + loop_qa_orchestrator.run_next_test(), + timeout=settings.thinking_timeout_seconds, + ) if result: status = "PASS" if result["success"] else "FAIL" logger.info( @@ -184,6 +197,13 @@ async def _loop_qa_scheduler() -> None: status, result.get("details", "")[:80], ) + except TimeoutError: + logger.warning( + "Loop QA test timed out after %ds", + settings.thinking_timeout_seconds, + ) + except asyncio.CancelledError: + raise except Exception as exc: logger.error("Loop QA scheduler error: %s", exc)