fix: 修复智能体调用卡死问题

- 添加--json参数到openclaw agent命令
- 正确解析JSON输出结构: result.payloads[0].text
- 使用Popen替代subprocess.run,支持进程组杀死
- 超时时间从5分钟改为3分钟
- 添加os.setsid创建新进程组,确保超时时能杀死所有子进程
- 增强异常处理和日志记录
This commit is contained in:
2026-07-16 00:08:21 +08:00
parent 9b11c02cba
commit 42c2a53623
+48 -16
View File
@@ -341,6 +341,9 @@ class ProcessMonitor:
except Exception as e:
logger.error(f"处理会话异常: {session_id} - {e}")
db.update_session_status(session_id, 'failed')
# 确保清理
if session_id in self.active_sessions:
del self.active_sessions[session_id]
return {'success': False, 'message': str(e)}
def _start_step(self, session_id, product_name, step_num, step_name):
@@ -466,36 +469,65 @@ class ProcessMonitor:
def _call_agent(self, task_text):
"""调用智能体执行任务"""
import signal
try:
cmd = [
'openclaw', 'agent',
'--agent', 'hz4th_editor',
'--message', task_text
'--message', task_text,
'--json' # 输出JSON格式以便解析
]
logger.info(f"调用智能体命令: openclaw agent --agent hz4th_editor --message '[任务文本 {len(task_text)} 字符]'")
logger.info(f"调用智能体命令: openclaw agent --agent hz4th_editor --message '[任务文本 {len(task_text)} 字符]' --json")
result = subprocess.run(
# 使用Popen以便更好地控制超时和进程杀死
proc = subprocess.Popen(
cmd,
capture_output=True,
text=True,
timeout=300 # 5分钟超时
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=os.setsid # 创建新进程组,方便杀死所有子进程
)
if result.returncode == 0:
output = result.stdout.strip()
logger.info(f"智能体返回: {output[:500]}...")
return {'success': True, 'output': output}
else:
error = result.stderr.strip() or result.stdout.strip()
logger.error(f"智能体调用失败: {error}")
return {'success': False, 'error': error}
try:
stdout, stderr = proc.communicate(timeout=180) # 3分钟超时
raw_output = stdout.decode('utf-8', errors='replace').strip()
if proc.returncode == 0:
# 解析JSON输出
try:
data = json.loads(raw_output)
# 提取实际回复文本: result.payloads[0].text
payloads = data.get('result', {}).get('payloads', [])
if payloads and isinstance(payloads[0], dict):
output = payloads[0].get('text', '')
else:
output = raw_output
logger.info(f"智能体返回: {output[:500]}...")
return {'success': True, 'output': output}
except json.JSONDecodeError as e:
logger.warning(f"JSON解析失败,使用原始输出: {e}")
return {'success': True, 'output': raw_output}
else:
error = stderr.decode('utf-8', errors='replace').strip() or raw_output
logger.error(f"智能体调用失败(returncode={proc.returncode}): {error}")
return {'success': False, 'error': error}
except subprocess.TimeoutExpired:
# 超时,杀死整个进程组
logger.error(f"智能体执行超时(>3分钟),杀死进程组")
try:
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
except Exception:
proc.kill()
proc.wait()
return {'success': False, 'error': '智能体执行超时(>3分钟)'}
except subprocess.TimeoutExpired:
return {'success': False, 'error': '智能体执行超时(>5分钟)'}
except FileNotFoundError:
return {'success': False, 'error': 'openclaw命令未找到'}
except Exception as e:
logger.error(f"智能体调用异常: {e}")
return {'success': False, 'error': str(e)}
def _parse_agent_response(self, output):