diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index dd1d696..a940b53 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -928,6 +928,11 @@ async def _exec_agent_tool(tool, params, workspace_dir): # 30 轮全耗在 list_files/read_file/run_shell 反复「了解现状 + 验证已有内容」,从不 write_file/deliver。 _FORCE_PRODUCE_TURN = 5 +# LLM 调用硬超时(外层 asyncio.wait_for 兜底)。llm_bridge 内部 300s×3 重试最坏 15 分钟, +# 期间 role_agent_run 心跳不更新(心跳在调用前 touch),观察上像任务挂起/僵尸。 +# 外层硬上限:① 缩短最坏时长到 7 分钟 ② 防 aiohttp total 超时因 DNS 等场景失效导致的真正无限挂起。 +_LLM_HARD_TIMEOUT = 420 + _FORCE_PRODUCE_HINT = ( "⚠️ 你已经探索了足够多轮(已超过 5 轮)。现在必须立即产出并交付:\n" "1. 用 write_file 写出实际交付文件(代码/文档/契约/DDL),不要再 read_file / list_files / run_shell / git_status 等探索或检查类工具。\n" @@ -1080,7 +1085,9 @@ async def role_agent_run(project_id, role, agent_id=None, model_name=None): if turn >= _FORCE_PRODUCE_TURN: msgs.append({"role": "user", "content": _FORCE_PRODUCE_HINT}) try: - resp = await llm_call_msgs_native(msgs, tools=tools_schema, model=model_name, temperature=0.4, org_id=org_id) + resp = await asyncio.wait_for( + llm_call_msgs_native(msgs, tools=tools_schema, model=model_name, temperature=0.4, org_id=org_id), + timeout=_LLM_HARD_TIMEOUT) except Exception as e: err_msg = f"{type(e).__name__}: {str(e)[:400]}" from .task_capability import mark_failed