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.

Files changed (32) hide show
  1. machineconfig/scripts/python/agents.py +12 -48
  2. machineconfig/scripts/python/ai/generate_files.py +197 -42
  3. machineconfig/scripts/python/croshell.py +5 -5
  4. machineconfig/scripts/python/devops_helpers/cli_config.py +1 -1
  5. machineconfig/scripts/python/devops_helpers/cli_self.py +3 -3
  6. machineconfig/scripts/python/devops_navigator.py +1 -890
  7. machineconfig/scripts/python/entry.py +17 -12
  8. machineconfig/scripts/python/fire_jobs.py +4 -4
  9. machineconfig/scripts/python/ftpx.py +4 -4
  10. machineconfig/scripts/python/helper_navigator/__init__.py +20 -0
  11. machineconfig/scripts/python/helper_navigator/command_builder.py +111 -0
  12. machineconfig/scripts/python/helper_navigator/command_detail.py +44 -0
  13. machineconfig/scripts/python/helper_navigator/command_tree.py +470 -0
  14. machineconfig/scripts/python/helper_navigator/data_models.py +28 -0
  15. machineconfig/scripts/python/helper_navigator/main_app.py +262 -0
  16. machineconfig/scripts/python/helper_navigator/search_bar.py +15 -0
  17. machineconfig/scripts/python/helpers_fire/template.sh +1 -0
  18. machineconfig/scripts/python/interactive.py +2 -2
  19. machineconfig/scripts/python/nw/mount_nfs +1 -1
  20. machineconfig/scripts/python/repos_helpers/count_lines_frontend.py +1 -1
  21. machineconfig/scripts/python/sessions.py +1 -1
  22. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
  23. machineconfig/setup_linux/web_shortcuts/interactive.sh +7 -7
  24. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +7 -7
  25. machineconfig/utils/ssh.py +2 -2
  26. {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/METADATA +1 -2
  27. {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/RECORD +30 -24
  28. machineconfig-5.66.dist-info/entry_points.txt +9 -0
  29. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  30. machineconfig-5.64.dist-info/entry_points.txt +0 -9
  31. {machineconfig-5.64.dist-info → machineconfig-5.66.dist-info}/WHEEL +0 -0
  32. {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 app as cloud_app
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 main as ftpx_func
9
- from machineconfig.scripts.python.croshell import main as croshell_func
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
- import typer
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 = typer.Typer(help="MachineConfig CLI - Manage your machine configurations and workflows", no_args_is_help=True)
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
- app.command("ftpx", no_args_is_help=True, help="File transfer utility though SSH")(ftpx_func)
23
- app.command("croshell", no_args_is_help=False, help="Cross-shell command execution")(croshell_func)
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 main(
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})(main)
265
+ app.command(context_settings={"allow_extra_args": True, "allow_interspersed_args": False})(fire)
266
266
  return app
267
267
 
268
- def main_from_parser():
268
+ def main():
269
269
  app = get_app()
270
270
  app()
271
271
 
272
272
 
273
273
  if __name__ == "__main__":
274
- main_from_parser()
274
+ pass
@@ -19,7 +19,7 @@ from machineconfig.utils.accessories import pprint
19
19
  console = Console()
20
20
 
21
21
 
22
- def main(
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 main_from_parser() -> None:
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.")(main)
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
- main_from_parser()
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"))