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.

Files changed (268) hide show
  1. machineconfig/cluster/cloud_manager.py +22 -29
  2. machineconfig/cluster/data_transfer.py +2 -3
  3. machineconfig/cluster/distribute.py +0 -2
  4. machineconfig/cluster/file_manager.py +4 -5
  5. machineconfig/cluster/job_params.py +1 -4
  6. machineconfig/cluster/loader_runner.py +8 -11
  7. machineconfig/cluster/remote_machine.py +4 -5
  8. machineconfig/cluster/script_execution.py +2 -2
  9. machineconfig/cluster/script_notify_upon_completion.py +0 -1
  10. machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +4 -6
  11. machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -1
  12. machineconfig/cluster/sessions_managers/enhanced_command_runner.py +35 -75
  13. machineconfig/cluster/sessions_managers/wt_local.py +113 -185
  14. machineconfig/cluster/sessions_managers/wt_local_manager.py +127 -197
  15. machineconfig/cluster/sessions_managers/wt_remote.py +60 -67
  16. machineconfig/cluster/sessions_managers/wt_remote_manager.py +110 -149
  17. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +61 -64
  18. machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +72 -172
  19. machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +27 -60
  20. machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +58 -137
  21. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +46 -74
  22. machineconfig/cluster/sessions_managers/zellij_local.py +91 -147
  23. machineconfig/cluster/sessions_managers/zellij_local_manager.py +165 -190
  24. machineconfig/cluster/sessions_managers/zellij_remote.py +51 -58
  25. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +40 -46
  26. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +19 -17
  27. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +30 -31
  28. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +64 -134
  29. machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +7 -11
  30. machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +27 -55
  31. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +14 -13
  32. machineconfig/cluster/templates/cli_click.py +0 -1
  33. machineconfig/cluster/templates/cli_gooey.py +0 -2
  34. machineconfig/cluster/templates/cli_trogon.py +0 -1
  35. machineconfig/cluster/templates/run_cloud.py +0 -1
  36. machineconfig/cluster/templates/run_cluster.py +0 -1
  37. machineconfig/cluster/templates/run_remote.py +0 -1
  38. machineconfig/cluster/templates/utils.py +27 -11
  39. machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
  40. machineconfig/jobs/linux/msc/cli_agents.sh +16 -0
  41. machineconfig/jobs/python/check_installations.py +9 -9
  42. machineconfig/jobs/python/create_bootable_media.py +0 -2
  43. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  44. machineconfig/jobs/python/python_ve_symlink.py +9 -11
  45. machineconfig/jobs/python/tasks.py +0 -1
  46. machineconfig/jobs/python/vscode/api.py +5 -5
  47. machineconfig/jobs/python/vscode/link_ve.py +20 -21
  48. machineconfig/jobs/python/vscode/select_interpreter.py +28 -29
  49. machineconfig/jobs/python/vscode/sync_code.py +14 -18
  50. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  51. machineconfig/jobs/python_custom_installers/archive/ngrok.py +15 -15
  52. machineconfig/jobs/python_custom_installers/dev/aider.py +10 -18
  53. machineconfig/jobs/python_custom_installers/dev/alacritty.py +12 -21
  54. machineconfig/jobs/python_custom_installers/dev/brave.py +13 -22
  55. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +13 -20
  56. machineconfig/jobs/python_custom_installers/dev/code.py +17 -24
  57. machineconfig/jobs/python_custom_installers/dev/cursor.py +10 -21
  58. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +12 -11
  59. machineconfig/jobs/python_custom_installers/dev/espanso.py +19 -23
  60. machineconfig/jobs/python_custom_installers/dev/goes.py +9 -16
  61. machineconfig/jobs/python_custom_installers/dev/lvim.py +13 -21
  62. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +15 -22
  63. machineconfig/jobs/python_custom_installers/dev/redis.py +15 -23
  64. machineconfig/jobs/python_custom_installers/dev/wezterm.py +15 -22
  65. machineconfig/jobs/python_custom_installers/dev/winget.py +32 -50
  66. machineconfig/jobs/python_custom_installers/docker.py +15 -24
  67. machineconfig/jobs/python_custom_installers/gh.py +18 -26
  68. machineconfig/jobs/python_custom_installers/hx.py +33 -17
  69. machineconfig/jobs/python_custom_installers/warp-cli.py +15 -23
  70. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  71. machineconfig/jobs/python_generic_installers/config.json +412 -389
  72. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
  73. machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
  74. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -1
  75. machineconfig/jobs/windows/msc/cli_agents.bat +0 -0
  76. machineconfig/jobs/windows/msc/cli_agents.ps1 +0 -0
  77. machineconfig/jobs/windows/start_terminal.ps1 +1 -1
  78. machineconfig/logger.py +50 -0
  79. machineconfig/profile/create.py +50 -36
  80. machineconfig/profile/create_hardlinks.py +33 -26
  81. machineconfig/profile/shell.py +87 -60
  82. machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  83. machineconfig/scripts/cloud/init.sh +2 -2
  84. machineconfig/scripts/linux/checkout_versions +1 -1
  85. machineconfig/scripts/linux/choose_wezterm_theme +1 -1
  86. machineconfig/scripts/linux/cloud_copy +1 -1
  87. machineconfig/scripts/linux/cloud_manager +1 -1
  88. machineconfig/scripts/linux/cloud_mount +1 -1
  89. machineconfig/scripts/linux/cloud_repo_sync +1 -1
  90. machineconfig/scripts/linux/cloud_sync +1 -1
  91. machineconfig/scripts/linux/croshell +1 -1
  92. machineconfig/scripts/linux/devops +3 -5
  93. machineconfig/scripts/linux/fire +2 -1
  94. machineconfig/scripts/linux/fire_agents +3 -3
  95. machineconfig/scripts/linux/ftpx +1 -1
  96. machineconfig/scripts/linux/gh_models +1 -1
  97. machineconfig/scripts/linux/kill_process +1 -1
  98. machineconfig/scripts/linux/mcinit +2 -2
  99. machineconfig/scripts/linux/repos +1 -1
  100. machineconfig/scripts/linux/scheduler +1 -1
  101. machineconfig/scripts/linux/start_slidev +1 -1
  102. machineconfig/scripts/linux/start_terminals +1 -1
  103. machineconfig/scripts/linux/url2md +1 -1
  104. machineconfig/scripts/linux/warp-cli.sh +122 -0
  105. machineconfig/scripts/linux/wifi_conn +1 -1
  106. machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
  107. machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
  108. machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
  109. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
  110. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
  111. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
  112. machineconfig/scripts/python/ai/__init__.py +0 -0
  113. machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
  114. machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
  115. machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
  116. machineconfig/scripts/python/ai/chatmodes/Thinking-Beast-Mode.chatmode.md +337 -0
  117. machineconfig/scripts/python/ai/chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +644 -0
  118. machineconfig/scripts/python/ai/chatmodes/deepResearch.chatmode.md +81 -0
  119. machineconfig/scripts/python/ai/configs/.gemini/settings.json +81 -0
  120. machineconfig/scripts/python/ai/generate_files.py +84 -0
  121. machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +45 -0
  122. machineconfig/scripts/python/ai/mcinit.py +107 -0
  123. machineconfig/scripts/python/ai/prompts/allLintersAndTypeCheckers.prompt.md +5 -0
  124. machineconfig/scripts/python/ai/prompts/research-report-skeleton.prompt.md +38 -0
  125. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +52 -0
  126. machineconfig/scripts/python/archive/tmate_conn.py +5 -5
  127. machineconfig/scripts/python/archive/tmate_start.py +3 -3
  128. machineconfig/scripts/python/choose_wezterm_theme.py +2 -2
  129. machineconfig/scripts/python/cloud_copy.py +20 -19
  130. machineconfig/scripts/python/cloud_mount.py +10 -8
  131. machineconfig/scripts/python/cloud_repo_sync.py +15 -15
  132. machineconfig/scripts/python/cloud_sync.py +1 -1
  133. machineconfig/scripts/python/croshell.py +18 -16
  134. machineconfig/scripts/python/devops.py +6 -6
  135. machineconfig/scripts/python/devops_add_identity.py +9 -7
  136. machineconfig/scripts/python/devops_add_ssh_key.py +19 -19
  137. machineconfig/scripts/python/devops_backup_retrieve.py +14 -14
  138. machineconfig/scripts/python/devops_devapps_install.py +3 -3
  139. machineconfig/scripts/python/devops_update_repos.py +141 -53
  140. machineconfig/scripts/python/dotfile.py +3 -3
  141. machineconfig/scripts/python/fire_agents.py +202 -41
  142. machineconfig/scripts/python/fire_jobs.py +20 -21
  143. machineconfig/scripts/python/ftpx.py +4 -3
  144. machineconfig/scripts/python/gh_models.py +94 -94
  145. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
  146. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
  147. machineconfig/scripts/python/helpers/cloud_helpers.py +3 -3
  148. machineconfig/scripts/python/helpers/helpers2.py +3 -3
  149. machineconfig/scripts/python/helpers/helpers4.py +8 -7
  150. machineconfig/scripts/python/helpers/helpers5.py +7 -7
  151. machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
  152. machineconfig/scripts/python/mount_nfs.py +4 -3
  153. machineconfig/scripts/python/mount_nw_drive.py +4 -4
  154. machineconfig/scripts/python/mount_ssh.py +4 -3
  155. machineconfig/scripts/python/repos.py +9 -9
  156. machineconfig/scripts/python/scheduler.py +1 -1
  157. machineconfig/scripts/python/start_slidev.py +9 -8
  158. machineconfig/scripts/python/start_terminals.py +1 -1
  159. machineconfig/scripts/python/viewer.py +40 -40
  160. machineconfig/scripts/python/wifi_conn.py +65 -66
  161. machineconfig/scripts/python/wsl_windows_transfer.py +2 -2
  162. machineconfig/scripts/windows/checkout_version.ps1 +1 -3
  163. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +1 -3
  164. machineconfig/scripts/windows/cloud_copy.ps1 +2 -6
  165. machineconfig/scripts/windows/cloud_manager.ps1 +1 -1
  166. machineconfig/scripts/windows/cloud_repo_sync.ps1 +1 -2
  167. machineconfig/scripts/windows/cloud_sync.ps1 +2 -2
  168. machineconfig/scripts/windows/croshell.ps1 +2 -2
  169. machineconfig/scripts/windows/devops.ps1 +1 -4
  170. machineconfig/scripts/windows/dotfile.ps1 +1 -3
  171. machineconfig/scripts/windows/fire.ps1 +1 -1
  172. machineconfig/scripts/windows/ftpx.ps1 +2 -2
  173. machineconfig/scripts/windows/gpt.ps1 +1 -1
  174. machineconfig/scripts/windows/kill_process.ps1 +1 -2
  175. machineconfig/scripts/windows/mcinit.ps1 +2 -2
  176. machineconfig/scripts/windows/mount_nfs.ps1 +1 -1
  177. machineconfig/scripts/windows/mount_ssh.ps1 +1 -1
  178. machineconfig/scripts/windows/pomodoro.ps1 +1 -1
  179. machineconfig/scripts/windows/py2exe.ps1 +1 -3
  180. machineconfig/scripts/windows/repos.ps1 +1 -1
  181. machineconfig/scripts/windows/scheduler.ps1 +1 -1
  182. machineconfig/scripts/windows/snapshot.ps1 +2 -2
  183. machineconfig/scripts/windows/start_slidev.ps1 +1 -1
  184. machineconfig/scripts/windows/start_terminals.ps1 +1 -1
  185. machineconfig/scripts/windows/wifi_conn.ps1 +1 -1
  186. machineconfig/scripts/windows/wsl_windows_transfer.ps1 +1 -3
  187. machineconfig/settings/lf/linux/lfrc +1 -1
  188. machineconfig/settings/linters/.ruff.toml +2 -2
  189. machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
  190. machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
  191. machineconfig/settings/lvim/windows/archive/config_additional.lua +1 -1
  192. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
  193. machineconfig/settings/shells/wt/settings.json +8 -8
  194. machineconfig/settings/svim/linux/init.toml +1 -1
  195. machineconfig/settings/svim/windows/init.toml +1 -1
  196. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -54
  197. machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -6
  198. machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
  199. machineconfig/setup_windows/web_shortcuts/all.ps1 +2 -2
  200. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +1 -1
  201. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +1 -1
  202. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +5 -5
  203. machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +51 -15
  204. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +75 -18
  205. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +52 -42
  206. machineconfig/utils/ai/browser_user_wrapper.py +5 -5
  207. machineconfig/utils/ai/generate_file_checklist.py +19 -22
  208. machineconfig/utils/ai/url2md.py +5 -3
  209. machineconfig/utils/cloud/onedrive/setup_oauth.py +5 -4
  210. machineconfig/utils/cloud/onedrive/transaction.py +192 -227
  211. machineconfig/utils/code.py +71 -43
  212. machineconfig/utils/installer.py +77 -85
  213. machineconfig/utils/installer_utils/installer_abc.py +29 -17
  214. machineconfig/utils/installer_utils/installer_class.py +188 -83
  215. machineconfig/utils/io_save.py +3 -15
  216. machineconfig/utils/links.py +22 -11
  217. machineconfig/utils/notifications.py +197 -0
  218. machineconfig/utils/options.py +38 -25
  219. machineconfig/utils/path.py +18 -6
  220. machineconfig/utils/path_reduced.py +637 -316
  221. machineconfig/utils/procs.py +69 -63
  222. machineconfig/utils/scheduling.py +11 -13
  223. machineconfig/utils/ssh.py +351 -0
  224. machineconfig/utils/terminal.py +225 -0
  225. machineconfig/utils/utils.py +13 -12
  226. machineconfig/utils/utils2.py +43 -10
  227. machineconfig/utils/utils5.py +242 -46
  228. machineconfig/utils/ve.py +11 -6
  229. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/METADATA +15 -9
  230. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/RECORD +232 -235
  231. machineconfig/cluster/self_ssh.py +0 -57
  232. machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
  233. machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
  234. machineconfig/jobs/python/archive/python_tools.txt +0 -12
  235. machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
  236. machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  237. machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  238. machineconfig/jobs/python_generic_installers/update.py +0 -3
  239. machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
  240. machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
  241. machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
  242. machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
  243. machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  244. machineconfig/scripts/linux/activate_ve +0 -87
  245. machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
  246. machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
  247. machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
  248. machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
  249. machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
  250. machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
  251. machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
  252. machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
  253. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
  254. machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
  255. machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
  256. machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
  257. machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
  258. machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
  259. machineconfig/scripts/python/ai/init.py +0 -56
  260. machineconfig/scripts/python/ai/rules/python/dev.md +0 -31
  261. machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
  262. machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
  263. machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
  264. machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
  265. machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
  266. machineconfig/scripts/windows/activate_ve.ps1 +0 -54
  267. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/WHEEL +0 -0
  268. {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  Windows Terminal local layout generator and session manager.
4
4
  Equivalent to zellij_local.py but for Windows Terminal.
5
5
  """
6
+
6
7
  import shlex
7
8
  import subprocess
8
9
  import random
@@ -22,82 +23,83 @@ class WTLayoutGenerator:
22
23
  self.session_name: Optional[str] = None
23
24
  self.tab_config: Dict[str, tuple[str, str]] = {} # Store entire tab config (cwd, command) for status checking
24
25
  self.script_path: Optional[str] = None # Store the full path to the script file
25
-
26
+
26
27
  @staticmethod
27
28
  def _generate_random_suffix(length: int = 8) -> str:
28
29
  """Generate a random string suffix for unique script file names."""
29
- return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
30
-
30
+ return "".join(random.choices(string.ascii_lowercase + string.digits, k=length))
31
+
31
32
  @staticmethod
32
33
  def _parse_command(command: str) -> tuple[str, List[str]]:
33
34
  try:
34
35
  parts = shlex.split(command)
35
- if not parts: raise ValueError("Empty command provided")
36
+ if not parts:
37
+ raise ValueError("Empty command provided")
36
38
  return parts[0], parts[1:] if len(parts) > 1 else []
37
39
  except ValueError as e:
38
40
  logger.error(f"Error parsing command '{command}': {e}")
39
41
  parts = command.split()
40
42
  return parts[0] if parts else "", parts[1:] if len(parts) > 1 else []
41
-
43
+
42
44
  @staticmethod
43
45
  def _escape_for_wt(text: str) -> str:
44
46
  """Escape text for use in Windows Terminal commands."""
45
47
  # Windows Terminal uses PowerShell-style escaping
46
48
  text = text.replace('"', '""') # Escape quotes for PowerShell
47
- if ' ' in text or ';' in text or '&' in text or '|' in text:
49
+ if " " in text or ";" in text or "&" in text or "|" in text:
48
50
  return f'"{text}"'
49
51
  return text
50
-
52
+
51
53
  @staticmethod
52
54
  def _create_tab_command(tab_name: str, cwd: str, command: str, is_first_tab: bool = False) -> str:
53
55
  """Create a Windows Terminal tab command string."""
54
56
  # Convert paths to Windows format if needed
55
- if cwd.startswith('~/'):
56
- cwd = cwd.replace('~/', f"{Path.home()}/")
57
- elif cwd == '~':
57
+ if cwd.startswith("~/"):
58
+ cwd = cwd.replace("~/", f"{Path.home()}/")
59
+ elif cwd == "~":
58
60
  cwd = str(Path.home())
59
-
61
+
60
62
  # Build the wt command parts
61
63
  tab_parts = []
62
-
64
+
63
65
  if not is_first_tab:
64
66
  tab_parts.append("new-tab")
65
-
67
+
66
68
  # Add starting directory
67
69
  tab_parts.extend(["-d", WTLayoutGenerator._escape_for_wt(cwd)])
68
-
70
+
69
71
  # Add tab title
70
72
  tab_parts.extend(["--title", WTLayoutGenerator._escape_for_wt(tab_name)])
71
-
73
+
72
74
  # Add the command to execute
73
75
  tab_parts.append(WTLayoutGenerator._escape_for_wt(command))
74
-
76
+
75
77
  return " ".join(tab_parts)
76
-
78
+
77
79
  @staticmethod
78
80
  def _validate_tab_config(tab_config: Dict[str, tuple[str, str]]) -> None:
79
81
  """Validate tab configuration format and content."""
80
- if not tab_config:
82
+ if not tab_config:
81
83
  raise ValueError("Tab configuration cannot be empty")
82
84
  for tab_name, (cwd, command) in tab_config.items():
83
- if not tab_name.strip():
85
+ if not tab_name.strip():
84
86
  raise ValueError(f"Invalid tab name: {tab_name}")
85
- if not command.strip():
87
+ if not command.strip():
86
88
  raise ValueError(f"Invalid command for tab '{tab_name}': {command}")
87
- if not cwd.strip():
89
+ if not cwd.strip():
88
90
  raise ValueError(f"Invalid cwd for tab '{tab_name}': {cwd}")
89
-
91
+
90
92
  def create_wt_layout(self, tab_config: Dict[str, tuple[str, str]], output_dir: Optional[str] = None, session_name: Optional[str] = None) -> str:
91
93
  WTLayoutGenerator._validate_tab_config(tab_config)
92
94
  logger.info(f"Creating Windows Terminal layout with {len(tab_config)} tabs")
93
-
95
+
94
96
  # Store session name and entire tab config for status checking
95
97
  self.session_name = session_name or "default"
96
98
  self.tab_config = tab_config.copy()
97
-
99
+
98
100
  # Generate Windows Terminal command
99
101
  wt_command = self._generate_wt_command_string(tab_config, self.session_name)
100
-
102
+
101
103
  try:
102
104
  random_suffix = WTLayoutGenerator._generate_random_suffix()
103
105
  if output_dir:
@@ -108,42 +110,44 @@ class WTLayoutGenerator:
108
110
  # Use the predefined TMP_LAYOUT_DIR for temporary files
109
111
  TMP_LAYOUT_DIR.mkdir(parents=True, exist_ok=True)
110
112
  script_file = TMP_LAYOUT_DIR / f"wt_layout_{self.session_name}_{random_suffix}.bat"
111
-
113
+
112
114
  # Create batch script
113
- with open(script_file, 'w', encoding='utf-8') as f:
114
- f.write("@echo off\n")
115
- f.write(f"REM Windows Terminal layout for {self.session_name}\n")
116
- f.write(f"{wt_command}\n")
117
-
115
+ text = f"""@echo off
116
+ REM Windows Terminal layout for {self.session_name}
117
+ {wt_command}
118
+ """
119
+ script_file.write_text(text, encoding="utf-8")
120
+
118
121
  # Also create PowerShell script for better command handling
119
- ps1_file = script_file.with_suffix('.ps1')
120
- with open(ps1_file, 'w', encoding='utf-8') as f:
121
- f.write(f"# Windows Terminal layout for {self.session_name}\n")
122
- f.write(f"# Generated with random suffix: {random_suffix}\n")
123
- f.write(f"{wt_command}\n")
124
-
122
+ ps1_file = script_file.with_suffix(".ps1")
123
+ text = f"""# Windows Terminal layout for {self.session_name}
124
+ # Generated with random suffix: {random_suffix}
125
+ {wt_command}
126
+ """
127
+ ps1_file.write_text(text, encoding="utf-8")
128
+
125
129
  self.script_path = str(script_file.absolute())
126
130
  logger.info(f"Windows Terminal script file created: {self.script_path}")
127
131
  return self.script_path
128
132
  except OSError as e:
129
133
  logger.error(f"Failed to create script file: {e}")
130
134
  raise
131
-
135
+
132
136
  def _generate_wt_command_string(self, tab_config: Dict[str, tuple[str, str]], window_name: str) -> str:
133
137
  """Generate complete Windows Terminal command string."""
134
138
  # Start building the wt command
135
139
  wt_parts = ["wt"]
136
-
140
+
137
141
  # Add window name
138
142
  wt_parts.extend(["-w", WTLayoutGenerator._escape_for_wt(window_name)])
139
-
143
+
140
144
  # Add tabs
141
145
  tab_commands = []
142
146
  for i, (tab_name, (cwd, command)) in enumerate(tab_config.items()):
143
147
  is_first = i == 0
144
148
  tab_cmd = self._create_tab_command(tab_name, cwd, command, is_first)
145
149
  tab_commands.append(tab_cmd)
146
-
150
+
147
151
  # Join all parts with semicolons (Windows Terminal command separator)
148
152
  if tab_commands:
149
153
  if len(tab_commands) == 1:
@@ -154,123 +158,81 @@ class WTLayoutGenerator:
154
158
  wt_parts.append(tab_commands[0]) # First tab
155
159
  for tab_cmd in tab_commands[1:]:
156
160
  wt_parts.extend([";", tab_cmd])
157
-
161
+
158
162
  return " ".join(wt_parts)
159
-
163
+
160
164
  def get_wt_layout_preview(self, tab_config: Dict[str, tuple[str, str]]) -> str:
161
165
  """Generate preview of the Windows Terminal command that would be created."""
162
166
  WTLayoutGenerator._validate_tab_config(tab_config)
163
167
  return self._generate_wt_command_string(tab_config, "preview")
164
-
168
+
165
169
  def check_all_commands_status(self) -> Dict[str, Dict[str, Any]]:
166
170
  if not self.tab_config:
167
171
  logger.warning("No tab config tracked. Make sure to create a layout first.")
168
172
  return {}
169
-
173
+
170
174
  status_report = {}
171
175
  for tab_name in self.tab_config:
172
176
  status_report[tab_name] = WTLayoutGenerator.check_command_status(tab_name, self.tab_config)
173
-
177
+
174
178
  return status_report
175
179
 
176
180
  @staticmethod
177
181
  def check_wt_session_status(session_name: str) -> Dict[str, Any]:
178
182
  try:
179
183
  # Check for Windows Terminal processes
180
- wt_check_cmd = [
181
- "powershell", "-Command",
182
- "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | "
183
- "Select-Object Id, ProcessName, StartTime, MainWindowTitle | "
184
- "ConvertTo-Json -Depth 2"
185
- ]
186
-
184
+ wt_check_cmd = ["powershell", "-Command", "Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, MainWindowTitle | ConvertTo-Json -Depth 2"]
185
+
187
186
  result = subprocess.run(wt_check_cmd, capture_output=True, text=True, timeout=10)
188
-
187
+
189
188
  if result.returncode == 0:
190
189
  output = result.stdout.strip()
191
190
  if output and output != "":
192
191
  try:
193
192
  import json
193
+
194
194
  processes = json.loads(output)
195
195
  if not isinstance(processes, list):
196
196
  processes = [processes]
197
-
197
+
198
198
  # Look for windows that might belong to our session
199
199
  session_windows = []
200
200
  for proc in processes:
201
201
  window_title = proc.get("MainWindowTitle", "")
202
202
  if session_name in window_title or not window_title:
203
203
  session_windows.append(proc)
204
-
205
- return {
206
- "wt_running": True,
207
- "session_exists": len(session_windows) > 0,
208
- "session_name": session_name,
209
- "all_windows": processes,
210
- "session_windows": session_windows
211
- }
204
+
205
+ return {"wt_running": True, "session_exists": len(session_windows) > 0, "session_name": session_name, "all_windows": processes, "session_windows": session_windows}
212
206
  except Exception as e:
213
- return {
214
- "wt_running": True,
215
- "session_exists": False,
216
- "error": f"Failed to parse process info: {e}",
217
- "session_name": session_name
218
- }
207
+ return {"wt_running": True, "session_exists": False, "error": f"Failed to parse process info: {e}", "session_name": session_name}
219
208
  else:
220
- return {
221
- "wt_running": False,
222
- "session_exists": False,
223
- "session_name": session_name,
224
- "all_windows": []
225
- }
209
+ return {"wt_running": False, "session_exists": False, "session_name": session_name, "all_windows": []}
226
210
  else:
227
- return {
228
- "wt_running": False,
229
- "error": result.stderr,
230
- "session_name": session_name
231
- }
232
-
211
+ return {"wt_running": False, "error": result.stderr, "session_name": session_name}
212
+
233
213
  except subprocess.TimeoutExpired:
234
- return {
235
- "wt_running": False,
236
- "error": "Timeout while checking Windows Terminal processes",
237
- "session_name": session_name
238
- }
214
+ return {"wt_running": False, "error": "Timeout while checking Windows Terminal processes", "session_name": session_name}
239
215
  except FileNotFoundError:
240
- return {
241
- "wt_running": False,
242
- "error": "PowerShell not found in PATH",
243
- "session_name": session_name
244
- }
216
+ return {"wt_running": False, "error": "PowerShell not found in PATH", "session_name": session_name}
245
217
  except Exception as e:
246
- return {
247
- "wt_running": False,
248
- "error": str(e),
249
- "session_name": session_name
250
- }
218
+ return {"wt_running": False, "error": str(e), "session_name": session_name}
251
219
 
252
220
  @staticmethod
253
221
  def check_command_status(tab_name: str, tab_config: Dict[str, tuple[str, str]]) -> Dict[str, Any]:
254
222
  """Check if a command is running by looking for processes."""
255
223
  if tab_name not in tab_config:
256
- return {
257
- "status": "unknown",
258
- "error": f"Tab '{tab_name}' not found in tracked configuration",
259
- "running": False,
260
- "pid": None,
261
- "command": None
262
- }
263
-
224
+ return {"status": "unknown", "error": f"Tab '{tab_name}' not found in tracked configuration", "running": False, "pid": None, "command": None}
225
+
264
226
  _, command = tab_config[tab_name]
265
-
227
+
266
228
  try:
267
229
  # Create PowerShell script to check for processes
268
230
  cmd_parts = [part for part in command.split() if len(part) > 2]
269
- primary_cmd = cmd_parts[0] if cmd_parts else ''
270
-
231
+ primary_cmd = cmd_parts[0] if cmd_parts else ""
232
+
271
233
  ps_script = f"""
272
- $targetCommand = '{command.replace("'", "''")}'
273
- $cmdParts = @({', '.join([f"'{part}'" for part in cmd_parts])})
234
+ $targetCommand = '{command.replace("'", "''")}'
235
+ $cmdParts = @({", ".join([f"'{part}'" for part in cmd_parts])})
274
236
  $primaryCmd = '{primary_cmd}'
275
237
  $currentPid = $PID
276
238
  $matchingProcesses = @()
@@ -278,23 +240,23 @@ $matchingProcesses = @()
278
240
  Get-Process | ForEach-Object {{
279
241
  try {{
280
242
  if ($_.Id -eq $currentPid) {{ return }}
281
-
243
+
282
244
  $cmdline = ""
283
245
  try {{
284
246
  $cmdline = (Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine
285
247
  }} catch {{
286
248
  $cmdline = $_.ProcessName
287
249
  }}
288
-
250
+
289
251
  if ($cmdline -and $cmdline -ne "") {{
290
252
  if ($cmdline -like "*PowerShell*" -and $cmdline -like "*Get-Process*") {{ return }}
291
-
253
+
292
254
  $matchesPrimary = $cmdline -like "*$primaryCmd*" -and $primaryCmd -ne "powershell"
293
255
  $matchCount = 0
294
256
  foreach ($part in $cmdParts[1..($cmdParts.Length-1)]) {{
295
257
  if ($cmdline -like "*$part*") {{ $matchCount++ }}
296
258
  }}
297
-
259
+
298
260
  if ($matchesPrimary -and $matchCount -ge 1) {{
299
261
  $procInfo = @{{
300
262
  "pid" = $_.Id
@@ -311,78 +273,44 @@ Get-Process | ForEach-Object {{
311
273
  }}
312
274
  }}
313
275
  """
314
-
315
- result = subprocess.run(
316
- ["powershell", "-Command", ps_script],
317
- capture_output=True,
318
- text=True,
319
- timeout=15
320
- )
321
-
276
+
277
+ result = subprocess.run(["powershell", "-Command", ps_script], capture_output=True, text=True, timeout=15)
278
+
322
279
  if result.returncode == 0:
323
- output_lines = [line.strip() for line in result.stdout.strip().split('\n') if line.strip()]
280
+ output_lines = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
324
281
  matching_processes = []
325
-
282
+
326
283
  for line in output_lines:
327
- if line.startswith('{') and line.endswith('}'):
284
+ if line.startswith("{") and line.endswith("}"):
328
285
  try:
329
286
  proc_info = json.loads(line)
330
287
  matching_processes.append(proc_info)
331
288
  except json.JSONDecodeError:
332
289
  continue
333
-
290
+
334
291
  if matching_processes:
335
- return {
336
- "status": "running",
337
- "running": True,
338
- "processes": matching_processes,
339
- "command": command,
340
- "tab_name": tab_name
341
- }
292
+ return {"status": "running", "running": True, "processes": matching_processes, "command": command, "tab_name": tab_name}
342
293
  else:
343
- return {
344
- "status": "not_running",
345
- "running": False,
346
- "processes": [],
347
- "command": command,
348
- "tab_name": tab_name
349
- }
294
+ return {"status": "not_running", "running": False, "processes": [], "command": command, "tab_name": tab_name}
350
295
  else:
351
- return {
352
- "status": "error",
353
- "error": f"Command failed: {result.stderr}",
354
- "running": False,
355
- "command": command,
356
- "tab_name": tab_name
357
- }
358
-
296
+ return {"status": "error", "error": f"Command failed: {result.stderr}", "running": False, "command": command, "tab_name": tab_name}
297
+
359
298
  except Exception as e:
360
299
  logger.error(f"Error checking command status for tab '{tab_name}': {e}")
361
- return {
362
- "status": "error",
363
- "error": str(e),
364
- "running": False,
365
- "command": command,
366
- "tab_name": tab_name
367
- }
300
+ return {"status": "error", "error": str(e), "running": False, "command": command, "tab_name": tab_name}
368
301
 
369
302
  def get_status_report(self) -> Dict[str, Any]:
370
303
  """Get status report for this layout including Windows Terminal and commands."""
371
304
  wt_status = WTLayoutGenerator.check_wt_session_status(self.session_name or "default")
372
305
  commands_status = self.check_all_commands_status()
373
-
306
+
374
307
  running_count = sum(1 for status in commands_status.values() if status.get("running", False))
375
308
  total_count = len(commands_status)
376
-
309
+
377
310
  return {
378
311
  "wt_session": wt_status,
379
312
  "commands": commands_status,
380
- "summary": {
381
- "total_commands": total_count,
382
- "running_commands": running_count,
383
- "stopped_commands": total_count - running_count,
384
- "session_healthy": wt_status.get("session_exists", False)
385
- }
313
+ "summary": {"total_commands": total_count, "running_commands": running_count, "stopped_commands": total_count - running_count, "session_healthy": wt_status.get("session_exists", False)},
386
314
  }
387
315
 
388
316
  def print_status_report(self) -> None:
@@ -391,11 +319,11 @@ Get-Process | ForEach-Object {{
391
319
  wt_session = status["wt_session"]
392
320
  commands = status["commands"]
393
321
  summary = status["summary"]
394
-
322
+
395
323
  print("=" * 80)
396
324
  print("šŸ–„ļø WINDOWS TERMINAL LAYOUT STATUS REPORT")
397
325
  print("=" * 80)
398
-
326
+
399
327
  # Windows Terminal session status
400
328
  print(f"🪟 Session: {self.session_name}")
401
329
  if wt_session.get("wt_running", False):
@@ -410,9 +338,9 @@ Get-Process | ForEach-Object {{
410
338
  else:
411
339
  error_msg = wt_session.get("error", "Unknown error")
412
340
  print(f"āŒ Windows Terminal session issue: {error_msg}")
413
-
341
+
414
342
  print()
415
-
343
+
416
344
  # Commands in this layout
417
345
  print(f"šŸ“‹ COMMANDS ({summary['running_commands']}/{summary['total_commands']} running):")
418
346
  for tab_name, cmd_status in commands.items():
@@ -420,16 +348,16 @@ Get-Process | ForEach-Object {{
420
348
  cmd_text = cmd_status.get("command", "Unknown")[:50]
421
349
  if len(cmd_status.get("command", "")) > 50:
422
350
  cmd_text += "..."
423
-
351
+
424
352
  print(f" {status_icon} {tab_name}: {cmd_text}")
425
-
353
+
426
354
  if cmd_status.get("processes"):
427
355
  for proc in cmd_status["processes"][:2]: # Show first 2 processes
428
356
  pid = proc.get("pid", "Unknown")
429
357
  name = proc.get("name", "Unknown")
430
358
  print(f" └─ PID {pid}: {name}")
431
359
  print()
432
-
360
+
433
361
  print("=" * 80)
434
362
 
435
363
 
@@ -437,15 +365,16 @@ def create_wt_layout(tab_config: Dict[str, tuple[str, str]], output_dir: Optiona
437
365
  generator = WTLayoutGenerator()
438
366
  return generator.create_wt_layout(tab_config, output_dir)
439
367
 
368
+
440
369
  def run_wt_layout(tab_config: Dict[str, tuple[str, str]], session_name: Optional[str] = None) -> str:
441
370
  """Create and run a Windows Terminal layout."""
442
371
  generator = WTLayoutGenerator()
443
372
  script_path = generator.create_wt_layout(tab_config, session_name=session_name)
444
-
373
+
445
374
  # Execute the script
446
- cmd = f"powershell -ExecutionPolicy Bypass -File \"{script_path}\""
375
+ cmd = f'powershell -ExecutionPolicy Bypass -File "{script_path}"'
447
376
  result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
448
-
377
+
449
378
  if result.returncode == 0:
450
379
  print(f"Windows Terminal layout is running @ {session_name}")
451
380
  return script_path
@@ -453,10 +382,11 @@ def run_wt_layout(tab_config: Dict[str, tuple[str, str]], session_name: Optional
453
382
  logger.error(f"Failed to run Windows Terminal layout: {result.stderr}")
454
383
  raise RuntimeError(f"Failed to run layout: {result.stderr}")
455
384
 
385
+
456
386
  def run_command_in_wt_tab(command: str, tab_name: str, cwd: Optional[str]) -> str:
457
387
  """Create a command to run in a new Windows Terminal tab."""
458
- cwd_part = f"-d \"{cwd}\"" if cwd else ""
459
-
388
+ cwd_part = f'-d "{cwd}"' if cwd else ""
389
+
460
390
  return f"""
461
391
  echo "Creating new Windows Terminal tab: {tab_name}"
462
392
  wt new-tab --title "{tab_name}" {cwd_part} "{command}"
@@ -465,30 +395,28 @@ wt new-tab --title "{tab_name}" {cwd_part} "{command}"
465
395
 
466
396
  if __name__ == "__main__":
467
397
  # Example usage
468
- sample_tabs = {
469
- "Frontend": ("~/code", "btm"),
470
- "Monitor": ("~", "lf"),
471
- }
472
-
398
+ sample_tabs = {"Frontend": ("~/code", "btm"), "Monitor": ("~", "lf")}
399
+
473
400
  try:
474
401
  # Create layout using the generator
475
402
  generator = WTLayoutGenerator()
476
403
  script_path = generator.create_wt_layout(sample_tabs, session_name="test_session")
477
404
  print(f"āœ… Windows Terminal layout created: {script_path}")
478
-
405
+
479
406
  # Show preview
480
407
  preview = generator.get_wt_layout_preview(sample_tabs)
481
408
  print(f"\nšŸ“‹ Command Preview:\n{preview}")
482
-
409
+
483
410
  # Check status (won't find anything since we haven't run it)
484
411
  print("\nšŸ” Current status:")
485
412
  generator.print_status_report()
486
-
413
+
487
414
  # Show how to run the layout
488
415
  print("\nā–¶ļø To run this layout, execute:")
489
- print(f" powershell -ExecutionPolicy Bypass -File \"{script_path}\"")
490
-
416
+ print(f' powershell -ExecutionPolicy Bypass -File "{script_path}"')
417
+
491
418
  except Exception as e:
492
419
  print(f"āŒ Error: {e}")
493
420
  import traceback
494
- traceback.print_exc()
421
+
422
+ traceback.print_exc()