myagent-ai 1.18.3 → 1.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.18.3",
3
+ "version": "1.18.4",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
@@ -383,6 +383,11 @@ class MCPClient:
383
383
  pass
384
384
  except Exception:
385
385
  pass
386
+ finally:
387
+ # [v1.18.3] stdout EOF = MCP Server 或 Chrome 已断开
388
+ # 标记为未初始化,下次 call_tool 会自动重建
389
+ self._initialized = False
390
+ logger.warning("MCP stdout 读取结束(Server 或 Chrome 已断开)")
386
391
 
387
392
  async def _handshake(self) -> bool:
388
393
  """执行 MCP 初始化握手"""
@@ -552,7 +557,12 @@ class MCPClient:
552
557
  self._cleanup()
553
558
 
554
559
  def _cleanup(self):
555
- """清理子进程"""
560
+ """清理子进程(包括 Chrome/Chromium 浏览器)
561
+
562
+ [v1.18.3] 修复 'Target closed' 问题:
563
+ 终止 MCP Server 后,额外杀死残留的 Chrome 进程,
564
+ 避免下次启动时因锁文件冲突导致 'Target closed'。
565
+ """
556
566
  self._initialized = False
557
567
  if self._process:
558
568
  try:
@@ -569,6 +579,48 @@ class MCPClient:
569
579
  pass
570
580
  self._process = None
571
581
 
582
+ # [v1.18.3] 清理残留的 Chrome/Chromium 进程
583
+ # chrome-devtools-mcp 启动的 Chrome 可能不会随 MCP 进程一起退出
584
+ self._kill_stale_chrome()
585
+
586
+ def _kill_stale_chrome(self):
587
+ """清理残留的 Chrome/Chromium 进程
588
+
589
+ 查找并杀死由 chrome-devtools-mcp 启动的 Chrome 进程。
590
+ 这些进程可能导致下次启动时 'Target closed' 错误。
591
+ """
592
+ import signal as _sig
593
+ try:
594
+ # 查找 chrome-devtools-mcp 启动的 Chrome 进程
595
+ # 特征: 父进程是 node/npx (chrome-devtools-mcp)
596
+ result = subprocess.run(
597
+ ["pgrep", "-f", "chromium-browser.*--remote-debugging-port"],
598
+ capture_output=True, text=True, timeout=5,
599
+ )
600
+ if result.returncode == 0 and result.stdout.strip():
601
+ pids = result.stdout.strip().split("\n")
602
+ for pid_str in pids:
603
+ try:
604
+ pid = int(pid_str)
605
+ os.kill(pid, _sig.SIGTERM)
606
+ logger.debug(f"清理残留 Chrome 进程: PID={pid}")
607
+ except (ProcessLookupError, PermissionError, ValueError):
608
+ pass
609
+
610
+ # 等一小会让 Chrome 优雅退出
611
+ import time
612
+ time.sleep(0.5)
613
+
614
+ # 还没退就强杀
615
+ for pid_str in pids:
616
+ try:
617
+ pid = int(pid_str)
618
+ os.kill(pid, _sig.SIGKILL)
619
+ except (ProcessLookupError, PermissionError, ValueError):
620
+ pass
621
+ except Exception as e:
622
+ logger.debug(f"清理 Chrome 进程异常: {e}")
623
+
572
624
  def is_running(self) -> bool:
573
625
  """检查 MCP Server 是否正在运行"""
574
626
  return self._process is not None and self._process.poll() is None
@@ -849,17 +901,13 @@ class BrowserOpenSkill(Skill):
849
901
  f"请执行: apt install -y chromium-browser 或 apt install -y chromium,"
850
902
  f"安装后重试即可。"
851
903
  )
852
- # [v1.16.18] 检测 Chrome 崩溃,尝试重建 MCP 客户端并重试
904
+ # [v1.16.18→18.3] 检测 Chrome 崩溃,彻底清理后重建 MCP 客户端并重试
853
905
  _crash_keywords = ["Target closed", "Target destroyed", "Protocol error",
854
906
  "Browser closed", "Connection closed", "Session closed"]
855
907
  if any(kw in err_text for kw in _crash_keywords) and attempt < max_attempts - 1:
856
908
  logger.warning(f"Chrome 连接丢失 ({err_text[:100]}),正在重建 MCP 客户端并重试...")
857
- try:
858
- if client:
859
- client._cleanup()
860
- except Exception:
861
- pass
862
- _mcp_client = None
909
+ # [v1.18.3] 彻底清理所有 MCP 客户端(包括残留 Chrome 进程)
910
+ await rebuild_mcp_client()
863
911
  continue # 重试
864
912
  return SkillResult(success=False, error=f"导航失败: {err_text}")
865
913
 
@@ -921,18 +969,13 @@ class BrowserOpenSkill(Skill):
921
969
  message=f"已打开: {page_title} (文本 {len(text)} 字符, {len(links)} 个链接)",
922
970
  )
923
971
  except Exception as e:
924
- # [v1.16.18] 异常时也检测 Chrome 崩溃并重试
972
+ # [v1.16.18→18.3] 异常时也检测 Chrome 崩溃并彻底重建
925
973
  _err_str = str(e)
926
974
  _crash_keywords = ["Target closed", "Target destroyed", "Protocol error",
927
975
  "Browser closed", "Connection closed", "Session closed"]
928
976
  if any(kw in _err_str for kw in _crash_keywords) and attempt < max_attempts - 1:
929
977
  logger.warning(f"Chrome 异常 ({_err_str[:100]}),正在重建 MCP 客户端并重试...")
930
- try:
931
- if _mcp_client:
932
- _mcp_client._cleanup()
933
- except Exception:
934
- pass
935
- _mcp_client = None
978
+ await rebuild_mcp_client()
936
979
  continue # 重试
937
980
  logger.error(f"浏览器打开失败: {e}")
938
981
  return SkillResult(success=False, error=f"浏览器打开失败: {e}")