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 +1 -1
- package/skills/chromedev_mcp.py +58 -15
package/package.json
CHANGED
package/skills/chromedev_mcp.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
858
|
-
|
|
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
|
-
|
|
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}")
|