machineconfig 5.64__py3-none-any.whl → 5.66__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/scripts/python/agents.py +12 -48
- machineconfig/scripts/python/ai/generate_files.py +197 -42
- machineconfig/scripts/python/croshell.py +5 -5
- machineconfig/scripts/python/devops_helpers/cli_config.py +1 -1
- machineconfig/scripts/python/devops_helpers/cli_self.py +3 -3
- machineconfig/scripts/python/devops_navigator.py +1 -890
- machineconfig/scripts/python/entry.py +17 -12
- machineconfig/scripts/python/fire_jobs.py +4 -4
- machineconfig/scripts/python/ftpx.py +4 -4
- machineconfig/scripts/python/helper_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helper_navigator/command_builder.py +111 -0
- machineconfig/scripts/python/helper_navigator/command_detail.py +44 -0
- machineconfig/scripts/python/helper_navigator/command_tree.py +470 -0
- machineconfig/scripts/python/helper_navigator/data_models.py +28 -0
- machineconfig/scripts/python/helper_navigator/main_app.py +262 -0
- machineconfig/scripts/python/helper_navigator/search_bar.py +15 -0
- machineconfig/scripts/python/helpers_fire/template.sh +1 -0
- machineconfig/scripts/python/interactive.py +2 -2
- machineconfig/scripts/python/nw/mount_nfs +1 -1
- machineconfig/scripts/python/repos_helpers/count_lines_frontend.py +1 -1
- machineconfig/scripts/python/sessions.py +1 -1
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- machineconfig/setup_linux/web_shortcuts/interactive.sh +7 -7
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +7 -7
- machineconfig/utils/ssh.py +2 -2
- {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/METADATA +1 -2
- {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/RECORD +30 -24
- machineconfig-5.66.dist-info/entry_points.txt +9 -0
- machineconfig/utils/ai/generate_file_checklist.py +0 -68
- machineconfig-5.64.dist-info/entry_points.txt +0 -9
- {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/WHEEL +0 -0
- {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/top_level.txt +0 -0
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
|
|
2
2
|
from machineconfig.scripts.python.devops import get_app as get_devops_app
|
|
3
|
-
from machineconfig.scripts.python.cloud import
|
|
3
|
+
from machineconfig.scripts.python.cloud import get_app as get_cloud_app
|
|
4
4
|
from machineconfig.scripts.python.agents import get_app as get_agents_app
|
|
5
5
|
from machineconfig.scripts.python.fire_jobs import get_app as get_fire_jobs_app
|
|
6
6
|
from machineconfig.scripts.python.sessions import get_app as get_sessions_app
|
|
7
7
|
|
|
8
|
-
from machineconfig.scripts.python.ftpx import
|
|
9
|
-
from machineconfig.scripts.python.croshell import
|
|
8
|
+
from machineconfig.scripts.python.ftpx import ftpx as ftpx_func
|
|
9
|
+
from machineconfig.scripts.python.croshell import croshell as croshell_func
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
def get_app():
|
|
13
|
+
import typer
|
|
14
|
+
app = typer.Typer(help="MachineConfig CLI - Manage your machine configurations and workflows", no_args_is_help=True)
|
|
15
|
+
app.add_typer(get_devops_app(), name="devops", help="DevOps related commands")
|
|
16
|
+
app.add_typer(get_cloud_app(), name="cloud", help="Cloud management commands")
|
|
17
|
+
app.add_typer(get_sessions_app(), name="sessions", help="Session and layout management")
|
|
18
|
+
app.add_typer(get_fire_jobs_app(), name="fire", help="Fire and manage jobs")
|
|
19
|
+
app.add_typer(get_agents_app(), name="agents", help="🤖 AI Agents management commands")
|
|
13
20
|
|
|
21
|
+
app.command("ftpx", no_args_is_help=True, help="File transfer utility though SSH")(ftpx_func)
|
|
22
|
+
app.command("croshell", no_args_is_help=False, help="Cross-shell command execution")(croshell_func)
|
|
14
23
|
|
|
15
|
-
app
|
|
16
|
-
app.add_typer(get_devops_app(), name="devops", help="DevOps related commands")
|
|
17
|
-
app.add_typer(cloud_app, name="cloud", help="Cloud management commands")
|
|
18
|
-
app.add_typer(get_sessions_app(), name="sessions", help="Session and layout management")
|
|
19
|
-
app.add_typer(get_fire_jobs_app(), name="fire", help="Fire and manage jobs")
|
|
20
|
-
app.add_typer(get_agents_app(), name="agents", help="🤖 AI Agents management commands")
|
|
24
|
+
return app
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
app
|
|
26
|
+
def main():
|
|
27
|
+
app = get_app()
|
|
28
|
+
app()
|
|
@@ -196,7 +196,7 @@ python -m machineconfig.cluster.templates.cli_click --file {choice_file} """
|
|
|
196
196
|
run_shell_script(command)
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
def
|
|
199
|
+
def fire(
|
|
200
200
|
ctx: typer.Context,
|
|
201
201
|
path: Annotated[str, typer.Argument(help="Path to the Python file to run")] = ".",
|
|
202
202
|
function: Annotated[Optional[str], typer.Argument(help="Function to run")] = None,
|
|
@@ -262,13 +262,13 @@ def main(
|
|
|
262
262
|
def get_app():
|
|
263
263
|
from typer import Typer
|
|
264
264
|
app = Typer(add_completion=False)
|
|
265
|
-
app.command(context_settings={"allow_extra_args": True, "allow_interspersed_args": False})(
|
|
265
|
+
app.command(context_settings={"allow_extra_args": True, "allow_interspersed_args": False})(fire)
|
|
266
266
|
return app
|
|
267
267
|
|
|
268
|
-
def
|
|
268
|
+
def main():
|
|
269
269
|
app = get_app()
|
|
270
270
|
app()
|
|
271
271
|
|
|
272
272
|
|
|
273
273
|
if __name__ == "__main__":
|
|
274
|
-
|
|
274
|
+
pass
|
|
@@ -19,7 +19,7 @@ from machineconfig.utils.accessories import pprint
|
|
|
19
19
|
console = Console()
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def
|
|
22
|
+
def ftpx(
|
|
23
23
|
source: Annotated[str, typer.Argument(help="Source path (machine:path)")],
|
|
24
24
|
target: Annotated[str, typer.Argument(help="Target path (machine:path)")],
|
|
25
25
|
recursive: Annotated[bool, typer.Option("--recursive", "-r", help="Send recursively.")] = False,
|
|
@@ -210,12 +210,12 @@ def main(
|
|
|
210
210
|
)
|
|
211
211
|
|
|
212
212
|
|
|
213
|
-
def
|
|
213
|
+
def main() -> None:
|
|
214
214
|
"""Entry point function that uses typer to parse arguments and call main."""
|
|
215
215
|
app = typer.Typer()
|
|
216
|
-
app.command(no_args_is_help=True, help="File transfer utility though SSH.")(
|
|
216
|
+
app.command(no_args_is_help=True, help="File transfer utility though SSH.")(ftpx)
|
|
217
217
|
app()
|
|
218
218
|
|
|
219
219
|
|
|
220
220
|
if __name__ == "__main__":
|
|
221
|
-
|
|
221
|
+
main()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Helper modules for the devops navigator TUI application.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from machineconfig.scripts.python.helper_navigator.data_models import CommandInfo, ArgumentInfo
|
|
6
|
+
from machineconfig.scripts.python.helper_navigator.command_builder import CommandBuilderScreen
|
|
7
|
+
from machineconfig.scripts.python.helper_navigator.command_tree import CommandTree
|
|
8
|
+
from machineconfig.scripts.python.helper_navigator.command_detail import CommandDetail
|
|
9
|
+
from machineconfig.scripts.python.helper_navigator.search_bar import SearchBar
|
|
10
|
+
from machineconfig.scripts.python.helper_navigator.main_app import CommandNavigatorApp
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"CommandInfo",
|
|
14
|
+
"ArgumentInfo",
|
|
15
|
+
"CommandBuilderScreen",
|
|
16
|
+
"CommandTree",
|
|
17
|
+
"CommandDetail",
|
|
18
|
+
"SearchBar",
|
|
19
|
+
"CommandNavigatorApp",
|
|
20
|
+
]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command builder screen for building commands with arguments.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from textual.app import ComposeResult
|
|
7
|
+
from textual.containers import Horizontal, VerticalScroll
|
|
8
|
+
from textual.widgets import Static, Input, Label, Button
|
|
9
|
+
from textual.screen import ModalScreen
|
|
10
|
+
from machineconfig.scripts.python.helper_navigator.data_models import CommandInfo, ArgumentInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CommandBuilderScreen(ModalScreen[str]):
|
|
14
|
+
"""Modal screen for building command with arguments."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, command_info: CommandInfo) -> None:
|
|
17
|
+
super().__init__()
|
|
18
|
+
self.command_info = command_info
|
|
19
|
+
self.arguments = self._parse_arguments()
|
|
20
|
+
self.input_widgets: dict[str, Input] = {}
|
|
21
|
+
|
|
22
|
+
def _parse_arguments(self) -> list[ArgumentInfo]:
|
|
23
|
+
"""Parse arguments from help_text."""
|
|
24
|
+
args: list[ArgumentInfo] = []
|
|
25
|
+
seen_names: set[str] = set()
|
|
26
|
+
|
|
27
|
+
if not self.command_info.help_text:
|
|
28
|
+
return args
|
|
29
|
+
|
|
30
|
+
help_text = self.command_info.help_text
|
|
31
|
+
|
|
32
|
+
optional_pattern = re.compile(r'--(\w+(?:-\w+)*)\s+<([^>]+)>')
|
|
33
|
+
for match in optional_pattern.finditer(help_text):
|
|
34
|
+
arg_name = match.group(1)
|
|
35
|
+
placeholder = match.group(2)
|
|
36
|
+
if arg_name not in seen_names:
|
|
37
|
+
args.append(ArgumentInfo(name=arg_name, is_required=False, is_flag=False, placeholder=placeholder))
|
|
38
|
+
seen_names.add(arg_name)
|
|
39
|
+
|
|
40
|
+
flag_pattern = re.compile(r'--(\w+(?:-\w+)*)(?:\s|$)')
|
|
41
|
+
for match in flag_pattern.finditer(help_text):
|
|
42
|
+
arg_name = match.group(1)
|
|
43
|
+
if arg_name not in seen_names:
|
|
44
|
+
args.append(ArgumentInfo(name=arg_name, is_required=False, is_flag=True))
|
|
45
|
+
seen_names.add(arg_name)
|
|
46
|
+
|
|
47
|
+
positional_pattern = re.compile(r'<(\w+)>(?!\s*>)')
|
|
48
|
+
for match in positional_pattern.finditer(help_text):
|
|
49
|
+
arg_name = match.group(1)
|
|
50
|
+
if arg_name not in seen_names and not re.search(rf'--\w+\s+<{arg_name}>', help_text):
|
|
51
|
+
args.append(ArgumentInfo(name=arg_name, is_required=True, is_flag=False, placeholder=arg_name))
|
|
52
|
+
seen_names.add(arg_name)
|
|
53
|
+
|
|
54
|
+
return args
|
|
55
|
+
|
|
56
|
+
def compose(self) -> ComposeResult:
|
|
57
|
+
"""Compose the modal screen."""
|
|
58
|
+
with VerticalScroll():
|
|
59
|
+
yield Static(f"[bold cyan]Build Command: {self.command_info.command}[/bold cyan]\n", classes="title")
|
|
60
|
+
|
|
61
|
+
if not self.arguments:
|
|
62
|
+
yield Static("[yellow]No arguments needed for this command[/yellow]\n")
|
|
63
|
+
else:
|
|
64
|
+
for arg in self.arguments:
|
|
65
|
+
if arg.is_flag:
|
|
66
|
+
label_text = f"--{arg.name} (flag, leave empty to skip)"
|
|
67
|
+
yield Label(label_text)
|
|
68
|
+
input_widget = Input(placeholder="yes/no or leave empty", id=f"arg_{arg.name}")
|
|
69
|
+
else:
|
|
70
|
+
required_marker = "[red]*[/red]" if arg.is_required else "[dim](optional)[/dim]"
|
|
71
|
+
label_text = f"--{arg.name} {required_marker}"
|
|
72
|
+
yield Label(label_text)
|
|
73
|
+
input_widget = Input(placeholder=arg.placeholder or arg.name, id=f"arg_{arg.name}")
|
|
74
|
+
|
|
75
|
+
self.input_widgets[arg.name] = input_widget
|
|
76
|
+
yield input_widget
|
|
77
|
+
|
|
78
|
+
with Horizontal(classes="buttons"):
|
|
79
|
+
yield Button("Execute", variant="primary", id="execute")
|
|
80
|
+
yield Button("Copy", variant="success", id="copy")
|
|
81
|
+
yield Button("Cancel", variant="error", id="cancel")
|
|
82
|
+
|
|
83
|
+
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
84
|
+
"""Handle button presses."""
|
|
85
|
+
if event.button.id == "cancel":
|
|
86
|
+
self.dismiss("")
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
built_command = self._build_command()
|
|
90
|
+
|
|
91
|
+
if event.button.id == "execute":
|
|
92
|
+
self.dismiss(f"EXECUTE:{built_command}")
|
|
93
|
+
elif event.button.id == "copy":
|
|
94
|
+
self.dismiss(f"COPY:{built_command}")
|
|
95
|
+
|
|
96
|
+
def _build_command(self) -> str:
|
|
97
|
+
"""Build the complete command with arguments."""
|
|
98
|
+
parts = [self.command_info.command]
|
|
99
|
+
|
|
100
|
+
for arg in self.arguments:
|
|
101
|
+
input_widget = self.input_widgets.get(arg.name)
|
|
102
|
+
if input_widget:
|
|
103
|
+
value = input_widget.value.strip()
|
|
104
|
+
if value:
|
|
105
|
+
if arg.is_flag:
|
|
106
|
+
if value.lower() in ('yes', 'y', 'true', '1'):
|
|
107
|
+
parts.append(f"--{arg.name}")
|
|
108
|
+
else:
|
|
109
|
+
parts.append(f"--{arg.name} {value}")
|
|
110
|
+
|
|
111
|
+
return " ".join(parts)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command detail widget for displaying command information.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from textual.widgets import Static
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
from machineconfig.scripts.python.helper_navigator.data_models import CommandInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CommandDetail(Static):
|
|
13
|
+
"""Widget for displaying command details."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, *, id: str) -> None: # type: ignore
|
|
16
|
+
super().__init__(id=id)
|
|
17
|
+
self.command_info: Optional[CommandInfo] = None
|
|
18
|
+
|
|
19
|
+
def update_command(self, command_info: Optional[CommandInfo]) -> None:
|
|
20
|
+
"""Update displayed command information."""
|
|
21
|
+
self.command_info = command_info
|
|
22
|
+
if command_info is None:
|
|
23
|
+
self.update("Select a command to view details")
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
content = Text()
|
|
27
|
+
content.append(f"{'🗂️ Group' if command_info.is_group else '⚡ Command'}: ", style="bold cyan")
|
|
28
|
+
content.append(f"{command_info.name}\n\n", style="bold yellow")
|
|
29
|
+
|
|
30
|
+
content.append("Description: ", style="bold green")
|
|
31
|
+
content.append(f"{command_info.description}\n\n", style="white")
|
|
32
|
+
|
|
33
|
+
content.append("Command: ", style="bold blue")
|
|
34
|
+
content.append(f"{command_info.command}\n\n", style="bold white")
|
|
35
|
+
|
|
36
|
+
if command_info.help_text:
|
|
37
|
+
content.append("Usage: ", style="bold magenta")
|
|
38
|
+
content.append(f"{command_info.help_text}\n\n", style="white")
|
|
39
|
+
|
|
40
|
+
if command_info.module_path:
|
|
41
|
+
content.append("Module: ", style="bold red")
|
|
42
|
+
content.append(f"{command_info.module_path}\n", style="white")
|
|
43
|
+
|
|
44
|
+
self.update(Panel(content, title=f"[bold]{command_info.name}[/bold]", border_style="blue"))
|