machineconfig 3.2__py3-none-any.whl → 3.5__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 (122) hide show
  1. machineconfig/cluster/sessions_managers/wt_local_manager.py +1 -1
  2. machineconfig/cluster/sessions_managers/wt_remote_manager.py +1 -1
  3. machineconfig/cluster/sessions_managers/zellij_local.py +2 -2
  4. machineconfig/cluster/sessions_managers/zellij_local_manager.py +1 -1
  5. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +1 -1
  6. machineconfig/cluster/sessions_managers/zellij_utils/monitoring_types.py +17 -7
  7. machineconfig/cluster/templates/utils.py +1 -1
  8. machineconfig/jobs/linux/msc/cli_agents.sh +18 -2
  9. machineconfig/jobs/python/python_ve_symlink.py +1 -1
  10. machineconfig/jobs/python/vscode/api.py +1 -1
  11. machineconfig/jobs/python/vscode/select_interpreter.py +2 -2
  12. machineconfig/jobs/python/vscode/sync_code.py +1 -1
  13. machineconfig/jobs/python_custom_installers/archive/ngrok.py +7 -6
  14. machineconfig/jobs/python_custom_installers/dev/aider.py +9 -1
  15. machineconfig/jobs/python_custom_installers/dev/alacritty.py +2 -1
  16. machineconfig/jobs/python_custom_installers/dev/brave.py +10 -1
  17. machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +12 -4
  18. machineconfig/jobs/python_custom_installers/dev/code.py +10 -3
  19. machineconfig/jobs/python_custom_installers/dev/cursor.py +2 -1
  20. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +7 -6
  21. machineconfig/jobs/python_custom_installers/dev/espanso.py +14 -6
  22. machineconfig/jobs/python_custom_installers/dev/goes.py +10 -1
  23. machineconfig/jobs/python_custom_installers/dev/lvim.py +9 -1
  24. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +9 -1
  25. machineconfig/jobs/python_custom_installers/dev/redis.py +2 -2
  26. machineconfig/jobs/python_custom_installers/dev/wezterm.py +3 -1
  27. machineconfig/jobs/python_custom_installers/dev/winget.py +2 -1
  28. machineconfig/jobs/python_custom_installers/docker.py +9 -1
  29. machineconfig/jobs/python_custom_installers/gh.py +11 -2
  30. machineconfig/jobs/python_custom_installers/hx.py +10 -9
  31. machineconfig/jobs/python_custom_installers/warp-cli.py +9 -1
  32. machineconfig/jobs/python_generic_installers/config.json +601 -412
  33. machineconfig/jobs/python_generic_installers/config.json.bak +414 -0
  34. machineconfig/jobs/python_generic_installers/dev/config.json +822 -562
  35. machineconfig/jobs/python_generic_installers/dev/config.json.bak +565 -0
  36. machineconfig/jobs/python_linux_installers/archive/config.json +16 -8
  37. machineconfig/jobs/python_linux_installers/archive/config.json.bak +10 -0
  38. machineconfig/jobs/python_linux_installers/config.json +134 -99
  39. machineconfig/jobs/python_linux_installers/config.json.bak +110 -0
  40. machineconfig/jobs/python_linux_installers/dev/config.json +273 -203
  41. machineconfig/jobs/python_linux_installers/dev/config.json.bak +206 -0
  42. machineconfig/jobs/python_windows_installers/config.json +74 -48
  43. machineconfig/jobs/python_windows_installers/config.json.bak +56 -0
  44. machineconfig/jobs/python_windows_installers/dev/config.json +3 -2
  45. machineconfig/jobs/python_windows_installers/dev/config.json.bak +3 -0
  46. machineconfig/profile/create.py +3 -3
  47. machineconfig/profile/shell.py +1 -1
  48. machineconfig/scripts/python/ai/mcinit.py +23 -67
  49. machineconfig/scripts/python/ai/solutions/__init__.py +0 -0
  50. machineconfig/scripts/python/ai/solutions/_shared.py +5 -0
  51. machineconfig/scripts/python/ai/solutions/claude/claude.py +8 -0
  52. machineconfig/scripts/python/ai/solutions/cline/cline.py +10 -0
  53. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +35 -0
  54. machineconfig/scripts/python/ai/solutions/copilot/privacy.md +4 -0
  55. machineconfig/scripts/python/ai/solutions/crush/crush.json +216 -0
  56. machineconfig/scripts/python/ai/solutions/crush/crush.py +25 -0
  57. machineconfig/scripts/python/ai/solutions/crush/privacy.md +2 -0
  58. machineconfig/scripts/python/ai/solutions/cursor/cursors.py +10 -0
  59. machineconfig/scripts/python/ai/solutions/gemini/gemini.py +14 -0
  60. machineconfig/scripts/python/ai/solutions/generic.py +41 -0
  61. machineconfig/scripts/python/ai/solutions/kilocode/privacy.md +3 -0
  62. machineconfig/scripts/python/ai/solutions/opencode/opencode.json +4 -0
  63. machineconfig/scripts/python/ai/solutions/opencode/opencode.py +1 -0
  64. machineconfig/scripts/python/choose_wezterm_theme.py +1 -1
  65. machineconfig/scripts/python/cloud_copy.py +2 -2
  66. machineconfig/scripts/python/cloud_mount.py +2 -2
  67. machineconfig/scripts/python/cloud_repo_sync.py +3 -2
  68. machineconfig/scripts/python/croshell.py +12 -7
  69. machineconfig/scripts/python/devops.py +1 -0
  70. machineconfig/scripts/python/devops_add_identity.py +1 -1
  71. machineconfig/scripts/python/devops_add_ssh_key.py +1 -1
  72. machineconfig/scripts/python/devops_backup_retrieve.py +4 -3
  73. machineconfig/scripts/python/devops_devapps_install.py +39 -17
  74. machineconfig/scripts/python/devops_update_repos.py +2 -2
  75. machineconfig/scripts/python/dotfile.py +1 -1
  76. machineconfig/scripts/python/fire_agents.py +7 -3
  77. machineconfig/scripts/python/fire_agents_help_launch.py +2 -2
  78. machineconfig/scripts/python/fire_jobs.py +8 -8
  79. machineconfig/scripts/python/fire_jobs_layout_helper.py +2 -2
  80. machineconfig/scripts/python/ftpx.py +2 -2
  81. machineconfig/scripts/python/helpers/cloud_helpers.py +2 -1
  82. machineconfig/scripts/python/helpers/helpers2.py +4 -3
  83. machineconfig/scripts/python/helpers/helpers4.py +1 -1
  84. machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
  85. machineconfig/scripts/python/mount_nfs.py +1 -1
  86. machineconfig/scripts/python/mount_ssh.py +1 -1
  87. machineconfig/scripts/python/repos.py +6 -3
  88. machineconfig/scripts/python/repos_helper_clone.py +121 -0
  89. machineconfig/scripts/python/repos_helper_record.py +2 -2
  90. machineconfig/scripts/python/start_slidev.py +1 -1
  91. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  92. machineconfig/setup_windows/wt_and_pwsh/install_nerd_fonts.py +9 -8
  93. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -3
  94. machineconfig/utils/{utils2.py → accessories.py} +13 -27
  95. machineconfig/utils/code.py +2 -2
  96. machineconfig/utils/installer.py +47 -33
  97. machineconfig/utils/installer_utils/installer_abc.py +2 -5
  98. machineconfig/utils/installer_utils/installer_class.py +109 -103
  99. machineconfig/utils/io.py +94 -0
  100. machineconfig/utils/links.py +2 -2
  101. machineconfig/utils/notifications.py +0 -9
  102. machineconfig/utils/{path_reduced.py → path_extended.py} +2 -2
  103. machineconfig/utils/{path.py → path_helper.py} +1 -1
  104. machineconfig/utils/procs.py +2 -1
  105. machineconfig/utils/{utils5.py → scheduler.py} +3 -8
  106. machineconfig/utils/schemas/installer/installer_types.py +20 -0
  107. machineconfig/utils/ssh.py +2 -2
  108. machineconfig/utils/terminal.py +12 -2
  109. machineconfig/utils/ve.py +2 -16
  110. {machineconfig-3.2.dist-info → machineconfig-3.5.dist-info}/METADATA +1 -4
  111. {machineconfig-3.2.dist-info → machineconfig-3.5.dist-info}/RECORD +121 -97
  112. machineconfig/utils/io_save.py +0 -95
  113. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Thinking-Beast-Mode.chatmode.md +0 -0
  114. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +0 -0
  115. /machineconfig/scripts/python/ai/{chatmodes → solutions/copilot/chatmodes}/deepResearch.chatmode.md +0 -0
  116. /machineconfig/scripts/python/ai/{instructions → solutions/copilot/instructions}/python/dev.instructions.md +0 -0
  117. /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/allLintersAndTypeCheckers.prompt.md +0 -0
  118. /machineconfig/scripts/python/ai/{prompts → solutions/copilot/prompts}/research-report-skeleton.prompt.md +0 -0
  119. /machineconfig/scripts/python/ai/{configs/.gemini → solutions/gemini}/settings.json +0 -0
  120. {machineconfig-3.2.dist-info → machineconfig-3.5.dist-info}/WHEEL +0 -0
  121. {machineconfig-3.2.dist-info → machineconfig-3.5.dist-info}/entry_points.txt +0 -0
  122. {machineconfig-3.2.dist-info → machineconfig-3.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,216 @@
1
+ {
2
+ "$schema": "https://charm.land/crush.json",
3
+ "providers": {
4
+ "openai": {
5
+ "id": "openai",
6
+ "name": "OpenAI",
7
+ "base_url": "https://api.openai.com/v1",
8
+ "type": "openai",
9
+ "api_key": "$OPENAI_API_KEY",
10
+ "extra_headers": {
11
+ "OpenAI-Beta": "assistants=v2"
12
+ },
13
+ "models": [
14
+ {
15
+ "id": "gpt-4o",
16
+ "name": "GPT-4o",
17
+ "cost_per_1m_in": 5,
18
+ "cost_per_1m_out": 15,
19
+ "cost_per_1m_in_cached": 1,
20
+ "cost_per_1m_out_cached": 3,
21
+ "context_window": 128000,
22
+ "default_max_tokens": 16384,
23
+ "can_reason": false,
24
+ "has_reasoning_efforts": false,
25
+ "supports_attachments": true
26
+ },
27
+ {
28
+ "id": "gpt-4o-mini",
29
+ "name": "GPT-4o mini",
30
+ "cost_per_1m_in": 0.15,
31
+ "cost_per_1m_out": 0.6,
32
+ "cost_per_1m_in_cached": 0.05,
33
+ "cost_per_1m_out_cached": 0.2,
34
+ "context_window": 128000,
35
+ "default_max_tokens": 8192,
36
+ "can_reason": false,
37
+ "has_reasoning_efforts": false,
38
+ "supports_attachments": true
39
+ }
40
+ ]
41
+ },
42
+ "anthropic": {
43
+ "id": "anthropic",
44
+ "name": "Anthropic",
45
+ "base_url": "https://api.anthropic.com/v1",
46
+ "type": "anthropic",
47
+ "api_key": "$ANTHROPIC_API_KEY",
48
+ "extra_headers": {
49
+ "anthropic-version": "2023-06-01"
50
+ },
51
+ "models": [
52
+ {
53
+ "id": "claude-3-5-sonnet-20240620",
54
+ "name": "Claude 3.5 Sonnet",
55
+ "cost_per_1m_in": 3,
56
+ "cost_per_1m_out": 15,
57
+ "cost_per_1m_in_cached": 3.75,
58
+ "cost_per_1m_out_cached": 0.3,
59
+ "context_window": 200000,
60
+ "default_max_tokens": 8000,
61
+ "can_reason": true,
62
+ "has_reasoning_efforts": true,
63
+ "default_reasoning_effort": "medium",
64
+ "supports_attachments": true
65
+ },
66
+ {
67
+ "id": "claude-3-haiku-20240307",
68
+ "name": "Claude 3 Haiku",
69
+ "cost_per_1m_in": 0.25,
70
+ "cost_per_1m_out": 1.25,
71
+ "cost_per_1m_in_cached": 0.05,
72
+ "cost_per_1m_out_cached": 0.1,
73
+ "context_window": 200000,
74
+ "default_max_tokens": 4000,
75
+ "can_reason": true,
76
+ "has_reasoning_efforts": true,
77
+ "default_reasoning_effort": "low",
78
+ "supports_attachments": true
79
+ }
80
+ ]
81
+ },
82
+ "openrouter": {
83
+ "id": "openrouter",
84
+ "name": "OpenRouter",
85
+ "base_url": "https://openrouter.ai/api/v1",
86
+ "type": "openai",
87
+ "api_key": "$OPENROUTER_API_KEY",
88
+ "models": [
89
+ {
90
+ "id": "deepseek/deepseek-chat",
91
+ "name": "Deepseek V3",
92
+ "cost_per_1m_in": 0.27,
93
+ "cost_per_1m_out": 1.1,
94
+ "cost_per_1m_in_cached": 0.07,
95
+ "cost_per_1m_out_cached": 0.3,
96
+ "context_window": 64000,
97
+ "default_max_tokens": 5000,
98
+ "can_reason": true,
99
+ "has_reasoning_efforts": false,
100
+ "supports_attachments": false
101
+ }
102
+ ]
103
+ },
104
+ "ollama": {
105
+ "id": "ollama",
106
+ "name": "Ollama",
107
+ "base_url": "http://localhost:11434/v1/",
108
+ "type": "openai",
109
+ "models": [
110
+ {
111
+ "id": "qwen2.5-coder:14b",
112
+ "name": "Qwen2.5 Coder 14B",
113
+ "cost_per_1m_in": 0,
114
+ "cost_per_1m_out": 0,
115
+ "cost_per_1m_in_cached": 0,
116
+ "cost_per_1m_out_cached": 0,
117
+ "context_window": 32768,
118
+ "default_max_tokens": 4096,
119
+ "can_reason": false,
120
+ "has_reasoning_efforts": false,
121
+ "supports_attachments": false
122
+ }
123
+ ]
124
+ }
125
+ },
126
+ "models": {
127
+ "large": {
128
+ "provider": "anthropic",
129
+ "model": "claude-3-5-sonnet-20240620",
130
+ "think": true,
131
+ "max_tokens": 6000
132
+ },
133
+ "small": {
134
+ "provider": "openai",
135
+ "model": "gpt-4o-mini",
136
+ "max_tokens": 4096
137
+ }
138
+ },
139
+ "lsp": {
140
+ "python": {
141
+ "command": "pyright-langserver",
142
+ "args": ["--stdio"],
143
+ "filetypes": ["py"],
144
+ "env": {
145
+ "PYRIGHT_PYTHON_FORCE_VERSION": "3.13"
146
+ }
147
+ },
148
+ "ruff": {
149
+ "command": "ruff",
150
+ "args": ["server"],
151
+ "filetypes": ["py"]
152
+ },
153
+ "json": {
154
+ "command": "vscode-json-languageserver",
155
+ "args": ["--stdio"]
156
+ }
157
+ },
158
+ "mcp": {
159
+ "filesystem": {
160
+ "type": "stdio",
161
+ "command": "uv",
162
+ "args": [
163
+ "run",
164
+ "python",
165
+ "-m",
166
+ "machineconfig.scripts.python.ai.solutions._shared"
167
+ ],
168
+ "timeout": 120,
169
+ "env": {
170
+ "UV_PROJECT_ENV": "$(pwd)"
171
+ }
172
+ },
173
+ "github-docs": {
174
+ "type": "http",
175
+ "url": "https://api.github.com/mcp/",
176
+ "timeout": 90,
177
+ "headers": {
178
+ "Authorization": "$(echo Bearer $GITHUB_MCP_TOKEN)",
179
+ "X-Crush-Client": "machineconfig"
180
+ }
181
+ },
182
+ "architect": {
183
+ "type": "sse",
184
+ "url": "https://architect.mcp.machineconfig.local/stream",
185
+ "timeout": 120,
186
+ "headers": {
187
+ "Authorization": "$(echo Bearer $ARCHITECT_MCP_TOKEN)"
188
+ }
189
+ }
190
+ },
191
+ "options": {
192
+ "context_paths": [
193
+ "CRUSH.md",
194
+ "src/machineconfig/scripts/python/ai/solutions/crush/privacy.md",
195
+ ".github/copilot-instructions.md",
196
+ "src/machineconfig/scripts/python/ai/solutions/_shared.py"
197
+ ],
198
+ "tui": {
199
+ "compact_mode": true,
200
+ "diff_mode": "unified"
201
+ },
202
+ "debug": false,
203
+ "debug_lsp": false,
204
+ "disable_auto_summarize": false,
205
+ "data_directory": ".crush"
206
+ },
207
+ "permissions": {
208
+ "allowed_tools": [
209
+ "view",
210
+ "ls",
211
+ "glob",
212
+ "grep",
213
+ "write"
214
+ ]
215
+ }
216
+ }
@@ -0,0 +1,25 @@
1
+
2
+
3
+ """
4
+ ref: https://github.com/charmbracelet/crush
5
+
6
+ """
7
+
8
+ from pathlib import Path
9
+ import platform
10
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
11
+
12
+
13
+
14
+ def build_configuration(repo_root: Path) -> None:
15
+ instructions_path = get_generic_instructions_path()
16
+ repo_root.joinpath("CRUSH.md").write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
17
+
18
+ repo_settings = repo_root.joinpath(".crush.json")
19
+ ignore_settings = repo_root.joinpath(".crushignore")
20
+ if platform.system() == "Windows":
21
+ global_settings = Path.home().joinpath("AppData/Local/crush/crush.json")
22
+ else:
23
+ global_settings = Path.home().joinpath(".config/crush/crush.json")
24
+
25
+ _ = repo_settings, ignore_settings, global_settings # to avoid unused variable warnings
@@ -0,0 +1,2 @@
1
+
2
+ docs don't mention at all anything about user code privacy, data collection or telemetry or any reporting.
@@ -0,0 +1,10 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
4
+
5
+
6
+ def build_configuration(repo_root: Path) -> None:
7
+ instructions_path = get_generic_instructions_path()
8
+ cursor_rules_path = repo_root.joinpath(".cursor/rules/python_dev.mdc")
9
+ cursor_rules_path.parent.mkdir(parents=True, exist_ok=True)
10
+ cursor_rules_path.write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.scripts.python.ai.solutions._shared import get_generic_instructions_path
4
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT
5
+
6
+ def build_configuration(repo_root: Path) -> None:
7
+ instructions_path = get_generic_instructions_path()
8
+ repo_root.joinpath("GEMINI.md").write_text(data=instructions_path.read_text(encoding="utf-8"), encoding="utf-8")
9
+
10
+ gemini_dir = repo_root.joinpath(".gemini")
11
+ settings_source_path = LIBRARY_ROOT.joinpath("scripts/python/ai/solutions/gemini/settings.json")
12
+ gemini_dir.mkdir(parents=True, exist_ok=True)
13
+
14
+ settings_source_path.write_text(data=settings_source_path.read_text(encoding="utf-8"), encoding="utf-8")
@@ -0,0 +1,41 @@
1
+ from pathlib import Path
2
+
3
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT
4
+
5
+
6
+ def create_dot_scripts(repo_root: Path) -> None:
7
+ scripts_dir = LIBRARY_ROOT.joinpath("scripts/python/ai/scripts")
8
+ target_dir = repo_root.joinpath(".scripts")
9
+ target_dir.mkdir(parents=True, exist_ok=True)
10
+ for script_path in scripts_dir.iterdir():
11
+ target_dir.joinpath(script_path.name).write_text(data=script_path.read_text(encoding="utf-8"), encoding="utf-8")
12
+
13
+
14
+ def adjust_gitignore(repo_root: Path) -> None:
15
+ dot_git_ignore_path = repo_root.joinpath(".gitignore")
16
+ if dot_git_ignore_path.exists() is False:
17
+ return
18
+
19
+ dot_git_ignore_content = dot_git_ignore_path.read_text(encoding="utf-8")
20
+ entries_to_add: list[str] = []
21
+ required_entries: list[str] = [
22
+ ".links",
23
+ "notebooks",
24
+ ".ai",
25
+ ".scripts",
26
+ "GEMINI.md",
27
+ "CLAUDE.md",
28
+ ".cursor",
29
+ ".github/instructions",
30
+ ".github/chatmodes",
31
+ ".github/prompts",
32
+ ]
33
+
34
+ for entry in required_entries:
35
+ if entry not in dot_git_ignore_content:
36
+ entries_to_add.append(entry)
37
+
38
+ if len(entries_to_add) == 0:
39
+ return
40
+
41
+ dot_git_ignore_path.write_text(data=dot_git_ignore_content + "\n" + "\n".join(entries_to_add), encoding="utf-8")
@@ -0,0 +1,3 @@
1
+
2
+ # disable usage and erroror reports to kilocode in About/Export page.
3
+ # Disable model api provider data collection.
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "instructions": [".github/instructions/*.md"]
4
+ }
@@ -3,7 +3,7 @@ Choose a theme for Wezterm
3
3
  """
4
4
 
5
5
  from machineconfig.utils.options import choose_one_option
6
- from machineconfig.utils.path_reduced import PathExtended
6
+ from machineconfig.utils.path_extended import PathExtended
7
7
  from typing import Any
8
8
  import time
9
9
  from rich.panel import Panel
@@ -2,7 +2,7 @@
2
2
  CC
3
3
  """
