myagent-ai 1.23.45 → 1.23.46

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.
Files changed (2) hide show
  1. package/core/vnc_manager.py +153 -0
  2. package/package.json +1 -1
@@ -76,11 +76,13 @@ class VNCManager:
76
76
  self._xvfb_process: Optional[subprocess.Popen] = None
77
77
  self._x11vnc_process: Optional[subprocess.Popen] = None
78
78
  self._websockify_process: Optional[subprocess.Popen] = None
79
+ self._wm_process: Optional[subprocess.Popen] = None # [v1.23.45] 窗口管理器进程
79
80
 
80
81
  # 状态标记
81
82
  self._running = False
82
83
  self._xvfb_attached = False # 是否附加到已有的 Xvfb 实例
83
84
  self._xvfb_attached_pid: Optional[int] = None # 附加的 Xvfb PID
85
+ self._wm_name: Optional[str] = None # [v1.23.45] 当前窗口管理器名称
84
86
  self._lock = asyncio.Lock()
85
87
 
86
88
  # noVNC web 文件路径(用于 aiohttp 静态文件服务)
@@ -477,6 +479,9 @@ class VNCManager:
477
479
  # 等待 Xvfb 就绪
478
480
  await asyncio.sleep(1)
479
481
 
482
+ # [v1.23.45] Step 2.5: 自动启动窗口管理器(解决黑屏问题)
483
+ await self._start_window_manager()
484
+
480
485
  # Step 3: 启动 x11vnc
481
486
  vnc_ok = await self._start_x11vnc()
482
487
  if not vnc_ok:
@@ -527,6 +532,12 @@ class VNCManager:
527
532
  errors.extend(await self._kill_process(self._x11vnc_process, "x11vnc"))
528
533
  self._x11vnc_process = None
529
534
 
535
+ # [v1.23.45] 停止窗口管理器
536
+ if self._wm_process:
537
+ errors.extend(await self._kill_process(self._wm_process, f"wm-{self._wm_name}"))
538
+ self._wm_process = None
539
+ self._wm_name = None
540
+
530
541
  # Xvfb: 只有自己启动的才杀,附加的不杀
531
542
  if self._xvfb_process:
532
543
  errors.extend(await self._kill_process(self._xvfb_process, "Xvfb"))
@@ -729,6 +740,148 @@ class VNCManager:
729
740
  logger.error(f"Xvfb 启动异常: {e}")
730
741
  return False
731
742
 
