machineconfig 1.97__py3-none-any.whl → 2.0__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 -26
- machineconfig/cluster/data_transfer.py +2 -2
- machineconfig/cluster/distribute.py +0 -2
- machineconfig/cluster/file_manager.py +4 -4
- machineconfig/cluster/job_params.py +1 -1
- machineconfig/cluster/loader_runner.py +8 -8
- machineconfig/cluster/remote_machine.py +4 -4
- machineconfig/cluster/script_execution.py +2 -2
- machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +1 -1
- machineconfig/cluster/sessions_managers/enhanced_command_runner.py +23 -23
- machineconfig/cluster/sessions_managers/wt_local.py +78 -76
- machineconfig/cluster/sessions_managers/wt_local_manager.py +91 -91
- machineconfig/cluster/sessions_managers/wt_remote.py +39 -39
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +94 -91
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +56 -54
- machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +49 -49
- machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +18 -18
- machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +42 -42
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +36 -36
- machineconfig/cluster/sessions_managers/zellij_local.py +43 -46
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +139 -120
- machineconfig/cluster/sessions_managers/zellij_remote.py +35 -35
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +33 -33
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +15 -15
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +25 -26
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +49 -49
- machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +5 -5
- machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +15 -15
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +11 -11
- machineconfig/cluster/templates/utils.py +3 -3
- machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/python_ve_symlink.cpython-311.pyc +0 -0
- machineconfig/jobs/python/check_installations.py +8 -9
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/vscode/link_ve.py +7 -7
- machineconfig/jobs/python/vscode/select_interpreter.py +7 -7
- machineconfig/jobs/python/vscode/sync_code.py +5 -5
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +2 -2
- machineconfig/jobs/python_custom_installers/dev/aider.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/brave.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +5 -5
- machineconfig/jobs/python_custom_installers/dev/code.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/cursor.py +9 -9
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/espanso.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/goes.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/lvim.py +4 -4
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/redis.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +3 -3
- machineconfig/jobs/python_custom_installers/dev/winget.py +27 -27
- machineconfig/jobs/python_custom_installers/docker.py +3 -3
- machineconfig/jobs/python_custom_installers/gh.py +7 -7
- machineconfig/jobs/python_custom_installers/hx.py +1 -1
- machineconfig/jobs/python_custom_installers/warp-cli.py +3 -3
- machineconfig/jobs/python_generic_installers/config.json +412 -389
- machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
- machineconfig/logger.py +50 -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/profile/create.py +23 -16
- machineconfig/profile/create_hardlinks.py +8 -8
- machineconfig/profile/shell.py +41 -37
- machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/linux/devops +2 -2
- machineconfig/scripts/linux/fire +1 -0
- machineconfig/scripts/linux/fire_agents +0 -1
- machineconfig/scripts/linux/mcinit +1 -1
- machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/__init__.cpython-313.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.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.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__/repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-311.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/instructions/python/dev.instructions.md +45 -0
- machineconfig/scripts/python/ai/mcinit.py +103 -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 +47 -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 +19 -18
- machineconfig/scripts/python/cloud_mount.py +9 -7
- machineconfig/scripts/python/cloud_repo_sync.py +11 -11
- machineconfig/scripts/python/cloud_sync.py +1 -1
- machineconfig/scripts/python/croshell.py +14 -14
- machineconfig/scripts/python/devops.py +6 -6
- machineconfig/scripts/python/devops_add_identity.py +8 -6
- machineconfig/scripts/python/devops_add_ssh_key.py +18 -18
- machineconfig/scripts/python/devops_backup_retrieve.py +13 -13
- machineconfig/scripts/python/devops_devapps_install.py +3 -3
- machineconfig/scripts/python/devops_update_repos.py +1 -1
- machineconfig/scripts/python/dotfile.py +2 -2
- machineconfig/scripts/python/fire_agents.py +183 -41
- machineconfig/scripts/python/fire_jobs.py +17 -17
- machineconfig/scripts/python/ftpx.py +2 -2
- machineconfig/scripts/python/gh_models.py +94 -94
- 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/cloud_helpers.py +3 -3
- machineconfig/scripts/python/helpers/helpers2.py +1 -1
- machineconfig/scripts/python/helpers/helpers4.py +8 -6
- machineconfig/scripts/python/helpers/helpers5.py +7 -7
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +1 -1
- machineconfig/scripts/python/mount_nfs.py +3 -2
- machineconfig/scripts/python/mount_nw_drive.py +4 -4
- machineconfig/scripts/python/mount_ssh.py +3 -2
- machineconfig/scripts/python/repos.py +8 -8
- machineconfig/scripts/python/scheduler.py +1 -1
- machineconfig/scripts/python/start_slidev.py +8 -7
- 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 +1 -1
- machineconfig/scripts/windows/mcinit.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +2 -2
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
- machineconfig/settings/shells/wt/settings.json +8 -8
- machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +10 -7
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +9 -7
- machineconfig/utils/ai/browser_user_wrapper.py +5 -5
- machineconfig/utils/ai/generate_file_checklist.py +11 -12
- machineconfig/utils/ai/url2md.py +1 -1
- machineconfig/utils/cloud/onedrive/setup_oauth.py +4 -4
- machineconfig/utils/cloud/onedrive/transaction.py +129 -129
- machineconfig/utils/code.py +13 -6
- machineconfig/utils/installer.py +51 -53
- machineconfig/utils/installer_utils/installer_abc.py +21 -10
- machineconfig/utils/installer_utils/installer_class.py +42 -16
- machineconfig/utils/io_save.py +3 -15
- machineconfig/utils/options.py +10 -3
- machineconfig/utils/path.py +5 -0
- machineconfig/utils/path_reduced.py +201 -149
- machineconfig/utils/procs.py +23 -23
- machineconfig/utils/scheduling.py +11 -12
- machineconfig/utils/ssh.py +270 -0
- machineconfig/utils/terminal.py +180 -0
- machineconfig/utils/utils.py +1 -2
- machineconfig/utils/utils2.py +43 -0
- machineconfig/utils/utils5.py +163 -34
- machineconfig/utils/ve.py +2 -2
- {machineconfig-1.97.dist-info → machineconfig-2.0.dist-info}/METADATA +13 -8
- {machineconfig-1.97.dist-info → machineconfig-2.0.dist-info}/RECORD +163 -149
- machineconfig/cluster/self_ssh.py +0 -57
- machineconfig/scripts/python/ai/init.py +0 -56
- machineconfig/scripts/python/ai/rules/python/dev.md +0 -31
- {machineconfig-1.97.dist-info → machineconfig-2.0.dist-info}/WHEEL +0 -0
- {machineconfig-1.97.dist-info → machineconfig-2.0.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,10 @@ logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
class WTRemoteExecutor:
|
|
14
14
|
"""Handles SSH command execution on remote Windows machines with Windows Terminal."""
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def __init__(self, remote_name: str):
|
|
17
17
|
self.remote_name = remote_name
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def run_command(self, command: str, timeout: int = 30, shell: str = "powershell") -> subprocess.CompletedProcess[str]:
|
|
20
20
|
"""Execute a command on the remote machine via SSH."""
|
|
21
21
|
# For Windows Terminal on remote machines, we need to use PowerShell or CMD
|
|
@@ -23,7 +23,7 @@ class WTRemoteExecutor:
|
|
|
23
23
|
# Wrap command in PowerShell invocation if needed
|
|
24
24
|
if not command.startswith("powershell"):
|
|
25
25
|
command = f"powershell -Command \"{command}\""
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
ssh_cmd = ["ssh", self.remote_name, command]
|
|
28
28
|
try:
|
|
29
29
|
result = subprocess.run(
|
|
@@ -39,7 +39,7 @@ class WTRemoteExecutor:
|
|
|
39
39
|
except Exception as e:
|
|
40
40
|
logger.error(f"SSH command failed: {e}")
|
|
41
41
|
raise
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def copy_file_to_remote(self, local_file: str, remote_path: str) -> Dict[str, Any]:
|
|
44
44
|
"""Copy a file to the remote machine using SCP."""
|
|
45
45
|
scp_cmd = ["scp", local_file, f"{self.remote_name}:{remote_path}"]
|
|
@@ -54,7 +54,7 @@ class WTRemoteExecutor:
|
|
|
54
54
|
except Exception as e:
|
|
55
55
|
logger.error(f"SCP operation failed: {e}")
|
|
56
56
|
return {"success": False, "error": str(e)}
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
def create_remote_directory(self, remote_dir: str) -> bool:
|
|
59
59
|
"""Create a directory on the remote machine."""
|
|
60
60
|
try:
|
|
@@ -64,7 +64,7 @@ class WTRemoteExecutor:
|
|
|
64
64
|
except Exception as e:
|
|
65
65
|
logger.error(f"Failed to create remote directory {remote_dir}: {e}")
|
|
66
66
|
return False
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
def start_wt_session_interactive(self, wt_command: str) -> None:
|
|
69
69
|
"""Start a Windows Terminal session interactively via SSH."""
|
|
70
70
|
try:
|
|
@@ -75,7 +75,7 @@ class WTRemoteExecutor:
|
|
|
75
75
|
except Exception as e:
|
|
76
76
|
logger.error(f"Failed to start Windows Terminal session: {e}")
|
|
77
77
|
raise
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
def check_wt_available(self) -> bool:
|
|
80
80
|
"""Check if Windows Terminal is available on the remote machine."""
|
|
81
81
|
try:
|
|
@@ -83,16 +83,16 @@ class WTRemoteExecutor:
|
|
|
83
83
|
return result.returncode == 0
|
|
84
84
|
except Exception:
|
|
85
85
|
return False
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
def get_remote_windows_info(self) -> Dict[str, Any]:
|
|
88
88
|
"""Get information about the remote Windows system."""
|
|
89
89
|
try:
|
|
90
90
|
# Get Windows version and terminal info
|
|
91
91
|
version_cmd = "Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion"
|
|
92
92
|
result = self.run_command(version_cmd, timeout=15)
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
wt_available = self.check_wt_available()
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
return {
|
|
97
97
|
"windows_info": result.stdout if result.returncode == 0 else "Unknown",
|
|
98
98
|
"wt_available": wt_available,
|
|
@@ -106,7 +106,7 @@ class WTRemoteExecutor:
|
|
|
106
106
|
"remote_name": self.remote_name,
|
|
107
107
|
"error": str(e)
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
def run_wt_command(self, wt_command: str, detached: bool = True) -> subprocess.CompletedProcess[str]:
|
|
111
111
|
"""Run a Windows Terminal command on the remote machine."""
|
|
112
112
|
try:
|
|
@@ -116,19 +116,19 @@ class WTRemoteExecutor:
|
|
|
116
116
|
else:
|
|
117
117
|
# Run in foreground
|
|
118
118
|
full_command = f"wt {wt_command}"
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
return self.run_command(full_command, timeout=30)
|
|
121
121
|
except Exception as e:
|
|
122
122
|
logger.error(f"Failed to run Windows Terminal command: {e}")
|
|
123
123
|
raise
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
def list_wt_processes(self) -> Dict[str, Any]:
|
|
126
126
|
"""List Windows Terminal processes on the remote machine."""
|
|
127
127
|
try:
|
|
128
128
|
# Get all WindowsTerminal.exe processes
|
|
129
129
|
ps_command = "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, CPU"
|
|
130
130
|
result = self.run_command(ps_command, timeout=15)
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
if result.returncode == 0:
|
|
133
133
|
return {
|
|
134
134
|
"success": True,
|
|
@@ -148,7 +148,7 @@ class WTRemoteExecutor:
|
|
|
148
148
|
"error": str(e),
|
|
149
149
|
"remote": self.remote_name
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
def kill_wt_processes(self, process_ids: Optional[List[Any]] = None) -> Dict[str, Any]:
|
|
153
153
|
"""Kill Windows Terminal processes on the remote machine."""
|
|
154
154
|
try:
|
|
@@ -158,9 +158,9 @@ class WTRemoteExecutor:
|
|
|
158
158
|
else:
|
|
159
159
|
# Kill all Windows Terminal processes
|
|
160
160
|
kill_cmd = "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Stop-Process -Force"
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
result = self.run_command(kill_cmd, timeout=10)
|
|
163
|
-
|
|
163
|
+
|
|
164
164
|
return {
|
|
165
165
|
"success": result.returncode == 0,
|
|
166
166
|
"message": "Processes killed" if result.returncode == 0 else result.stderr,
|
|
@@ -172,4 +172,4 @@ class WTRemoteExecutor:
|
|
|
172
172
|
"success": False,
|
|
173
173
|
"error": str(e),
|
|
174
174
|
"remote": self.remote_name
|
|
175
|
-
}
|
|
175
|
+
}
|
|
@@ -13,19 +13,19 @@ logger = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
class WTSessionManager:
|
|
15
15
|
"""Handles Windows Terminal session operations on local and remote machines."""
|
|
16
|
-
|
|
17
|
-
def __init__(self, remote_executor: Optional[WTRemoteExecutor] = None,
|
|
16
|
+
|
|
17
|
+
def __init__(self, remote_executor: Optional[WTRemoteExecutor] = None,
|
|
18
18
|
session_name: str = "default", tmp_layout_dir: Path | None = None):
|
|
19
19
|
self.remote_executor = remote_executor
|
|
20
20
|
self.session_name = session_name
|
|
21
21
|
self.tmp_layout_dir = tmp_layout_dir or Path.home() / "tmp_results" / "wt_layouts" / "layout_manager"
|
|
22
22
|
self.is_local = remote_executor is None
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
@property
|
|
25
25
|
def location_name(self) -> str:
|
|
26
26
|
"""Get the location name for status reporting."""
|
|
27
27
|
return "local" if self.is_local else (self.remote_executor.remote_name if self.remote_executor else "unknown")
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def _run_command(self, command: str, timeout: int = 30) -> subprocess.CompletedProcess[str]:
|
|
30
30
|
"""Run command either locally or remotely."""
|
|
31
31
|
if self.is_local:
|
|
@@ -39,31 +39,31 @@ class WTSessionManager:
|
|
|
39
39
|
if self.remote_executor is None:
|
|
40
40
|
raise ValueError("Remote executor is None but is_local is False")
|
|
41
41
|
return self.remote_executor.run_command(command, timeout)
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def copy_script_to_remote(self, local_script_file: Path, random_suffix: str) -> str:
|
|
44
44
|
"""Copy the script file to the remote machine and return the remote path."""
|
|
45
45
|
if self.is_local:
|
|
46
46
|
# For local operations, just return the local path
|
|
47
47
|
return str(local_script_file)
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
if self.remote_executor is None:
|
|
50
50
|
raise ValueError("Remote executor is None but operation requires remote access")
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
remote_layout_dir = f"~/{self.tmp_layout_dir.relative_to(Path.home())}"
|
|
53
53
|
remote_script_file = f"{remote_layout_dir}/wt_script_{self.session_name}_{random_suffix}.ps1"
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
# Create remote directory
|
|
56
56
|
if not self.remote_executor.create_remote_directory(remote_layout_dir):
|
|
57
57
|
raise RuntimeError(f"Failed to create remote directory: {remote_layout_dir}")
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
# Copy script file to remote machine
|
|
60
60
|
copy_result = self.remote_executor.copy_file_to_remote(str(local_script_file), remote_script_file)
|
|
61
61
|
if not copy_result["success"]:
|
|
62
62
|
raise RuntimeError(f"Failed to copy script file to remote: {copy_result['error']}")
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
logger.info(f"Windows Terminal script file copied to remote: {self.remote_executor.remote_name}:{remote_script_file}")
|
|
65
65
|
return remote_script_file
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
def check_wt_session_status(self) -> Dict[str, Any]:
|
|
68
68
|
"""Check if Windows Terminal windows exist and are running."""
|
|
69
69
|
try:
|
|
@@ -74,7 +74,7 @@ Select-Object Id, ProcessName, StartTime, MainWindowTitle |
|
|
|
74
74
|
ConvertTo-Json -Depth 2
|
|
75
75
|
"""
|
|
76
76
|
result = self._run_command(wt_check_cmd, timeout=10)
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
if result.returncode == 0:
|
|
79
79
|
output = result.stdout.strip()
|
|
80
80
|
if output and output != "":
|
|
@@ -83,14 +83,14 @@ ConvertTo-Json -Depth 2
|
|
|
83
83
|
processes = json.loads(output)
|
|
84
84
|
if not isinstance(processes, list):
|
|
85
85
|
processes = [processes]
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
# Look for windows that might belong to our session
|
|
88
88
|
session_windows = []
|
|
89
89
|
for proc in processes:
|
|
90
90
|
window_title = proc.get("MainWindowTitle", "")
|
|
91
91
|
if self.session_name in window_title or not window_title:
|
|
92
92
|
session_windows.append(proc)
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
return {
|
|
95
95
|
"wt_running": True,
|
|
96
96
|
"session_exists": len(session_windows) > 0,
|
|
@@ -123,7 +123,7 @@ ConvertTo-Json -Depth 2
|
|
|
123
123
|
"session_name": self.session_name,
|
|
124
124
|
"location": self.location_name
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
except Exception as e:
|
|
128
128
|
return {
|
|
129
129
|
"wt_running": False,
|
|
@@ -131,8 +131,8 @@ ConvertTo-Json -Depth 2
|
|
|
131
131
|
"session_name": self.session_name,
|
|
132
132
|
"location": self.location_name
|
|
133
133
|
}
|
|
134
|
-
|
|
135
|
-
def start_wt_session(self, script_file_path: Optional[str] = None,
|
|
134
|
+
|
|
135
|
+
def start_wt_session(self, script_file_path: Optional[str] = None,
|
|
136
136
|
wt_command: Optional[str] = None) -> Dict[str, Any]:
|
|
137
137
|
"""Start a Windows Terminal session with the generated layout."""
|
|
138
138
|
try:
|
|
@@ -143,25 +143,25 @@ ConvertTo-Json -Depth 2
|
|
|
143
143
|
else:
|
|
144
144
|
script_filename = Path(script_file_path).name
|
|
145
145
|
script_path = f"~/{self.tmp_layout_dir.relative_to(Path.home())}/{script_filename}"
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
logger.info(f"Starting Windows Terminal session '{self.session_name}' with script: {script_path}")
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
# Execute the PowerShell script
|
|
150
150
|
if self.is_local:
|
|
151
151
|
start_cmd = f"& '{script_path}'"
|
|
152
152
|
else:
|
|
153
153
|
start_cmd = f"powershell -ExecutionPolicy Bypass -File '{script_path}'"
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
elif wt_command:
|
|
156
156
|
# Execute the wt command directly
|
|
157
157
|
logger.info(f"Starting Windows Terminal session '{self.session_name}' with command: {wt_command}")
|
|
158
158
|
start_cmd = wt_command
|
|
159
159
|
else:
|
|
160
160
|
raise ValueError("Either script_file_path or wt_command must be provided.")
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
logger.info(f"Executing command: {start_cmd}")
|
|
163
163
|
result = self._run_command(start_cmd, timeout=30)
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
if result.returncode == 0:
|
|
166
166
|
logger.info(f"Windows Terminal session '{self.session_name}' started successfully")
|
|
167
167
|
return {
|
|
@@ -177,7 +177,7 @@ ConvertTo-Json -Depth 2
|
|
|
177
177
|
"session_name": self.session_name,
|
|
178
178
|
"location": self.location_name
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
except Exception as e:
|
|
182
182
|
error_location = "locally" if self.is_local else f"on {self.remote_executor.remote_name if self.remote_executor else 'unknown'}"
|
|
183
183
|
logger.error(f"Failed to start Windows Terminal session {error_location}: {e}")
|
|
@@ -187,7 +187,7 @@ ConvertTo-Json -Depth 2
|
|
|
187
187
|
"session_name": self.session_name,
|
|
188
188
|
"location": self.location_name
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
def attach_to_session(self, window_name: Optional[str] = None) -> None:
|
|
192
192
|
"""Attach to a Windows Terminal session/window."""
|
|
193
193
|
try:
|
|
@@ -197,24 +197,24 @@ ConvertTo-Json -Depth 2
|
|
|
197
197
|
attach_cmd = f"wt -w {window_name}"
|
|
198
198
|
else:
|
|
199
199
|
attach_cmd = f"wt -w {self.session_name}"
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
logger.info(f"Attaching to local Windows Terminal window '{window_name or self.session_name}'")
|
|
202
202
|
subprocess.run(attach_cmd, shell=True)
|
|
203
203
|
else:
|
|
204
204
|
# For remote sessions, use SSH with interactive terminal
|
|
205
205
|
if self.remote_executor is None:
|
|
206
206
|
raise ValueError("Remote executor is None but operation requires remote access")
|
|
207
|
-
|
|
207
|
+
|
|
208
208
|
if window_name:
|
|
209
209
|
attach_cmd = f"wt -w {window_name}"
|
|
210
210
|
else:
|
|
211
211
|
attach_cmd = f"wt -w {self.session_name}"
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
self.remote_executor.start_wt_session_interactive(attach_cmd)
|
|
214
214
|
except Exception as e:
|
|
215
215
|
logger.error(f"Failed to attach to Windows Terminal session: {e}")
|
|
216
216
|
raise
|
|
217
|
-
|
|
217
|
+
|
|
218
218
|
def kill_wt_session(self, force: bool = True) -> Dict[str, Any]:
|
|
219
219
|
"""Kill Windows Terminal processes related to this session."""
|
|
220
220
|
try:
|
|
@@ -224,17 +224,17 @@ ConvertTo-Json -Depth 2
|
|
|
224
224
|
else:
|
|
225
225
|
# Try to gracefully close windows (this is harder to target specific windows)
|
|
226
226
|
kill_cmd = "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | ForEach-Object { $_.CloseMainWindow() }"
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
logger.info(f"Killing Windows Terminal session '{self.session_name}'")
|
|
229
229
|
result = self._run_command(kill_cmd, timeout=10)
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
return {
|
|
232
232
|
"success": result.returncode == 0,
|
|
233
233
|
"message": "Session killed" if result.returncode == 0 else result.stderr,
|
|
234
234
|
"session_name": self.session_name,
|
|
235
235
|
"location": self.location_name
|
|
236
236
|
}
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
except Exception as e:
|
|
239
239
|
logger.error(f"Failed to kill Windows Terminal session: {e}")
|
|
240
240
|
return {
|
|
@@ -243,27 +243,27 @@ ConvertTo-Json -Depth 2
|
|
|
243
243
|
"session_name": self.session_name,
|
|
244
244
|
"location": self.location_name
|
|
245
245
|
}
|
|
246
|
-
|
|
247
|
-
def create_new_tab(self, tab_name: str, cwd: str, command: str,
|
|
246
|
+
|
|
247
|
+
def create_new_tab(self, tab_name: str, cwd: str, command: str,
|
|
248
248
|
window_name: Optional[str] = None) -> Dict[str, Any]:
|
|
249
249
|
"""Create a new tab in the Windows Terminal session."""
|
|
250
250
|
try:
|
|
251
251
|
# Build the new-tab command
|
|
252
252
|
tab_cmd_parts = ["wt"]
|
|
253
|
-
|
|
253
|
+
|
|
254
254
|
if window_name:
|
|
255
255
|
tab_cmd_parts.extend(["-w", f'"{window_name}"'])
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
tab_cmd_parts.append("new-tab")
|
|
258
258
|
tab_cmd_parts.extend(["-d", f'"{cwd}"'])
|
|
259
259
|
tab_cmd_parts.extend(["--title", f'"{tab_name}"'])
|
|
260
260
|
tab_cmd_parts.append(f'"{command}"')
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
new_tab_cmd = " ".join(tab_cmd_parts)
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
logger.info(f"Creating new tab '{tab_name}' in Windows Terminal")
|
|
265
265
|
result = self._run_command(new_tab_cmd, timeout=15)
|
|
266
|
-
|
|
266
|
+
|
|
267
267
|
return {
|
|
268
268
|
"success": result.returncode == 0,
|
|
269
269
|
"message": f"Tab '{tab_name}' created" if result.returncode == 0 else result.stderr,
|
|
@@ -271,7 +271,7 @@ ConvertTo-Json -Depth 2
|
|
|
271
271
|
"command": command,
|
|
272
272
|
"location": self.location_name
|
|
273
273
|
}
|
|
274
|
-
|
|
274
|
+
|
|
275
275
|
except Exception as e:
|
|
276
276
|
logger.error(f"Failed to create new tab '{tab_name}': {e}")
|
|
277
277
|
return {
|
|
@@ -280,13 +280,13 @@ ConvertTo-Json -Depth 2
|
|
|
280
280
|
"tab_name": tab_name,
|
|
281
281
|
"location": self.location_name
|
|
282
282
|
}
|
|
283
|
-
|
|
283
|
+
|
|
284
284
|
def get_wt_version(self) -> Dict[str, Any]:
|
|
285
285
|
"""Get Windows Terminal version information."""
|
|
286
286
|
try:
|
|
287
287
|
version_cmd = "wt --version"
|
|
288
288
|
result = self._run_command(version_cmd, timeout=10)
|
|
289
|
-
|
|
289
|
+
|
|
290
290
|
return {
|
|
291
291
|
"success": result.returncode == 0,
|
|
292
292
|
"version": result.stdout.strip() if result.returncode == 0 else "Unknown",
|
|
@@ -297,4 +297,4 @@ ConvertTo-Json -Depth 2
|
|
|
297
297
|
"success": False,
|
|
298
298
|
"error": str(e),
|
|
299
299
|
"location": self.location_name
|
|
300
|
-
}
|
|
300
|
+
}
|
|
@@ -12,19 +12,19 @@ logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
class WTStatusReporter:
|
|
14
14
|
"""Handles comprehensive status reporting for Windows Terminal sessions."""
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def __init__(self, process_monitor: WTProcessMonitor, session_manager: WTSessionManager):
|
|
17
17
|
self.process_monitor = process_monitor
|
|
18
18
|
self.session_manager = session_manager
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def get_comprehensive_status(self, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
21
21
|
"""Get comprehensive status including Windows Terminal session and all commands."""
|
|
22
22
|
wt_status = self.session_manager.check_wt_session_status()
|
|
23
23
|
commands_status = self.process_monitor.check_all_commands_status(tab_config)
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
running_count = sum(1 for status in commands_status.values() if status.get("running", False))
|
|
26
26
|
total_count = len(commands_status)
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
return {
|
|
29
29
|
"wt_session": wt_status,
|
|
30
30
|
"commands": commands_status,
|
|
@@ -36,23 +36,23 @@ class WTStatusReporter:
|
|
|
36
36
|
"location": wt_status.get("location", "unknown")
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
def print_status_report(self, tab_config: Dict[str, Tuple[str, str]]) -> None:
|
|
41
41
|
"""Print a comprehensive status report for the Windows Terminal session."""
|
|
42
42
|
status = self.get_comprehensive_status(tab_config)
|
|
43
43
|
wt_session = status["wt_session"]
|
|
44
44
|
commands = status["commands"]
|
|
45
45
|
summary = status["summary"]
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
print("=" * 80)
|
|
48
48
|
print("🖥️ WINDOWS TERMINAL STATUS REPORT")
|
|
49
49
|
print("=" * 80)
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
# Session status
|
|
52
52
|
location = wt_session.get("location", "unknown")
|
|
53
53
|
print(f"📍 Location: {location}")
|
|
54
54
|
print(f"🪟 Session: {self.session_manager.session_name}")
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
if wt_session.get("wt_running", False):
|
|
57
57
|
if wt_session.get("session_exists", False):
|
|
58
58
|
session_windows = wt_session.get("session_windows", [])
|
|
@@ -65,53 +65,53 @@ class WTStatusReporter:
|
|
|
65
65
|
else:
|
|
66
66
|
error_msg = wt_session.get("error", "Unknown error")
|
|
67
67
|
print(f"❌ Windows Terminal session issue: {error_msg}")
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
print()
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
# Commands status
|
|
72
72
|
print(f"📋 COMMANDS STATUS ({summary['running_commands']}/{summary['total_commands']} running):")
|
|
73
73
|
print("-" * 60)
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
for tab_name, cmd_status in commands.items():
|
|
76
76
|
status_icon = "✅" if cmd_status.get("running", False) else "❌"
|
|
77
77
|
cmd_text = cmd_status.get("command", "Unknown")[:50]
|
|
78
78
|
if len(cmd_status.get("command", "")) > 50:
|
|
79
79
|
cmd_text += "..."
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
print(f" {status_icon} {tab_name}")
|
|
82
82
|
print(f" Command: {cmd_text}")
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
if cmd_status.get("processes"):
|
|
85
85
|
processes = cmd_status["processes"][:3] # Show first 3 processes
|
|
86
86
|
for proc in processes:
|
|
87
87
|
pid = proc.get("pid", "Unknown")
|
|
88
88
|
name = proc.get("name", "Unknown")
|
|
89
89
|
print(f" └─ PID {pid}: {name}")
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
if len(cmd_status["processes"]) > 3:
|
|
92
92
|
remaining = len(cmd_status["processes"]) - 3
|
|
93
93
|
print(f" └─ ... and {remaining} more processes")
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
if cmd_status.get("error"):
|
|
96
96
|
print(f" Error: {cmd_status['error']}")
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
print()
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
# Summary
|
|
101
101
|
print("📊 SUMMARY:")
|
|
102
102
|
print(f" Total commands: {summary['total_commands']}")
|
|
103
103
|
print(f" Running: {summary['running_commands']}")
|
|
104
104
|
print(f" Stopped: {summary['stopped_commands']}")
|
|
105
105
|
print(f" Session healthy: {'✅' if summary['session_healthy'] else '❌'}")
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
print("=" * 80)
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
def get_windows_terminal_overview(self) -> Dict[str, Any]:
|
|
110
110
|
"""Get an overview of all Windows Terminal windows and processes."""
|
|
111
111
|
try:
|
|
112
112
|
wt_windows = self.process_monitor.get_windows_terminal_windows()
|
|
113
113
|
wt_version = self.session_manager.get_wt_version()
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
return {
|
|
116
116
|
"success": True,
|
|
117
117
|
"windows_info": wt_windows,
|
|
@@ -125,32 +125,32 @@ class WTStatusReporter:
|
|
|
125
125
|
"error": str(e),
|
|
126
126
|
"location": self.process_monitor.location_name
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
def print_windows_terminal_overview(self) -> None:
|
|
130
130
|
"""Print an overview of Windows Terminal status."""
|
|
131
131
|
overview = self.get_windows_terminal_overview()
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
print("=" * 80)
|
|
134
134
|
print("🖥️ WINDOWS TERMINAL OVERVIEW")
|
|
135
135
|
print("=" * 80)
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
if overview["success"]:
|
|
138
138
|
location = overview.get("location", "unknown")
|
|
139
139
|
print(f"📍 Location: {location}")
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
# Version info
|
|
142
142
|
version_info = overview.get("version_info", {})
|
|
143
143
|
if version_info.get("success"):
|
|
144
144
|
print(f"📦 Version: {version_info.get('version', 'Unknown')}")
|
|
145
145
|
else:
|
|
146
146
|
print(f"📦 Version: Error getting version - {version_info.get('error', 'Unknown')}")
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
# Windows info
|
|
149
149
|
windows_info = overview.get("windows_info", {})
|
|
150
150
|
if windows_info.get("success"):
|
|
151
151
|
windows = windows_info.get("windows", [])
|
|
152
152
|
print(f"🪟 Active Windows: {len(windows)}")
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
if windows:
|
|
155
155
|
print("\nActive Windows:")
|
|
156
156
|
for i, window in enumerate(windows[:5], 1): # Show first 5 windows
|
|
@@ -158,7 +158,7 @@ class WTStatusReporter:
|
|
|
158
158
|
title = window.get("WindowTitle", "No Title")
|
|
159
159
|
start_time = window.get("StartTime", "Unknown")
|
|
160
160
|
print(f" {i}. PID {pid}: {title} (Started: {start_time})")
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
if len(windows) > 5:
|
|
163
163
|
print(f" ... and {len(windows) - 5} more windows")
|
|
164
164
|
else:
|
|
@@ -167,18 +167,18 @@ class WTStatusReporter:
|
|
|
167
167
|
print(f"🪟 Windows Info: Error - {windows_info.get('error', 'Unknown')}")
|
|
168
168
|
else:
|
|
169
169
|
print(f"❌ Failed to get overview: {overview.get('error', 'Unknown')}")
|
|
170
|
-
|
|
170
|
+
|
|
171
171
|
print("=" * 80)
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
def generate_status_summary(self, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
174
174
|
"""Generate a concise status summary suitable for monitoring."""
|
|
175
175
|
try:
|
|
176
176
|
comprehensive_status = self.get_comprehensive_status(tab_config)
|
|
177
177
|
wt_overview = self.get_windows_terminal_overview()
|
|
178
|
-
|
|
178
|
+
|
|
179
179
|
summary = comprehensive_status["summary"]
|
|
180
180
|
wt_status = comprehensive_status["wt_session"]
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
return {
|
|
183
183
|
"timestamp": None, # Will be filled by caller if needed
|
|
184
184
|
"session_name": self.session_manager.session_name,
|
|
@@ -199,7 +199,7 @@ class WTStatusReporter:
|
|
|
199
199
|
"session_name": self.session_manager.session_name,
|
|
200
200
|
"location": self.process_monitor.location_name
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
def check_tab_specific_status(self, tab_name: str, tab_config: Dict[str, Tuple[str, str]]) -> Dict[str, Any]:
|
|
204
204
|
"""Get detailed status for a specific tab."""
|
|
205
205
|
if tab_name not in tab_config:
|
|
@@ -207,17 +207,17 @@ class WTStatusReporter:
|
|
|
207
207
|
"error": f"Tab '{tab_name}' not found in configuration",
|
|
208
208
|
"tab_name": tab_name
|
|
209
209
|
}
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
try:
|
|
212
212
|
cmd_status = self.process_monitor.check_command_status(tab_name, tab_config)
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
# Add additional context
|
|
215
215
|
cwd, command = tab_config[tab_name]
|
|
216
216
|
cmd_status["tab_config"] = {
|
|
217
217
|
"working_directory": cwd,
|
|
218
218
|
"command": command
|
|
219
219
|
}
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
return cmd_status
|
|
222
222
|
except Exception as e:
|
|
223
223
|
logger.error(f"Failed to check status for tab '{tab_name}': {e}")
|
|
@@ -225,4 +225,4 @@ class WTStatusReporter:
|
|
|
225
225
|
"error": str(e),
|
|
226
226
|
"tab_name": tab_name,
|
|
227
227
|
"location": self.process_monitor.location_name
|
|
228
|
-
}
|
|
228
|
+
}
|