4
4
 
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
  from tenacity import retry, stop_after_attempt, wait_chain, wait_fixed
7
7
  import getpass
8
8
  import argparse
@@ -14,7 +14,7 @@ from machineconfig.scripts.python.helpers.cloud_helpers import ArgsDefaults, Arg
14
14
  from rich.console import Console
15
15
  from rich.panel import Panel
16
16
  from rich.progress import Progress
17
- from machineconfig.utils.utils2 import pprint
17
+ from machineconfig.utils.accessories import pprint
18
18
 
19
19
  console = Console()
20
20
 
@@ -1,8 +1,8 @@
1
1
  """Cloud mount script"""
2
2
 
3
3
  from machineconfig.utils.options import choose_one_option
4
- from machineconfig.utils.utils2 import read_ini
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
4
+ from machineconfig.utils.io import read_ini
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
 
7
7
  import platform
8
8
  import argparse
@@ -2,9 +2,10 @@
2
2
 
3
3
  from pathlib import Path
4
4
  import git
5
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
+ from machineconfig.utils.io import read_ini
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
7
  from machineconfig.utils.terminal import Terminal
7
- from machineconfig.utils.utils2 import randstr, read_ini
8
+ from machineconfig.utils.accessories import randstr
8
9
 
9
10
  from machineconfig.scripts.python.helpers.repo_sync_helpers import fetch_dotfiles
