machineconfig 4.7__py3-none-any.whl → 4.9__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/wt_local_manager.py +15 -6
- machineconfig/jobs/installer/custom_dev/winget.py +1 -0
- machineconfig/jobs/installer/installer_data.json +2403 -0
- machineconfig/jobs/installer/package_groups.py +154 -0
- machineconfig/scripts/python/devops.py +33 -42
- machineconfig/scripts/python/devops_devapps_install.py +87 -34
- machineconfig/scripts/python/fire_agents.py +49 -70
- machineconfig/scripts/python/fire_agents_help_launch.py +1 -8
- machineconfig/scripts/python/fire_agents_helper_types.py +12 -0
- machineconfig/scripts/python/fire_jobs.py +0 -6
- machineconfig/scripts/python/fire_jobs_args_helper.py +0 -1
- machineconfig/scripts/python/fire_jobs_layout_helper.py +100 -36
- machineconfig/scripts/python/interactive.py +10 -31
- machineconfig/scripts/python/repos.py +7 -6
- machineconfig/scripts/python/share_terminal.py +6 -4
- machineconfig/setup_linux/web_shortcuts/interactive.sh +1 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +1 -1
- machineconfig/utils/installer.py +15 -14
- machineconfig/utils/installer_utils/github_release_bulk.py +2 -12
- machineconfig/utils/installer_utils/installer_abc.py +56 -60
- machineconfig/utils/procs.py +0 -4
- machineconfig/utils/schemas/installer/installer_types.py +0 -1
- {machineconfig-4.7.dist-info → machineconfig-4.9.dist-info}/METADATA +1 -1
- {machineconfig-4.7.dist-info → machineconfig-4.9.dist-info}/RECORD +27 -30
- {machineconfig-4.7.dist-info → machineconfig-4.9.dist-info}/entry_points.txt +0 -1
- machineconfig/jobs/installer/packages_custom_dev.json +0 -380
- machineconfig/jobs/installer/packages_custom_essential.json +0 -39
- machineconfig/jobs/installer/packages_github_dev.json +0 -1127
- machineconfig/jobs/installer/packages_github_essential.json +0 -787
- machineconfig/scripts/linux/fire_agents +0 -2
- machineconfig/scripts/linux/programs +0 -21
- {machineconfig-4.7.dist-info → machineconfig-4.9.dist-info}/WHEEL +0 -0
- {machineconfig-4.7.dist-info → machineconfig-4.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from typing import Literal, TypeAlias, Union
|
|
2
|
+
|
|
3
|
+
PACKAGES_NAMES_DEV = Literal[
|
|
4
|
+
"ngrok",
|
|
5
|
+
"Visual Studio Code",
|
|
6
|
+
"aider",
|
|
7
|
+
"github-copilot-cli",
|
|
8
|
+
"gemini",
|
|
9
|
+
"crush",
|
|
10
|
+
"opencode-ai",
|
|
11
|
+
"warp",
|
|
12
|
+
"q",
|
|
13
|
+
"cursor-cli",
|
|
14
|
+
"droid",
|
|
15
|
+
"Alacritty",
|
|
16
|
+
"Brave",
|
|
17
|
+
"bypass-paywalls-chrome",
|
|
18
|
+
"Cursor",
|
|
19
|
+
"espanso",
|
|
20
|
+
"Gorilla",
|
|
21
|
+
"lvim",
|
|
22
|
+
"nerdfont",
|
|
23
|
+
"Redis",
|
|
24
|
+
"Wezterm",
|
|
25
|
+
"winget",
|
|
26
|
+
"ytui-music",
|
|
27
|
+
"youtube-tui",
|
|
28
|
+
"termusic",
|
|
29
|
+
"kronos",
|
|
30
|
+
"transmission",
|
|
31
|
+
"nnn",
|
|
32
|
+
"exa",
|
|
33
|
+
"bytehound",
|
|
34
|
+
"atuin",
|
|
35
|
+
"browsh",
|
|
36
|
+
"carbonyl",
|
|
37
|
+
"patat",
|
|
38
|
+
"SqliteBrowser",
|
|
39
|
+
"DBeaver",
|
|
40
|
+
"rainfrog",
|
|
41
|
+
"duckdb",
|
|
42
|
+
"cpz",
|
|
43
|
+
"rmz",
|
|
44
|
+
"mermaid-cli",
|
|
45
|
+
"html2markdown",
|
|
46
|
+
"xcrawl3r",
|
|
47
|
+
"obsidian",
|
|
48
|
+
"marp",
|
|
49
|
+
"presenterm",
|
|
50
|
+
"pandoc",
|
|
51
|
+
"devcontainer",
|
|
52
|
+
"bitwarden",
|
|
53
|
+
"OBS Background removal",
|
|
54
|
+
"rustdesk",
|
|
55
|
+
"evcxr",
|
|
56
|
+
"forward-cli",
|
|
57
|
+
"bandwhich",
|
|
58
|
+
"ipinfo",
|
|
59
|
+
"dust",
|
|
60
|
+
"ots",
|
|
61
|
+
"ffsend",
|
|
62
|
+
"portal",
|
|
63
|
+
"qrcp",
|
|
64
|
+
"qrscan",
|
|
65
|
+
"termscp",
|
|
66
|
+
"qr",
|
|
67
|
+
"filebrowser",
|
|
68
|
+
"cloudreve",
|
|
69
|
+
"restic",
|
|
70
|
+
"syncthing",
|
|
71
|
+
"istio",
|
|
72
|
+
"openpomodoro-cli",
|
|
73
|
+
"rust-analyzer",
|
|
74
|
+
"kondo",
|
|
75
|
+
"tokei",
|
|
76
|
+
"lazygit",
|
|
77
|
+
"lazydocker",
|
|
78
|
+
"onefetch",
|
|
79
|
+
"gitcs",
|
|
80
|
+
"just",
|
|
81
|
+
"navi",
|
|
82
|
+
"tealdeer",
|
|
83
|
+
"sniffnet",
|
|
84
|
+
"hyperfine",
|
|
85
|
+
"ollama",
|
|
86
|
+
"cointop",
|
|
87
|
+
"vtm",
|
|
88
|
+
"edex-ui",
|
|
89
|
+
"extraterm",
|
|
90
|
+
"nushell",
|
|
91
|
+
"geckodriver",
|
|
92
|
+
"lolcatjs",
|
|
93
|
+
"figlet-cli",
|
|
94
|
+
"sharewifi",
|
|
95
|
+
"share-wifi",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
PACKAGES_NAMES_ESSENTIAL = Literal[
|
|
99
|
+
"gh",
|
|
100
|
+
"hx",
|
|
101
|
+
"speedtest",
|
|
102
|
+
"pistol",
|
|
103
|
+
"diskonaut",
|
|
104
|
+
"xplr",
|
|
105
|
+
"btop",
|
|
106
|
+
"gotty",
|
|
107
|
+
"joshuto",
|
|
108
|
+
"zellij",
|
|
109
|
+
"boxes",
|
|
110
|
+
"ugrep",
|
|
111
|
+
"zoomit",
|
|
112
|
+
"ntop",
|
|
113
|
+
"devtunnel",
|
|
114
|
+
"bat",
|
|
115
|
+
"broot",
|
|
116
|
+
"btm",
|
|
117
|
+
"chatgpt",
|
|
118
|
+
"cloudflared",
|
|
119
|
+
"cpufetch",
|
|
120
|
+
"delta",
|
|
121
|
+
"dua",
|
|
122
|
+
"fastfetch",
|
|
123
|
+
"fd",
|
|
124
|
+
"fzf",
|
|
125
|
+
"gitui",
|
|
126
|
+
"glow",
|
|
127
|
+
"gum",
|
|
128
|
+
"lf",
|
|
129
|
+
"lsd",
|
|
130
|
+
"m365",
|
|
131
|
+
"mcfly",
|
|
132
|
+
"mods",
|
|
133
|
+
"mprocs",
|
|
134
|
+
"ouch",
|
|
135
|
+
"procs",
|
|
136
|
+
"rclone",
|
|
137
|
+
"rg",
|
|
138
|
+
"rga",
|
|
139
|
+
"starship",
|
|
140
|
+
"tere",
|
|
141
|
+
"topgrade",
|
|
142
|
+
"ttyd",
|
|
143
|
+
"viu",
|
|
144
|
+
"watchexec",
|
|
145
|
+
"yazi",
|
|
146
|
+
"zoxide",
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
PACKAGE_GROUPS: TypeAlias = Literal["ESSENTIAL", "DEV"]
|
|
150
|
+
PACKAGE_GROUP2NAMES: dict[PACKAGE_GROUPS, list[str]] = {
|
|
151
|
+
"ESSENTIAL": list(PACKAGES_NAMES_ESSENTIAL.__args__),
|
|
152
|
+
"DEV": list(PACKAGES_NAMES_DEV.__args__),
|
|
153
|
+
}
|
|
154
|
+
_ = Union
|
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
"""devops with emojis"""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import machineconfig.scripts.python.fire_agents as fire_agents
|
|
4
|
+
import machineconfig.scripts.python.fire_jobs_layout_helper as fire_jobs_layout_helper
|
|
4
5
|
import machineconfig.scripts.python.devops_devapps_install as installer_entry_point
|
|
6
|
+
import machineconfig.scripts.python.share_terminal as share_terminal
|
|
7
|
+
import machineconfig.scripts.python.repos as repos
|
|
5
8
|
|
|
6
|
-
from platform import system
|
|
7
|
-
from rich.console import Console
|
|
8
|
-
from rich.panel import Panel
|
|
9
9
|
import typer
|
|
10
10
|
|
|
11
|
-
console = Console()
|
|
12
11
|
app = typer.Typer(help="🛠️ DevOps operations with emojis", no_args_is_help=True)
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
agents_app = typer.Typer(help="🤖 AI Agents management subcommands")
|
|
15
|
+
agents_app.command("create")(fire_agents.create)
|
|
16
|
+
agents_app.command("collect")(fire_agents.collect)
|
|
17
|
+
app.add_typer(agents_app, name="agents")
|
|
18
|
+
|
|
19
|
+
layouts_app = typer.Typer(help="Layouts management subcommands")
|
|
20
|
+
layouts_app.command("launch")(fire_jobs_layout_helper.launch)
|
|
21
|
+
layouts_app.command("load-balance")(fire_jobs_layout_helper.load_balance)
|
|
22
|
+
app.add_typer(layouts_app, name="session")
|
|
23
|
+
|
|
24
|
+
app.command(name="install", help="📦 Install essential packages")(installer_entry_point.main)
|
|
25
|
+
app.command(name="share-terminal", help="📡 Share terminal via web browser")(share_terminal.main)
|
|
26
|
+
app.command(name="repos", help="📁 Manage git repositories")(repos.main)
|
|
27
|
+
|
|
28
|
+
ssh_app = typer.Typer(help="🔐 SSH operations subcommands", no_args_is_help=True)
|
|
29
|
+
app.add_typer(ssh_app, name="ssh")
|
|
16
30
|
|
|
17
31
|
|
|
18
32
|
@app.command()
|
|
19
33
|
def update():
|
|
20
34
|
"""🔄 UPDATE essential repos"""
|
|
21
|
-
console.print(Panel("🔄 Updating essential repositories...", width=BOX_WIDTH, border_style="blue"))
|
|
22
35
|
import machineconfig.scripts.python.devops_update_repos as helper
|
|
23
36
|
helper.main()
|
|
24
37
|
|
|
25
38
|
|
|
26
|
-
app.command(name="install", help="📦 Install essential packages")(installer_entry_point.main)
|
|
27
|
-
app.command(name="share-terminal", help="📡 Share terminal via web browser")(share_terminal_main)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
39
|
@app.command()
|
|
32
40
|
def symlinks():
|
|
33
41
|
"""🔗 SYMLINKS of dotfiles."""
|
|
34
|
-
console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
|
|
35
42
|
import machineconfig.profile.create as helper
|
|
36
43
|
helper.main_symlinks()
|
|
37
44
|
|
|
@@ -39,7 +46,6 @@ def symlinks():
|
|
|
39
46
|
@app.command()
|
|
40
47
|
def profile():
|
|
41
48
|
"""🔗 Update shell profile."""
|
|
42
|
-
console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
|
|
43
49
|
import machineconfig.profile.create as helper
|
|
44
50
|
helper.main_profile()
|
|
45
51
|
|
|
@@ -47,48 +53,35 @@ def profile():
|
|
|
47
53
|
@app.command()
|
|
48
54
|
def symlinks_new():
|
|
49
55
|
"""🆕 SYMLINKS new"""
|
|
50
|
-
console.print(Panel("🔄 Creating new symlinks...", width=BOX_WIDTH, border_style="blue"))
|
|
51
56
|
import machineconfig.jobs.python.python_ve_symlink as helper
|
|
52
57
|
helper.main()
|
|
53
58
|
|
|
54
59
|
|
|
55
|
-
@
|
|
56
|
-
def
|
|
60
|
+
@ssh_app.command()
|
|
61
|
+
def add_key():
|
|
57
62
|
"""🔑 SSH add pub key to this machine"""
|
|
58
|
-
console.print(Panel("🔑 Adding public SSH key to this machine...", width=BOX_WIDTH, border_style="blue"))
|
|
59
63
|
import machineconfig.scripts.python.devops_add_ssh_key as helper
|
|
60
64
|
helper.main()
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@app.command()
|
|
64
|
-
def ssh_add_identity():
|
|
65
|
+
@ssh_app.command()
|
|
66
|
+
def add_identity():
|
|
65
67
|
"""🗝️ SSH add identity (private key) to this machine"""
|
|
66
|
-
console.print(Panel("🗝️ Adding SSH identity (private key) to this machine...", width=BOX_WIDTH, border_style="blue"))
|
|
67
68
|
import machineconfig.scripts.python.devops_add_identity as helper
|
|
68
69
|
helper.main()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@app.command()
|
|
72
|
-
def ssh_connect():
|
|
70
|
+
@ssh_app.command()
|
|
71
|
+
def connect():
|
|
73
72
|
"""🔐 SSH use key pair to connect two machines"""
|
|
74
|
-
console.print(Panel("❌ ERROR: Not Implemented\nSSH key pair connection feature is not yet implemented", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
75
73
|
raise NotImplementedError
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@app.command()
|
|
79
|
-
def ssh_setup():
|
|
74
|
+
@ssh_app.command()
|
|
75
|
+
def setup():
|
|
80
76
|
"""📡 SSH setup"""
|
|
81
|
-
console.print(Panel("📡 Setting up SSH...", width=BOX_WIDTH, border_style="blue"))
|
|
82
77
|
_program_windows = """Invoke-WebRequest https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/openssh_all.ps1 | Invoke-Expression # https://github.com/thisismygitrepo.keys"""
|
|
83
78
|
_program_linux = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_all.sh | sudo bash # https://github.com/thisismygitrepo.keys"""
|
|
84
79
|
import subprocess
|
|
80
|
+
from platform import system
|
|
85
81
|
subprocess.run(_program_linux if system() == "Linux" else _program_windows, shell=True, check=True)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@app.command()
|
|
89
|
-
def ssh_setup_wsl():
|
|
82
|
+
@ssh_app.command()
|
|
83
|
+
def setup_wsl():
|
|
90
84
|
"""🐧 SSH setup wsl"""
|
|
91
|
-
console.print(Panel("🐧 Setting up SSH for WSL...", width=BOX_WIDTH, border_style="blue"))
|
|
92
85
|
import subprocess
|
|
93
86
|
subprocess.run("curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_wsl.sh | sudo bash", shell=True, check=True)
|
|
94
87
|
|
|
@@ -96,7 +89,6 @@ def ssh_setup_wsl():
|
|
|
96
89
|
@app.command()
|
|
97
90
|
def backup():
|
|
98
91
|
"""💾 BACKUP"""
|
|
99
|
-
console.print(Panel("💾 Creating backup...", width=BOX_WIDTH, border_style="blue"))
|
|
100
92
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
|
|
101
93
|
main_backup_retrieve(direction="BACKUP")
|
|
102
94
|
|
|
@@ -104,7 +96,6 @@ def backup():
|
|
|
104
96
|
@app.command()
|
|
105
97
|
def retrieve():
|
|
106
98
|
"""📥 RETRIEVE"""
|
|
107
|
-
console.print(Panel("📥 Retrieving backup...", width=BOX_WIDTH, border_style="blue"))
|
|
108
99
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
|
|
109
100
|
main_backup_retrieve(direction="RETRIEVE")
|
|
110
101
|
|
|
@@ -112,16 +103,16 @@ def retrieve():
|
|
|
112
103
|
@app.command()
|
|
113
104
|
def scheduler():
|
|
114
105
|
"""⏰ SCHEDULER"""
|
|
115
|
-
console.print(Panel("⏰ Setting up scheduler...", width=BOX_WIDTH, border_style="blue"))
|
|
116
106
|
# from machineconfig.scripts.python.scheduler import main as helper
|
|
117
107
|
# helper()
|
|
118
108
|
|
|
119
|
-
@app.command(
|
|
109
|
+
@app.command()
|
|
120
110
|
def interactive():
|
|
121
111
|
"""🤖 INTERACTIVE configuration of machine."""
|
|
122
112
|
from machineconfig.scripts.python.interactive import main
|
|
123
113
|
main()
|
|
124
114
|
|
|
125
115
|
|
|
116
|
+
|
|
126
117
|
if __name__ == "__main__":
|
|
127
118
|
pass
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
4
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
from rich.panel import Panel
|
|
7
|
+
from rich.table import Table
|
|
5
8
|
from platform import system
|
|
6
9
|
from typing import Optional, Literal, TypeAlias, cast, get_args, Annotated
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
WHICH_CAT: TypeAlias = Literal["essentials", "essentialsDev", "systemPackages", "precheckedPackages", "ia"]
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
def _handle_installer_not_found(search_term: str, all_installers: list["InstallerData"]) -> None: # type: ignore
|
|
@@ -21,27 +26,37 @@ def _handle_installer_not_found(search_term: str, all_installers: list["Installe
|
|
|
21
26
|
# Find close matches using fuzzy matching
|
|
22
27
|
close_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
|
|
23
28
|
|
|
24
|
-
print(f"\n❌ '{search_term}' was not found.")
|
|
29
|
+
console.print(f"\n❌ '[red]{search_term}[/red]' was not found.", style="bold")
|
|
25
30
|
|
|
26
31
|
if close_matches:
|
|
27
|
-
print("🤔 Did you mean one of these?")
|
|
32
|
+
console.print("🤔 Did you mean one of these?", style="yellow")
|
|
33
|
+
table = Table(show_header=False, box=None, pad_edge=False)
|
|
28
34
|
for i, match in enumerate(close_matches, 1):
|
|
29
|
-
|
|
35
|
+
table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{match}[/green]")
|
|
36
|
+
console.print(table)
|
|
30
37
|
else:
|
|
31
|
-
print("📋 Here are some available options:")
|
|
38
|
+
console.print("📋 Here are some available options:", style="blue")
|
|
32
39
|
# Show first 10 installers as examples
|
|
33
40
|
sample_names = []
|
|
34
41
|
for inst in all_installers[:10]:
|
|
35
42
|
exe_name = inst["appName"]
|
|
36
43
|
sample_names.append(exe_name)
|
|
44
|
+
|
|
45
|
+
table = Table(show_header=False, box=None, pad_edge=False)
|
|
37
46
|
for i, name in enumerate(sample_names, 1):
|
|
38
|
-
|
|
47
|
+
table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{name}[/green]")
|
|
48
|
+
console.print(table)
|
|
39
49
|
|
|
40
50
|
if len(all_installers) > 10:
|
|
41
|
-
print(f" ... and {len(all_installers) - 10} more")
|
|
51
|
+
console.print(f" [dim]... and {len(all_installers) - 10} more[/dim]")
|
|
42
52
|
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
panel = Panel(
|
|
54
|
+
"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n"
|
|
55
|
+
f"[bold blue]💡 Use one of the categories: {list(get_args(WHICH_CAT))}[/bold blue]",
|
|
56
|
+
title="[yellow]Helpful Tips[/yellow]",
|
|
57
|
+
border_style="yellow"
|
|
58
|
+
)
|
|
59
|
+
console.print(panel)
|
|
45
60
|
|
|
46
61
|
|
|
47
62
|
def main_with_parser():
|
|
@@ -60,7 +75,7 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
60
75
|
if which != "ia" and which is not None: # install by name
|
|
61
76
|
total_messages: list[str] = []
|
|
62
77
|
for a_which in which.split(",") if type(which) == str else which:
|
|
63
|
-
all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
78
|
+
all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
|
|
64
79
|
|
|
65
80
|
# Find installer by exe_name or name
|
|
66
81
|
selected_installer = None
|
|
@@ -76,8 +91,11 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
76
91
|
return None
|
|
77
92
|
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
78
93
|
total_messages.append(message)
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
|
|
95
|
+
if total_messages:
|
|
96
|
+
console.print("\n[bold green]📊 Installation Results:[/bold green]")
|
|
97
|
+
for a_message in total_messages:
|
|
98
|
+
console.print(f"[blue]• {a_message}[/blue]")
|
|
81
99
|
return None
|
|
82
100
|
|
|
83
101
|
|
|
@@ -87,7 +105,7 @@ def install_interactively():
|
|
|
87
105
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
88
106
|
from machineconfig.utils.installer import get_installers
|
|
89
107
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
90
|
-
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
108
|
+
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
|
|
91
109
|
with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
|
|
92
110
|
task = progress.add_task("✅ Checking installed programs...", total=len(installers))
|
|
93
111
|
installer_options = []
|
|
@@ -110,17 +128,24 @@ def install_interactively():
|
|
|
110
128
|
an_installer_data = installers[installer_idx]
|
|
111
129
|
status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
|
|
112
130
|
installation_messages.append(status_message)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
if installation_messages:
|
|
132
|
+
panel = Panel(
|
|
133
|
+
"\n".join([f"[blue]• {message}[/blue]" for message in installation_messages]),
|
|
134
|
+
title="[bold green]📊 Installation Summary[/bold green]",
|
|
135
|
+
border_style="green",
|
|
136
|
+
padding=(1, 2)
|
|
137
|
+
)
|
|
138
|
+
console.print(panel)
|
|
117
139
|
|
|
118
140
|
|
|
119
141
|
def get_programs_by_category(program_name: WHICH_CAT):
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
142
|
+
panel = Panel(
|
|
143
|
+
f"[bold yellow]Installing programs from category: [green]{program_name}[/green][/bold yellow]",
|
|
144
|
+
title="[bold blue]📦 Category Installation[/bold blue]",
|
|
145
|
+
border_style="blue",
|
|
146
|
+
padding=(1, 2)
|
|
147
|
+
)
|
|
148
|
+
console.print(panel)
|
|
124
149
|
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
125
150
|
from machineconfig.utils.installer import get_installers, install_all
|
|
126
151
|
from machineconfig.utils.installer_utils.installer_abc import parse_apps_installer_linux, parse_apps_installer_windows
|
|
@@ -128,31 +153,59 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
128
153
|
from machineconfig.utils.options import choose_from_options
|
|
129
154
|
match program_name:
|
|
130
155
|
case "essentials":
|
|
131
|
-
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
156
|
+
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL"])
|
|
132
157
|
install_all(installers_data=installers_)
|
|
133
158
|
case "essentialsDev":
|
|
134
|
-
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
159
|
+
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["DEV", "ESSENTIAL"])
|
|
135
160
|
install_all(installers_data=installers_)
|
|
136
|
-
case "
|
|
161
|
+
case "systemPackages":
|
|
137
162
|
if system() == "Windows":
|
|
138
163
|
options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
|
|
139
164
|
elif system() == "Linux":
|
|
140
|
-
|
|
141
|
-
options_system_2 = parse_apps_installer_linux(LIBRARY_ROOT.joinpath("setup_linux/apps.sh").read_text(encoding="utf-8"))
|
|
142
|
-
options_system = {**options_system_1, **options_system_2}
|
|
165
|
+
options_system = parse_apps_installer_linux(LIBRARY_ROOT.joinpath("setup_linux/apps.sh").read_text(encoding="utf-8"))
|
|
143
166
|
else:
|
|
144
167
|
raise NotImplementedError(f"❌ System {system()} not supported")
|
|
145
|
-
|
|
168
|
+
|
|
169
|
+
# Create display options that include descriptions for user selection
|
|
170
|
+
display_options = []
|
|
171
|
+
for group_name, (description, _) in options_system.items():
|
|
172
|
+
if description:
|
|
173
|
+
display_options.append(f"{group_name:<20} - {description}")
|
|
174
|
+
else:
|
|
175
|
+
display_options.append(group_name)
|
|
176
|
+
|
|
177
|
+
program_names = choose_from_options(multi=True, msg="", options=sorted(display_options), header="🚀 CHOOSE DEV APP", fzf=True)
|
|
146
178
|
program = ""
|
|
147
|
-
for
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
179
|
+
for display_name in program_names:
|
|
180
|
+
# Extract the actual group name (everything before " - " if present)
|
|
181
|
+
group_name = display_name.split(" - ")[0].strip() if " - " in display_name else display_name.strip()
|
|
182
|
+
|
|
183
|
+
console.print(f"\n[bold cyan]⚙️ Installing: [yellow]{group_name}[/yellow][/bold cyan]", style="bold")
|
|
184
|
+
|
|
185
|
+
_, sub_program = options_system[group_name] # Extract content from tuple
|
|
153
186
|
if sub_program.startswith("#winget"):
|
|
154
187
|
sub_program = sub_program[1:]
|
|
155
188
|
program += "\n" + sub_program
|
|
189
|
+
from pathlib import Path
|
|
190
|
+
if system() == "Windows":
|
|
191
|
+
temp_script_path = Path("C:/Windows/Temp/temp_install_script.ps1")
|
|
192
|
+
lexer = "powershell"
|
|
193
|
+
else:
|
|
194
|
+
temp_script_path = Path("/tmp/temp_install_script.sh")
|
|
195
|
+
lexer = "bash"
|
|
196
|
+
temp_script_path.write_text(program, encoding="utf-8")
|
|
197
|
+
console.print(f"📝 [blue]Temporary script written to:[/blue] [green]{temp_script_path}[/green]")
|
|
198
|
+
from rich.syntax import Syntax
|
|
199
|
+
console.print(Panel(Syntax(code=program, lexer=lexer), title="📄 Installation Program", subtitle="shell code"), style="bold red")
|
|
200
|
+
console.print("🚀 [bold yellow]Starting installation...[/bold yellow]")
|
|
201
|
+
if system() == "Windows":
|
|
202
|
+
import subprocess
|
|
203
|
+
subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(temp_script_path)], check=True)
|
|
204
|
+
elif system() == "Linux":
|
|
205
|
+
import subprocess
|
|
206
|
+
subprocess.run(["bash", str(temp_script_path)], check=True)
|
|
207
|
+
console.print("✅ [bold green]Installation completed.[/bold green]")
|
|
208
|
+
temp_script_path.unlink(missing_ok=True)
|
|
156
209
|
case "ia":
|
|
157
210
|
install_interactively()
|
|
158
211
|
case "precheckedPackages":
|
|
@@ -1,35 +1,11 @@
|
|
|
1
1
|
"""Utilitfrom pathlib import Path
|
|
2
|
-
from typing import cast, get_args, Iterable, Optional, TypeAlias, Literal
|
|
3
|
-
import json
|
|
4
|
-
import typer
|
|
5
|
-
|
|
6
|
-
from machineconfig.scripts.python.fire_agents_help_launch import prep_agent_launch, get_agents_launch_layout, AGENTS
|
|
7
|
-
from machineconfig.scripts.python.fire_agents_help_search import search_files_by_pattern, search_python_files
|
|
8
|
-
from machineconfig.scripts.python.fire_agents_load_balancer import chunk_prompts
|
|
9
|
-
from machineconfig.utils.accessories import get_repo_rootch multiple AI agent prompts in a Zellij session.
|
|
10
2
|
|
|
11
|
-
Improved design notes:
|
|
12
|
-
* Clear separation of: input collection, prompt preparation, agent launch.
|
|
13
|
-
* Configurable max agent cap (default 15) with interactive confirmation if exceeded.
|
|
14
|
-
* Added type aliases + docstrings for maintainability.
|
|
15
|
-
* Preserves original core behavior & command generation for each agent type.
|
|
16
3
|
"""
|
|
17
4
|
|
|
18
5
|
from pathlib import Path
|
|
19
|
-
from typing import cast, Iterable, Optional,
|
|
20
|
-
import json
|
|
21
|
-
import time
|
|
6
|
+
from typing import cast, Iterable, Optional, get_args
|
|
22
7
|
import typer
|
|
23
|
-
|
|
24
|
-
from machineconfig.scripts.python.fire_agents_help_launch import prep_agent_launch, get_agents_launch_layout, AGENTS
|
|
25
|
-
from machineconfig.scripts.python.fire_agents_help_search import search_files_by_pattern, search_python_files
|
|
26
|
-
from machineconfig.scripts.python.fire_agents_load_balancer import chunk_prompts
|
|
27
|
-
from machineconfig.utils.schemas.layouts.layout_types import LayoutsFile
|
|
28
|
-
from machineconfig.utils.accessories import get_repo_root, randstr
|
|
29
|
-
|
|
30
|
-
SEARCH_STRATEGIES: TypeAlias = Literal["file_path", "keyword_search", "filename_pattern"]
|
|
31
|
-
|
|
32
|
-
app = typer.Typer()
|
|
8
|
+
from machineconfig.scripts.python.fire_agents_helper_types import AGENTS
|
|
33
9
|
|
|
34
10
|
|
|
35
11
|
def _write_list_file(target: Path, files: Iterable[Path]) -> None:
|
|
@@ -37,7 +13,6 @@ def _write_list_file(target: Path, files: Iterable[Path]) -> None:
|
|
|
37
13
|
target.write_text("\n".join(str(f) for f in files), encoding="utf-8")
|
|
38
14
|
|
|
39
15
|
|
|
40
|
-
@app.command()
|
|
41
16
|
def create(
|
|
42
17
|
context_path: Optional[Path] = typer.Option(None, help="Path to the context file"),
|
|
43
18
|
keyword_search: Optional[str] = typer.Option(None, help="Keyword to search in Python files"),
|
|
@@ -52,6 +27,13 @@ def create(
|
|
|
52
27
|
output_path: Optional[Path] = typer.Option(None, help="Path to write the layout.json file"),
|
|
53
28
|
agents_dir: Optional[Path] = typer.Option(None, help="Directory to store agent files. If not provided, will be constructed automatically."),
|
|
54
29
|
):
|
|
30
|
+
|
|
31
|
+
from machineconfig.scripts.python.fire_agents_help_launch import prep_agent_launch, get_agents_launch_layout
|
|
32
|
+
from machineconfig.scripts.python.fire_agents_help_search import search_files_by_pattern, search_python_files
|
|
33
|
+
from machineconfig.scripts.python.fire_agents_load_balancer import chunk_prompts
|
|
34
|
+
from machineconfig.utils.accessories import get_repo_root, randstr
|
|
35
|
+
import json
|
|
36
|
+
|
|
55
37
|
# validate mutual exclusive
|
|
56
38
|
context_options = [context_path, keyword_search, filename_pattern]
|
|
57
39
|
provided_context = [opt for opt in context_options if opt is not None]
|
|
@@ -131,48 +113,6 @@ fire_agents create --context-path "{prompt_material_path}" \\
|
|
|
131
113
|
typer.echo(f"Ceated layout in {layout_output_path}")
|
|
132
114
|
|
|
133
115
|
|
|
134
|
-
@app.command()
|
|
135
|
-
def run(layout_path: Path = typer.Argument(..., help="Path to the layout.json file"),
|
|
136
|
-
max_tabs: int = typer.Option(6, help="Maximum number of tabs to launch"),
|
|
137
|
-
sleep_inbetween: float = typer.Option(1.0, help="Sleep time in seconds between launching layouts"),
|
|
138
|
-
kill_upon_completion: bool = typer.Option(False, help="Kill the layout sessions upon completion")):
|
|
139
|
-
layoutfile: LayoutsFile = json.loads(layout_path.read_text())
|
|
140
|
-
for a_layout in layoutfile["layouts"]:
|
|
141
|
-
if len(a_layout["layoutTabs"]) > max_tabs:
|
|
142
|
-
typer.echo(f"Layout '{a_layout.get('layoutName', 'Unnamed')}' has {len(a_layout['layoutTabs'])} tabs which exceeds the max of {max_tabs}.")
|
|
143
|
-
confirm = typer.confirm("Do you want to proceed with launching this layout?", default=False)
|
|
144
|
-
if not confirm:
|
|
145
|
-
typer.echo("Aborting launch.")
|
|
146
|
-
raise typer.Exit(0)
|
|
147
|
-
from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
|
|
148
|
-
for i, a_layouts in enumerate(layoutfile["layouts"]):
|
|
149
|
-
manager = ZellijLocalManager(session_layouts=[a_layouts])
|
|
150
|
-
manager.start_all_sessions(poll_interval=2, poll_seconds=2)
|
|
151
|
-
manager.run_monitoring_routine(wait_ms=2000)
|
|
152
|
-
if kill_upon_completion:
|
|
153
|
-
manager.kill_all_sessions()
|
|
154
|
-
if i < len(layoutfile["layouts"]) - 1: # Don't sleep after the last layout
|
|
155
|
-
time.sleep(sleep_inbetween)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
@app.command(help="Adjust layout file to limit max tabs per layout, etc.")
|
|
159
|
-
def load_balance(layout_path: Path = typer.Argument(..., help="Path to the layout.json file"),
|
|
160
|
-
max_thresh: int = typer.Option(..., help="Maximum tabs per layout"),
|
|
161
|
-
thresh_type: Literal['number', 'weight'] = typer.Option(..., help="Threshold type"),
|
|
162
|
-
breaking_method: Literal['moreLayouts', 'combineTabs'] = typer.Option(..., help="Breaking method"),
|
|
163
|
-
output_path: Optional[Path] = typer.Option(None, help="Path to write the adjusted layout.json file")):
|
|
164
|
-
layoutfile: LayoutsFile = json.loads(layout_path.read_text())
|
|
165
|
-
layout_configs = layoutfile["layouts"]
|
|
166
|
-
from machineconfig.cluster.sessions_managers.utils.load_balancer import limit_tab_num
|
|
167
|
-
new_layouts = limit_tab_num(layout_configs=layout_configs, max_thresh=max_thresh, threshold_type=thresh_type, breaking_method=breaking_method)
|
|
168
|
-
layoutfile["layouts"] = new_layouts
|
|
169
|
-
target_file = output_path if output_path is not None else layout_path.parent / f'{layout_path.stem}_adjusted_{max_thresh}_{thresh_type}_{breaking_method}.json'
|
|
170
|
-
target_file.parent.mkdir(parents=True, exist_ok=True)
|
|
171
|
-
target_file.write_text(data=json.dumps(layoutfile, indent=4), encoding="utf-8")
|
|
172
|
-
typer.echo(f"Adjusted layout saved to {target_file}")
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
@app.command()
|
|
176
116
|
def collect(
|
|
177
117
|
agent_dir: Path = typer.Argument(..., help="Path to the agent directory containing the prompts folder"),
|
|
178
118
|
output_path: Path = typer.Argument(..., help="Path to write the concatenated material files"),
|
|
@@ -214,5 +154,44 @@ def collect(
|
|
|
214
154
|
typer.echo(f"Concatenated material written to {output_path}")
|
|
215
155
|
|
|
216
156
|
|
|
157
|
+
def template():
|
|
158
|
+
template_bash = """#!/bin/bash
|
|
159
|
+
JOB_NAME="outpatient_mapping"
|
|
160
|
+
REPO_ROOT="$HOME/code/work/winter_planning/"
|
|
161
|
+
CONTEXT_PATH="$REPO_ROOT/data/outpatient_mapping/op_services_collected.csv"
|
|
162
|
+
PROMPT_PATH="$REPO_ROOT/data/outpatient_mapping/prompt"
|
|
163
|
+
|
|
164
|
+
AGENTS_DIR="$REPO_ROOT/.ai/agents/$JOB_NAME"
|
|
165
|
+
LAYOUT_PATH="$REPO_ROOT/.ai/agents/$JOB_NAME/layout_unbalanced.json"
|
|
166
|
+
LAYOUT_BALANCED_PATH="$REPO_ROOT/.ai/agents/$JOB_NAME/layout_balanced.json"
|
|
167
|
+
|
|
168
|
+
fire_agents create --context-path $CONTEXT_PATH --tasks-per-prompt 10 --agent crush --prompt-path $PROMPT_PATH --keep-separate --output-path $LAYOUT_PATH --agents-dir $AGENTS_DIR
|
|
169
|
+
fire_agents load-balance $LAYOUT_PATH --max-thresh 6 --breaking-method moreLayouts --thresh-type number --output-path $LAYOUT_BALANCED_PATH
|
|
170
|
+
|
|
171
|
+
fire_agents run $LAYOUT_BALANCED_PATH --kill-upon-completion
|
|
172
|
+
fire_agents collect $AGENTS_DIR "$REPO_ROOT/.ai/agents/$JOB_NAME/collected.txt"
|
|
173
|
+
"""
|
|
174
|
+
template_powershell = """
|
|
175
|
+
|
|
176
|
+
"""
|
|
177
|
+
from platform import system
|
|
178
|
+
if system() == "Linux":
|
|
179
|
+
template = template_bash
|
|
180
|
+
elif system() == "Windows":
|
|
181
|
+
template = template_powershell
|
|
182
|
+
else:
|
|
183
|
+
raise typer.BadParameter(f"Unsupported OS: {system()}")
|
|
184
|
+
|
|
185
|
+
from machineconfig.utils.accessories import get_repo_root
|
|
186
|
+
repo_root = get_repo_root(Path.cwd())
|
|
187
|
+
if repo_root is None:
|
|
188
|
+
typer.echo("💥 Could not determine the repository root. Please run this script from within a git repository.")
|
|
189
|
+
raise typer.Exit(1)
|
|
190
|
+
save_path = repo_root / ".ai" / "agents" / "template_fire_agents.sh"
|
|
191
|
+
save_path.parent.mkdir(parents=True, exist_ok=True)
|
|
192
|
+
save_path.write_text(template, encoding="utf-8")
|
|
193
|
+
typer.echo(f"Template bash script written to {save_path}")
|
|
194
|
+
|
|
195
|
+
|
|
217
196
|
if __name__ == "__main__": # pragma: no cover
|
|
218
|
-
|
|
197
|
+
pass
|