machineconfig 1.96__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.

Files changed (164) hide show
  1. machineconfig/cluster/cloud_manager.py +22 -26
  2. machineconfig/cluster/data_transfer.py +2 -2
  3. machineconfig/cluster/distribute.py +0 -2
  4. machineconfig/cluster/file_manager.py +4 -4
  5. machineconfig/cluster/job_params.py +1 -1
  6. machineconfig/cluster/loader_runner.py +8 -8
  7. machineconfig/cluster/remote_machine.py +4 -4
  8. machineconfig/cluster/script_execution.py +2 -2
  9. machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +1 -1
  10. machineconfig/cluster/sessions_managers/enhanced_command_runner.py +23 -23
  11. machineconfig/cluster/sessions_managers/wt_local.py +78 -76
  12. machineconfig/cluster/sessions_managers/wt_local_manager.py +91 -91
  13. machineconfig/cluster/sessions_managers/wt_remote.py +39 -39
  14. machineconfig/cluster/sessions_managers/wt_remote_manager.py +94 -91
  15. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +56 -54
  16. machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +49 -49
  17. machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +18 -18
  18. machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +42 -42
  19. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +36 -36
  20. machineconfig/cluster/sessions_managers/zellij_local.py +43 -46
  21. machineconfig/cluster/sessions_managers/zellij_local_manager.py +139 -120
  22. machineconfig/cluster/sessions_managers/zellij_remote.py +35 -35
  23. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +33 -33
  24. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +15 -15
  25. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +25 -26
  26. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +49 -49
  27. machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +5 -5
  28. machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +15 -15
  29. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +11 -11
  30. machineconfig/cluster/templates/utils.py +3 -3
  31. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  32. machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
  33. machineconfig/jobs/python/__pycache__/python_ve_symlink.cpython-311.pyc +0 -0
  34. machineconfig/jobs/python/check_installations.py +8 -9
  35. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  36. machineconfig/jobs/python/vscode/link_ve.py +7 -7
  37. machineconfig/jobs/python/vscode/select_interpreter.py +7 -7
  38. machineconfig/jobs/python/vscode/sync_code.py +5 -5
  39. machineconfig/jobs/python_custom_installers/archive/ngrok.py +2 -2
  40. machineconfig/jobs/python_custom_installers/dev/aider.py +3 -3
  41. machineconfig/jobs/python_custom_installers/dev/alacritty.py +3 -3
  42. machineconfig/jobs/python_custom_installers/dev/brave.py +3 -3
  43. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +5 -5
  44. machineconfig/jobs/python_custom_installers/dev/code.py +3 -3
  45. machineconfig/jobs/python_custom_installers/dev/cursor.py +9 -9
  46. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +4 -4
  47. machineconfig/jobs/python_custom_installers/dev/espanso.py +4 -4
  48. machineconfig/jobs/python_custom_installers/dev/goes.py +4 -4
  49. machineconfig/jobs/python_custom_installers/dev/lvim.py +4 -4
  50. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +3 -3
  51. machineconfig/jobs/python_custom_installers/dev/redis.py +3 -3
  52. machineconfig/jobs/python_custom_installers/dev/wezterm.py +3 -3
  53. machineconfig/jobs/python_custom_installers/dev/winget.py +27 -27
  54. machineconfig/jobs/python_custom_installers/docker.py +3 -3
  55. machineconfig/jobs/python_custom_installers/gh.py +7 -7
  56. machineconfig/jobs/python_custom_installers/hx.py +1 -1
  57. machineconfig/jobs/python_custom_installers/warp-cli.py +3 -3
  58. machineconfig/jobs/python_generic_installers/config.json +412 -389
  59. machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
  60. machineconfig/logger.py +50 -0
  61. machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
  62. machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
  63. machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
  64. machineconfig/profile/create.py +23 -16
  65. machineconfig/profile/create_hardlinks.py +8 -8
  66. machineconfig/profile/shell.py +41 -37
  67. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  68. machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  69. machineconfig/scripts/linux/devops +2 -2
  70. machineconfig/scripts/linux/fire +1 -0
  71. machineconfig/scripts/linux/fire_agents +0 -1
  72. machineconfig/scripts/linux/mcinit +27 -0
  73. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  74. machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
  75. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  76. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  77. machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
  78. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  79. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
  80. machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
  81. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  82. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  83. machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
  84. machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-311.pyc +0 -0
  85. machineconfig/scripts/python/ai/chatmodes/Thinking-Beast-Mode.chatmode.md +337 -0
  86. machineconfig/scripts/python/ai/chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +644 -0
  87. machineconfig/scripts/python/ai/chatmodes/deepResearch.chatmode.md +81 -0
  88. machineconfig/scripts/python/ai/configs/.gemini/settings.json +81 -0
  89. machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +45 -0
  90. machineconfig/scripts/python/ai/mcinit.py +103 -0
  91. machineconfig/scripts/python/ai/prompts/allLintersAndTypeCheckers.prompt.md +5 -0
  92. machineconfig/scripts/python/ai/prompts/research-report-skeleton.prompt.md +38 -0
  93. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +47 -0
  94. machineconfig/scripts/python/archive/tmate_conn.py +5 -5
  95. machineconfig/scripts/python/archive/tmate_start.py +3 -3
  96. machineconfig/scripts/python/choose_wezterm_theme.py +2 -2
  97. machineconfig/scripts/python/cloud_copy.py +19 -18
  98. machineconfig/scripts/python/cloud_mount.py +9 -7
  99. machineconfig/scripts/python/cloud_repo_sync.py +11 -11
  100. machineconfig/scripts/python/cloud_sync.py +1 -1
  101. machineconfig/scripts/python/croshell.py +14 -14
  102. machineconfig/scripts/python/devops.py +6 -6
  103. machineconfig/scripts/python/devops_add_identity.py +8 -6
  104. machineconfig/scripts/python/devops_add_ssh_key.py +18 -18
  105. machineconfig/scripts/python/devops_backup_retrieve.py +13 -13
  106. machineconfig/scripts/python/devops_devapps_install.py +3 -3
  107. machineconfig/scripts/python/devops_update_repos.py +1 -1
  108. machineconfig/scripts/python/dotfile.py +2 -2
  109. machineconfig/scripts/python/fire_agents.py +183 -41
  110. machineconfig/scripts/python/fire_jobs.py +17 -11
  111. machineconfig/scripts/python/ftpx.py +2 -2
  112. machineconfig/scripts/python/gh_models.py +94 -94
  113. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  114. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  115. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  116. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  117. machineconfig/scripts/python/helpers/cloud_helpers.py +3 -3
  118. machineconfig/scripts/python/helpers/helpers2.py +1 -1
  119. machineconfig/scripts/python/helpers/helpers4.py +8 -6
  120. machineconfig/scripts/python/helpers/helpers5.py +7 -7
  121. machineconfig/scripts/python/helpers/repo_sync_helpers.py +1 -1
  122. machineconfig/scripts/python/mount_nfs.py +3 -2
  123. machineconfig/scripts/python/mount_nw_drive.py +4 -4
  124. machineconfig/scripts/python/mount_ssh.py +3 -2
  125. machineconfig/scripts/python/repos.py +8 -8
  126. machineconfig/scripts/python/scheduler.py +1 -1
  127. machineconfig/scripts/python/start_slidev.py +8 -7
  128. machineconfig/scripts/python/start_terminals.py +1 -1
  129. machineconfig/scripts/python/viewer.py +40 -40
  130. machineconfig/scripts/python/wifi_conn.py +65 -66
  131. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  132. machineconfig/scripts/windows/mcinit.ps1 +4 -0
  133. machineconfig/settings/linters/.ruff.toml +2 -2
  134. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
  135. machineconfig/settings/shells/wt/settings.json +8 -8
  136. machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
  137. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +10 -7
  138. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +9 -7
  139. machineconfig/utils/ai/browser_user_wrapper.py +5 -5
  140. machineconfig/utils/ai/generate_file_checklist.py +11 -12
  141. machineconfig/utils/ai/url2md.py +1 -1
  142. machineconfig/utils/cloud/onedrive/setup_oauth.py +4 -4
  143. machineconfig/utils/cloud/onedrive/transaction.py +129 -129
  144. machineconfig/utils/code.py +13 -6
  145. machineconfig/utils/installer.py +51 -53
  146. machineconfig/utils/installer_utils/installer_abc.py +21 -10
  147. machineconfig/utils/installer_utils/installer_class.py +42 -16
  148. machineconfig/utils/io_save.py +3 -15
  149. machineconfig/utils/options.py +10 -3
  150. machineconfig/utils/path.py +5 -0
  151. machineconfig/utils/path_reduced.py +201 -149
  152. machineconfig/utils/procs.py +23 -23
  153. machineconfig/utils/scheduling.py +11 -12
  154. machineconfig/utils/ssh.py +270 -0
  155. machineconfig/utils/terminal.py +180 -0
  156. machineconfig/utils/utils.py +1 -2
  157. machineconfig/utils/utils2.py +43 -0
  158. machineconfig/utils/utils5.py +163 -34
  159. machineconfig/utils/ve.py +2 -2
  160. {machineconfig-1.96.dist-info → machineconfig-2.0.dist-info}/METADATA +13 -8
  161. {machineconfig-1.96.dist-info → machineconfig-2.0.dist-info}/RECORD +163 -144
  162. machineconfig/cluster/self_ssh.py +0 -57
  163. {machineconfig-1.96.dist-info → machineconfig-2.0.dist-info}/WHEEL +0 -0
  164. {machineconfig-1.96.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
+ }