10
11
  from machineconfig.utils.source_of_truth import CONFIG_PATH, DEFAULTS_PATH
@@ -5,8 +5,8 @@ croshell
5
5
  """
6
6
 
7
7
  import argparse
8
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
9
- from machineconfig.utils.utils2 import randstr
8
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
9
+ from machineconfig.utils.accessories import randstr
10
10
 
11
11
  from machineconfig.utils.options import display_options
12
12
  from machineconfig.utils.ve import get_ve_activate_line
@@ -21,8 +21,10 @@ console = Console()
21
21
 
22
22
  def add_print_header_pycode(path: str, title: str):
23
23
  return f"""
24
- # from machineconfig.utils.path_reduced import P as PathExtended
25
- from crocodile.file_management import P as PathExtended
24
+ try:
25
+ from crocodile.file_management import P as PathExtended
26
+ except ImportError:
27
+ from machineconfig.utils.path_reduced import PathExtended
26
28
  pycode = PathExtended(r'{path}').read_text(encoding="utf-8")
27
29
  pycode = pycode.split("except Exception: print(pycode)")[2]
28
30
 
@@ -160,10 +162,13 @@ def build_parser():
160
162
  preprogram = """
161
163
 
162
164
  #%%
163
- from crocodile.croshell import *
165
+ try:
166
+ from crocodile.croshell import *
167
+ print_header()
168
+ print_logo(logo="crocodile")
169
+ except ImportError:
170
+ print("Crocodile not found, skipping import.")
164
171
  from pathlib import Path
165
- print_header()
166
- print_logo(logo="crocodile")
167
172
  print(f"🐊 Crocodile Shell | Running @ {Path.cwd()}")
168
173
  """
