machineconfig 3.99__py3-none-any.whl → 4.1__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/utils/load_balancer.py +168 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
- machineconfig/jobs/installer/linux_scripts/ngrok.sh +6 -0
- machineconfig/jobs/installer/linux_scripts/q.sh +8 -0
- machineconfig/jobs/installer/packages_custom_dev.json +155 -1
- machineconfig/jobs/installer/packages_github_dev.json +19 -2
- machineconfig/jobs/installer/packages_github_essential.json +0 -17
- machineconfig/jobs/linux/msc/cli_agents.sh +0 -21
- machineconfig/scripts/python/devops_devapps_install.py +52 -41
- machineconfig/scripts/python/fire_agents.py +0 -22
- machineconfig/scripts/python/share_terminal.py +37 -6
- machineconfig/utils/installer.py +9 -9
- machineconfig/utils/schemas/layouts/layout_types.py +2 -1
- {machineconfig-3.99.dist-info → machineconfig-4.1.dist-info}/METADATA +1 -1
- {machineconfig-3.99.dist-info → machineconfig-4.1.dist-info}/RECORD +19 -16
- /machineconfig/cluster/sessions_managers/{enhanced_command_runner.py → utils/enhanced_command_runner.py} +0 -0
- {machineconfig-3.99.dist-info → machineconfig-4.1.dist-info}/WHEEL +0 -0
- {machineconfig-3.99.dist-info → machineconfig-4.1.dist-info}/entry_points.txt +0 -0
- {machineconfig-3.99.dist-info → machineconfig-4.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
|
|
2
|
+
from machineconfig.utils.schemas.layouts.layout_types import TabConfig, LayoutConfig
|
|
3
|
+
from machineconfig.utils.accessories import split_list
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def split_tabs_by_weight(tabs: list[TabConfig], max_weight: int) -> list[list[TabConfig]]:
|
|
9
|
+
"""Split tabs into chunks where each chunk's total weight <= max_weight."""
|
|
10
|
+
chunks: list[list[TabConfig]] = []
|
|
11
|
+
current_chunk: list[TabConfig] = []
|
|
12
|
+
current_weight = 0
|
|
13
|
+
for tab in tabs:
|
|
14
|
+
tab_weight = tab.get("tabWeight", 1)
|
|
15
|
+
if current_weight + tab_weight > max_weight and current_chunk:
|
|
16
|
+
chunks.append(current_chunk)
|
|
17
|
+
current_chunk = [tab]
|
|
18
|
+
current_weight = tab_weight
|
|
19
|
+
else:
|
|
20
|
+
current_chunk.append(tab)
|
|
21
|
+
current_weight += tab_weight
|
|
22
|
+
|
|
23
|
+
if current_chunk:
|
|
24
|
+
chunks.append(current_chunk)
|
|
25
|
+
|
|
26
|
+
return chunks
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def combine_tabs_into_super_tabs(tabs: list[TabConfig], num_super_tabs: int) -> list[TabConfig]:
|
|
30
|
+
"""Combine tabs into num_super_tabs super tabs with combined commands."""
|
|
31
|
+
if len(tabs) <= num_super_tabs:
|
|
32
|
+
return tabs # No need to combine
|
|
33
|
+
|
|
34
|
+
tab_groups = split_list(tabs, to=num_super_tabs)
|
|
35
|
+
super_tabs: list[TabConfig] = []
|
|
36
|
+
for idx, group in enumerate(tab_groups):
|
|
37
|
+
if len(group) == 1:
|
|
38
|
+
super_tabs.append(group[0])
|
|
39
|
+
else:
|
|
40
|
+
combined_command = "; ".join(tab["command"] for tab in group)
|
|
41
|
+
combined_name = f"super_tab_{idx+1}"
|
|
42
|
+
# Use startDir of the first tab
|
|
43
|
+
start_dir = group[0]["startDir"]
|
|
44
|
+
# Sum weights
|
|
45
|
+
total_weight = sum(tab.get("tabWeight", 1) for tab in group)
|
|
46
|
+
super_tabs.append({
|
|
47
|
+
"tabName": combined_name,
|
|
48
|
+
"startDir": start_dir,
|
|
49
|
+
"command": combined_command,
|
|
50
|
+
"tabWeight": total_weight
|
|
51
|
+
})
|
|
52
|
+
return super_tabs
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def combine_tabs_by_weight_into_super_tabs(tabs: list[TabConfig], max_weight: int) -> list[TabConfig]:
|
|
56
|
+
"""Combine tabs into super tabs where each super tab has weight <= max_weight."""
|
|
57
|
+
tab_groups = split_tabs_by_weight(tabs, max_weight=max_weight)
|
|
58
|
+
super_tabs: list[TabConfig] = []
|
|
59
|
+
for idx, group in enumerate(tab_groups):
|
|
60
|
+
if len(group) == 1:
|
|
61
|
+
super_tabs.append(group[0])
|
|
62
|
+
else:
|
|
63
|
+
combined_command = "; ".join(tab["command"] for tab in group)
|
|
64
|
+
combined_name = f"super_tab_{idx+1}"
|
|
65
|
+
start_dir = group[0]["startDir"]
|
|
66
|
+
total_weight = sum(tab.get("tabWeight", 1) for tab in group)
|
|
67
|
+
super_tabs.append({
|
|
68
|
+
"tabName": combined_name,
|
|
69
|
+
"startDir": start_dir,
|
|
70
|
+
"command": combined_command,
|
|
71
|
+
"tabWeight": total_weight
|
|
72
|
+
})
|
|
73
|
+
return super_tabs
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def restrict_num_tabs(layout_configs: list[LayoutConfig], max_thresh: int, threshold_type: Literal["number", "weight"], breaking_method: Literal["moreLayouts", "combineTabs"]) -> list[LayoutConfig]:
|
|
77
|
+
match threshold_type, breaking_method:
|
|
78
|
+
case "number", "moreLayouts":
|
|
79
|
+
return _restrict_num_tabs_helper1(layout_configs=layout_configs, max_thresh=max_thresh, threshold_type=threshold_type, breaking_method=breaking_method)
|
|
80
|
+
case "number", "combineTabs":
|
|
81
|
+
return _restrict_num_tabs_helper2(layout_configs=layout_configs, max_thresh=max_thresh, threshold_type=threshold_type, breaking_method=breaking_method)
|
|
82
|
+
case "weight", "moreLayouts":
|
|
83
|
+
return _restrict_num_tabs_helper3(layout_configs=layout_configs, max_thresh=max_thresh, threshold_type=threshold_type, breaking_method=breaking_method)
|
|
84
|
+
case "weight", "combineTabs":
|
|
85
|
+
return _restrict_num_tabs_helper4(layout_configs=layout_configs, max_thresh=max_thresh, threshold_type=threshold_type, breaking_method=breaking_method)
|
|
86
|
+
case _:
|
|
87
|
+
raise NotImplementedError(f"The combination {threshold_type}, {breaking_method} is not implemented")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _restrict_num_tabs_helper1(layout_configs: list[LayoutConfig], max_thresh: int, threshold_type: Literal["number"], breaking_method: Literal["moreLayouts"]) -> list[LayoutConfig]:
|
|
91
|
+
"""When threshold is exceeded, create more layouts with max_thresh tabs each."""
|
|
92
|
+
new_layout_configs: list[LayoutConfig] = []
|
|
93
|
+
for a_layout_config in layout_configs:
|
|
94
|
+
if len(a_layout_config["layoutTabs"]) > max_thresh:
|
|
95
|
+
print(f"Layout '{a_layout_config['layoutName']}' has too many tabs ({len(a_layout_config['layoutTabs'])} > {max_thresh}). Splitting into multiple layouts.")
|
|
96
|
+
tab_chunks = split_list(a_layout_config["layoutTabs"], every=max_thresh)
|
|
97
|
+
for idx, tab_chunk in enumerate(tab_chunks):
|
|
98
|
+
new_layout_configs.append({
|
|
99
|
+
"layoutName": f"{a_layout_config['layoutName']}_part{idx+1}",
|
|
100
|
+
"layoutTabs": tab_chunk
|
|
101
|
+
})
|
|
102
|
+
else:
|
|
103
|
+
print(f"Layout '{a_layout_config['layoutName']}' has acceptable number of tabs ({len(a_layout_config['layoutTabs'])} <= {max_thresh}). Keeping as is.")
|
|
104
|
+
new_layout_configs.append(a_layout_config)
|
|
105
|
+
return new_layout_configs
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _restrict_num_tabs_helper2(layout_configs: list[LayoutConfig], max_thresh: int, threshold_type: Literal["number"], breaking_method: Literal["combineTabs"]) -> list[LayoutConfig]:
|
|
109
|
+
"""When threshold is exceeded, combine tabs into super tabs to reduce count to max_thresh."""
|
|
110
|
+
new_layout_configs: list[LayoutConfig] = []
|
|
111
|
+
for a_layout_config in layout_configs:
|
|
112
|
+
num_tabs = len(a_layout_config["layoutTabs"])
|
|
113
|
+
if num_tabs > max_thresh:
|
|
114
|
+
print(f"Layout '{a_layout_config['layoutName']}' has too many tabs ({num_tabs} > {max_thresh}). Combining into {max_thresh} super tabs.")
|
|
115
|
+
super_tabs = combine_tabs_into_super_tabs(a_layout_config["layoutTabs"], num_super_tabs=max_thresh)
|
|
116
|
+
new_layout_configs.append({
|
|
117
|
+
"layoutName": a_layout_config["layoutName"],
|
|
118
|
+
"layoutTabs": super_tabs
|
|
119
|
+
})
|
|
120
|
+
else:
|
|
121
|
+
print(f"Layout '{a_layout_config['layoutName']}' has acceptable number of tabs ({num_tabs} <= {max_thresh}). Keeping as is.")
|
|
122
|
+
new_layout_configs.append(a_layout_config)
|
|
123
|
+
return new_layout_configs
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _restrict_num_tabs_helper3(layout_configs: list[LayoutConfig], max_thresh: int, threshold_type: Literal["weight"], breaking_method: Literal["moreLayouts"]) -> list[LayoutConfig]:
|
|
127
|
+
"""When threshold is exceeded, create more layouts with max_thresh total weight each."""
|
|
128
|
+
new_layout_configs: list[LayoutConfig] = []
|
|
129
|
+
for a_layout_config in layout_configs:
|
|
130
|
+
layout_weight = sum(tab.get("tabWeight", 1) for tab in a_layout_config["layoutTabs"])
|
|
131
|
+
if layout_weight > max_thresh:
|
|
132
|
+
print(f"Layout '{a_layout_config['layoutName']}' has too much weight ({layout_weight} > {max_thresh}). Splitting into multiple layouts.")
|
|
133
|
+
tab_chunks = split_tabs_by_weight(a_layout_config["layoutTabs"], max_weight=max_thresh)
|
|
134
|
+
for idx, tab_chunk in enumerate(tab_chunks):
|
|
135
|
+
new_layout_configs.append({
|
|
136
|
+
"layoutName": f"{a_layout_config['layoutName']}_part{idx+1}",
|
|
137
|
+
"layoutTabs": tab_chunk
|
|
138
|
+
})
|
|
139
|
+
else:
|
|
140
|
+
print(f"Layout '{a_layout_config['layoutName']}' has acceptable total weight ({layout_weight} <= {max_thresh}). Keeping as is.")
|
|
141
|
+
new_layout_configs.append(a_layout_config)
|
|
142
|
+
return new_layout_configs
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _restrict_num_tabs_helper4(layout_configs: list[LayoutConfig], max_thresh: int, threshold_type: Literal["weight"], breaking_method: Literal["combineTabs"]) -> list[LayoutConfig]:
|
|
146
|
+
"""When threshold is exceeded, combine tabs into super tabs with weight <= max_thresh."""
|
|
147
|
+
new_layout_configs: list[LayoutConfig] = []
|
|
148
|
+
for a_layout_config in layout_configs:
|
|
149
|
+
layout_weight = sum(tab.get("tabWeight", 1) for tab in a_layout_config["layoutTabs"])
|
|
150
|
+
if layout_weight > max_thresh:
|
|
151
|
+
print(f"Layout '{a_layout_config['layoutName']}' has too much weight ({layout_weight} > {max_thresh}). Combining into super tabs with weight <= {max_thresh}.")
|
|
152
|
+
super_tabs = combine_tabs_by_weight_into_super_tabs(a_layout_config["layoutTabs"], max_weight=max_thresh)
|
|
153
|
+
new_layout_configs.append({
|
|
154
|
+
"layoutName": a_layout_config["layoutName"],
|
|
155
|
+
"layoutTabs": super_tabs
|
|
156
|
+
})
|
|
157
|
+
else:
|
|
158
|
+
print(f"Layout '{a_layout_config['layoutName']}' has acceptable total weight ({layout_weight} <= {max_thresh}). Keeping as is.")
|
|
159
|
+
new_layout_configs.append(a_layout_config)
|
|
160
|
+
return new_layout_configs
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def run(layouts: list[LayoutConfig]):
|
|
164
|
+
from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
|
|
165
|
+
manager = ZellijLocalManager(session_layouts=layouts)
|
|
166
|
+
manager.start_all_sessions(poll_interval=2, poll_seconds=2)
|
|
167
|
+
manager.run_monitoring_routine(wait_ms=2000)
|
|
168
|
+
manager.kill_all_sessions()
|
|
@@ -456,7 +456,7 @@ def run_zellij_layout(layout_config: LayoutConfig):
|
|
|
456
456
|
layout_path = created_zellij_layout(layout_config, None)
|
|
457
457
|
session_name = layout_config["layoutName"]
|
|
458
458
|
try:
|
|
459
|
-
from machineconfig.cluster.sessions_managers.enhanced_command_runner import enhanced_zellij_session_start
|
|
459
|
+
from machineconfig.cluster.sessions_managers.utils.enhanced_command_runner import enhanced_zellij_session_start
|
|
460
460
|
|
|
461
461
|
enhanced_zellij_session_start(session_name, layout_path)
|
|
462
462
|
except ImportError:
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
|
|
2
|
+
| sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \
|
|
3
|
+
&& echo "deb https://ngrok-agent.s3.amazonaws.com bookworm main" \
|
|
4
|
+
| sudo tee /etc/apt/sources.list.d/ngrok.list \
|
|
5
|
+
&& sudo apt update \
|
|
6
|
+
&& sudo apt install ngrok
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1",
|
|
3
3
|
"installers": [
|
|
4
|
+
{
|
|
5
|
+
"appName": "ngrok",
|
|
6
|
+
"repoURL": "CMD",
|
|
7
|
+
"doc": "Secure introspectable tunnels to localhost",
|
|
8
|
+
"fileNamePattern": {
|
|
9
|
+
"amd64": {
|
|
10
|
+
"linux": "ngrok.sh",
|
|
11
|
+
"windows": "winget install ngrok -s msstore",
|
|
12
|
+
"macos": "brew install ngrok"
|
|
13
|
+
},
|
|
14
|
+
"arm64": {
|
|
15
|
+
"linux": "ngrok.sh",
|
|
16
|
+
"windows": "winget install ngrok -s msstore",
|
|
17
|
+
"macos": "brew install ngrok"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
},
|
|
4
22
|
{
|
|
5
23
|
"appName": "Visual Studio Code",
|
|
6
24
|
"repoURL": "CMD",
|
|
@@ -19,7 +37,7 @@
|
|
|
19
37
|
}
|
|
20
38
|
},
|
|
21
39
|
{
|
|
22
|
-
"appName": "aider
|
|
40
|
+
"appName": "aider",
|
|
23
41
|
"repoURL": "CMD",
|
|
24
42
|
"doc": "Aider Chat",
|
|
25
43
|
"fileNamePattern": {
|
|
@@ -35,6 +53,142 @@
|
|
|
35
53
|
}
|
|
36
54
|
}
|
|
37
55
|
},
|
|
56
|
+
{
|
|
57
|
+
"appName": "github-copilot-cli",
|
|
58
|
+
"repoURL": "CMD",
|
|
59
|
+
"doc": "Terminal-based CLI agents and tools for productivity and coding.",
|
|
60
|
+
"fileNamePattern": {
|
|
61
|
+
"amd64": {
|
|
62
|
+
"linux": "npm install -g @github/copilot",
|
|
63
|
+
"windows": "npm install -g @github/copilot",
|
|
64
|
+
"macos": "npm install -g @github/copilot"
|
|
65
|
+
},
|
|
66
|
+
"arm64": {
|
|
67
|
+
"linux": "npm install -g @github/copilot",
|
|
68
|
+
"windows": "npm install -g @github/copilot",
|
|
69
|
+
"macos": "npm install -g @github/copilot"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"appName": "gemini",
|
|
75
|
+
"repoURL": "CMD",
|
|
76
|
+
"doc": "Terminal-based CLI agents and tools for productivity and coding.",
|
|
77
|
+
"fileNamePattern": {
|
|
78
|
+
"amd64": {
|
|
79
|
+
"linux": "npm install -g @google/gemini-cli",
|
|
80
|
+
"windows": "npm install -g @google/gemini-cli",
|
|
81
|
+
"macos": "npm install -g @google/gemini-cli"
|
|
82
|
+
},
|
|
83
|
+
"arm64": {
|
|
84
|
+
"linux": "npm install -g @google/gemini-cli",
|
|
85
|
+
"windows": "npm install -g @google/gemini-cli",
|
|
86
|
+
"macos": "npm install -g @google/gemini-cli"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"appName": "crush",
|
|
92
|
+
"repoURL": "CMD",
|
|
93
|
+
"doc": "Terminal-based CLI agents and tools for productivity and coding.",
|
|
94
|
+
"fileNamePattern": {
|
|
95
|
+
"amd64": {
|
|
96
|
+
"linux": "npm install -g @charmland/crush",
|
|
97
|
+
"windows": "npm install -g @charmland/crush",
|
|
98
|
+
"macos": "npm install -g @charmland/crush"
|
|
99
|
+
},
|
|
100
|
+
"arm64": {
|
|
101
|
+
"linux": "npm install -g @charmland/crush",
|
|
102
|
+
"windows": "npm install -g @charmland/crush",
|
|
103
|
+
"macos": "npm install -g @charmland/crush"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"appName": "opencode-ai",
|
|
109
|
+
"repoURL": "CMD",
|
|
110
|
+
"doc": "Terminal-based CLI agents and tools for productivity and coding.",
|
|
111
|
+
"fileNamePattern": {
|
|
112
|
+
"amd64": {
|
|
113
|
+
"linux": "npm install -g opencode-ai@latest",
|
|
114
|
+
"windows": "npm install -g opencode-ai@latest",
|
|
115
|
+
"macos": "npm install -g opencode-ai@latest"
|
|
116
|
+
},
|
|
117
|
+
"arm64": {
|
|
118
|
+
"linux": "npm install -g opencode-ai@latest",
|
|
119
|
+
"windows": "npm install -g opencode-ai@latest",
|
|
120
|
+
"macos": "npm install -g opencode-ai@latest"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"appName": "warp",
|
|
126
|
+
"repoURL": "CMD",
|
|
127
|
+
"doc": "Modern terminal with AI-powered features",
|
|
128
|
+
"fileNamePattern": {
|
|
129
|
+
"amd64": {
|
|
130
|
+
"linux": "https://app.warp.dev/download/cli?os=linux&package=deb&arch=x86_64",
|
|
131
|
+
"windows": null,
|
|
132
|
+
"macos": null
|
|
133
|
+
},
|
|
134
|
+
"arm64": {
|
|
135
|
+
"linux": "https://app.warp.dev/download/cli?os=linux&package=deb&arch=aarch64",
|
|
136
|
+
"windows": null,
|
|
137
|
+
"macos": null
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"appName": "q",
|
|
143
|
+
"repoURL": "CMD",
|
|
144
|
+
"doc": "Q desktop application",
|
|
145
|
+
"fileNamePattern": {
|
|
146
|
+
"amd64": {
|
|
147
|
+
"linux": "q.sh",
|
|
148
|
+
"windows": null,
|
|
149
|
+
"macos": null
|
|
150
|
+
},
|
|
151
|
+
"arm64": {
|
|
152
|
+
"linux": null,
|
|
153
|
+
"windows": null,
|
|
154
|
+
"macos": null
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"appName": "cursor-cli",
|
|
160
|
+
"repoURL": "CMD",
|
|
161
|
+
"doc": "Cursor CLI installer",
|
|
162
|
+
"fileNamePattern": {
|
|
163
|
+
"amd64": {
|
|
164
|
+
"linux": "curl https://cursor.com/install -fsS | bash",
|
|
165
|
+
"windows": null,
|
|
166
|
+
"macos": null
|
|
167
|
+
},
|
|
168
|
+
"arm64": {
|
|
169
|
+
"linux": null,
|
|
170
|
+
"windows": null,
|
|
171
|
+
"macos": null
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"appName": "droid",
|
|
177
|
+
"repoURL": "CMD",
|
|
178
|
+
"doc": "Factory AI CLI installer",
|
|
179
|
+
"fileNamePattern": {
|
|
180
|
+
"amd64": {
|
|
181
|
+
"linux": "curl -fsSL https://app.factory.ai/cli | sh",
|
|
182
|
+
"windows": null,
|
|
183
|
+
"macos": null
|
|
184
|
+
},
|
|
185
|
+
"arm64": {
|
|
186
|
+
"linux": null,
|
|
187
|
+
"windows": null,
|
|
188
|
+
"macos": null
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
},
|
|
38
192
|
{
|
|
39
193
|
"appName": "Alacritty",
|
|
40
194
|
"repoURL": "CMD",
|
|
@@ -245,17 +245,34 @@
|
|
|
245
245
|
"doc": "🗃️ TUI DB Visualizer",
|
|
246
246
|
"fileNamePattern": {
|
|
247
247
|
"amd64": {
|
|
248
|
-
"linux": "rainfrog-{version}-x86_64-unknown-linux-
|
|
248
|
+
"linux": "rainfrog-{version}-x86_64-unknown-linux-musl.tar.gz",
|
|
249
249
|
"macos": null,
|
|
250
250
|
"windows": null
|
|
251
251
|
},
|
|
252
252
|
"arm64": {
|
|
253
|
-
"linux": "rainfrog-{version}-aarch64-unknown-linux-
|
|
253
|
+
"linux": "rainfrog-{version}-aarch64-unknown-linux-musl.tar.gz",
|
|
254
254
|
"macos": null,
|
|
255
255
|
"windows": null
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
},
|
|
259
|
+
{
|
|
260
|
+
"appName": "duckdb",
|
|
261
|
+
"repoURL": "https://github.com/duckdb/duckdb",
|
|
262
|
+
"doc": "🗃️ An in-process SQL OLAP database management system",
|
|
263
|
+
"fileNamePattern": {
|
|
264
|
+
"amd64": {
|
|
265
|
+
"linux": "duckdb_cli-linux-amd64.zip",
|
|
266
|
+
"macos": "duckdb_cli-osx-universal.zip",
|
|
267
|
+
"windows": "duckdb_cli-windows-amd64.zip"
|
|
268
|
+
},
|
|
269
|
+
"arm64": {
|
|
270
|
+
"linux": "duckdb_cli-linux-arm64.zip",
|
|
271
|
+
"macos": "duckdb_cli-osx-universal.zip",
|
|
272
|
+
"windows": "duckdb_cli-windows-arm64.zip"
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
},
|
|
259
276
|
{
|
|
260
277
|
"appName": "cpz",
|
|
261
278
|
"repoURL": "https://github.com/SUPERCILEX/fuc",
|
|
@@ -409,23 +409,6 @@
|
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
},
|
|
412
|
-
{
|
|
413
|
-
"appName": "gemini-cli",
|
|
414
|
-
"repoURL": "CMD",
|
|
415
|
-
"doc": "🤖 Gemini CLI is a command line interface for Google Gemini AI.",
|
|
416
|
-
"fileNamePattern": {
|
|
417
|
-
"amd64": {
|
|
418
|
-
"linux": "npm install -g @google/gemini-cli",
|
|
419
|
-
"macos": "npm install -g @google/gemini-cli",
|
|
420
|
-
"windows": "npm install -g @google/gemini-cli"
|
|
421
|
-
},
|
|
422
|
-
"arm64": {
|
|
423
|
-
"linux": "npm install -g @google/gemini-cli",
|
|
424
|
-
"macos": "npm install -g @google/gemini-cli",
|
|
425
|
-
"windows": "npm install -g @google/gemini-cli"
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
},
|
|
429
412
|
{
|
|
430
413
|
"appName": "gitui",
|
|
431
414
|
"repoURL": "https://github.com/gitui-org/gitui",
|
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
# Terminal-based CLI agents and tools for productivity and coding.
|
|
5
|
-
npm install -g @github/copilot
|
|
6
|
-
npm install -g @google/gemini-cli
|
|
7
|
-
npm install -g @charmland/crush
|
|
8
|
-
npm install -g opencode-ai@latest # or curl -fsSL https://opencode.ai/install | bash
|
|
9
|
-
uv tool install --force --python python3.12 --with pip aider-chat@latest
|
|
10
|
-
curl -fsSL https://app.factory.ai/cli | sh
|
|
11
|
-
# WARP TERMINAL CLI
|
|
12
|
-
# droid
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# cursor-cli
|
|
16
|
-
curl https://cursor.com/install -fsS | bash
|
|
17
|
-
cd $HOME/Downloads
|
|
18
|
-
curl --proto '=https' --tlsv1.2 -sSf "https://desktop-release.q.us-east-1.amazonaws.com/latest/q-x86_64-linux.zip" -o "q.zip"
|
|
19
|
-
unzip q.zip
|
|
20
|
-
./q/install.sh # goes to ~/.local/bin.
|
|
21
|
-
rm q.zip
|
|
22
|
-
rm -rfd q
|
|
23
|
-
|
|
24
4
|
# Vscode extensions for AI-assisted coding.
|
|
25
5
|
# Github copilot
|
|
26
6
|
# Roo
|
|
@@ -34,4 +14,3 @@ rm -rfd q
|
|
|
34
14
|
# Kiro
|
|
35
15
|
# Cursor
|
|
36
16
|
# Warp
|
|
37
|
-
|
|
@@ -8,6 +8,42 @@ from typing import Optional, Literal, TypeAlias, cast, get_args, Annotated
|
|
|
8
8
|
WHICH_CAT: TypeAlias = Literal["essentials", "essentialsDev", "systymPackages", "precheckedPackages", "ia"]
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
def _handle_installer_not_found(search_term: str, all_installers: list["InstallerData"]) -> None: # type: ignore
|
|
12
|
+
"""Handle installer not found with friendly suggestions using fuzzy matching."""
|
|
13
|
+
from difflib import get_close_matches
|
|
14
|
+
|
|
15
|
+
# Get all possible names (both exe names and app names)
|
|
16
|
+
all_names = []
|
|
17
|
+
for inst in all_installers:
|
|
18
|
+
exe_name = inst["appName"]
|
|
19
|
+
all_names.append(exe_name)
|
|
20
|
+
|
|
21
|
+
# Find close matches using fuzzy matching
|
|
22
|
+
close_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
|
|
23
|
+
|
|
24
|
+
print(f"\n❌ '{search_term}' was not found.")
|
|
25
|
+
|
|
26
|
+
if close_matches:
|
|
27
|
+
print("🤔 Did you mean one of these?")
|
|
28
|
+
for i, match in enumerate(close_matches, 1):
|
|
29
|
+
print(f" {i}. {match}")
|
|
30
|
+
else:
|
|
31
|
+
print("📋 Here are some available options:")
|
|
32
|
+
# Show first 10 installers as examples
|
|
33
|
+
sample_names = []
|
|
34
|
+
for inst in all_installers[:10]:
|
|
35
|
+
exe_name = inst["appName"]
|
|
36
|
+
sample_names.append(exe_name)
|
|
37
|
+
for i, name in enumerate(sample_names, 1):
|
|
38
|
+
print(f" {i}. {name}")
|
|
39
|
+
|
|
40
|
+
if len(all_installers) > 10:
|
|
41
|
+
print(f" ... and {len(all_installers) - 10} more")
|
|
42
|
+
|
|
43
|
+
print("\n💡 Use 'ia' to interactively browse all available installers.")
|
|
44
|
+
print(f"💡 Use one of the categories: {list(get_args(WHICH_CAT))}")
|
|
45
|
+
|
|
46
|
+
|
|
11
47
|
def main_with_parser():
|
|
12
48
|
import typer
|
|
13
49
|
app = typer.Typer()
|
|
@@ -20,6 +56,7 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
20
56
|
return get_programs_by_category(program_name=which) # type: ignore
|
|
21
57
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
22
58
|
from machineconfig.utils.installer import get_installers
|
|
59
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
23
60
|
if which != "ia" and which is not None: # install by name
|
|
24
61
|
total_messages: list[str] = []
|
|
25
62
|
for a_which in which.split(",") if type(which) == str else which:
|
|
@@ -28,22 +65,16 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
28
65
|
# Find installer by exe_name or name
|
|
29
66
|
selected_installer = None
|
|
30
67
|
for installer in all_installers:
|
|
31
|
-
exe_name = installer
|
|
32
|
-
app_name = installer
|
|
68
|
+
exe_name = installer["appName"]
|
|
69
|
+
app_name = installer["appName"]
|
|
33
70
|
if exe_name == a_which or app_name == a_which:
|
|
34
71
|
selected_installer = installer
|
|
35
72
|
break
|
|
36
73
|
|
|
37
74
|
if selected_installer is None:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
print(f"""
|
|
42
|
-
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
43
|
-
┃ 🔧 Installing: {a_which}
|
|
44
|
-
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
45
|
-
print(selected_installer)
|
|
46
|
-
message = selected_installer.install_robust(version=None) # finish the task
|
|
75
|
+
_handle_installer_not_found(a_which, all_installers)
|
|
76
|
+
return None
|
|
77
|
+
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
47
78
|
total_messages.append(message)
|
|
48
79
|
for a_message in total_messages:
|
|
49
80
|
print(a_message)
|
|
@@ -55,58 +86,35 @@ def install_interactively():
|
|
|
55
86
|
from machineconfig.utils.options import choose_from_options
|
|
56
87
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
57
88
|
from machineconfig.utils.installer import get_installers
|
|
89
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
58
90
|
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
|
|
59
|
-
# Check installed programs with progress indicator
|
|
60
91
|
with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
|
|
61
92
|
task = progress.add_task("✅ Checking installed programs...", total=len(installers))
|
|
62
93
|
installer_options = []
|
|
63
94
|
for x in installers:
|
|
64
|
-
installer_options.append(x.get_description())
|
|
95
|
+
installer_options.append(Installer(installer_data=x).get_description())
|
|
65
96
|
progress.update(task, advance=1)
|
|
66
|
-
|
|
67
|
-
# Add category options at the beginning for better visibility
|
|
68
97
|
category_options = [f"📦 {cat}" for cat in get_args(WHICH_CAT)]
|
|
69
|
-
options = category_options + ["─" * 50] + installer_options
|
|
70
|
-
|
|
98
|
+
options = category_options + ["─" * 50] + installer_options
|
|
71
99
|
program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", default="📦 essentials", fzf=True)
|
|
72
|
-
|
|
73
|
-
total_commands = ""
|
|
74
100
|
installation_messages: list[str] = []
|
|
75
101
|
for _an_idx, a_program_name in enumerate(program_names):
|
|
76
|
-
# Skip separator lines
|
|
77
102
|
if a_program_name.startswith("─"):
|
|
78
103
|
continue
|
|
79
|
-
|
|
80
|
-
print(f"""
|
|
81
|
-
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
82
|
-
┃ 🔄 Processing: {a_program_name}
|
|
83
|
-
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
84
|
-
|
|
85
|
-
# Handle category options (remove emoji prefix)
|
|
86
104
|
if a_program_name.startswith("📦 "):
|
|
87
105
|
category_name = a_program_name[2:] # Remove "📦 " prefix
|
|
88
106
|
if category_name in get_args(WHICH_CAT):
|
|
89
107
|
get_programs_by_category(program_name=cast(WHICH_CAT, category_name))
|
|
90
108
|
else:
|
|
91
|
-
# Handle individual installer options
|
|
92
109
|
installer_idx = installer_options.index(a_program_name)
|
|
93
|
-
|
|
94
|
-
status_message =
|
|
110
|
+
an_installer_data = installers[installer_idx]
|
|
111
|
+
status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
|
|
95
112
|
installation_messages.append(status_message)
|
|
96
|
-
|
|
97
|
-
# Print all installation status messages
|
|
98
113
|
print("\n📊 INSTALLATION SUMMARY:")
|
|
99
114
|
print("=" * 50)
|
|
100
115
|
for message in installation_messages:
|
|
101
116
|
print(message)
|
|
102
117
|
|
|
103
|
-
# Only run shell commands if there are any (from category installations)
|
|
104
|
-
if total_commands.strip():
|
|
105
|
-
import subprocess
|
|
106
|
-
|
|
107
|
-
print("\n🚀 Running additional shell commands...")
|
|
108
|
-
subprocess.run(total_commands, shell=True, check=True)
|
|
109
|
-
|
|
110
118
|
|
|
111
119
|
def get_programs_by_category(program_name: WHICH_CAT):
|
|
112
120
|
print(f"""
|
|
@@ -121,10 +129,10 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
121
129
|
match program_name:
|
|
122
130
|
case "essentials":
|
|
123
131
|
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
124
|
-
install_all(
|
|
132
|
+
install_all(installers_data=installers_)
|
|
125
133
|
case "essentialsDev":
|
|
126
134
|
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_DEV", "CUSTOM_DEV", "GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
127
|
-
install_all(
|
|
135
|
+
install_all(installers_data=installers_)
|
|
128
136
|
case "systymPackages":
|
|
129
137
|
if system() == "Windows":
|
|
130
138
|
options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
|
|
@@ -156,4 +164,7 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
156
164
|
|
|
157
165
|
|
|
158
166
|
if __name__ == "__main__":
|
|
167
|
+
from machineconfig.utils.schemas.installer.installer_types import InstallerData
|
|
168
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
169
|
+
_ = InstallerData, Installer
|
|
159
170
|
pass
|
|
@@ -16,7 +16,6 @@ from machineconfig.scripts.python.fire_agents_help_launch import prep_agent_laun
|
|
|
16
16
|
from machineconfig.scripts.python.fire_agents_help_search import search_files_by_pattern, search_python_files
|
|
17
17
|
from machineconfig.scripts.python.fire_agents_load_balancer import chunk_prompts, SPLITTING_STRATEGY, DEFAULT_AGENT_CAP
|
|
18
18
|
from machineconfig.utils.options import choose_from_options
|
|
19
|
-
from machineconfig.utils.schemas.layouts.layout_types import TabConfig, LayoutConfig
|
|
20
19
|
from machineconfig.utils.accessories import get_repo_root
|
|
21
20
|
|
|
22
21
|
SEARCH_STRATEGIES: TypeAlias = Literal["file_path", "keyword_search", "filename_pattern"]
|
|
@@ -150,26 +149,5 @@ manager.run_monitoring_routine()
|
|
|
150
149
|
manager.run_monitoring_routine(wait_ms=2000)
|
|
151
150
|
|
|
152
151
|
|
|
153
|
-
def split_too_many_tabs_to_run_in_sequential_sessions(layout_tabs: list[TabConfig], every: int):
|
|
154
|
-
from machineconfig.utils.accessories import split_list
|
|
155
|
-
from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
|
|
156
|
-
|
|
157
|
-
for idx, layout_tabs_chunk in enumerate(split_list(layout_tabs, every=every, to=None)):
|
|
158
|
-
a_layout_file: LayoutConfig = {"layoutName": f"split_{idx}", "layoutTabs": layout_tabs_chunk}
|
|
159
|
-
manager = ZellijLocalManager(session_layouts=[a_layout_file])
|
|
160
|
-
manager.start_all_sessions(poll_interval=2, poll_seconds=2)
|
|
161
|
-
manager.run_monitoring_routine(wait_ms=2000)
|
|
162
|
-
manager.kill_all_sessions()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def split_too_many_layouts_to_run_in_sequential_sessions(layouts: list[LayoutConfig], every: int):
|
|
166
|
-
from machineconfig.utils.accessories import split_list
|
|
167
|
-
from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
|
|
168
|
-
for _idx, layout_chunk in enumerate(split_list(layouts, every=every)):
|
|
169
|
-
manager = ZellijLocalManager(session_layouts=layout_chunk)
|
|
170
|
-
manager.start_all_sessions(poll_interval=2, poll_seconds=2)
|
|
171
|
-
manager.run_monitoring_routine(wait_ms=2000)
|
|
172
|
-
|
|
173
|
-
|
|
174
152
|
if __name__ == "__main__": # pragma: no cover
|
|
175
153
|
main()
|
|
@@ -19,12 +19,12 @@ reference:
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def display_terminal_url(local_ip_v4: str, port: int) -> None:
|
|
22
|
+
def display_terminal_url(local_ip_v4: str, port: int, protocol: str = "http") -> None:
|
|
23
23
|
"""Display a flashy, unmissable terminal URL announcement."""
|
|
24
24
|
console = Console()
|
|
25
25
|
|
|
26
26
|
# Create the main message with styling
|
|
27
|
-
url_text = Text(f"
|
|
27
|
+
url_text = Text(f"{protocol}://{local_ip_v4}:{port}", style="bold bright_cyan underline")
|
|
28
28
|
message = Text.assemble(
|
|
29
29
|
("🚀 ", "bright_red"),
|
|
30
30
|
("Terminal is now accessible at: ", "bright_white bold"),
|
|
@@ -64,7 +64,11 @@ def install_ttyd():
|
|
|
64
64
|
def main(
|
|
65
65
|
port: Annotated[Optional[int], typer.Option("--port", "-p", help="Port to run the terminal server on (default: 7681)")] = None,
|
|
66
66
|
username: Annotated[Optional[str], typer.Option("--username", "-u", help="Username for terminal access (default: current user)")] = None,
|
|
67
|
-
password: Annotated[Optional[str], typer.Option("--password", "-w", help="Password for terminal access (default: from ~/dotfiles/creds/passwords/quick_password)")] = None
|
|
67
|
+
password: Annotated[Optional[str], typer.Option("--password", "-w", help="Password for terminal access (default: from ~/dotfiles/creds/passwords/quick_password)")] = None,
|
|
68
|
+
ssl: Annotated[bool, typer.Option("--ssl", "-S", help="Enable SSL")] = False,
|
|
69
|
+
ssl_cert: Annotated[Optional[str], typer.Option("--ssl-cert", "-C", help="SSL certificate file path")] = None,
|
|
70
|
+
ssl_key: Annotated[Optional[str], typer.Option("--ssl-key", "-K", help="SSL key file path")] = None,
|
|
71
|
+
ssl_ca: Annotated[Optional[str], typer.Option("--ssl-ca", "-A", help="SSL CA file path for client certificate verification")] = None
|
|
68
72
|
) -> None:
|
|
69
73
|
install_ttyd()
|
|
70
74
|
if username is None:
|
|
@@ -80,17 +84,44 @@ def main(
|
|
|
80
84
|
if port is None:
|
|
81
85
|
port = 7681 # Default port for ttyd
|
|
82
86
|
|
|
87
|
+
# Handle SSL certificate defaults
|
|
88
|
+
if ssl:
|
|
89
|
+
if ssl_cert is None:
|
|
90
|
+
ssl_cert = str(Path.home().joinpath("dotfiles/creds/passwords/ssl/origin_server/cert.pem"))
|
|
91
|
+
if ssl_key is None:
|
|
92
|
+
ssl_key = str(Path.home().joinpath("dotfiles/creds/passwords/ssl/origin_server/key.pem"))
|
|
93
|
+
|
|
94
|
+
# Verify SSL files exist
|
|
95
|
+
cert_path = Path(ssl_cert)
|
|
96
|
+
key_path = Path(ssl_key)
|
|
97
|
+
|
|
98
|
+
if not cert_path.exists():
|
|
99
|
+
raise FileNotFoundError(f"SSL certificate file not found: {ssl_cert}")
|
|
100
|
+
if not key_path.exists():
|
|
101
|
+
raise FileNotFoundError(f"SSL key file not found: {ssl_key}")
|
|
102
|
+
|
|
103
|
+
if ssl_ca and not Path(ssl_ca).exists():
|
|
104
|
+
raise FileNotFoundError(f"SSL CA file not found: {ssl_ca}")
|
|
105
|
+
|
|
83
106
|
import socket
|
|
84
107
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
85
108
|
s.connect(('8.8.8.8',80))
|
|
86
109
|
local_ip_v4 = s.getsockname()[0]
|
|
87
110
|
s.close()
|
|
88
111
|
|
|
89
|
-
# Display the flashy terminal announcement
|
|
90
|
-
|
|
112
|
+
# Display the flashy terminal announcement
|
|
113
|
+
protocol = "https" if ssl else "http"
|
|
114
|
+
display_terminal_url(local_ip_v4, port, protocol)
|
|
115
|
+
|
|
116
|
+
# Build ttyd command with SSL options
|
|
117
|
+
ssl_args = ""
|
|
118
|
+
if ssl:
|
|
119
|
+
ssl_args = f"--ssl --ssl-cert {ssl_cert} --ssl-key {ssl_key}"
|
|
120
|
+
if ssl_ca:
|
|
121
|
+
ssl_args += f" --ssl-ca {ssl_ca}"
|
|
91
122
|
|
|
92
123
|
code = f"""#!/bin/bash
|
|
93
|
-
ttyd --writable -t enableSixel=true --port {port} --credential "{username}:{password}" -t 'theme={{"background": "black"}}' bash
|
|
124
|
+
ttyd --writable -t enableSixel=true {ssl_args} --port {port} --credential "{username}:{password}" -t 'theme={{"background": "black"}}' bash
|
|
94
125
|
"""
|
|
95
126
|
import subprocess
|
|
96
127
|
subprocess.run(code, shell=True, check=True)
|
machineconfig/utils/installer.py
CHANGED
|
@@ -21,8 +21,8 @@ def check_latest():
|
|
|
21
21
|
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
22
22
|
installers_github = []
|
|
23
23
|
for inst__ in installers:
|
|
24
|
-
app_name = inst__
|
|
25
|
-
repo_url = inst__
|
|
24
|
+
app_name = inst__["appName"]
|
|
25
|
+
repo_url = inst__["repoURL"]
|
|
26
26
|
if "ntop" in app_name:
|
|
27
27
|
print(f"⏭️ Skipping {app_name} (ntop)")
|
|
28
28
|
continue
|
|
@@ -91,7 +91,7 @@ def get_installed_cli_apps():
|
|
|
91
91
|
return apps
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: list[APP_INSTALLER_CATEGORY]) -> list[
|
|
94
|
+
def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: list[APP_INSTALLER_CATEGORY]) -> list[InstallerData]:
|
|
95
95
|
print(f"\n{'=' * 80}\n🔍 LOADING INSTALLER CONFIGURATIONS 🔍\n{'=' * 80}")
|
|
96
96
|
res_all = get_all_installer_data_files(which_cats=which_cats)
|
|
97
97
|
all_installers: list[InstallerData] = []
|
|
@@ -103,7 +103,7 @@ def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: l
|
|
|
103
103
|
suitable_installers.append(an_installer)
|
|
104
104
|
all_installers.extend(suitable_installers)
|
|
105
105
|
print(f"✅ Loaded {len(all_installers)} installer configurations\n{'=' * 80}")
|
|
106
|
-
return
|
|
106
|
+
return all_installers
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
def get_all_installer_data_files(which_cats: list[APP_INSTALLER_CATEGORY]) -> dict[APP_INSTALLER_CATEGORY, InstallerDataFiles]:
|
|
@@ -118,7 +118,7 @@ def get_all_installer_data_files(which_cats: list[APP_INSTALLER_CATEGORY]) -> di
|
|
|
118
118
|
return res_final
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
def install_all(
|
|
121
|
+
def install_all(installers_data: list[InstallerData], safe: bool = False, jobs: int = 10, fresh: bool = False):
|
|
122
122
|
print(f"\n{'=' * 80}\n🚀 BULK INSTALLATION PROCESS 🚀\n{'=' * 80}")
|
|
123
123
|
if fresh:
|
|
124
124
|
print("🧹 Fresh install requested - clearing version cache...")
|
|
@@ -151,14 +151,14 @@ def install_all(installers: list[Installer], safe: bool = False, jobs: int = 10,
|
|
|
151
151
|
# print(f"✅ Safe installation completed\n{'='*80}")
|
|
152
152
|
# return None
|
|
153
153
|
|
|
154
|
-
print(f"🚀 Starting installation of {len(
|
|
154
|
+
print(f"🚀 Starting installation of {len(installers_data)} packages...")
|
|
155
155
|
print(f"\n{'=' * 80}\n📦 INSTALLING FIRST PACKAGE 📦\n{'=' * 80}")
|
|
156
|
-
|
|
157
|
-
installers_remaining =
|
|
156
|
+
Installer(installers_data[0]).install(version=None)
|
|
157
|
+
installers_remaining = installers_data[1:]
|
|
158
158
|
print(f"\n{'=' * 80}\n📦 INSTALLING REMAINING PACKAGES 📦\n{'=' * 80}")
|
|
159
159
|
|
|
160
160
|
# Use joblib for parallel processing of remaining installers
|
|
161
|
-
res = Parallel(n_jobs=jobs)(delayed(lambda x: x.install_robust(version=None))(installer) for installer in installers_remaining)
|
|
161
|
+
res = Parallel(n_jobs=jobs)(delayed(lambda x: Installer(x).install_robust(version=None))(installer) for installer in installers_remaining)
|
|
162
162
|
|
|
163
163
|
console = Console()
|
|
164
164
|
|
|
@@ -4,7 +4,7 @@ Type definitions for the standardized layout configuration schema.
|
|
|
4
4
|
This module defines the data structures that match the layout.json schema.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import TypedDict, List, Literal
|
|
7
|
+
from typing import TypedDict, List, Literal, NotRequired
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class TabConfig(TypedDict):
|
|
@@ -13,6 +13,7 @@ class TabConfig(TypedDict):
|
|
|
13
13
|
tabName: str
|
|
14
14
|
startDir: str
|
|
15
15
|
command: str
|
|
16
|
+
tabWeight: NotRequired[int] # Optional, defaults to 1 if not provided
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class LayoutConfig(TypedDict):
|
|
@@ -11,15 +11,16 @@ machineconfig/cluster/remote/remote_machine.py,sha256=xRuoHKNsIT0-FTFSvF1q7scnGK
|
|
|
11
11
|
machineconfig/cluster/remote/script_execution.py,sha256=4U70FDtjOh6A6C2Ei-Xh90S888q64VhRPbExoEbdepk,9980
|
|
12
12
|
machineconfig/cluster/remote/script_notify_upon_completion.py,sha256=GRxnnbnOl1-hTovTN-zI_M9wdV7x293yA77_mou9I1o,2032
|
|
13
13
|
machineconfig/cluster/sessions_managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
machineconfig/cluster/sessions_managers/enhanced_command_runner.py,sha256=3vcQVg-HHa_WTxBGPtKMAdoSqJVa2EO5KAtrY8a6I3c,5264
|
|
15
14
|
machineconfig/cluster/sessions_managers/wt_local.py,sha256=-e4yNxvu6ytI-u1Kihhtn_wd_qNKZMzN_WrZ9ab1qYA,18220
|
|
16
15
|
machineconfig/cluster/sessions_managers/wt_local_manager.py,sha256=LqOuA9fqVDu5mWa04pxY9IUqMR4v-kDQbhZY0simvlQ,24193
|
|
17
16
|
machineconfig/cluster/sessions_managers/wt_remote.py,sha256=XmZV9rLubwxND5UYAS15mAcpzDdXvm4KyubVGYkVBmo,8743
|
|
18
17
|
machineconfig/cluster/sessions_managers/wt_remote_manager.py,sha256=CnnOtPiwLx0pIfs_KlcKnclLSqiDTNzfm8t8sW6nXf0,19764
|
|
19
|
-
machineconfig/cluster/sessions_managers/zellij_local.py,sha256=
|
|
18
|
+
machineconfig/cluster/sessions_managers/zellij_local.py,sha256=T2wXkW9ug1nzdnhlD-1G2HPlBpBaNw6rdM9rk4KKeHQ,26137
|
|
20
19
|
machineconfig/cluster/sessions_managers/zellij_local_manager.py,sha256=4ap0Gtd8wOybFc461OItA2kU-1jpgPQUX03s8Zjyk_4,24028
|
|
21
20
|
machineconfig/cluster/sessions_managers/zellij_remote.py,sha256=3gz-wgqVW7B-4CgvJq0fiDh8691h4yeK3Xh3CfSPc2s,8749
|
|
22
21
|
machineconfig/cluster/sessions_managers/zellij_remote_manager.py,sha256=T-j1KMV7mDTeGSHC5To0_JmqNtjSR_LVZT9VanP4lyI,8313
|
|
22
|
+
machineconfig/cluster/sessions_managers/utils/enhanced_command_runner.py,sha256=3vcQVg-HHa_WTxBGPtKMAdoSqJVa2EO5KAtrY8a6I3c,5264
|
|
23
|
+
machineconfig/cluster/sessions_managers/utils/load_balancer.py,sha256=ODnYCkMwpnD9ooMemJsaADAnmFSGELTW5QKJwepajL4,9051
|
|
23
24
|
machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py,sha256=CFGcZPFTZQJtFf0OvMUHhadZ0qbImCP3wxvbWYVcVYo,7445
|
|
24
25
|
machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py,sha256=Mitm7mKiKl5lT0OiEUHAqVg2Q21RjsKO1-hpJTHJ5lM,15196
|
|
25
26
|
machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py,sha256=lApUy67_WhfaBXqt0meZSx_QvwiXjN0YLdyE3c7kP_s,6744
|
|
@@ -40,10 +41,10 @@ machineconfig/cluster/templates/run_remote.py,sha256=vCc56t8BUAUJp7tyb0PFfwy5hlm
|
|
|
40
41
|
machineconfig/cluster/templates/utils.py,sha256=5lHgjHvodoSPBD31AwluHBBNgwimwThUsDNWGN8iH9I,1647
|
|
41
42
|
machineconfig/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
43
|
machineconfig/jobs/installer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
machineconfig/jobs/installer/packages_custom_dev.json,sha256=
|
|
44
|
+
machineconfig/jobs/installer/packages_custom_dev.json,sha256=MiHmV7hCfa4RzmO6LK3PPz0VGn3yQJgPJxrSgxKvwdc,10027
|
|
44
45
|
machineconfig/jobs/installer/packages_custom_essential.json,sha256=-Mgu436rbGE7JWCy-NYxxsnkxCxPxv4Gatu0wXp5XMI,775
|
|
45
|
-
machineconfig/jobs/installer/packages_github_dev.json,sha256=
|
|
46
|
-
machineconfig/jobs/installer/packages_github_essential.json,sha256=
|
|
46
|
+
machineconfig/jobs/installer/packages_github_dev.json,sha256=11LVsvIVKMjp8i3y_TNO31IpXaZgQWGGlmhMa_wUilE,31889
|
|
47
|
+
machineconfig/jobs/installer/packages_github_essential.json,sha256=dCGFovFPCnEu-4wed7FJDBxPHdz8ekkAK58VTQobsdg,26472
|
|
47
48
|
machineconfig/jobs/installer/custom/gh.py,sha256=hic8Z1ZdncbljY6hgHzl2rmOLOcb6imIUstMALSS3-Y,3082
|
|
48
49
|
machineconfig/jobs/installer/custom/hx.py,sha256=FrUD0mlhWG2GxrnarccVIaW_sHJ5mxeF6yyzbBWyx6w,5840
|
|
49
50
|
machineconfig/jobs/installer/custom_dev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -65,14 +66,16 @@ machineconfig/jobs/installer/linux_scripts/docker.sh,sha256=xP219QeQ5eLwhvOHsNYq
|
|
|
65
66
|
machineconfig/jobs/installer/linux_scripts/docker_start.sh,sha256=TiS-hWRltw66_p_Fq8gfkA_rqUIuwxoIkFZItVF6TXA,1478
|
|
66
67
|
machineconfig/jobs/installer/linux_scripts/edge.sh,sha256=2JclQOi6sBTs2VQPsQWh6dPFRu1C36OyRREI0a76yJQ,1903
|
|
67
68
|
machineconfig/jobs/installer/linux_scripts/nerdfont.sh,sha256=vSJQfGYVpWF2T1vz1zZuVXdeus_PWXdP7VquRQjsLwU,2351
|
|
69
|
+
machineconfig/jobs/installer/linux_scripts/ngrok.sh,sha256=K-t62nhnAHxhppTmqjubIJRHozkNHfBxXGbn1Oz3w-A,287
|
|
68
70
|
machineconfig/jobs/installer/linux_scripts/pgsql.sh,sha256=qe_yo4dM16B8L1VYIPqyLVvI1uns2jg7if_cokuOofY,2239
|
|
71
|
+
machineconfig/jobs/installer/linux_scripts/q.sh,sha256=jXokwpfwotI7X5v1dXbYKZyH5ifzSCOek-d_BociyY0,228
|
|
69
72
|
machineconfig/jobs/installer/linux_scripts/redis.sh,sha256=XNsnypuP0UQDdNnLQ1rHC8XRYeqeaM213i1aga5_Q0M,2940
|
|
70
73
|
machineconfig/jobs/installer/linux_scripts/timescaledb.sh,sha256=-thz4K7Eo_4IsNTQMLsmQdyMdVhW7NAMn5S2CB3-blE,3530
|
|
71
74
|
machineconfig/jobs/installer/linux_scripts/vscode.sh,sha256=8S0nZpOeAdhpVHvygt6rs1sywCtjHNECfNNRhXMHWW8,5417
|
|
72
75
|
machineconfig/jobs/installer/linux_scripts/warp-cli.sh,sha256=PVNLeYWdh3XEFllCVZDYIHBI42btjGlH5jbyXjJGz-Y,3033
|
|
73
76
|
machineconfig/jobs/installer/linux_scripts/wezterm.sh,sha256=m697rRoIIVk-f8JdI1YQmphk-JWpMc5IYbD5YaQ3SeQ,1874
|
|
74
77
|
machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1,sha256=JsQfGAMkvirhiUmBNOifMlbum2PfHSs0-Akgj-J-WZw,3177
|
|
75
|
-
machineconfig/jobs/linux/msc/cli_agents.sh,sha256=
|
|
78
|
+
machineconfig/jobs/linux/msc/cli_agents.sh,sha256=MMa_cd4yijI69c7tztTY1b0tl9I1ECTbxqLCShElhFU,184
|
|
76
79
|
machineconfig/jobs/linux/msc/lid.sh,sha256=09LeoSaXCGjCn7YxPcIFQpHroYdglJlEtFU2agarh3I,1302
|
|
77
80
|
machineconfig/jobs/linux/msc/network.sh,sha256=dmISsh0hioDheinqee3qHfo2k7ClFx6G_GfGDxuflmc,1796
|
|
78
81
|
machineconfig/jobs/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -148,10 +151,10 @@ machineconfig/scripts/python/devops.py,sha256=W18odC0__ZNGY_WAI-Ojr9Vf3WUTqcXk90
|
|
|
148
151
|
machineconfig/scripts/python/devops_add_identity.py,sha256=JfN3ZrYMCgmt4ks_VCfnV9BIIHAsOYO3E0W0wZ15FR8,3791
|
|
149
152
|
machineconfig/scripts/python/devops_add_ssh_key.py,sha256=KaoX83KltBsmutfKhSfZjd7nP_R1hJ2OLAWRhbswO7o,6889
|
|
150
153
|
machineconfig/scripts/python/devops_backup_retrieve.py,sha256=jZe5Vki7E2GCMG8hvqUZeOONFC4cNzISoGzq_dMG4GA,5601
|
|
151
|
-
machineconfig/scripts/python/devops_devapps_install.py,sha256=
|
|
154
|
+
machineconfig/scripts/python/devops_devapps_install.py,sha256=QbRQhNdDRLLtgJwaRl2pbLmWvajb1b_Xte2ql8N3JRs,9096
|
|
152
155
|
machineconfig/scripts/python/devops_update_repos.py,sha256=c5qBc9cuTGDEqDHufkjDT4d_vvJsswv3tlqk9MAulYk,8063
|
|
153
156
|
machineconfig/scripts/python/dotfile.py,sha256=SRcX-9Ak1jRvF-killBTTm2IWcsNxfiLucH6ZsytAFA,2202
|
|
154
|
-
machineconfig/scripts/python/fire_agents.py,sha256=
|
|
157
|
+
machineconfig/scripts/python/fire_agents.py,sha256=BgWyzac_yXzp4xpzcEOQ62UeVIiH-KR-KURAwaiAF-4,7936
|
|
155
158
|
machineconfig/scripts/python/fire_agents_help_launch.py,sha256=sTdjNz2pDinDMMjUAMN7OqH-KAUeHh6Aihr_zUvtM6k,6128
|
|
156
159
|
machineconfig/scripts/python/fire_agents_help_search.py,sha256=qIfSS_su2YJ1Gb0_lu4cbjlJlYMBw0v52NTGiSrGjk8,2991
|
|
157
160
|
machineconfig/scripts/python/fire_agents_load_balancer.py,sha256=QPiCbQq9j5REHStPdYqQcGNkz_rp5CjotqOpMY3v5TM,2099
|
|
@@ -174,7 +177,7 @@ machineconfig/scripts/python/repos_helper_clone.py,sha256=xW5YZEoNt3k7h9NIULhUhO
|
|
|
174
177
|
machineconfig/scripts/python/repos_helper_record.py,sha256=YEEQORfEiLddOIIgePo5eEkyQUFruFg3kc8npMvRL-o,10927
|
|
175
178
|
machineconfig/scripts/python/repos_helper_update.py,sha256=AYyKIB7eQ48yoYmFjydIhRI1lV39TBv_S4_LCa-oKuQ,11042
|
|
176
179
|
machineconfig/scripts/python/scheduler.py,sha256=rKhssuxkD697EY6qaV6CSdNhxpAQLDWO4fE8GMCQ9FA,3061
|
|
177
|
-
machineconfig/scripts/python/share_terminal.py,sha256=
|
|
180
|
+
machineconfig/scripts/python/share_terminal.py,sha256=fVE0_c70EEfTNyhVov4HNtDXjR-Kx0wn0Mz1CKYEij8,4991
|
|
178
181
|
machineconfig/scripts/python/snapshot.py,sha256=aDvKeoniZaeTSNv9zWBUajaj2yagAxVdfuvO1_tgq5Y,1026
|
|
179
182
|
machineconfig/scripts/python/start_slidev.py,sha256=U5ujAL7R5Gd5CzFReTsnF2SThjY91aFBg0Qz_MMl6U4,4573
|
|
180
183
|
machineconfig/scripts/python/start_terminals.py,sha256=DRWbMZumhPmL0DvvsCsbRNFL5AVQn1SgaziafTio3YQ,6149
|
|
@@ -375,7 +378,7 @@ machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=rZZJamy3YxAeJh
|
|
|
375
378
|
machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
376
379
|
machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
|
|
377
380
|
machineconfig/utils/code.py,sha256=pKPHInKgXJWeACVbxuE7sMdYeZCbNttaYCsfonGhFfc,4464
|
|
378
|
-
machineconfig/utils/installer.py,sha256=
|
|
381
|
+
machineconfig/utils/installer.py,sha256=AVAzuJqWkbMmfEk5_eKLGA3kgM6PCTXq7We2QoppZo0,8886
|
|
379
382
|
machineconfig/utils/io.py,sha256=ZXB3aataS1IZ_0WMcCRSmoN1nbkvEO-bWYcs-TpngqU,2872
|
|
380
383
|
machineconfig/utils/links.py,sha256=riNUrG8aGElRszdOPOic4M2AyOcpdcth_-y8JEiZpJ4,10253
|
|
381
384
|
machineconfig/utils/notifications.py,sha256=vvdsY5IX6XEiILTnt5lNyHxhCi0ljdGX2T_67VRfrG4,9009
|
|
@@ -400,10 +403,10 @@ machineconfig/utils/installer_utils/installer_abc.py,sha256=3jjLHL1xqTPowx52r7Bf
|
|
|
400
403
|
machineconfig/utils/installer_utils/installer_class.py,sha256=6IQswaC9mxIdeaMG-rOt-vqyKGYibBRMvC0UglZ_3mI,20268
|
|
401
404
|
machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=CCs5ebomW1acKWZRpv9dyDzM-W6pwvVplikcutE2D8I,2339
|
|
402
405
|
machineconfig/utils/schemas/installer/installer_types.py,sha256=DLagmIe0G5-xg7HZ9VrlFCDk1gIbwvX7O4gZjwq0wh0,1326
|
|
403
|
-
machineconfig/utils/schemas/layouts/layout_types.py,sha256=
|
|
406
|
+
machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
|
|
404
407
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
405
|
-
machineconfig-
|
|
406
|
-
machineconfig-
|
|
407
|
-
machineconfig-
|
|
408
|
-
machineconfig-
|
|
409
|
-
machineconfig-
|
|
408
|
+
machineconfig-4.1.dist-info/METADATA,sha256=b3JCS_zyxDLbFlIDEu5k4EdmkuOHwIIclgCSorz6Jdg,7031
|
|
409
|
+
machineconfig-4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
410
|
+
machineconfig-4.1.dist-info/entry_points.txt,sha256=c6ea0waVseT1rbfz1bw3k-eph2yVaB67x9hx64Mpvfs,1066
|
|
411
|
+
machineconfig-4.1.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
412
|
+
machineconfig-4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|