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.
- 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 +27 -0
- 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 -11
- 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 +4 -0
- 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.96.dist-info β machineconfig-2.0.dist-info}/METADATA +13 -8
- {machineconfig-1.96.dist-info β machineconfig-2.0.dist-info}/RECORD +163 -144
- machineconfig/cluster/self_ssh.py +0 -57
- {machineconfig-1.96.dist-info β machineconfig-2.0.dist-info}/WHEEL +0 -0
- {machineconfig-1.96.dist-info β machineconfig-2.0.dist-info}/top_level.txt +0 -0
|
@@ -17,11 +17,11 @@ TMP_SERIALIZATION_DIR = Path.home().joinpath("tmp_results", "session_manager", "
|
|
|
17
17
|
|
|
18
18
|
class WTLocalManager:
|
|
19
19
|
"""Manages multiple local Windows Terminal sessions and monitors their tabs and processes."""
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def __init__(self, session2wt_tabs: Dict[str, Dict[str, tuple[str, str]]], session_name_prefix: str = "LocalWTMgr"):
|
|
22
22
|
"""
|
|
23
23
|
Initialize the local Windows Terminal manager.
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
Args:
|
|
26
26
|
session2wt_tabs: Dict mapping session names to their tab configs
|
|
27
27
|
Format: {session_name: {tab_name: (cwd, command), ...}, ...}
|
|
@@ -30,14 +30,14 @@ class WTLocalManager:
|
|
|
30
30
|
self.session_name_prefix = session_name_prefix
|
|
31
31
|
self.session2wt_tabs = session2wt_tabs # Store the original config
|
|
32
32
|
self.managers: List[WTLayoutGenerator] = []
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
# Create a WTLayoutGenerator for each session
|
|
35
35
|
for session_name, tab_config in session2wt_tabs.items():
|
|
36
36
|
manager = WTLayoutGenerator()
|
|
37
37
|
full_session_name = f"{self.session_name_prefix}_{session_name}"
|
|
38
38
|
manager.create_wt_layout(tab_config=tab_config, session_name=full_session_name)
|
|
39
39
|
self.managers.append(manager)
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
logger.info(f"Initialized WTLocalManager with {len(self.managers)} sessions")
|
|
42
42
|
|
|
43
43
|
def get_all_session_names(self) -> List[str]:
|
|
@@ -51,20 +51,20 @@ class WTLocalManager:
|
|
|
51
51
|
session_name = manager.session_name or "unknown"
|
|
52
52
|
try:
|
|
53
53
|
script_path = manager.script_path
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
if not script_path:
|
|
56
56
|
results[session_name] = {
|
|
57
57
|
"success": False,
|
|
58
58
|
"error": "No script file path available"
|
|
59
59
|
}
|
|
60
60
|
continue
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
# Execute the PowerShell script to start Windows Terminal
|
|
63
63
|
cmd = f"powershell -ExecutionPolicy Bypass -File \"{script_path}\""
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
logger.info(f"Starting session '{session_name}' with script: {script_path}")
|
|
66
66
|
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30)
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
if result.returncode == 0:
|
|
69
69
|
results[session_name] = {
|
|
70
70
|
"success": True,
|
|
@@ -77,14 +77,14 @@ class WTLocalManager:
|
|
|
77
77
|
"error": result.stderr or result.stdout
|
|
78
78
|
}
|
|
79
79
|
logger.error(f"β Failed to start session '{session_name}': {result.stderr}")
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
except Exception as e:
|
|
82
82
|
results[session_name] = {
|
|
83
83
|
"success": False,
|
|
84
84
|
"error": str(e)
|
|
85
85
|
}
|
|
86
86
|
logger.error(f"β Exception starting session '{session_name}': {e}")
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
return results
|
|
89
89
|
|
|
90
90
|
def kill_all_sessions(self) -> Dict[str, Any]:
|
|
@@ -95,30 +95,30 @@ class WTLocalManager:
|
|
|
95
95
|
try:
|
|
96
96
|
# Kill all Windows Terminal processes (Windows Terminal doesn't have session-specific killing)
|
|
97
97
|
cmd = "powershell -Command \"Get-Process -Name 'WindowsTerminal' -ErrorAction SilentlyContinue | Stop-Process -Force\""
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
logger.info(f"Killing Windows Terminal processes for session '{session_name}'")
|
|
100
100
|
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10)
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
results[session_name] = {
|
|
103
103
|
"success": result.returncode == 0,
|
|
104
104
|
"message": "Windows Terminal processes killed" if result.returncode == 0 else result.stderr
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
except Exception as e:
|
|
108
108
|
results[session_name] = {
|
|
109
109
|
"success": False,
|
|
110
110
|
"error": str(e)
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
return results
|
|
114
114
|
|
|
115
115
|
def attach_to_session(self, session_name: Optional[str] = None) -> str:
|
|
116
116
|
"""
|
|
117
117
|
Generate command to attach to a specific session or list attachment commands for all.
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
Args:
|
|
120
120
|
session_name: Specific session to attach to, or None for all sessions
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
Returns:
|
|
123
123
|
Command string to attach to session(s)
|
|
124
124
|
"""
|
|
@@ -140,20 +140,20 @@ class WTLocalManager:
|
|
|
140
140
|
def check_all_sessions_status(self) -> Dict[str, Dict[str, Any]]:
|
|
141
141
|
"""Check the status of all sessions and their commands."""
|
|
142
142
|
status_report = {}
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
for manager in self.managers:
|
|
145
145
|
session_name = manager.session_name or "default"
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
# Get session status
|
|
148
148
|
session_status = WTLayoutGenerator.check_wt_session_status(session_name)
|
|
149
|
-
|
|
149
|
+
|
|
150
150
|
# Get commands status for this session
|
|
151
151
|
commands_status = manager.check_all_commands_status()
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
# Calculate summary for this session
|
|
154
154
|
running_count = sum(1 for status in commands_status.values() if status.get("running", False))
|
|
155
155
|
total_count = len(commands_status)
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
status_report[session_name] = {
|
|
158
158
|
"session_status": session_status,
|
|
159
159
|
"commands_status": commands_status,
|
|
@@ -164,21 +164,21 @@ class WTLocalManager:
|
|
|
164
164
|
"session_healthy": session_status.get("session_exists", False)
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
return status_report
|
|
169
169
|
|
|
170
170
|
def get_global_summary(self) -> Dict[str, Any]:
|
|
171
171
|
"""Get a global summary across all sessions."""
|
|
172
172
|
all_status = self.check_all_sessions_status()
|
|
173
|
-
|
|
173
|
+
|
|
174
174
|
total_sessions = len(all_status)
|
|
175
|
-
healthy_sessions = sum(1 for status in all_status.values()
|
|
175
|
+
healthy_sessions = sum(1 for status in all_status.values()
|
|
176
176
|
if status["summary"]["session_healthy"])
|
|
177
|
-
total_commands = sum(status["summary"]["total_commands"]
|
|
177
|
+
total_commands = sum(status["summary"]["total_commands"]
|
|
178
178
|
for status in all_status.values())
|
|
179
|
-
total_running = sum(status["summary"]["running_commands"]
|
|
179
|
+
total_running = sum(status["summary"]["running_commands"]
|
|
180
180
|
for status in all_status.values())
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
return {
|
|
183
183
|
"total_sessions": total_sessions,
|
|
184
184
|
"healthy_sessions": healthy_sessions,
|
|
@@ -194,11 +194,11 @@ class WTLocalManager:
|
|
|
194
194
|
"""Print a comprehensive status report for all sessions."""
|
|
195
195
|
all_status = self.check_all_sessions_status()
|
|
196
196
|
global_summary = self.get_global_summary()
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
print("=" * 80)
|
|
199
199
|
print("π₯οΈ WINDOWS TERMINAL LOCAL MANAGER STATUS REPORT")
|
|
200
200
|
print("=" * 80)
|
|
201
|
-
|
|
201
|
+
|
|
202
202
|
# Global summary
|
|
203
203
|
print("π GLOBAL SUMMARY:")
|
|
204
204
|
print(f" Total sessions: {global_summary['total_sessions']}")
|
|
@@ -207,16 +207,16 @@ class WTLocalManager:
|
|
|
207
207
|
print(f" Running commands: {global_summary['running_commands']}")
|
|
208
208
|
print(f" All healthy: {'β
' if global_summary['all_sessions_healthy'] else 'β'}")
|
|
209
209
|
print()
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
# Per-session details
|
|
212
212
|
for session_name, status in all_status.items():
|
|
213
213
|
session_status = status["session_status"]
|
|
214
214
|
commands_status = status["commands_status"]
|
|
215
215
|
summary = status["summary"]
|
|
216
|
-
|
|
216
|
+
|
|
217
217
|
print(f"πͺ SESSION: {session_name}")
|
|
218
218
|
print("-" * 60)
|
|
219
|
-
|
|
219
|
+
|
|
220
220
|
# Session health
|
|
221
221
|
if session_status.get("wt_running", False):
|
|
222
222
|
if session_status.get("session_exists", False):
|
|
@@ -229,7 +229,7 @@ class WTLocalManager:
|
|
|
229
229
|
print("β οΈ Windows Terminal is running but no session windows found")
|
|
230
230
|
else:
|
|
231
231
|
print(f"β Windows Terminal session issue: {session_status.get('error', 'Unknown error')}")
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
# Commands in this session
|
|
234
234
|
print(f" Commands ({summary['running_commands']}/{summary['total_commands']} running):")
|
|
235
235
|
for tab_name, cmd_status in commands_status.items():
|
|
@@ -238,29 +238,29 @@ class WTLocalManager:
|
|
|
238
238
|
if len(cmd_status.get("command", "")) > 50:
|
|
239
239
|
cmd_text += "..."
|
|
240
240
|
print(f" {status_icon} {tab_name}: {cmd_text}")
|
|
241
|
-
|
|
241
|
+
|
|
242
242
|
if cmd_status.get("processes"):
|
|
243
243
|
for proc in cmd_status["processes"][:2]: # Show first 2 processes
|
|
244
244
|
print(f" ββ PID {proc['pid']}: {proc['name']}")
|
|
245
245
|
print()
|
|
246
|
-
|
|
246
|
+
|
|
247
247
|
print("=" * 80)
|
|
248
248
|
|
|
249
249
|
def run_monitoring_routine(self, wait_ms: int = 30000) -> None:
|
|
250
250
|
"""
|
|
251
251
|
Run a continuous monitoring routine that checks status periodically.
|
|
252
|
-
|
|
252
|
+
|
|
253
253
|
Args:
|
|
254
254
|
wait_ms: How long to wait between checks in milliseconds (default: 30000ms = 30s)
|
|
255
255
|
"""
|
|
256
256
|
def routine(scheduler: Scheduler):
|
|
257
257
|
print(f"\nβ° Monitoring cycle {scheduler.cycle} at {datetime.now()}")
|
|
258
258
|
print("-" * 50)
|
|
259
|
-
|
|
259
|
+
|
|
260
260
|
if scheduler.cycle % 2 == 0:
|
|
261
261
|
# Detailed status check every other cycle
|
|
262
262
|
all_status = self.check_all_sessions_status()
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
# Create DataFrame-like data for easier viewing
|
|
265
265
|
status_data = []
|
|
266
266
|
for session_name, status in all_status.items():
|
|
@@ -272,7 +272,7 @@ class WTLocalManager:
|
|
|
272
272
|
"command": cmd_status.get("command", "Unknown")[:50] + "..." if len(cmd_status.get("command", "")) > 50 else cmd_status.get("command", ""),
|
|
273
273
|
"processes": len(cmd_status.get("processes", []))
|
|
274
274
|
})
|
|
275
|
-
|
|
275
|
+
|
|
276
276
|
if status_data:
|
|
277
277
|
# Format data as table
|
|
278
278
|
headers = ["session", "tab", "running", "command", "processes"]
|
|
@@ -283,7 +283,7 @@ class WTLocalManager:
|
|
|
283
283
|
for row in status_data:
|
|
284
284
|
values = [str(row.get(h, ""))[:15] for h in headers]
|
|
285
285
|
print(" | ".join(f"{v:<15}" for v in values))
|
|
286
|
-
|
|
286
|
+
|
|
287
287
|
# Check if all sessions have stopped
|
|
288
288
|
running_count = sum(1 for row in status_data if row.get("running", False))
|
|
289
289
|
if running_count == 0:
|
|
@@ -296,25 +296,25 @@ class WTLocalManager:
|
|
|
296
296
|
# Quick summary check
|
|
297
297
|
global_summary = self.get_global_summary()
|
|
298
298
|
print(f"π Quick Summary: {global_summary['running_commands']}/{global_summary['total_commands']} commands running across {global_summary['healthy_sessions']}/{global_summary['total_sessions']} sessions")
|
|
299
|
-
|
|
299
|
+
|
|
300
300
|
logger.info(f"Starting monitoring routine with {wait_ms}ms intervals")
|
|
301
|
-
sched = Scheduler(routine=routine, wait_ms=wait_ms)
|
|
301
|
+
sched = Scheduler(routine=routine, wait_ms=wait_ms, logger=logger)
|
|
302
302
|
sched.run(max_cycles=None)
|
|
303
303
|
|
|
304
304
|
def save(self, session_id: Optional[str] = None) -> str:
|
|
305
305
|
"""Save the manager state to disk."""
|
|
306
306
|
if session_id is None:
|
|
307
307
|
session_id = str(uuid.uuid4())[:8]
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
# Create session directory
|
|
310
310
|
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
311
311
|
session_dir.mkdir(parents=True, exist_ok=True)
|
|
312
|
-
|
|
312
|
+
|
|
313
313
|
# Save the session2wt_tabs configuration
|
|
314
314
|
config_file = session_dir / "session2wt_tabs.json"
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
315
|
+
text = json.dumps(self.session2wt_tabs, indent=2, ensure_ascii=False)
|
|
316
|
+
config_file.write_text(text, encoding="utf-8")
|
|
317
|
+
|
|
318
318
|
# Save metadata
|
|
319
319
|
metadata = {
|
|
320
320
|
"session_name_prefix": self.session_name_prefix,
|
|
@@ -324,13 +324,13 @@ class WTLocalManager:
|
|
|
324
324
|
"manager_type": "WTLocalManager"
|
|
325
325
|
}
|
|
326
326
|
metadata_file = session_dir / "metadata.json"
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
327
|
+
text = json.dumps(metadata, indent=2, ensure_ascii=False)
|
|
328
|
+
metadata_file.write_text(text, encoding="utf-8")
|
|
329
|
+
|
|
330
330
|
# Save each manager's state
|
|
331
331
|
managers_dir = session_dir / "managers"
|
|
332
332
|
managers_dir.mkdir(exist_ok=True)
|
|
333
|
-
|
|
333
|
+
|
|
334
334
|
for i, manager in enumerate(self.managers):
|
|
335
335
|
manager_data = {
|
|
336
336
|
"session_name": manager.session_name,
|
|
@@ -338,9 +338,9 @@ class WTLocalManager:
|
|
|
338
338
|
"script_path": manager.script_path
|
|
339
339
|
}
|
|
340
340
|
manager_file = managers_dir / f"manager_{i}_{manager.session_name}.json"
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
text = json.dumps(manager_data, indent=2, ensure_ascii=False)
|
|
342
|
+
manager_file.write_text(text, encoding="utf-8")
|
|
343
|
+
|
|
344
344
|
logger.info(f"β
Saved WTLocalManager session to: {session_dir}")
|
|
345
345
|
return session_id
|
|
346
346
|
|
|
@@ -348,18 +348,18 @@ class WTLocalManager:
|
|
|
348
348
|
def load(cls, session_id: str) -> 'WTLocalManager':
|
|
349
349
|
"""Load a saved manager state from disk."""
|
|
350
350
|
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
351
|
-
|
|
351
|
+
|
|
352
352
|
if not session_dir.exists():
|
|
353
353
|
raise FileNotFoundError(f"Session directory not found: {session_dir}")
|
|
354
|
-
|
|
354
|
+
|
|
355
355
|
# Load configuration
|
|
356
356
|
config_file = session_dir / "session2wt_tabs.json"
|
|
357
357
|
if not config_file.exists():
|
|
358
358
|
raise FileNotFoundError(f"Configuration file not found: {config_file}")
|
|
359
|
-
|
|
359
|
+
|
|
360
360
|
with open(config_file, 'r', encoding='utf-8') as f:
|
|
361
361
|
session2wt_tabs = json.load(f)
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
# Load metadata
|
|
364
364
|
metadata_file = session_dir / "metadata.json"
|
|
365
365
|
session_name_prefix = "LocalWTMgr" # default fallback
|
|
@@ -367,32 +367,32 @@ class WTLocalManager:
|
|
|
367
367
|
with open(metadata_file, 'r', encoding='utf-8') as f:
|
|
368
368
|
metadata = json.load(f)
|
|
369
369
|
session_name_prefix = metadata.get("session_name_prefix", "LocalWTMgr")
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
# Create new instance
|
|
372
372
|
instance = cls(session2wt_tabs=session2wt_tabs, session_name_prefix=session_name_prefix)
|
|
373
|
-
|
|
373
|
+
|
|
374
374
|
# Load saved manager states
|
|
375
375
|
managers_dir = session_dir / "managers"
|
|
376
376
|
if managers_dir.exists():
|
|
377
377
|
instance.managers = []
|
|
378
378
|
manager_files = sorted(managers_dir.glob("manager_*.json"))
|
|
379
|
-
|
|
379
|
+
|
|
380
380
|
for manager_file in manager_files:
|
|
381
381
|
try:
|
|
382
382
|
with open(manager_file, 'r', encoding='utf-8') as f:
|
|
383
383
|
manager_data = json.load(f)
|
|
384
|
-
|
|
384
|
+
|
|
385
385
|
# Recreate the manager
|
|
386
386
|
manager = WTLayoutGenerator()
|
|
387
387
|
manager.session_name = manager_data["session_name"]
|
|
388
388
|
manager.tab_config = manager_data["tab_config"]
|
|
389
389
|
manager.script_path = manager_data["script_path"]
|
|
390
|
-
|
|
390
|
+
|
|
391
391
|
instance.managers.append(manager)
|
|
392
|
-
|
|
392
|
+
|
|
393
393
|
except Exception as e:
|
|
394
394
|
logger.warning(f"Failed to load manager from {manager_file}: {e}")
|
|
395
|
-
|
|
395
|
+
|
|
396
396
|
logger.info(f"β
Loaded WTLocalManager session from: {session_dir}")
|
|
397
397
|
return instance
|
|
398
398
|
|
|
@@ -401,23 +401,23 @@ class WTLocalManager:
|
|
|
401
401
|
"""List all saved session IDs."""
|
|
402
402
|
if not TMP_SERIALIZATION_DIR.exists():
|
|
403
403
|
return []
|
|
404
|
-
|
|
404
|
+
|
|
405
405
|
sessions = []
|
|
406
406
|
for item in TMP_SERIALIZATION_DIR.iterdir():
|
|
407
407
|
if item.is_dir() and (item / "metadata.json").exists():
|
|
408
408
|
sessions.append(item.name)
|
|
409
|
-
|
|
409
|
+
|
|
410
410
|
return sorted(sessions)
|
|
411
411
|
|
|
412
412
|
@staticmethod
|
|
413
413
|
def delete_session(session_id: str) -> bool:
|
|
414
414
|
"""Delete a saved session."""
|
|
415
415
|
session_dir = TMP_SERIALIZATION_DIR / session_id
|
|
416
|
-
|
|
416
|
+
|
|
417
417
|
if not session_dir.exists():
|
|
418
418
|
logger.warning(f"Session directory not found: {session_dir}")
|
|
419
419
|
return False
|
|
420
|
-
|
|
420
|
+
|
|
421
421
|
try:
|
|
422
422
|
import shutil
|
|
423
423
|
shutil.rmtree(session_dir)
|
|
@@ -430,33 +430,33 @@ class WTLocalManager:
|
|
|
430
430
|
def list_active_sessions(self) -> List[Dict[str, Any]]:
|
|
431
431
|
"""List currently active Windows Terminal sessions managed by this instance."""
|
|
432
432
|
active_sessions = []
|
|
433
|
-
|
|
433
|
+
|
|
434
434
|
try:
|
|
435
435
|
# Get all running Windows Terminal processes
|
|
436
436
|
result = subprocess.run(
|
|
437
|
-
['powershell', '-Command',
|
|
437
|
+
['powershell', '-Command',
|
|
438
438
|
'Get-Process -Name "WindowsTerminal" -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, MainWindowTitle | ConvertTo-Json -Depth 2'],
|
|
439
439
|
capture_output=True,
|
|
440
440
|
text=True,
|
|
441
441
|
timeout=10
|
|
442
442
|
)
|
|
443
|
-
|
|
443
|
+
|
|
444
444
|
if result.returncode == 0 and result.stdout.strip():
|
|
445
445
|
import json
|
|
446
446
|
all_processes = json.loads(result.stdout.strip())
|
|
447
447
|
if not isinstance(all_processes, list):
|
|
448
448
|
all_processes = [all_processes]
|
|
449
|
-
|
|
449
|
+
|
|
450
450
|
# Filter to only our managed sessions
|
|
451
451
|
for manager in self.managers:
|
|
452
452
|
session_name = manager.session_name
|
|
453
453
|
session_windows = []
|
|
454
|
-
|
|
454
|
+
|
|
455
455
|
for proc in all_processes:
|
|
456
456
|
window_title = proc.get("MainWindowTitle", "")
|
|
457
457
|
if session_name in window_title or not window_title:
|
|
458
458
|
session_windows.append(proc)
|
|
459
|
-
|
|
459
|
+
|
|
460
460
|
active_sessions.append({
|
|
461
461
|
"session_name": session_name,
|
|
462
462
|
"is_active": len(session_windows) > 0,
|
|
@@ -464,29 +464,29 @@ class WTLocalManager:
|
|
|
464
464
|
"tabs": list(manager.tab_config.keys()),
|
|
465
465
|
"windows": session_windows
|
|
466
466
|
})
|
|
467
|
-
|
|
467
|
+
|
|
468
468
|
except Exception as e:
|
|
469
469
|
logger.error(f"Error listing active sessions: {e}")
|
|
470
|
-
|
|
470
|
+
|
|
471
471
|
return active_sessions
|
|
472
472
|
|
|
473
473
|
def get_wt_overview(self) -> Dict[str, Any]:
|
|
474
474
|
"""Get overview of all Windows Terminal windows and processes."""
|
|
475
475
|
try:
|
|
476
476
|
result = subprocess.run(
|
|
477
|
-
['powershell', '-Command',
|
|
477
|
+
['powershell', '-Command',
|
|
478
478
|
'Get-Process -Name "WindowsTerminal" -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, MainWindowTitle, CPU | ConvertTo-Json -Depth 2'],
|
|
479
479
|
capture_output=True,
|
|
480
480
|
text=True,
|
|
481
481
|
timeout=10
|
|
482
482
|
)
|
|
483
|
-
|
|
483
|
+
|
|
484
484
|
if result.returncode == 0 and result.stdout.strip():
|
|
485
485
|
import json
|
|
486
486
|
processes = json.loads(result.stdout.strip())
|
|
487
487
|
if not isinstance(processes, list):
|
|
488
488
|
processes = [processes]
|
|
489
|
-
|
|
489
|
+
|
|
490
490
|
return {
|
|
491
491
|
"success": True,
|
|
492
492
|
"total_windows": len(processes),
|
|
@@ -528,23 +528,23 @@ if __name__ == "__main__":
|
|
|
528
528
|
"πMetrics": ("~", "Get-Counter \"\\Processor(_Total)\\% Processor Time\" -SampleInterval 2 -MaxSamples 30")
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
|
-
|
|
531
|
+
|
|
532
532
|
try:
|
|
533
533
|
# Create the local manager
|
|
534
534
|
manager = WTLocalManager(sample_sessions, session_name_prefix="DevEnv")
|
|
535
535
|
print(f"β
Local manager created with {len(manager.managers)} sessions")
|
|
536
|
-
|
|
536
|
+
|
|
537
537
|
# Show session names
|
|
538
538
|
print(f"π Sessions: {manager.get_all_session_names()}")
|
|
539
|
-
|
|
539
|
+
|
|
540
540
|
# Print attachment commands (without actually starting)
|
|
541
541
|
print("\nπ Attachment commands:")
|
|
542
542
|
print(manager.attach_to_session())
|
|
543
|
-
|
|
543
|
+
|
|
544
544
|
# Show current status
|
|
545
545
|
print("\nπ Current status:")
|
|
546
546
|
manager.print_status_report()
|
|
547
|
-
|
|
547
|
+
|
|
548
548
|
# Show Windows Terminal overview
|
|
549
549
|
print("\nπ₯οΈ Windows Terminal Overview:")
|
|
550
550
|
overview = manager.get_wt_overview()
|
|
@@ -553,25 +553,25 @@ if __name__ == "__main__":
|
|
|
553
553
|
print(f" Managed sessions: {overview['managed_sessions']}")
|
|
554
554
|
else:
|
|
555
555
|
print(f" Error: {overview.get('error', 'Unknown')}")
|
|
556
|
-
|
|
556
|
+
|
|
557
557
|
# Demonstrate save/load
|
|
558
558
|
print("\nπΎ Demonstrating save/load...")
|
|
559
559
|
session_id = manager.save()
|
|
560
560
|
print(f"β
Saved session: {session_id}")
|
|
561
|
-
|
|
561
|
+
|
|
562
562
|
# List saved sessions
|
|
563
563
|
saved_sessions = WTLocalManager.list_saved_sessions()
|
|
564
564
|
print(f"π Saved sessions: {saved_sessions}")
|
|
565
|
-
|
|
565
|
+
|
|
566
566
|
# Load and verify
|
|
567
567
|
loaded_manager = WTLocalManager.load(session_id)
|
|
568
568
|
print(f"β
Loaded session with {len(loaded_manager.managers)} sessions")
|
|
569
|
-
|
|
569
|
+
|
|
570
570
|
# Show how to start monitoring (commented out to prevent infinite loop in demo)
|
|
571
571
|
print("\nβ° To start monitoring, run:")
|
|
572
572
|
print("manager.run_monitoring_routine(wait_ms=30000) # 30 seconds")
|
|
573
|
-
|
|
573
|
+
|
|
574
574
|
except Exception as e:
|
|
575
575
|
print(f"β Error: {e}")
|
|
576
576
|
import traceback
|
|
577
|
-
traceback.print_exc()
|
|
577
|
+
traceback.print_exc()
|