169
174
 
@@ -62,6 +62,7 @@ def main(which: Optional[str] = None):
62
62
  elif choice_key == Options.cli_install.value:
63
63
  console.print(Panel("⚙️ Installing development applications...", width=BOX_WIDTH, border_style="blue"))
64
64
  import machineconfig.scripts.python.devops_devapps_install as helper
65
+
65
66
  helper.main(which=None)
66
67
 
67
68
  elif choice_key == Options.sym_new.value:
@@ -1,7 +1,7 @@
1
1
  """ID"""
2
2
 
3
3
  # from platform import system
4
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
4
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
5
5
  from machineconfig.utils.options import display_options
6
6
  from rich.panel import Panel
7
7
  from rich.text import Text
@@ -3,7 +3,7 @@
3
3
  from platform import system
4
4
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
5
5
  from machineconfig.utils.options import display_options
6
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
7
7
  from rich.console import Console
8
8
  from rich.panel import Panel
9
9
  from rich import box # Import box
@@ -1,8 +1,8 @@
1
1
  """BR: Backup and Retrieve"""
2
2
 
3
3
  # import subprocess
4
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
5
- from machineconfig.utils.utils2 import read_ini, read_toml
4
+ from machineconfig.utils.io import read_ini
5
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
6
6
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT, DEFAULTS_PATH
7
7
  from machineconfig.utils.code import print_code
