Compare commits

...
1 Commits
Author SHA1 Message Date
hz4th_coder 42c2a53623 fix: 修复智能体调用卡死问题
- 添加--json参数到openclaw agent命令
- 正确解析JSON输出结构: result.payloads[0].text
- 使用Popen替代subprocess.run,支持进程组杀死
- 超时时间从5分钟改为3分钟
- 添加os.setsid创建新进程组,确保超时时能杀死所有子进程
- 增强异常处理和日志记录
2026-07-16 00:08:21 +08:00
+48 -16
View File
@@ -341,6 +341,9 @@ class ProcessMonitor:
except Exception as e: except Exception as e:
logger.error(f"处理会话异常: {session_id} - {e}") logger.error(f"处理会话异常: {session_id} - {e}")
db.update_session_status(session_id, 'failed') 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)} return {'success': False, 'message': str(e)}
def _start_step(self, session_id, product_name, step_num, step_name): def _start_step(self, session_id, product_name, step_num, step_name):
@@ -466,36 +469,65 @@ class ProcessMonitor:
def _call_agent(self, task_text): def _call_agent(self, task_text):
"""调用智能体执行任务""" """调用智能体执行任务"""
import signal
try: try:
cmd = [ cmd = [
'openclaw', 'agent', 'openclaw', 'agent',
'--agent', 'hz4th_editor', '--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, cmd,
capture_output=True, stdout=subprocess.PIPE,
text=True, stderr=subprocess.PIPE,
timeout=300 # 5分钟超时 preexec_fn=os.setsid # 创建新进程组,方便杀死所有子进程
) )
if result.returncode == 0: try:
output = result.stdout.strip() stdout, stderr = proc.communicate(timeout=180) # 3分钟超时
logger.info(f"智能体返回: {output[:500]}...") raw_output = stdout.decode('utf-8', errors='replace').strip()
return {'success': True, 'output': output}
else: if proc.returncode == 0:
error = result.stderr.strip() or result.stdout.strip() # 解析JSON输出
logger.error(f"智能体调用失败: {error}") try:
return {'success': False, 'error': error} 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: except FileNotFoundError:
return {'success': False, 'error': 'openclaw命令未找到'} return {'success': False, 'error': 'openclaw命令未找到'}
except Exception as e: except Exception as e:
logger.error(f"智能体调用异常: {e}")
return {'success': False, 'error': str(e)} return {'success': False, 'error': str(e)}
def _parse_agent_response(self, output): def _parse_agent_response(self, output):