machineconfig 1.97__py3-none-any.whl → 2.1__py3-none-any.whl
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.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/cloud_manager.py +22 -29
- machineconfig/cluster/data_transfer.py +2 -3
- machineconfig/cluster/distribute.py +0 -2
- machineconfig/cluster/file_manager.py +4 -5
- machineconfig/cluster/job_params.py +1 -4
- machineconfig/cluster/loader_runner.py +8 -11
- machineconfig/cluster/remote_machine.py +4 -5
- machineconfig/cluster/script_execution.py +2 -2
- machineconfig/cluster/script_notify_upon_completion.py +0 -1
- machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +4 -6
- machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -1
- machineconfig/cluster/sessions_managers/enhanced_command_runner.py +35 -75
- machineconfig/cluster/sessions_managers/wt_local.py +113 -185
- machineconfig/cluster/sessions_managers/wt_local_manager.py +127 -197
- machineconfig/cluster/sessions_managers/wt_remote.py +60 -67
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +110 -149
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +61 -64
- machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +72 -172
- machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +27 -60
- machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +58 -137
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +46 -74
- machineconfig/cluster/sessions_managers/zellij_local.py +91 -147
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +165 -190
- machineconfig/cluster/sessions_managers/zellij_remote.py +51 -58
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +40 -46
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +19 -17
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +30 -31
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +64 -134
- machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +7 -11
- machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +27 -55
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +14 -13
- machineconfig/cluster/templates/cli_click.py +0 -1
- machineconfig/cluster/templates/cli_gooey.py +0 -2
- machineconfig/cluster/templates/cli_trogon.py +0 -1
- machineconfig/cluster/templates/run_cloud.py +0 -1
- machineconfig/cluster/templates/run_cluster.py +0 -1
- machineconfig/cluster/templates/run_remote.py +0 -1
- machineconfig/cluster/templates/utils.py +27 -11
- machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/linux/msc/cli_agents.sh +16 -0
- machineconfig/jobs/python/check_installations.py +9 -9
- machineconfig/jobs/python/create_bootable_media.py +0 -2
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/python_ve_symlink.py +9 -11
- machineconfig/jobs/python/tasks.py +0 -1
- machineconfig/jobs/python/vscode/api.py +5 -5
- machineconfig/jobs/python/vscode/link_ve.py +20 -21
- machineconfig/jobs/python/vscode/select_interpreter.py +28 -29
- machineconfig/jobs/python/vscode/sync_code.py +14 -18
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +15 -15
- machineconfig/jobs/python_custom_installers/dev/aider.py +10 -18
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +12 -21
- machineconfig/jobs/python_custom_installers/dev/brave.py +13 -22
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +13 -20
- machineconfig/jobs/python_custom_installers/dev/code.py +17 -24
- machineconfig/jobs/python_custom_installers/dev/cursor.py +10 -21
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +12 -11
- machineconfig/jobs/python_custom_installers/dev/espanso.py +19 -23
- machineconfig/jobs/python_custom_installers/dev/goes.py +9 -16
- machineconfig/jobs/python_custom_installers/dev/lvim.py +13 -21
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +15 -22
- machineconfig/jobs/python_custom_installers/dev/redis.py +15 -23
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +15 -22
- machineconfig/jobs/python_custom_installers/dev/winget.py +32 -50
- machineconfig/jobs/python_custom_installers/docker.py +15 -24
- machineconfig/jobs/python_custom_installers/gh.py +18 -26
- machineconfig/jobs/python_custom_installers/hx.py +33 -17
- machineconfig/jobs/python_custom_installers/warp-cli.py +15 -23
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_generic_installers/config.json +412 -389
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -1
- machineconfig/jobs/windows/msc/cli_agents.bat +0 -0
- machineconfig/jobs/windows/msc/cli_agents.ps1 +0 -0
- machineconfig/jobs/windows/start_terminal.ps1 +1 -1
- machineconfig/logger.py +50 -0
- machineconfig/profile/create.py +50 -36
- machineconfig/profile/create_hardlinks.py +33 -26
- machineconfig/profile/shell.py +87 -60
- machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/cloud/init.sh +2 -2
- machineconfig/scripts/linux/checkout_versions +1 -1
- machineconfig/scripts/linux/choose_wezterm_theme +1 -1
- machineconfig/scripts/linux/cloud_copy +1 -1
- machineconfig/scripts/linux/cloud_manager +1 -1
- machineconfig/scripts/linux/cloud_mount +1 -1
- machineconfig/scripts/linux/cloud_repo_sync +1 -1
- machineconfig/scripts/linux/cloud_sync +1 -1
- machineconfig/scripts/linux/croshell +1 -1
- machineconfig/scripts/linux/devops +3 -5
- machineconfig/scripts/linux/fire +2 -1
- machineconfig/scripts/linux/fire_agents +3 -3
- machineconfig/scripts/linux/ftpx +1 -1
- machineconfig/scripts/linux/gh_models +1 -1
- machineconfig/scripts/linux/kill_process +1 -1
- machineconfig/scripts/linux/mcinit +2 -2
- machineconfig/scripts/linux/repos +1 -1
- machineconfig/scripts/linux/scheduler +1 -1
- machineconfig/scripts/linux/start_slidev +1 -1
- machineconfig/scripts/linux/start_terminals +1 -1
- machineconfig/scripts/linux/url2md +1 -1
- machineconfig/scripts/linux/warp-cli.sh +122 -0
- machineconfig/scripts/linux/wifi_conn +1 -1
- machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__init__.py +0 -0
- machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/chatmodes/Thinking-Beast-Mode.chatmode.md +337 -0
- machineconfig/scripts/python/ai/chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +644 -0
- machineconfig/scripts/python/ai/chatmodes/deepResearch.chatmode.md +81 -0
- machineconfig/scripts/python/ai/configs/.gemini/settings.json +81 -0
- machineconfig/scripts/python/ai/generate_files.py +84 -0
- machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +45 -0
- machineconfig/scripts/python/ai/mcinit.py +107 -0
- machineconfig/scripts/python/ai/prompts/allLintersAndTypeCheckers.prompt.md +5 -0
- machineconfig/scripts/python/ai/prompts/research-report-skeleton.prompt.md +38 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +52 -0
- machineconfig/scripts/python/archive/tmate_conn.py +5 -5
- machineconfig/scripts/python/archive/tmate_start.py +3 -3
- machineconfig/scripts/python/choose_wezterm_theme.py +2 -2
- machineconfig/scripts/python/cloud_copy.py +20 -19
- machineconfig/scripts/python/cloud_mount.py +10 -8
- machineconfig/scripts/python/cloud_repo_sync.py +15 -15
- machineconfig/scripts/python/cloud_sync.py +1 -1
- machineconfig/scripts/python/croshell.py +18 -16
- machineconfig/scripts/python/devops.py +6 -6
- machineconfig/scripts/python/devops_add_identity.py +9 -7
- machineconfig/scripts/python/devops_add_ssh_key.py +19 -19
- machineconfig/scripts/python/devops_backup_retrieve.py +14 -14
- machineconfig/scripts/python/devops_devapps_install.py +3 -3
- machineconfig/scripts/python/devops_update_repos.py +141 -53
- machineconfig/scripts/python/dotfile.py +3 -3
- machineconfig/scripts/python/fire_agents.py +202 -41
- machineconfig/scripts/python/fire_jobs.py +20 -21
- machineconfig/scripts/python/ftpx.py +4 -3
- machineconfig/scripts/python/gh_models.py +94 -94
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/cloud_helpers.py +3 -3
- machineconfig/scripts/python/helpers/helpers2.py +3 -3
- machineconfig/scripts/python/helpers/helpers4.py +8 -7
- machineconfig/scripts/python/helpers/helpers5.py +7 -7
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
- machineconfig/scripts/python/mount_nfs.py +4 -3
- machineconfig/scripts/python/mount_nw_drive.py +4 -4
- machineconfig/scripts/python/mount_ssh.py +4 -3
- machineconfig/scripts/python/repos.py +9 -9
- machineconfig/scripts/python/scheduler.py +1 -1
- machineconfig/scripts/python/start_slidev.py +9 -8
- machineconfig/scripts/python/start_terminals.py +1 -1
- machineconfig/scripts/python/viewer.py +40 -40
- machineconfig/scripts/python/wifi_conn.py +65 -66
- machineconfig/scripts/python/wsl_windows_transfer.py +2 -2
- machineconfig/scripts/windows/checkout_version.ps1 +1 -3
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +1 -3
- machineconfig/scripts/windows/cloud_copy.ps1 +2 -6
- machineconfig/scripts/windows/cloud_manager.ps1 +1 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +1 -2
- machineconfig/scripts/windows/cloud_sync.ps1 +2 -2
- machineconfig/scripts/windows/croshell.ps1 +2 -2
- machineconfig/scripts/windows/devops.ps1 +1 -4
- machineconfig/scripts/windows/dotfile.ps1 +1 -3
- machineconfig/scripts/windows/fire.ps1 +1 -1
- machineconfig/scripts/windows/ftpx.ps1 +2 -2
- machineconfig/scripts/windows/gpt.ps1 +1 -1
- machineconfig/scripts/windows/kill_process.ps1 +1 -2
- machineconfig/scripts/windows/mcinit.ps1 +2 -2
- machineconfig/scripts/windows/mount_nfs.ps1 +1 -1
- machineconfig/scripts/windows/mount_ssh.ps1 +1 -1
- machineconfig/scripts/windows/pomodoro.ps1 +1 -1
- machineconfig/scripts/windows/py2exe.ps1 +1 -3
- machineconfig/scripts/windows/repos.ps1 +1 -1
- machineconfig/scripts/windows/scheduler.ps1 +1 -1
- machineconfig/scripts/windows/snapshot.ps1 +2 -2
- machineconfig/scripts/windows/start_slidev.ps1 +1 -1
- machineconfig/scripts/windows/start_terminals.ps1 +1 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +1 -1
- machineconfig/scripts/windows/wsl_windows_transfer.ps1 +1 -3
- machineconfig/settings/lf/linux/lfrc +1 -1
- machineconfig/settings/linters/.ruff.toml +2 -2
- machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
- machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
- machineconfig/settings/lvim/windows/archive/config_additional.lua +1 -1
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
- machineconfig/settings/shells/wt/settings.json +8 -8
- machineconfig/settings/svim/linux/init.toml +1 -1
- machineconfig/settings/svim/windows/init.toml +1 -1
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -54
- machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -6
- machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
- machineconfig/setup_windows/web_shortcuts/all.ps1 +2 -2
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +1 -1
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +1 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +5 -5
- machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +51 -15
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +75 -18
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +52 -42
- machineconfig/utils/ai/browser_user_wrapper.py +5 -5
- machineconfig/utils/ai/generate_file_checklist.py +19 -22
- machineconfig/utils/ai/url2md.py +5 -3
- machineconfig/utils/cloud/onedrive/setup_oauth.py +5 -4
- machineconfig/utils/cloud/onedrive/transaction.py +192 -227
- machineconfig/utils/code.py +71 -43
- machineconfig/utils/installer.py +77 -85
- machineconfig/utils/installer_utils/installer_abc.py +29 -17
- machineconfig/utils/installer_utils/installer_class.py +188 -83
- machineconfig/utils/io_save.py +3 -15
- machineconfig/utils/links.py +22 -11
- machineconfig/utils/notifications.py +197 -0
- machineconfig/utils/options.py +38 -25
- machineconfig/utils/path.py +18 -6
- machineconfig/utils/path_reduced.py +637 -316
- machineconfig/utils/procs.py +69 -63
- machineconfig/utils/scheduling.py +11 -13
- machineconfig/utils/ssh.py +351 -0
- machineconfig/utils/terminal.py +225 -0
- machineconfig/utils/utils.py +13 -12
- machineconfig/utils/utils2.py +43 -10
- machineconfig/utils/utils5.py +242 -46
- machineconfig/utils/ve.py +11 -6
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/METADATA +15 -9
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/RECORD +232 -235
- machineconfig/cluster/self_ssh.py +0 -57
- machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/archive/python_tools.txt +0 -12
- machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_generic_installers/update.py +0 -3
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
- machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/linux/activate_ve +0 -87
- machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/init.py +0 -56
- machineconfig/scripts/python/ai/rules/python/dev.md +0 -31
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/windows/activate_ve.ps1 +0 -54
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/WHEEL +0 -0
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Process monitoring and status checking utilities for Windows Terminal commands.
|
|
4
4
|
Adapted from zellij process monitor but focused on Windows processes.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import json
|
|
7
8
|
import logging
|
|
8
9
|
import subprocess
|
|
@@ -14,153 +15,105 @@ logger = logging.getLogger(__name__)
|
|
|
14
15
|
|
|
15
16
|
class WTProcessMonitor:
|
|
16
17
|
"""Handles process status checking and verification on local and remote Windows machines."""
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
def __init__(self, remote_executor: Optional[WTRemoteExecutor] = None):
|
|
19
20
|
self.remote_executor = remote_executor
|
|
20
21
|
self.is_local = remote_executor is None
|
|
21
|
-
|
|
22
|
+
|
|
22
23
|
@property
|
|
23
24
|
def location_name(self) -> str:
|
|
24
25
|
"""Get the location name for status reporting."""
|
|
25
26
|
return "local" if self.is_local else (self.remote_executor.remote_name if self.remote_executor else "unknown")
|
|
26
|
-
|
|
27
|
+
|
|
27
28
|
def _run_command(self, command: str, timeout: int = 30) -> subprocess.CompletedProcess[str]:
|
|
28
29
|
"""Run command either locally or remotely."""
|
|
29
30
|
if self.is_local:
|
|
30
|
-
return subprocess.run(
|
|
31
|
-
["powershell", "-Command", command],
|
|
32
|
-
capture_output=True,
|
|
33
|
-
text=True,
|
|
34
|
-
timeout=timeout
|
|
35
|
-
)
|
|
31
|
+
return subprocess.run(["powershell", "-Command", command], capture_output=True, text=True, timeout=timeout)
|
|
36
32
|
else:
|
|
37
33
|
if self.remote_executor is None:
|
|
38
34
|
raise ValueError("Remote executor is None but is_local is False")
|
|
39
35
|
return self.remote_executor.run_command(command, timeout)
|
|
40
|
-
|
|
41
|
-
def check_command_status(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]],
|
|
42
|
-
use_verification: bool = True) -> Dict[str, Any]:
|
|
36
|
+
|
|
37
|
+
def check_command_status(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]], use_verification: bool = True) -> Dict[str, Any]:
|
|
43
38
|
"""Check command status with optional process verification."""
|
|
44
39
|
if tab_name not in tab_config:
|
|
45
|
-
return {
|
|
46
|
-
|
|
47
|
-
"error": f"Tab '{tab_name}' not found in tracked configuration",
|
|
48
|
-
"running": False,
|
|
49
|
-
"pid": None,
|
|
50
|
-
"command": None,
|
|
51
|
-
"location": self.location_name
|
|
52
|
-
}
|
|
53
|
-
|
|
40
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in tracked configuration", "running": False, "pid": None, "command": None, "location": self.location_name}
|
|
41
|
+
|
|
54
42
|
# Use the verified method by default for more accurate results
|
|
55
43
|
if use_verification:
|
|
56
44
|
return self.get_verified_process_status(tab_name, tab_config)
|
|
57
|
-
|
|
45
|
+
|
|
58
46
|
return self._basic_process_check(tab_name, tab_config)
|
|
59
|
-
|
|
47
|
+
|
|
60
48
|
def _basic_process_check(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
61
49
|
"""Basic process checking without verification."""
|
|
62
50
|
_, command = tab_config[tab_name]
|
|
63
|
-
|
|
51
|
+
|
|
64
52
|
try:
|
|
65
53
|
check_script = self._create_process_check_script(command)
|
|
66
54
|
result = self._run_command(check_script, timeout=15)
|
|
67
|
-
|
|
55
|
+
|
|
68
56
|
if result.returncode == 0:
|
|
69
57
|
try:
|
|
70
58
|
# Parse PowerShell output (JSON format)
|
|
71
|
-
output_lines = [line.strip() for line in result.stdout.strip().split(
|
|
59
|
+
output_lines = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
|
|
72
60
|
matching_processes = []
|
|
73
|
-
|
|
61
|
+
|
|
74
62
|
for line in output_lines:
|
|
75
|
-
if line.startswith(
|
|
63
|
+
if line.startswith("{") and line.endswith("}"):
|
|
76
64
|
try:
|
|
77
65
|
proc_info = json.loads(line)
|
|
78
66
|
matching_processes.append(proc_info)
|
|
79
67
|
except json.JSONDecodeError:
|
|
80
68
|
continue
|
|
81
|
-
|
|
69
|
+
|
|
82
70
|
if matching_processes:
|
|
83
|
-
return {
|
|
84
|
-
"status": "running",
|
|
85
|
-
"running": True,
|
|
86
|
-
"processes": matching_processes,
|
|
87
|
-
"command": command,
|
|
88
|
-
"tab_name": tab_name,
|
|
89
|
-
"location": self.location_name
|
|
90
|
-
}
|
|
71
|
+
return {"status": "running", "running": True, "processes": matching_processes, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
91
72
|
else:
|
|
92
|
-
return {
|
|
93
|
-
"status": "not_running",
|
|
94
|
-
"running": False,
|
|
95
|
-
"processes": [],
|
|
96
|
-
"command": command,
|
|
97
|
-
"tab_name": tab_name,
|
|
98
|
-
"location": self.location_name
|
|
99
|
-
}
|
|
73
|
+
return {"status": "not_running", "running": False, "processes": [], "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
100
74
|
except Exception as e:
|
|
101
75
|
logger.error(f"Failed to parse process check output: {e}")
|
|
102
|
-
return {
|
|
103
|
-
"status": "error",
|
|
104
|
-
"error": f"Failed to parse output: {e}",
|
|
105
|
-
"running": False,
|
|
106
|
-
"command": command,
|
|
107
|
-
"tab_name": tab_name,
|
|
108
|
-
"location": self.location_name
|
|
109
|
-
}
|
|
76
|
+
return {"status": "error", "error": f"Failed to parse output: {e}", "running": False, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
110
77
|
else:
|
|
111
|
-
return {
|
|
112
|
-
|
|
113
|
-
"error": f"Command failed: {result.stderr}",
|
|
114
|
-
"running": False,
|
|
115
|
-
"command": command,
|
|
116
|
-
"tab_name": tab_name,
|
|
117
|
-
"location": self.location_name
|
|
118
|
-
}
|
|
119
|
-
|
|
78
|
+
return {"status": "error", "error": f"Command failed: {result.stderr}", "running": False, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
79
|
+
|
|
120
80
|
except Exception as e:
|
|
121
81
|
logger.error(f"Error checking command status for tab '{tab_name}': {e}")
|
|
122
|
-
return {
|
|
123
|
-
|
|
124
|
-
"error": str(e),
|
|
125
|
-
"running": False,
|
|
126
|
-
"command": command,
|
|
127
|
-
"tab_name": tab_name,
|
|
128
|
-
"location": self.location_name
|
|
129
|
-
}
|
|
130
|
-
|
|
82
|
+
return {"status": "error", "error": str(e), "running": False, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
83
|
+
|
|
131
84
|
def _create_process_check_script(self, command: str) -> str:
|
|
132
85
|
"""Create PowerShell script for checking processes."""
|
|
133
86
|
# Escape command for PowerShell
|
|
134
87
|
escaped_command = command.replace("'", "''").replace('"', '""')
|
|
135
88
|
cmd_parts = [part for part in command.split() if len(part) > 2]
|
|
136
|
-
primary_cmd = cmd_parts[0] if cmd_parts else
|
|
137
|
-
|
|
89
|
+
primary_cmd = cmd_parts[0] if cmd_parts else ""
|
|
90
|
+
|
|
138
91
|
return f"""
|
|
139
92
|
$targetCommand = '{escaped_command}'
|
|
140
|
-
$cmdParts = @({
|
|
93
|
+
$cmdParts = @({", ".join([f"'{part}'" for part in cmd_parts])})
|
|
141
94
|
$primaryCmd = '{primary_cmd}'
|
|
142
95
|
$currentPid = $PID
|
|
143
96
|
|
|
144
97
|
Get-Process | ForEach-Object {{
|
|
145
98
|
try {{
|
|
146
99
|
if ($_.Id -eq $currentPid) {{ return }}
|
|
147
|
-
|
|
100
|
+
|
|
148
101
|
$cmdline = ""
|
|
149
102
|
try {{
|
|
150
103
|
$cmdline = (Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine
|
|
151
104
|
}} catch {{
|
|
152
105
|
$cmdline = $_.ProcessName
|
|
153
106
|
}}
|
|
154
|
-
|
|
107
|
+
|
|
155
108
|
if ($cmdline -and $cmdline -ne "") {{
|
|
156
109
|
if ($cmdline -like "*PowerShell*" -and $cmdline -like "*Get-Process*") {{ return }}
|
|
157
|
-
|
|
110
|
+
|
|
158
111
|
$matchesPrimary = $cmdline -like "*$primaryCmd*" -and $primaryCmd -ne "powershell"
|
|
159
112
|
$matchCount = 0
|
|
160
113
|
foreach ($part in $cmdParts[1..($cmdParts.Length-1)]) {{
|
|
161
114
|
if ($cmdline -like "*$part*") {{ $matchCount++ }}
|
|
162
115
|
}}
|
|
163
|
-
|
|
116
|
+
|
|
164
117
|
if ($matchesPrimary -and $matchCount -ge 2) {{
|
|
165
118
|
$procInfo = @{{
|
|
166
119
|
"pid" = $_.Id
|
|
@@ -178,38 +131,32 @@ Get-Process | ForEach-Object {{
|
|
|
178
131
|
}}
|
|
179
132
|
}}
|
|
180
133
|
"""
|
|
181
|
-
|
|
134
|
+
|
|
182
135
|
def force_fresh_process_check(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
183
136
|
"""Force a fresh process check with additional validation."""
|
|
184
137
|
if tab_name not in tab_config:
|
|
185
|
-
return {
|
|
186
|
-
|
|
187
|
-
"error": f"Tab '{tab_name}' not found in tracked configuration",
|
|
188
|
-
"running": False,
|
|
189
|
-
"command": None,
|
|
190
|
-
"location": self.location_name
|
|
191
|
-
}
|
|
192
|
-
|
|
138
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in tracked configuration", "running": False, "command": None, "location": self.location_name}
|
|
139
|
+
|
|
193
140
|
_, command = tab_config[tab_name]
|
|
194
|
-
|
|
141
|
+
|
|
195
142
|
try:
|
|
196
143
|
# Get timestamp for freshness validation
|
|
197
144
|
timestamp_cmd = "Get-Date -UFormat %s"
|
|
198
145
|
timestamp_result = self._run_command(timestamp_cmd, timeout=5)
|
|
199
146
|
check_timestamp = timestamp_result.stdout.strip() if timestamp_result.returncode == 0 else "unknown"
|
|
200
|
-
|
|
147
|
+
|
|
201
148
|
check_script = self._create_fresh_check_script(command)
|
|
202
149
|
result = self._run_command(check_script, timeout=15)
|
|
203
|
-
|
|
150
|
+
|
|
204
151
|
if result.returncode == 0:
|
|
205
152
|
try:
|
|
206
153
|
# Parse the output to extract JSON
|
|
207
|
-
output_lines = [line.strip() for line in result.stdout.strip().split(
|
|
154
|
+
output_lines = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
|
|
208
155
|
for line in output_lines:
|
|
209
|
-
if line.startswith(
|
|
156
|
+
if line.startswith("{") and '"processes"' in line:
|
|
210
157
|
check_result = json.loads(line)
|
|
211
158
|
matching_processes = check_result.get("processes", [])
|
|
212
|
-
|
|
159
|
+
|
|
213
160
|
return {
|
|
214
161
|
"status": "running" if matching_processes else "not_running",
|
|
215
162
|
"running": bool(matching_processes),
|
|
@@ -218,62 +165,32 @@ Get-Process | ForEach-Object {{
|
|
|
218
165
|
"tab_name": tab_name,
|
|
219
166
|
"location": self.location_name,
|
|
220
167
|
"check_timestamp": check_timestamp,
|
|
221
|
-
"method": "force_fresh_check"
|
|
168
|
+
"method": "force_fresh_check",
|
|
222
169
|
}
|
|
223
|
-
|
|
170
|
+
|
|
224
171
|
# Fallback if no JSON found
|
|
225
|
-
return {
|
|
226
|
-
"status": "not_running",
|
|
227
|
-
"running": False,
|
|
228
|
-
"processes": [],
|
|
229
|
-
"command": command,
|
|
230
|
-
"tab_name": tab_name,
|
|
231
|
-
"location": self.location_name,
|
|
232
|
-
"raw_output": result.stdout
|
|
233
|
-
}
|
|
172
|
+
return {"status": "not_running", "running": False, "processes": [], "command": command, "tab_name": tab_name, "location": self.location_name, "raw_output": result.stdout}
|
|
234
173
|
except json.JSONDecodeError as e:
|
|
235
174
|
logger.error(f"Failed to parse fresh check output: {e}")
|
|
236
|
-
return {
|
|
237
|
-
"status": "error",
|
|
238
|
-
"error": f"Failed to parse output: {e}",
|
|
239
|
-
"running": False,
|
|
240
|
-
"command": command,
|
|
241
|
-
"tab_name": tab_name,
|
|
242
|
-
"location": self.location_name,
|
|
243
|
-
"raw_output": result.stdout
|
|
244
|
-
}
|
|
175
|
+
return {"status": "error", "error": f"Failed to parse output: {e}", "running": False, "command": command, "tab_name": tab_name, "location": self.location_name, "raw_output": result.stdout}
|
|
245
176
|
else:
|
|
246
|
-
return {
|
|
247
|
-
|
|
248
|
-
"error": f"Command failed: {result.stderr}",
|
|
249
|
-
"running": False,
|
|
250
|
-
"command": command,
|
|
251
|
-
"tab_name": tab_name,
|
|
252
|
-
"location": self.location_name
|
|
253
|
-
}
|
|
254
|
-
|
|
177
|
+
return {"status": "error", "error": f"Command failed: {result.stderr}", "running": False, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
178
|
+
|
|
255
179
|
except Exception as e:
|
|
256
180
|
logger.error(f"Error in fresh process check for tab '{tab_name}': {e}")
|
|
257
|
-
return {
|
|
258
|
-
|
|
259
|
-
"error": str(e),
|
|
260
|
-
"running": False,
|
|
261
|
-
"command": command,
|
|
262
|
-
"tab_name": tab_name,
|
|
263
|
-
"location": self.location_name
|
|
264
|
-
}
|
|
265
|
-
|
|
181
|
+
return {"status": "error", "error": str(e), "running": False, "command": command, "tab_name": tab_name, "location": self.location_name}
|
|
182
|
+
|
|
266
183
|
def _create_fresh_check_script(self, command: str) -> str:
|
|
267
184
|
"""Create enhanced PowerShell process checking script with freshness validation."""
|
|
268
185
|
escaped_command = command.replace("'", "''").replace('"', '""')
|
|
269
186
|
cmd_parts = [part for part in command.split() if len(part) > 2]
|
|
270
|
-
primary_cmd = cmd_parts[0] if cmd_parts else
|
|
271
|
-
|
|
187
|
+
primary_cmd = cmd_parts[0] if cmd_parts else ""
|
|
188
|
+
|
|
272
189
|
return f"""
|
|
273
190
|
Start-Sleep -Milliseconds 100
|
|
274
191
|
|
|
275
192
|
$targetCommand = '{escaped_command}'
|
|
276
|
-
$cmdParts = @({
|
|
193
|
+
$cmdParts = @({", ".join([f"'{part}'" for part in cmd_parts])})
|
|
277
194
|
$primaryCmd = '{primary_cmd}'
|
|
278
195
|
$currentPid = $PID
|
|
279
196
|
$checkTime = Get-Date
|
|
@@ -282,30 +199,30 @@ $matchingProcesses = @()
|
|
|
282
199
|
Get-Process | ForEach-Object {{
|
|
283
200
|
try {{
|
|
284
201
|
if ($_.Id -eq $currentPid) {{ return }}
|
|
285
|
-
|
|
202
|
+
|
|
286
203
|
$cmdline = ""
|
|
287
204
|
try {{
|
|
288
205
|
$cmdline = (Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine
|
|
289
206
|
}} catch {{
|
|
290
207
|
$cmdline = $_.ProcessName
|
|
291
208
|
}}
|
|
292
|
-
|
|
209
|
+
|
|
293
210
|
if ($cmdline -and $cmdline -ne "") {{
|
|
294
211
|
# Skip our own checking processes
|
|
295
212
|
if ($cmdline -like "*Get-Process*" -or $cmdline -like "*force_fresh_check*") {{ return }}
|
|
296
|
-
|
|
213
|
+
|
|
297
214
|
# Skip processes that started very recently (likely our own scripts)
|
|
298
215
|
if ($_.StartTime -and ($checkTime - $_.StartTime).TotalSeconds -lt 5) {{ return }}
|
|
299
|
-
|
|
216
|
+
|
|
300
217
|
$matchesPrimary = $cmdline -like "*$primaryCmd*" -and $primaryCmd -ne "powershell"
|
|
301
218
|
$matchCount = 0
|
|
302
219
|
foreach ($part in $cmdParts[1..($cmdParts.Length-1)]) {{
|
|
303
220
|
if ($cmdline -like "*$part*") {{ $matchCount++ }}
|
|
304
221
|
}}
|
|
305
|
-
|
|
222
|
+
|
|
306
223
|
if ($matchesPrimary -and $matchCount -ge 2) {{
|
|
307
224
|
$isDirectCommand = -not ($cmdline -like "*-Command*" -or $cmdline -like "*Get-Process*")
|
|
308
|
-
|
|
225
|
+
|
|
309
226
|
if ($isDirectCommand -or ($targetCommand -in $cmdline -and $cmdline -notlike "*powershell -Command*")) {{
|
|
310
227
|
$procInfo = @{{
|
|
311
228
|
"pid" = $_.Id
|
|
@@ -334,21 +251,21 @@ $result = @{{
|
|
|
334
251
|
|
|
335
252
|
Write-Output $result
|
|
336
253
|
"""
|
|
337
|
-
|
|
254
|
+
|
|
338
255
|
def verify_process_alive(self, pid: int) -> bool:
|
|
339
256
|
"""Verify if a process with given PID is actually alive."""
|
|
340
257
|
try:
|
|
341
258
|
verify_cmd = f"Get-Process -Id {pid} -ErrorAction SilentlyContinue | Select-Object -First 1"
|
|
342
259
|
result = self._run_command(verify_cmd, timeout=5)
|
|
343
|
-
|
|
260
|
+
|
|
344
261
|
return result.returncode == 0 and result.stdout.strip() != ""
|
|
345
262
|
except Exception:
|
|
346
263
|
return False
|
|
347
|
-
|
|
264
|
+
|
|
348
265
|
def get_verified_process_status(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
349
266
|
"""Get process status with additional verification that processes are actually alive."""
|
|
350
267
|
status = self.force_fresh_process_check(tab_name, tab_config)
|
|
351
|
-
|
|
268
|
+
|
|
352
269
|
if status.get("running") and status.get("processes"):
|
|
353
270
|
verified_processes = []
|
|
354
271
|
for proc in status["processes"]:
|
|
@@ -359,60 +276,43 @@ Write-Output $result
|
|
|
359
276
|
else:
|
|
360
277
|
proc["verified_alive"] = False
|
|
361
278
|
logger.warning(f"Process PID {pid} found in process list but not actually alive")
|
|
362
|
-
|
|
279
|
+
|
|
363
280
|
status["processes"] = verified_processes
|
|
364
281
|
status["running"] = bool(verified_processes)
|
|
365
282
|
status["status"] = "running" if verified_processes else "not_running"
|
|
366
283
|
status["verification_method"] = "get_process_check"
|
|
367
|
-
|
|
284
|
+
|
|
368
285
|
return status
|
|
369
|
-
|
|
286
|
+
|
|
370
287
|
def check_all_commands_status(self, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Dict[str, Any]]:
|
|
371
288
|
"""Check status of all commands in the tab configuration."""
|
|
372
289
|
if not tab_config:
|
|
373
290
|
logger.warning("No tab configuration provided.")
|
|
374
291
|
return {}
|
|
375
|
-
|
|
292
|
+
|
|
376
293
|
status_report = {}
|
|
377
294
|
for tab_name in tab_config:
|
|
378
295
|
status_report[tab_name] = self.check_command_status(tab_name, tab_config)
|
|
379
296
|
return status_report
|
|
380
|
-
|
|
297
|
+
|
|
381
298
|
def get_windows_terminal_windows(self) -> Dict[str, Any]:
|
|
382
299
|
"""Get information about currently running Windows Terminal windows."""
|
|
383
300
|
try:
|
|
384
301
|
wt_info_cmd = """
|
|
385
|
-
Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue |
|
|
302
|
+
Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue |
|
|
386
303
|
Select-Object Id, ProcessName, StartTime, @{Name="WindowTitle";Expression={(Get-Process -Id $_.Id).MainWindowTitle}} |
|
|
387
304
|
ConvertTo-Json -Depth 2
|
|
388
305
|
"""
|
|
389
306
|
result = self._run_command(wt_info_cmd, timeout=15)
|
|
390
|
-
|
|
307
|
+
|
|
391
308
|
if result.returncode == 0 and result.stdout.strip():
|
|
392
309
|
try:
|
|
393
310
|
wt_processes = json.loads(result.stdout)
|
|
394
|
-
return {
|
|
395
|
-
"success": True,
|
|
396
|
-
"windows": wt_processes if isinstance(wt_processes, list) else [wt_processes],
|
|
397
|
-
"location": self.location_name
|
|
398
|
-
}
|
|
311
|
+
return {"success": True, "windows": wt_processes if isinstance(wt_processes, list) else [wt_processes], "location": self.location_name}
|
|
399
312
|
except json.JSONDecodeError:
|
|
400
|
-
return {
|
|
401
|
-
"success": False,
|
|
402
|
-
"error": "Failed to parse Windows Terminal process info",
|
|
403
|
-
"location": self.location_name
|
|
404
|
-
}
|
|
313
|
+
return {"success": False, "error": "Failed to parse Windows Terminal process info", "location": self.location_name}
|
|
405
314
|
else:
|
|
406
|
-
return {
|
|
407
|
-
"success": True,
|
|
408
|
-
"windows": [],
|
|
409
|
-
"message": "No Windows Terminal processes found",
|
|
410
|
-
"location": self.location_name
|
|
411
|
-
}
|
|
315
|
+
return {"success": True, "windows": [], "message": "No Windows Terminal processes found", "location": self.location_name}
|
|
412
316
|
except Exception as e:
|
|
413
317
|
logger.error(f"Failed to get Windows Terminal windows: {e}")
|
|
414
|
-
return {
|
|
415
|
-
"success": False,
|
|
416
|
-
"error": str(e),
|
|
417
|
-
"location": self.location_name
|
|
418
|
-
}
|
|
318
|
+
return {"success": False, "error": str(e), "location": self.location_name}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Remote command execution utilities for SSH operations with Windows Terminal.
|
|
4
4
|
Adapted from zellij remote executor but focused on Windows Terminal commands.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import subprocess
|
|
7
8
|
import logging
|
|
8
9
|
from typing import Dict, Any, Optional, List
|
|
@@ -12,26 +13,21 @@ logger = logging.getLogger(__name__)
|
|
|
12
13
|
|
|
13
14
|
class WTRemoteExecutor:
|
|
14
15
|
"""Handles SSH command execution on remote Windows machines with Windows Terminal."""
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
def __init__(self, remote_name: str):
|
|
17
18
|
self.remote_name = remote_name
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
def run_command(self, command: str, timeout: int = 30, shell: str = "powershell") -> subprocess.CompletedProcess[str]:
|
|
20
21
|
"""Execute a command on the remote machine via SSH."""
|
|
21
22
|
# For Windows Terminal on remote machines, we need to use PowerShell or CMD
|
|
22
23
|
if shell == "powershell":
|
|
23
24
|
# Wrap command in PowerShell invocation if needed
|
|
24
25
|
if not command.startswith("powershell"):
|
|
25
|
-
command = f
|
|
26
|
-
|
|
26
|
+
command = f'powershell -Command "{command}"'
|
|
27
|
+
|
|
27
28
|
ssh_cmd = ["ssh", self.remote_name, command]
|
|
28
29
|
try:
|
|
29
|
-
result = subprocess.run(
|
|
30
|
-
ssh_cmd,
|
|
31
|
-
capture_output=True,
|
|
32
|
-
text=True,
|
|
33
|
-
timeout=timeout
|
|
34
|
-
)
|
|
30
|
+
result = subprocess.run(ssh_cmd, capture_output=True, text=True, timeout=timeout)
|
|
35
31
|
return result
|
|
36
32
|
except subprocess.TimeoutExpired:
|
|
37
33
|
logger.error(f"SSH command timed out after {timeout}s: {command}")
|
|
@@ -39,7 +35,7 @@ class WTRemoteExecutor:
|
|
|
39
35
|
except Exception as e:
|
|
40
36
|
logger.error(f"SSH command failed: {e}")
|
|
41
37
|
raise
|
|
42
|
-
|
|
38
|
+
|
|
43
39
|
def copy_file_to_remote(self, local_file: str, remote_path: str) -> Dict[str, Any]:
|
|
44
40
|
"""Copy a file to the remote machine using SCP."""
|
|
45
41
|
scp_cmd = ["scp", local_file, f"{self.remote_name}:{remote_path}"]
|
|
@@ -54,7 +50,7 @@ class WTRemoteExecutor:
|
|
|
54
50
|
except Exception as e:
|
|
55
51
|
logger.error(f"SCP operation failed: {e}")
|
|
56
52
|
return {"success": False, "error": str(e)}
|
|
57
|
-
|
|
53
|
+
|
|
58
54
|
def create_remote_directory(self, remote_dir: str) -> bool:
|
|
59
55
|
"""Create a directory on the remote machine."""
|
|
60
56
|
try:
|
|
@@ -64,7 +60,7 @@ class WTRemoteExecutor:
|
|
|
64
60
|
except Exception as e:
|
|
65
61
|
logger.error(f"Failed to create remote directory {remote_dir}: {e}")
|
|
66
62
|
return False
|
|
67
|
-
|
|
63
|
+
|
|
68
64
|
def start_wt_session_interactive(self, wt_command: str) -> None:
|
|
69
65
|
"""Start a Windows Terminal session interactively via SSH."""
|
|
70
66
|
try:
|
|
@@ -75,7 +71,7 @@ class WTRemoteExecutor:
|
|
|
75
71
|
except Exception as e:
|
|
76
72
|
logger.error(f"Failed to start Windows Terminal session: {e}")
|
|
77
73
|
raise
|
|
78
|
-
|
|
74
|
+
|
|
79
75
|
def check_wt_available(self) -> bool:
|
|
80
76
|
"""Check if Windows Terminal is available on the remote machine."""
|
|
81
77
|
try:
|
|
@@ -83,30 +79,21 @@ class WTRemoteExecutor:
|
|
|
83
79
|
return result.returncode == 0
|
|
84
80
|
except Exception:
|
|
85
81
|
return False
|
|
86
|
-
|
|
82
|
+
|
|
87
83
|
def get_remote_windows_info(self) -> Dict[str, Any]:
|
|
88
84
|
"""Get information about the remote Windows system."""
|
|
89
85
|
try:
|
|
90
86
|
# Get Windows version and terminal info
|
|
91
87
|
version_cmd = "Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion"
|
|
92
88
|
result = self.run_command(version_cmd, timeout=15)
|
|
93
|
-
|
|
89
|
+
|
|
94
90
|
wt_available = self.check_wt_available()
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
"windows_info": result.stdout if result.returncode == 0 else "Unknown",
|
|
98
|
-
"wt_available": wt_available,
|
|
99
|
-
"remote_name": self.remote_name
|
|
100
|
-
}
|
|
91
|
+
|
|
92
|
+
return {"windows_info": result.stdout if result.returncode == 0 else "Unknown", "wt_available": wt_available, "remote_name": self.remote_name}
|
|
101
93
|
except Exception as e:
|
|
102
94
|
logger.error(f"Failed to get remote Windows info: {e}")
|
|
103
|
-
return {
|
|
104
|
-
|
|
105
|
-
"wt_available": False,
|
|
106
|
-
"remote_name": self.remote_name,
|
|
107
|
-
"error": str(e)
|
|
108
|
-
}
|
|
109
|
-
|
|
95
|
+
return {"windows_info": "Error getting info", "wt_available": False, "remote_name": self.remote_name, "error": str(e)}
|
|
96
|
+
|
|
110
97
|
def run_wt_command(self, wt_command: str, detached: bool = True) -> subprocess.CompletedProcess[str]:
|
|
111
98
|
"""Run a Windows Terminal command on the remote machine."""
|
|
112
99
|
try:
|
|
@@ -116,39 +103,27 @@ class WTRemoteExecutor:
|
|
|
116
103
|
else:
|
|
117
104
|
# Run in foreground
|
|
118
105
|
full_command = f"wt {wt_command}"
|
|
119
|
-
|
|
106
|
+
|
|
120
107
|
return self.run_command(full_command, timeout=30)
|
|
121
108
|
except Exception as e:
|
|
122
109
|
logger.error(f"Failed to run Windows Terminal command: {e}")
|
|
123
110
|
raise
|
|
124
|
-
|
|
111
|
+
|
|
125
112
|
def list_wt_processes(self) -> Dict[str, Any]:
|
|
126
113
|
"""List Windows Terminal processes on the remote machine."""
|
|
127
114
|
try:
|
|
128
115
|
# Get all WindowsTerminal.exe processes
|
|
129
116
|
ps_command = "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, CPU"
|
|
130
117
|
result = self.run_command(ps_command, timeout=15)
|
|
131
|
-
|
|
118
|
+
|
|
132
119
|
if result.returncode == 0:
|
|
133
|
-
return {
|
|
134
|
-
"success": True,
|
|
135
|
-
"processes": result.stdout,
|
|
136
|
-
"remote": self.remote_name
|
|
137
|
-
}
|
|
120
|
+
return {"success": True, "processes": result.stdout, "remote": self.remote_name}
|
|
138
121
|
else:
|
|
139
|
-
return {
|
|
140
|
-
"success": False,
|
|
141
|
-
"error": result.stderr,
|
|
142
|
-
"remote": self.remote_name
|
|
143
|
-
}
|
|
122
|
+
return {"success": False, "error": result.stderr, "remote": self.remote_name}
|
|
144
123
|
except Exception as e:
|
|
145
124
|
logger.error(f"Failed to list Windows Terminal processes: {e}")
|
|
146
|
-
return {
|
|
147
|
-
|
|
148
|
-
"error": str(e),
|
|
149
|
-
"remote": self.remote_name
|
|
150
|
-
}
|
|
151
|
-
|
|
125
|
+
return {"success": False, "error": str(e), "remote": self.remote_name}
|
|
126
|
+
|
|
152
127
|
def kill_wt_processes(self, process_ids: Optional[List[Any]] = None) -> Dict[str, Any]:
|
|
153
128
|
"""Kill Windows Terminal processes on the remote machine."""
|
|
154
129
|
try:
|
|
@@ -158,18 +133,10 @@ class WTRemoteExecutor:
|
|
|
158
133
|
else:
|
|
159
134
|
# Kill all Windows Terminal processes
|
|
160
135
|
kill_cmd = "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Stop-Process -Force"
|
|
161
|
-
|
|
136
|
+
|
|
162
137
|
result = self.run_command(kill_cmd, timeout=10)
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
"success": result.returncode == 0,
|
|
166
|
-
"message": "Processes killed" if result.returncode == 0 else result.stderr,
|
|
167
|
-
"remote": self.remote_name
|
|
168
|
-
}
|
|
138
|
+
|
|
139
|
+
return {"success": result.returncode == 0, "message": "Processes killed" if result.returncode == 0 else result.stderr, "remote": self.remote_name}
|
|
169
140
|
except Exception as e:
|
|
170
141
|
logger.error(f"Failed to kill Windows Terminal processes: {e}")
|
|
171
|
-
return {
|
|
172
|
-
"success": False,
|
|
173
|
-
"error": str(e),
|
|
174
|
-
"remote": self.remote_name
|
|
175
|
-
}
|
|
142
|
+
return {"success": False, "error": str(e), "remote": self.remote_name}
|