myagent-ai 1.47.12 → 1.47.14
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/aiskills/browser_stealth.py +54 -15
- package/aiskills/chromedev_mcp.py +47 -19
- package/core/vnc_manager.py +46 -0
- package/package.json +1 -1
|
@@ -241,24 +241,63 @@ def _ensure_display() -> Optional[Dict[str, Any]]:
|
|
|
241
241
|
logger.info(f"VNC 远程桌面已在运行,复用显示: {display}")
|
|
242
242
|
return {"display": display, "vnc": True, "xvfb_standalone": False}
|
|
243
243
|
|
|
244
|
-
# VNC 未运行 → 尝试自动启动
|
|
244
|
+
# [v1.47.13] VNC 未运行 → 尝试自动启动
|
|
245
|
+
# 重要修复: 不能在 ThreadPoolExecutor + asyncio.run 中调用 vnc.start()!
|
|
246
|
+
# 因为 vnc.start() 内部用 asyncio.Lock(),跨 event loop 会导致死锁。
|
|
247
|
+
# 正确做法:在单独线程中用 asyncio.run 启动,然后轮询等待 VNC 就绪。
|
|
245
248
|
try:
|
|
246
249
|
import asyncio
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
import concurrent.futures
|
|
251
|
+
|
|
252
|
+
# 在独立线程中启动 VNC(新的 event loop,避免冲突)
|
|
253
|
+
def _start_vnc_in_thread():
|
|
254
|
+
try:
|
|
255
|
+
return asyncio.run(vnc.start())
|
|
256
|
+
except Exception as e:
|
|
257
|
+
return {"success": False, "message": str(e)}
|
|
258
|
+
|
|
259
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
|
|
260
|
+
future = pool.submit(_start_vnc_in_thread)
|
|
261
|
+
|
|
262
|
+
# 轮询等待 VNC 就绪(同时等待 future 完成)
|
|
263
|
+
max_wait = 60 # 最多等60秒
|
|
264
|
+
check_interval = 2
|
|
265
|
+
elapsed = 0
|
|
266
|
+
while elapsed < max_wait:
|
|
267
|
+
# 先检查 VNC 是否已就绪
|
|
268
|
+
if vnc.is_running:
|
|
269
|
+
display = vnc.display
|
|
270
|
+
os.environ["DISPLAY"] = display
|
|
271
|
+
logger.info(f"VNC 远程桌面已启动,复用显示: {display}")
|
|
272
|
+
return {"display": display, "vnc": True, "xvfb_standalone": False}
|
|
273
|
+
|
|
274
|
+
# 检查启动线程是否已完成(非阻塞)
|
|
275
|
+
try:
|
|
276
|
+
result = future.result(timeout=0.1)
|
|
277
|
+
# 线程完成了,检查结果
|
|
278
|
+
if result.get("success") or vnc.is_running:
|
|
279
|
+
display = vnc.display
|
|
280
|
+
os.environ["DISPLAY"] = display
|
|
281
|
+
logger.info(f"VNC 远程桌面已启动,显示: {display}")
|
|
282
|
+
return {"display": display, "vnc": True, "xvfb_standalone": False}
|
|
283
|
+
else:
|
|
284
|
+
logger.warning(f"VNC 启动失败: {result.get('message', '')}")
|
|
285
|
+
break
|
|
286
|
+
except concurrent.futures.TimeoutError:
|
|
287
|
+
# 线程还在运行,继续等待
|
|
288
|
+
pass
|
|
289
|
+
|
|
290
|
+
import time
|
|
291
|
+
time.sleep(check_interval)
|
|
292
|
+
elapsed += check_interval
|
|
293
|
+
|
|
294
|
+
# 超时后再做最后检查
|
|
295
|
+
if vnc.is_running:
|
|
296
|
+
display = vnc.display
|
|
297
|
+
os.environ["DISPLAY"] = display
|
|
298
|
+
logger.info(f"VNC 远程桌面已启动(等待后),显示: {display}")
|
|
299
|
+
return {"display": display, "vnc": True, "xvfb_standalone": False}
|
|
254
300
|
|
|
255
|
-
if result.get("success"):
|
|
256
|
-
display = vnc.display
|
|
257
|
-
os.environ["DISPLAY"] = display
|
|
258
|
-
logger.info(f"VNC 远程桌面已自动启动,显示: {display},可在 VNC 中查看浏览器操作")
|
|
259
|
-
return {"display": display, "vnc": True, "xvfb_standalone": False}
|
|
260
|
-
else:
|
|
261
|
-
logger.warning(f"VNC 自动启动失败: {result.get('message', '')}")
|
|
262
301
|
except Exception as e:
|
|
263
302
|
logger.warning(f"VNC 自动启动异常: {e}")
|
|
264
303
|
|
|
@@ -189,27 +189,55 @@ def _ensure_display() -> Optional[str]:
|
|
|
189
189
|
logger.info(f"VNC 远程桌面已在运行,复用显示: {display}")
|
|
190
190
|
return display
|
|
191
191
|
|
|
192
|
-
# VNC 未运行 → 尝试自动启动
|
|
192
|
+
# [v1.47.13] VNC 未运行 → 尝试自动启动
|
|
193
|
+
# 修复: 不能在 ThreadPoolExecutor + asyncio.run 中直接调用 vnc.start()!
|
|
194
|
+
# 因为 vnc.start() 内部用 asyncio.Lock(),跨 event loop 会导致死锁。
|
|
195
|
+
# 正确做法:在单独线程中用 asyncio.run 启动,然后轮询等待 VNC 就绪。
|
|
193
196
|
try:
|
|
194
197
|
import asyncio
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
198
|
+
import concurrent.futures
|
|
199
|
+
|
|
200
|
+
def _start_vnc_in_thread():
|
|
201
|
+
try:
|
|
202
|
+
return asyncio.run(vnc.start())
|
|
203
|
+
except Exception as e:
|
|
204
|
+
return {"success": False, "message": str(e)}
|
|
205
|
+
|
|
206
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
|
|
207
|
+
future = pool.submit(_start_vnc_in_thread)
|
|
208
|
+
|
|
209
|
+
max_wait = 60
|
|
210
|
+
check_interval = 2
|
|
211
|
+
elapsed = 0
|
|
212
|
+
while elapsed < max_wait:
|
|
213
|
+
if vnc.is_running:
|
|
214
|
+
display = vnc.display
|
|
215
|
+
os.environ["DISPLAY"] = display
|
|
216
|
+
logger.info(f"VNC 远程桌面已启动,复用显示: {display}")
|
|
217
|
+
return display
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
result = future.result(timeout=0.1)
|
|
221
|
+
if result.get("success") or vnc.is_running:
|
|
222
|
+
display = vnc.display
|
|
223
|
+
os.environ["DISPLAY"] = display
|
|
224
|
+
logger.info(f"VNC 远程桌面已启动,显示: {display}")
|
|
225
|
+
return display
|
|
226
|
+
else:
|
|
227
|
+
logger.warning(f"VNC 启动失败: {result.get('message', '')}")
|
|
228
|
+
break
|
|
229
|
+
except concurrent.futures.TimeoutError:
|
|
230
|
+
pass
|
|
231
|
+
|
|
232
|
+
import time
|
|
233
|
+
time.sleep(check_interval)
|
|
234
|
+
elapsed += check_interval
|
|
235
|
+
|
|
236
|
+
if vnc.is_running:
|
|
237
|
+
display = vnc.display
|
|
238
|
+
os.environ["DISPLAY"] = display
|
|
239
|
+
return display
|
|
240
|
+
|
|
213
241
|
except Exception as e:
|
|
214
242
|
logger.warning(f"VNC 自动启动异常: {e}")
|
|
215
243
|
|
package/core/vnc_manager.py
CHANGED
|
@@ -877,6 +877,12 @@ class VNCManager:
|
|
|
877
877
|
logger.warning(f"后台升级 icewm 异常: {e}")
|
|
878
878
|
|
|
879
879
|
# 3. 启动 D-Bus 会话(Epiphany 等 GNOME 程序需要)
|
|
880
|
+
# [v1.47.12] 在启动 D-Bus 之前先修复 dbus-daemon-launch-helper
|
|
881
|
+
# 否则 D-Bus 激活服务时仍会触发 --shm-helper 错误
|
|
882
|
+
try:
|
|
883
|
+
self._fix_dbus_launch_helper()
|
|
884
|
+
except Exception:
|
|
885
|
+
pass
|
|
880
886
|
self._ensure_dbus_session()
|
|
881
887
|
|
|
882
888
|
# 3.5 如果 icewm 刚安装好,重新配置主题
|
|
@@ -1501,9 +1507,13 @@ class VNCManager:
|
|
|
1501
1507
|
解决方法:创建包装脚本,去掉 --shm-helper 参数。
|
|
1502
1508
|
"""
|
|
1503
1509
|
# 查找原始的 dbus-daemon-launch-helper
|
|
1510
|
+
# [v1.47.12] 扩展搜索路径,覆盖 ARM64 Ubuntu (aarch64-linux-gnu)
|
|
1504
1511
|
helper_paths = [
|
|
1505
1512
|
"/usr/lib/dbus-1.0/dbus-daemon-launch-helper",
|
|
1506
1513
|
"/usr/libexec/dbus-daemon-launch-helper",
|
|
1514
|
+
"/usr/lib/aarch64-linux-gnu/dbus-1.0/dbus-daemon-launch-helper",
|
|
1515
|
+
"/usr/lib/arm-linux-gnueabihf/dbus-1.0/dbus-daemon-launch-helper",
|
|
1516
|
+
"/usr/lib/x86_64-linux-gnu/dbus-1.0/dbus-daemon-launch-helper",
|
|
1507
1517
|
]
|
|
1508
1518
|
original_helper = None
|
|
1509
1519
|
for hp in helper_paths:
|
|
@@ -1519,6 +1529,29 @@ class VNCManager:
|
|
|
1519
1529
|
original_helper = hp
|
|
1520
1530
|
break
|
|
1521
1531
|
|
|
1532
|
+
# [v1.47.12] 兜底: 用 find 搜索所有 dbus-daemon-launch-helper
|
|
1533
|
+
if not original_helper:
|
|
1534
|
+
try:
|
|
1535
|
+
result = subprocess.run(
|
|
1536
|
+
["find", "/usr/lib", "-name", "dbus-daemon-launch-helper", "-type", "f"],
|
|
1537
|
+
capture_output=True, text=True, timeout=5,
|
|
1538
|
+
)
|
|
1539
|
+
if result.returncode == 0:
|
|
1540
|
+
for line in result.stdout.strip().split("\n"):
|
|
1541
|
+
path = line.strip()
|
|
1542
|
+
if path and os.path.isfile(path) and not os.path.islink(path):
|
|
1543
|
+
try:
|
|
1544
|
+
with open(path, "r", errors="replace") as f:
|
|
1545
|
+
head = f.read(100)
|
|
1546
|
+
if "MYAGENT_WRAPPER" in head:
|
|
1547
|
+
continue
|
|
1548
|
+
except Exception:
|
|
1549
|
+
pass
|
|
1550
|
+
original_helper = path
|
|
1551
|
+
break
|
|
1552
|
+
except Exception:
|
|
1553
|
+
pass
|
|
1554
|
+
|
|
1522
1555
|
if not original_helper:
|
|
1523
1556
|
logger.debug("dbus-daemon-launch-helper 未找到或已是包装脚本,跳过修复")
|
|
1524
1557
|
return
|
|
@@ -1782,6 +1815,9 @@ exec {backup_path} "${{args[@]}}"
|
|
|
1782
1815
|
env["DBUS_SESSION_BUS_ADDRESS"] = os.environ["DBUS_SESSION_BUS_ADDRESS"]
|
|
1783
1816
|
if not env.get("GSETTINGS_BACKEND"):
|
|
1784
1817
|
env["GSETTINGS_BACKEND"] = "memory"
|
|
1818
|
+
# [v1.47.12] proot 兼容: 避免浏览器启动时 dbus --shm-helper 错误
|
|
1819
|
+
if not env.get("G_SLICE"):
|
|
1820
|
+
env["G_SLICE"] = "always-malloc"
|
|
1785
1821
|
xdg_runtime = env.get("XDG_RUNTIME_DIR") or f"/run/user/{os.getuid()}"
|
|
1786
1822
|
env["XDG_RUNTIME_DIR"] = xdg_runtime
|
|
1787
1823
|
try:
|
|
@@ -4778,6 +4814,13 @@ chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null
|
|
|
4778
4814
|
export MOZ_DISABLE_CONTENT_SANDBOX=1
|
|
4779
4815
|
export MOZ_DISABLE_GPU_SANDBOX=1
|
|
4780
4816
|
|
|
4817
|
+
# [v1.47.12] proot 兼容环境变量 — 避免 dbus --shm-helper 错误
|
|
4818
|
+
# G_SLICE=always-malloc — 禁用 glib2 共享内存分配器
|
|
4819
|
+
# 避免 "error: expected absolute path: --shm-helper" 错误
|
|
4820
|
+
export G_SLICE=always-malloc
|
|
4821
|
+
# GSettings 内存后端 — 不依赖 dconf/gsettings 守护进程
|
|
4822
|
+
export GSETTINGS_BACKEND=memory
|
|
4823
|
+
|
|
4781
4824
|
# [v1.46.8] PulseAudio 音频 — 确保Firefox输出音频到PulseAudio
|
|
4782
4825
|
export PULSE_SERVER=unix:${{XDG_RUNTIME_DIR}}/pulse/native
|
|
4783
4826
|
if [ -z "$PULSE_SERVER" ]; then
|
|
@@ -4830,6 +4873,9 @@ chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null
|
|
|
4830
4873
|
# GSettings 内存后端
|
|
4831
4874
|
export GSETTINGS_BACKEND=memory
|
|
4832
4875
|
|
|
4876
|
+
# [v1.47.12] proot 兼容环境变量 — 避免 dbus --shm-helper 错误
|
|
4877
|
+
export G_SLICE=always-malloc
|
|
4878
|
+
|
|
4833
4879
|
# 启动 D-Bus 会话(如果还没有)
|
|
4834
4880
|
# [v1.43.3] proot 下跳过 dbus-launch,直接用 dbus-daemon
|
|
4835
4881
|
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
|