8
8
  from machineconfig.utils.options import choose_cloud_interactively, choose_multiple_options
@@ -11,6 +11,7 @@ from platform import system
11
11
  from typing import Any, Literal, Optional
12
12
  from rich.console import Console
13
13
  from rich.panel import Panel
14
+ import tomllib
14
15
 
15
16
 
16
17
  OPTIONS = Literal["BACKUP", "RETRIEVE"]
@@ -26,7 +27,7 @@ def main_backup_retrieve(direction: OPTIONS, which: Optional[str] = None) -> Non
26
27
  console.print(Panel("🔍 DEFAULT CLOUD NOT FOUND\n🔄 Please select a cloud configuration from the options below", title="[bold red]Error: Cloud Not Found[/bold red]", border_style="red"))
27
28
  cloud = choose_cloud_interactively()
28
29
 
29
- bu_file: dict[str, Any] = read_toml(LIBRARY_ROOT.joinpath("profile/backup.toml"))
30
+ bu_file: dict[str, Any] = tomllib.loads(LIBRARY_ROOT.joinpath("profile/backup.toml").read_text(encoding="utf-8"))
30
31
 
31
32
  console.print(Panel(f"🧰 LOADING BACKUP CONFIGURATION\n📄 File: {LIBRARY_ROOT.joinpath('profile/backup.toml')}", title="[bold blue]Backup Configuration[/bold blue]", border_style="blue"))