743
+ async def _start_window_manager(self) -> None:
744
+ """[v1.23.45] 自动检测并启动窗口管理器,解决 VNC 黑屏问题。
745
+
746
+ 优先级: 已运行的 WM > fluxbox > openbox > xfce4-session > icewm > jwm > 自动安装 fluxbox
747
+ """
748
+ import shutil
749
+
750
+ # 1. 检查是否已有窗口管理器在目标 DISPLAY 上运行
751
+ env = {**os.environ, "DISPLAY": self.display}
752
+ try:
753
+ result = subprocess.run(
754
+ ["pgrep", "-f", f"(fluxbox|openbox|xfce4-session|icewm|jwm|lxsession|gnome-session|startkde|mutter|kwin)"],
755
+ capture_output=True, text=True, timeout=5,
756
+ )
757
+ if result.returncode == 0 and result.stdout.strip():
758
+ pids = result.stdout.strip().split()
759
+ logger.info(f"检测到已有窗口管理器运行 (PIDs={pids[:3]}),跳过自动启动")
760
+ self._wm_name = "existing"
761
+ return
762
+ except Exception:
763
+ pass
764
+
765
+ # 2. 按优先级尝试启动
766
+ # 优先级: fluxbox > openbox > xfce4-session > icewm > jwm > twm
767
+ _wm_commands = [
768
+ ("fluxbox", ["fluxbox"]),
769
+ ("openbox", ["openbox", "--sm-disable"]),
770
+ ("xfce4-session", ["startxfce4"]),
771
+ ("icewm", ["icewm-session"]),
772
+ ("jwm", ["jwm"]),
773
+ ("twm", ["twm"]), # twm 是 X11 自带的最小 WM
774
+ ]
775
+
776
+ wm_name = None
777
+ wm_cmd = None
778
+ for name, cmd in _wm_commands:
779
+ if shutil.which(cmd[0]):
780
+ wm_name = name
781
+ wm_cmd = cmd
782
+ break
783
+
784
+ if wm_name and wm_cmd:
785
+ try:
786
+ logger.info(f"启动窗口管理器: {wm_name} ({' '.join(wm_cmd)})")
787
+ self._wm_process = subprocess.Popen(
788
+ wm_cmd,
789
+ stdin=subprocess.DEVNULL,
790
+ stdout=subprocess.DEVNULL,
791
+ stderr=subprocess.DEVNULL,
792
+ env=env,
793
+ preexec_fn=os.setpgrp,
794
+ )
795
+ self._wm_name = wm_name
796
+ await asyncio.sleep(0.5)
797
+
798
+ if self._wm_process.poll() is None:
799
+ logger.info(f"窗口管理器 {wm_name} 已启动 (PID={self._wm_process.pid})")
800
+ # 设置一个简单的深灰色背景(避免纯黑)
801
+ try:
802
+ subprocess.run(
803
+ ["xsetroot", "-solid", "#2d2d2d"],
804
+ capture_output=True, timeout=5, env=env,
805
+ )
806
+ except Exception:
807
+ pass
808
+ return
809
+ else:
810
+ logger.warning(f"窗口管理器 {wm_name} 启动后立即退出")
811
+ except Exception as e:
812
+ logger.warning(f"启动窗口管理器 {wm_name} 失败: {e}")
813
+
814
+ # 3. 没有可用的 WM → 尝试自动安装 fluxbox
815
+ logger.info("未找到已安装的窗口管理器,尝试自动安装 fluxbox...")
816
+ install_ok = await self._auto_install_wm()
817
+ if install_ok:
818
+ # 安装成功,重新尝试启动
819
+ for name, cmd in _wm_commands[:1]: # 只尝试 fluxbox
820
+ if shutil.which(cmd[0]):
821
+ try:
822
+ logger.info(f"重新启动窗口管理器: {name}")
823
+ self._wm_process = subprocess.Popen(
824
+ cmd,
825
+ stdin=subprocess.DEVNULL,
826
+ stdout=subprocess.DEVNULL,
827
+ stderr=subprocess.DEVNULL,
828
+ env=env,
829
+ preexec_fn=os.setpgrp,
830
+ )
831
+ self._wm_name = name
832
+ await asyncio.sleep(0.5)
833
+ if self._wm_process.poll() is None:
834
+ logger.info(f"窗口管理器 {name} 已启动 (PID={self._wm_process.pid})")
835
+ try:
836
+ subprocess.run(
837
+ ["xsetroot", "-solid", "#2d2d2d"],
838
+ capture_output=True, timeout=5, env=env,
839
+ )
840
+ except Exception:
841
+ pass
842
+ return
843
+ except Exception as e:
844
+ logger.warning(f"重新启动 {name} 失败: {e}")
845
+ break
846
+
847
+ logger.warning(
848
+ "未能启动任何窗口管理器,VNC 将显示黑屏。"
849
+ "请手动安装: sudo apt install -y fluxbox xterm"
850
+ )
851
+
852
+ async def _auto_install_wm(self) -> bool:
853
+ """[v1.23.45] 自动安装 fluxbox 窗口管理器。"""
854
+ _apt_cmd = ["apt-get", "install", "-y", "fluxbox", "xterm"]
855
+ try:
856
+ # 尝试直接执行(root 环境)
857
+ result = subprocess.run(
858
+ _apt_cmd,
859
+ capture_output=True, text=True, timeout=120,
860
+ )
861
+ if result.returncode == 0:
862
+ logger.info("fluxbox 安装成功")
863
+ return True
864
+ # 尝试 sudo
865
+ result = subprocess.run(
866
+ ["sudo"] + _apt_cmd,
867
+ capture_output=True, text=True, timeout=120,
868
+ )
869
+ if result.returncode == 0:
870
+ logger.info("fluxbox 安装成功 (sudo)")
871
+ return True
872
+ stderr = result.stderr[:300] if result.stderr else ""
873
+ logger.warning(f"fluxbox 自动安装失败: {stderr}")
874
+ return False
875
+ except FileNotFoundError:
876
+ logger.warning("未找到 apt-get,无法自动安装窗口管理器")
877
+ return False
878
+ except subprocess.TimeoutExpired:
879
+ logger.warning("fluxbox 安装超时 (120s)")
880
+ return False
881
+ except Exception as e:
882
+ logger.warning(f"fluxbox 安装异常: {e}")
883
+ return False
884
+
732
885
  async def _start_x11vnc(self) -> bool:
733
886
  """启动 x11vnc VNC 服务器"""
734
887
  try:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.23.45",
3
+ "version": "1.23.46",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {