machineconfig 5.22__py3-none-any.whl → 5.23__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/sessions_managers/helpers/zellij_local_helper.py +298 -0
- machineconfig/cluster/sessions_managers/helpers/zellij_local_helper_restart.py +77 -0
- machineconfig/cluster/sessions_managers/helpers/zellij_local_helper_with_panes.py +228 -0
- machineconfig/cluster/sessions_managers/helpers/zellij_local_manager_helper.py +165 -0
- machineconfig/cluster/sessions_managers/wt_local.py +100 -75
- machineconfig/cluster/sessions_managers/wt_local_manager.py +17 -21
- machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +16 -8
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
- machineconfig/cluster/sessions_managers/zellij_local.py +79 -371
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +20 -168
- machineconfig/cluster/sessions_managers/zellij_remote.py +38 -39
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -1
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -17
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -17
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +1 -1
- machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
- machineconfig/scripts/python/ai/solutions/generic.py +15 -4
- machineconfig/scripts/python/cloud_repo_sync.py +7 -5
- machineconfig/scripts/python/count_lines.py +6 -6
- machineconfig/scripts/python/fire_agents_help_launch.py +6 -1
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -3
- machineconfig/scripts/windows/share_smb.ps1 +0 -6
- machineconfig/utils/source_of_truth.py +1 -1
- {machineconfig-5.22.dist-info → machineconfig-5.23.dist-info}/METADATA +1 -1
- {machineconfig-5.22.dist-info → machineconfig-5.23.dist-info}/RECORD +31 -28
- machineconfig/cluster/sessions_managers/ffile.py +0 -4
- machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
- {machineconfig-5.22.dist-info → machineconfig-5.23.dist-info}/WHEEL +0 -0
- {machineconfig-5.22.dist-info → machineconfig-5.23.dist-info}/entry_points.txt +0 -0
- {machineconfig-5.22.dist-info → machineconfig-5.23.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional, Any
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
import logging
|
|
5
5
|
import json
|
|
@@ -11,18 +11,18 @@ from machineconfig.cluster.sessions_managers.wt_utils.layout_generator import WT
|
|
|
11
11
|
from machineconfig.cluster.sessions_managers.wt_utils.process_monitor import WTProcessMonitor
|
|
12
12
|
from machineconfig.cluster.sessions_managers.wt_utils.session_manager import WTSessionManager
|
|
13
13
|
from machineconfig.cluster.sessions_managers.wt_utils.status_reporter import WTStatusReporter
|
|
14
|
-
from machineconfig.utils.schemas.layouts.layout_types import TabConfig
|
|
14
|
+
from machineconfig.utils.schemas.layouts.layout_types import TabConfig, LayoutConfig
|
|
15
15
|
|
|
16
16
|
logging.basicConfig(level=logging.INFO)
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
|
-
TMP_LAYOUT_DIR = Path.home()
|
|
18
|
+
TMP_LAYOUT_DIR = Path.home() / "tmp_results" / "wt_layouts"
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class WTRemoteLayoutGenerator:
|
|
22
|
-
def __init__(self, remote_name: str,
|
|
23
|
-
self.remote_name = remote_name
|
|
24
|
-
self.session_name =
|
|
25
|
-
self.
|
|
22
|
+
def __init__(self, layout_config: LayoutConfig, remote_name: str, session_name: str):
|
|
23
|
+
self.remote_name: str = remote_name
|
|
24
|
+
self.session_name: str = session_name
|
|
25
|
+
self.layout_config: LayoutConfig = layout_config.copy()
|
|
26
26
|
self.script_path: Optional[str] = None
|
|
27
27
|
|
|
28
28
|
# Initialize modular components
|
|
@@ -32,22 +32,30 @@ class WTRemoteLayoutGenerator:
|
|
|
32
32
|
self.session_manager = WTSessionManager(self.remote_executor, self.session_name, TMP_LAYOUT_DIR)
|
|
33
33
|
self.status_reporter = WTStatusReporter(self.process_monitor, self.session_manager)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
logger.info(f"Creating Windows Terminal layout with {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
def create_layout_file(self) -> bool:
|
|
36
|
+
"""Create Windows Terminal layout file and return success status."""
|
|
37
|
+
tab_count = len(self.layout_config["layoutTabs"])
|
|
38
|
+
logger.info(f"Creating Windows Terminal layout with {tab_count} tabs for remote '{self.remote_name}'")
|
|
39
|
+
|
|
40
|
+
# Extract tabs from layout_config
|
|
41
|
+
tabs: list[TabConfig] = self.layout_config["layoutTabs"]
|
|
42
|
+
script_content = self.layout_generator.create_wt_script(tabs, self.session_name, window_name=None)
|
|
43
|
+
|
|
44
|
+
# Write to file
|
|
45
|
+
tmp_layout_dir = Path.home() / "tmp_results" / "wt_layouts" / "remote"
|
|
46
|
+
tmp_layout_dir.mkdir(parents=True, exist_ok=True)
|
|
47
|
+
random_suffix = WTLayoutGenerator.generate_random_suffix(8)
|
|
48
|
+
script_file = tmp_layout_dir / f"wt_layout_{self.session_name}_{random_suffix}.ps1"
|
|
49
|
+
script_file.write_text(script_content, encoding="utf-8")
|
|
50
|
+
self.script_path = str(script_file.absolute())
|
|
51
|
+
|
|
52
|
+
logger.info(f"✅ Remote layout created: {self.script_path}")
|
|
53
|
+
return True
|
|
46
54
|
|
|
47
55
|
# Legacy methods for backward compatibility
|
|
48
56
|
|
|
49
|
-
def to_dict(self) ->
|
|
50
|
-
return {"remote_name": self.remote_name, "session_name": self.session_name, "
|
|
57
|
+
def to_dict(self) -> dict[str, Any]:
|
|
58
|
+
return {"remote_name": self.remote_name, "session_name": self.session_name, "layout_config": self.layout_config, "script_path": self.script_path, "created_at": datetime.now().isoformat(), "class_name": self.__class__.__name__}
|
|
51
59
|
|
|
52
60
|
def to_json(self, file_path: Optional[str]) -> str:
|
|
53
61
|
# Generate file path if not provided
|
|
@@ -95,29 +103,18 @@ class WTRemoteLayoutGenerator:
|
|
|
95
103
|
logger.warning(f"Class name mismatch: expected {cls.__name__}, got {data.get('class_name')}")
|
|
96
104
|
|
|
97
105
|
# Create new instance
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
session_name_prefix = session_name
|
|
104
|
-
|
|
105
|
-
instance = cls(remote_name=data["remote_name"], session_name_prefix=session_name_prefix)
|
|
106
|
-
|
|
107
|
-
# Restore state
|
|
108
|
-
instance.session_name = data["session_name"]
|
|
109
|
-
# New schema only
|
|
110
|
-
if "tabs" in data:
|
|
111
|
-
instance.tabs = data["tabs"]
|
|
112
|
-
else:
|
|
113
|
-
instance.tabs = []
|
|
106
|
+
instance = cls(
|
|
107
|
+
layout_config=data["layout_config"],
|
|
108
|
+
remote_name=data["remote_name"],
|
|
109
|
+
session_name=data["session_name"]
|
|
110
|
+
)
|
|
114
111
|
instance.script_path = data["script_path"]
|
|
115
112
|
|
|
116
113
|
logger.info(f"✅ Loaded WTRemoteLayoutGenerator from: {file_path}")
|
|
117
114
|
return instance
|
|
118
115
|
|
|
119
116
|
@staticmethod
|
|
120
|
-
def list_saved_sessions(directory_path: Optional[str]) ->
|
|
117
|
+
def list_saved_sessions(directory_path: Optional[str]) -> list[str]:
|
|
121
118
|
if directory_path is None:
|
|
122
119
|
dir_path = Path.home() / "tmp_results" / "wt_sessions" / "serialized"
|
|
123
120
|
else:
|
|
@@ -132,7 +129,7 @@ class WTRemoteLayoutGenerator:
|
|
|
132
129
|
|
|
133
130
|
if __name__ == "__main__":
|
|
134
131
|
# Example usage
|
|
135
|
-
sample_tabs:
|
|
132
|
+
sample_tabs: list[TabConfig] = [
|
|
136
133
|
{"tabName": "🤖Bot1", "startDir": "~/code/bytesense/bithence", "command": "python bot1.py --create_new_bot True"},
|
|
137
134
|
{"tabName": "🤖Bot2", "startDir": "~/code/bytesense/bithence", "command": "python bot2.py --create_new_bot True"},
|
|
138
135
|
{"tabName": "📊Monitor", "startDir": "~", "command": "Get-Process | Sort-Object CPU -Descending | Select-Object -First 10"},
|
|
@@ -144,10 +141,21 @@ if __name__ == "__main__":
|
|
|
144
141
|
session_name = "test_remote_session"
|
|
145
142
|
|
|
146
143
|
try:
|
|
144
|
+
# Create layout config from tabs
|
|
145
|
+
sample_layout: LayoutConfig = {
|
|
146
|
+
"layoutName": "RemoteBots",
|
|
147
|
+
"layoutTabs": sample_tabs
|
|
148
|
+
}
|
|
149
|
+
|
|
147
150
|
# Create layout using the remote generator
|
|
148
|
-
generator = WTRemoteLayoutGenerator(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
generator = WTRemoteLayoutGenerator(
|
|
152
|
+
layout_config=sample_layout,
|
|
153
|
+
remote_name=remote_name,
|
|
154
|
+
session_name=session_name
|
|
155
|
+
)
|
|
156
|
+
generator.create_layout_file()
|
|
157
|
+
|
|
158
|
+
print(f"✅ Remote layout created successfully: {generator.script_path}")
|
|
151
159
|
|
|
152
160
|
# Check if Windows Terminal is available on remote
|
|
153
161
|
wt_available = generator.remote_executor.check_wt_available()
|
|
@@ -170,7 +178,7 @@ if __name__ == "__main__":
|
|
|
170
178
|
# Demonstrate loading (using the full path)
|
|
171
179
|
loaded_generator = WTRemoteLayoutGenerator.from_json(saved_path)
|
|
172
180
|
print(f"✅ Session loaded successfully: {loaded_generator.session_name}")
|
|
173
|
-
print(f"📊 Loaded tabs: {[tab['tabName'] for tab in loaded_generator.
|
|
181
|
+
print(f"📊 Loaded tabs: {[tab['tabName'] for tab in loaded_generator.layout_config['layoutTabs']]}")
|
|
174
182
|
|
|
175
183
|
# Show command preview
|
|
176
184
|
preview = generator.layout_generator.generate_wt_command(sample_tabs)
|
|
@@ -178,7 +186,7 @@ if __name__ == "__main__":
|
|
|
178
186
|
|
|
179
187
|
# Demonstrate status checking
|
|
180
188
|
print(f"\n🔍 Checking command status on remote '{remote_name}':")
|
|
181
|
-
generator.status_reporter.print_status_report(
|
|
189
|
+
generator.status_reporter.print_status_report(sample_tabs)
|
|
182
190
|
|
|
183
191
|
# Show Windows Terminal overview
|
|
184
192
|
print("\n🖥️ Windows Terminal Overview:")
|
|
@@ -8,13 +8,14 @@ from rich.console import Console
|
|
|
8
8
|
from machineconfig.utils.scheduler import Scheduler
|
|
9
9
|
from machineconfig.cluster.sessions_managers.wt_local import run_command_in_wt_tab
|
|
10
10
|
from machineconfig.cluster.sessions_managers.wt_remote import WTRemoteLayoutGenerator
|
|
11
|
-
from machineconfig.
|
|
11
|
+
from machineconfig.cluster.sessions_managers.wt_utils.layout_generator import WTLayoutGenerator
|
|
12
|
+
from machineconfig.utils.schemas.layouts.layout_types import TabConfig, LayoutConfig
|
|
12
13
|
|
|
13
|
-
TMP_SERIALIZATION_DIR = Path.home().joinpath("tmp_results", "session_manager", "wt", "remote_manager")
|
|
14
14
|
|
|
15
15
|
# Module-level logger to be used throughout this module
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
console = Console()
|
|
18
|
+
TMP_SERIALIZATION_DIR = Path.home() / "tmp_results" / "wt_sessions" / "serialized"
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class WTSessionManager:
|
|
@@ -23,10 +24,15 @@ class WTSessionManager:
|
|
|
23
24
|
self.machine2wt_tabs = machine2wt_tabs # Store the original config
|
|
24
25
|
self.managers: list[WTRemoteLayoutGenerator] = []
|
|
25
26
|
for machine, tab_config in machine2wt_tabs.items():
|
|
26
|
-
|
|
27
|
-
# Convert legacy dict[str, tuple[str,str]] to List[TabConfig]
|
|
27
|
+
# Convert legacy dict[str, tuple[str,str]] to LayoutConfig
|
|
28
28
|
tabs: list[TabConfig] = [{"tabName": name, "startDir": cwd, "command": cmd} for name, (cwd, cmd) in tab_config.items()]
|
|
29
|
-
|
|
29
|
+
layout_config: LayoutConfig = {
|
|
30
|
+
"layoutName": f"{session_name_prefix}_{machine}",
|
|
31
|
+
"layoutTabs": tabs
|
|
32
|
+
}
|
|
33
|
+
session_name = f"{session_name_prefix}_{WTLayoutGenerator.generate_random_suffix(8)}"
|
|
34
|
+
an_m = WTRemoteLayoutGenerator(layout_config=layout_config, remote_name=machine, session_name=session_name)
|
|
35
|
+
an_m.create_layout_file()
|
|
30
36
|
self.managers.append(an_m)
|
|
31
37
|
|
|
32
38
|
def ssh_to_all_machines(self) -> str:
|
|
@@ -52,7 +58,8 @@ class WTSessionManager:
|
|
|
52
58
|
if scheduler.cycle % 2 == 0:
|
|
53
59
|
statuses = []
|
|
54
60
|
for _idx, an_m in enumerate(self.managers):
|
|
55
|
-
|
|
61
|
+
tabs = an_m.layout_config["layoutTabs"]
|
|
62
|
+
a_status = an_m.process_monitor.check_all_commands_status(tabs)
|
|
56
63
|
statuses.append(a_status)
|
|
57
64
|
keys = []
|
|
58
65
|
for item in statuses:
|
|
@@ -220,7 +227,8 @@ class WTSessionManager:
|
|
|
220
227
|
wt_status = manager.session_manager.check_wt_session_status()
|
|
221
228
|
|
|
222
229
|
# Get commands status for this session
|
|
223
|
-
|
|
230
|
+
tabs = manager.layout_config["layoutTabs"]
|
|
231
|
+
commands_status = manager.process_monitor.check_all_commands_status(tabs)
|
|
224
232
|
|
|
225
233
|
# Calculate summary for this session
|
|
226
234
|
running_count = sum(1 for status in commands_status.values() if status.get("running", False))
|
|
@@ -343,7 +351,7 @@ class WTSessionManager:
|
|
|
343
351
|
# Get Windows Terminal version
|
|
344
352
|
wt_version = manager.session_manager.get_wt_version()
|
|
345
353
|
|
|
346
|
-
overview[remote_name] = {"windows_info": windows_info, "wt_processes": wt_processes, "wt_version": wt_version, "session_name": manager.session_name, "tab_count": len(manager.
|
|
354
|
+
overview[remote_name] = {"windows_info": windows_info, "wt_processes": wt_processes, "wt_version": wt_version, "session_name": manager.session_name, "tab_count": len(manager.layout_config["layoutTabs"])}
|
|
347
355
|
|
|
348
356
|
except Exception as e:
|
|
349
357
|
overview[manager.remote_name] = {"error": str(e), "session_name": manager.session_name}
|
|
@@ -130,34 +130,21 @@ class WTLayoutGenerator:
|
|
|
130
130
|
|
|
131
131
|
return " ".join(wt_parts)
|
|
132
132
|
|
|
133
|
-
def create_wt_script(self, tabs: List[TabConfig],
|
|
134
|
-
"""Create a Windows Terminal PowerShell script and return
|
|
133
|
+
def create_wt_script(self, tabs: List[TabConfig], session_name: str, window_name: str | None = None) -> str:
|
|
134
|
+
"""Create a Windows Terminal PowerShell script content and return it as string."""
|
|
135
135
|
self.validate_tab_config(tabs)
|
|
136
136
|
|
|
137
137
|
# Generate unique suffix for this script
|
|
138
138
|
random_suffix = self.generate_random_suffix()
|
|
139
139
|
wt_command = self.generate_wt_command(tabs, window_name or session_name)
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
output_dir.mkdir(parents=True, exist_ok=True)
|
|
144
|
-
|
|
145
|
-
# Create PowerShell script
|
|
146
|
-
ps1_file = output_dir / f"wt_layout_{session_name}_{random_suffix}.ps1"
|
|
147
|
-
|
|
148
|
-
# Create PowerShell script content
|
|
149
|
-
text = f"""# Windows Terminal layout for {session_name}
|
|
141
|
+
# Create PowerShell script content
|
|
142
|
+
script_content = f"""# Windows Terminal layout for {session_name}
|
|
150
143
|
# Generated on {random_suffix}
|
|
151
144
|
{wt_command}
|
|
152
145
|
"""
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
logger.info(f"Windows Terminal PowerShell script created: {ps1_file.absolute()}")
|
|
156
|
-
return str(ps1_file.absolute())
|
|
157
|
-
|
|
158
|
-
except OSError as e:
|
|
159
|
-
logger.error(f"Failed to create PowerShell script: {e}")
|
|
160
|
-
raise
|
|
146
|
+
logger.info("Windows Terminal PowerShell script content generated")
|
|
147
|
+
return script_content
|
|
161
148
|
|
|
162
149
|
def generate_split_pane_command(self, tabs: List[TabConfig], window_name: str | None = None) -> str:
|
|
163
150
|
"""Generate Windows Terminal command with split panes instead of separate tabs."""
|