32
33
 
@@ -1,11 +1,10 @@
1
1
  """Devops Devapps Install"""
2
2
 
3
3
  # import subprocess
4
- from machineconfig.utils.installer_utils.installer_class import Installer
5
4
  from rich.progress import Progress, SpinnerColumn, TextColumn
6
5
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
7
6
  from machineconfig.utils.options import choose_multiple_options
8
- from machineconfig.utils.installer import get_installers, install_all, get_all_dicts
7
+ from machineconfig.utils.installer import get_installers, install_all
9
8
  from platform import system
10
9
  from typing import Any, Optional, Literal, TypeAlias, get_args
11
10
 
@@ -20,25 +19,35 @@ def main(which: Optional[WHICH_CAT | str]) -> None:
20
19
  if which is not None: # install by name
21
20
  total_messages: list[str] = []
22
21
  for a_which in which.split(",") if type(which) == str else which:
23
- kv = {}
24
- for _category, v in get_all_dicts(system=system()).items():
25
- kv.update(v)
26
- if a_which not in kv:
27
- raise ValueError(f"{a_which=} not found in {kv.keys()}")
22
+ # Use get_installers to get properly converted installer objects
23
+ all_installers = get_installers(system=system(), dev=False) + get_installers(system=system(), dev=True)
24
+
25
+ # Find installer by exe_name or name
26
+ selected_installer = None
27
+ for installer in all_installers:
28
+ exe_name = installer.installer_data.get("exeName", "")
29
+ app_name = installer.installer_data.get("appName", "")
30
+ if exe_name == a_which or app_name == a_which:
31
+ selected_installer = installer
32
+ break
33
+
34
+ if selected_installer is None:
35
+ available_names = [f"{inst.installer_data.get('exeName', 'unknown')} ({inst.installer_data.get('appName', 'unknown')})" for inst in all_installers[:10]] # Show first 10
36
+ raise ValueError(f"{a_which=} not found. Available installers include: {available_names}")
37
+
28
38
  print(f"""
29
39
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
30
40
  ┃ 🔧 Installing: {a_which}
31
41
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
32
- installer = Installer.from_dict(name=a_which, d=kv[a_which])
33
- print(installer)
34
- program = installer.install_robust(version=None) # finish the task
35
- total_messages.append(program)
42
+ print(selected_installer)
43
+ message = selected_installer.install_robust(version=None) # finish the task
44
+ total_messages.append(message)
36
45
  for a_message in total_messages:
37
46
  print(a_message)
38
47
  return None
39
48
 
40
49
  # interactive installation
41
- installers = [Installer.from_dict(d=vd, name=name) for __kat, vds in get_all_dicts(system=system()).items() for name, vd in vds.items()]
50
+ installers = get_installers(system=system(), dev=False) + get_installers(system=system(), dev=True)
42
51
 
43
52
  # Check installed programs with progress indicator
44
53
  with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
@@ -52,20 +61,33 @@ def main(which: Optional[WHICH_CAT | str]) -> None:
52
61
  # print("s"*1000)
53
62
  program_names = choose_multiple_options(msg="", options=options, header="🚀 CHOOSE DEV APP", default="AllEssentials")
54
63
 
55
- total_program = ""
64
+ total_commands = ""
65
+ installation_messages: list[str] = []
56
66
  for _an_idx, a_program_name in enumerate(program_names):
57
67
  print(f"""
58
68
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
59
69
  ┃ 🔄 Processing: {a_program_name}
60
70
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
61
71
  if a_program_name in get_args(WHICH_CAT):
62
- total_program += "\n" + get_programs_by_category(program_name=a_program_name) # type: ignore
72
+ shell_commands = get_programs_by_category(program_name=a_program_name) # type: ignore
73
+ total_commands += "\n" + shell_commands
63
74
  else:
64
75
  an_installer = installers[options.index(a_program_name)]
65
- total_program += "\n" + an_installer.install_robust(version=None) # finish the task
66
- import subprocess
76
+ status_message = an_installer.install_robust(version=None) # finish the task - this returns a status message, not a command
77
+ installation_messages.append(status_message)
78
+
79
+ # Print all installation status messages
80
+ print("\n📊 INSTALLATION SUMMARY:")
81
+ print("=" * 50)
82
+ for message in installation_messages:
83
+ print(message)
84
+
85
+ # Only run shell commands if there are any (from category installations)
86
+ if total_commands.strip():
87
+ import subprocess
67
88
 
68
- subprocess.run(total_program, shell=True, check=True)
89
+ print("\n🚀 Running additional shell commands...")
90
+ subprocess.run(total_commands, shell=True, check=True)
69
91
 
70
92
 
71
93
  def get_programs_by_category(program_name: WHICH_CAT):
@@ -3,9 +3,9 @@
3
3
  import git
4
4
  from pathlib import Path
5
5
  from machineconfig.scripts.python.repos_helper_update import RepositoryUpdateResult, run_uv_sync, update_repository
6
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
6
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
7
7
  from machineconfig.utils.source_of_truth import DEFAULTS_PATH
8
- from machineconfig.utils.utils2 import read_ini
8
+ from machineconfig.utils.io import read_ini
9
9
 
10
10
 
11
11
  def _display_summary(results: list[RepositoryUpdateResult]) -> None:
@@ -1,6 +1,6 @@
1
1
  """Like yadm and dotter."""
2
2
 
3
- from machineconfig.utils.path_reduced import PathExtended as PathExtended
3
+ from machineconfig.utils.path_extended import PathExtended as PathExtended
4
4
  from machineconfig.utils.links import symlink_func
5
5
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT, REPO_ROOT
6
6
  import argparse
@@ -17,7 +17,7 @@ from machineconfig.scripts.python.fire_agents_help_search import search_files_by
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_one_option
19
19
  from machineconfig.utils.schemas.layouts.layout_types import TabConfig, LayoutConfig
20
- from machineconfig.utils.ve import get_repo_root
20
+ from machineconfig.utils.accessories import get_repo_root
21
21
 
22
22
  SEARCH_STRATEGIES: TypeAlias = Literal["file_path", "keyword_search", "filename_pattern"]
23
23
 
@@ -151,17 +151,21 @@ manager.run_monitoring_routine()
151
151
 
152
152
 
153
153
  def split_too_many_tabs_to_run_in_sequential_sessions(layout_tabs: list[TabConfig], every: int):
154
- from machineconfig.utils.utils2 import split
154
+ from machineconfig.utils.accessories import split
155
155
  from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
156
+
156
157
  for idx, layout_tabs_chunk in enumerate(split(layout_tabs, every=every)):
157
158
  a_layout_file: LayoutConfig = {"layoutName": f"split_{idx}", "layoutTabs": layout_tabs_chunk}
158
159
  manager = ZellijLocalManager(session_layouts=[a_layout_file])
159
160
  manager.start_all_sessions(poll_interval=2, poll_seconds=2)
160
161
  manager.run_monitoring_routine(wait_ms=2000)
161
162
  manager.kill_all_sessions()
163
+
164
+
162
165
  def split_too_many_layouts_to_run_in_sequential_sessions(layouts: list[LayoutConfig], every: int):
163
- from machineconfig.utils.utils2 import split
166
+ from machineconfig.utils.accessories import split
164
167
  from machineconfig.cluster.sessions_managers.zellij_local_manager import ZellijLocalManager
168
+
165
169
  for _idx, layout_chunk in enumerate(split(layouts, every=every)):
166
170
  manager = ZellijLocalManager(session_layouts=layout_chunk)
167
171
  manager.start_all_sessions(poll_interval=2, poll_seconds=2)
@@ -1,4 +1,4 @@
1
- from machineconfig.utils.utils2 import randstr
1
+ from machineconfig.utils.accessories import randstr
2
2
 
3
3
  import random
4
4
  import shlex
@@ -14,7 +14,7 @@ AGENT_NAME_FORMATTER = "agent_{idx}_cmd.sh" # e.g., agent_0_cmd.sh
14
14
 
15
15
 
16
16
  def get_gemini_api_keys() -> list[str]:
17
- from machineconfig.utils.utils2 import read_ini
17
+ from machineconfig.utils.io import read_ini
18
18
 
19
19
  config = read_ini(Path.home().joinpath("dotfiles/creds/llm/gemini/api_keys.ini"))
20
20
  res: list[str] = []