machineconfig 5.15__py3-none-any.whl → 7.66__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

Files changed (389) hide show
  1. machineconfig/__init__.py +0 -28
  2. machineconfig/cluster/remote/distribute.py +0 -1
  3. machineconfig/cluster/remote/file_manager.py +0 -2
  4. machineconfig/cluster/remote/script_execution.py +0 -1
  5. machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
  6. machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
  7. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  8. machineconfig/cluster/sessions_managers/wt_local.py +114 -289
  9. machineconfig/cluster/sessions_managers/wt_local_manager.py +50 -193
  10. machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
  11. machineconfig/cluster/sessions_managers/wt_remote_manager.py +49 -197
  12. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
  13. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  14. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  15. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
  16. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  17. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  18. machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
  19. machineconfig/cluster/sessions_managers/zellij_local_manager.py +22 -169
  20. machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
  21. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
  22. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
  23. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
  24. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
  25. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
  26. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
  27. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
  28. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
  29. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
  30. machineconfig/jobs/{python → installer}/check_installations.py +2 -3
  31. machineconfig/jobs/installer/custom/boxes.py +61 -0
  32. machineconfig/jobs/installer/custom/hx.py +76 -19
  33. machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
  34. machineconfig/jobs/installer/custom_dev/brave.py +1 -7
  35. machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
  36. machineconfig/jobs/installer/custom_dev/code.py +4 -1
  37. machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
  38. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +9 -18
  39. machineconfig/jobs/installer/custom_dev/sysabc.py +119 -0
  40. machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
  41. machineconfig/jobs/installer/installer_data.json +1101 -115
  42. machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
  43. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
  44. machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
  45. machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
  46. machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
  47. machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
  48. machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
  49. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
  50. machineconfig/jobs/installer/linux_scripts/q.sh +1 -0
  51. machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
  52. machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
  53. machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
  54. machineconfig/jobs/installer/package_groups.py +108 -180
  55. machineconfig/logger.py +0 -1
  56. machineconfig/profile/backup.toml +49 -0
  57. machineconfig/profile/bash_shell_profiles.md +11 -0
  58. machineconfig/profile/create_helper.py +74 -0
  59. machineconfig/profile/create_links.py +288 -0
  60. machineconfig/profile/create_links_export.py +100 -0
  61. machineconfig/profile/create_shell_profile.py +136 -0
  62. machineconfig/profile/mapper.toml +258 -0
  63. machineconfig/scripts/Restore-ThunderbirdProfile.ps1 +92 -0
  64. machineconfig/scripts/__init__.py +0 -4
  65. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
  66. machineconfig/scripts/linux/wrap_mcfg +47 -0
  67. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  68. machineconfig/scripts/python/agents.py +92 -103
  69. machineconfig/scripts/python/ai/command_runner/command_runner.sh +9 -0
  70. machineconfig/scripts/python/ai/command_runner/prompt.txt +9 -0
  71. machineconfig/scripts/python/ai/generate_files.py +307 -42
  72. machineconfig/scripts/python/ai/initai.py +3 -28
  73. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
  74. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
  75. machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
  76. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +1 -1
  77. machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
  78. machineconfig/scripts/python/ai/solutions/generic.py +27 -4
  79. machineconfig/scripts/python/ai/vscode_tasks.py +37 -0
  80. machineconfig/scripts/python/cloud.py +29 -0
  81. machineconfig/scripts/python/croshell.py +111 -114
  82. machineconfig/scripts/python/define.py +31 -0
  83. machineconfig/scripts/python/devops.py +44 -103
  84. machineconfig/scripts/python/devops_navigator.py +10 -0
  85. machineconfig/scripts/python/env_manager/__init__.py +1 -0
  86. machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
  87. machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
  88. machineconfig/scripts/python/explore.py +49 -0
  89. machineconfig/scripts/python/fire_jobs.py +115 -152
  90. machineconfig/scripts/python/ftpx.py +29 -24
  91. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
  92. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +37 -0
  93. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
  94. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +42 -0
  95. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  96. machineconfig/scripts/python/{fire_agents_help_launch.py → helpers_agents/fire_agents_help_launch.py} +34 -44
  97. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +34 -0
  98. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
  99. machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
  100. machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
  101. machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
  102. machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +10 -18
  103. machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
  104. machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
  105. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  106. machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +2 -2
  107. machineconfig/scripts/python/helpers_devops/cli_config.py +95 -0
  108. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  109. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  110. machineconfig/scripts/python/helpers_devops/cli_nw.py +134 -0
  111. machineconfig/scripts/python/helpers_devops/cli_repos.py +182 -0
  112. machineconfig/scripts/python/helpers_devops/cli_self.py +134 -0
  113. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  114. machineconfig/scripts/python/helpers_devops/cli_share_server.py +141 -0
  115. machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_terminal.py} +35 -23
  116. machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
  117. machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
  118. machineconfig/scripts/python/helpers_devops/devops_status.py +511 -0
  119. machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
  120. machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
  121. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  122. machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +2 -2
  123. machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
  124. machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
  125. machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
  126. machineconfig/scripts/python/{fire_jobs_route_helper.py → helpers_fire_command/fire_jobs_route_helper.py} +47 -2
  127. machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
  128. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  129. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfag +1 -1
  130. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +1 -1
  131. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfrga +1 -1
  132. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  133. machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
  134. machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
  135. machineconfig/scripts/python/helpers_navigator/command_tree.py +588 -0
  136. machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
  137. machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
  138. machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
  139. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  140. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  141. machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
  142. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
  143. machineconfig/scripts/python/{count_lines.py → helpers_repos/count_lines.py} +10 -10
  144. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +17 -0
  145. machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
  146. machineconfig/scripts/python/helpers_repos/grource.py +340 -0
  147. machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
  148. machineconfig/scripts/python/helpers_repos/sync.py +66 -0
  149. machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
  150. machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
  151. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +58 -0
  152. machineconfig/scripts/python/helpers_utils/download.py +152 -0
  153. machineconfig/scripts/python/helpers_utils/path.py +108 -0
  154. machineconfig/scripts/python/interactive.py +64 -84
  155. machineconfig/scripts/python/machineconfig.py +63 -0
  156. machineconfig/scripts/python/msearch.py +21 -0
  157. machineconfig/scripts/python/nw/__init__.py +0 -0
  158. machineconfig/scripts/python/{devops_add_identity.py → nw/devops_add_identity.py} +0 -2
  159. machineconfig/scripts/python/{devops_add_ssh_key.py → nw/devops_add_ssh_key.py} +73 -43
  160. machineconfig/scripts/{linux → python/nw}/mount_nfs +1 -1
  161. machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +3 -3
  162. machineconfig/scripts/{linux → python/nw}/mount_nw_drive +1 -2
  163. machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +3 -3
  164. machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -1
  165. machineconfig/scripts/python/nw/ssh_debug_linux.py +391 -0
  166. machineconfig/scripts/python/nw/ssh_debug_windows.py +338 -0
  167. machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +1 -53
  168. machineconfig/scripts/python/{wsl_windows_transfer.py → nw/wsl_windows_transfer.py} +5 -4
  169. machineconfig/scripts/python/sessions.py +64 -44
  170. machineconfig/scripts/python/terminal.py +127 -0
  171. machineconfig/scripts/python/utils.py +66 -0
  172. machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
  173. machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
  174. machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
  175. machineconfig/scripts/windows/wrap_mcfg.ps1 +60 -0
  176. machineconfig/settings/broot/br.sh +0 -4
  177. machineconfig/settings/broot/conf.toml +1 -1
  178. machineconfig/settings/helix/config.toml +16 -0
  179. machineconfig/settings/helix/languages.toml +13 -4
  180. machineconfig/settings/helix/yazi-picker.sh +12 -0
  181. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  182. machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
  183. machineconfig/settings/lf/linux/lfrc +10 -12
  184. machineconfig/settings/lf/windows/fzf_edit.ps1 +2 -2
  185. machineconfig/settings/lf/windows/lfrc +18 -38
  186. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  187. machineconfig/settings/linters/.ruff.toml +1 -1
  188. machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
  189. machineconfig/settings/marimo/marimo.toml +80 -0
  190. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  191. machineconfig/settings/pistol/pistol.conf +1 -1
  192. machineconfig/settings/shells/bash/init.sh +55 -31
  193. machineconfig/settings/shells/nushell/config.nu +1 -34
  194. machineconfig/settings/shells/nushell/init.nu +127 -0
  195. machineconfig/settings/shells/pwsh/init.ps1 +60 -43
  196. machineconfig/settings/shells/starship/starship.toml +16 -0
  197. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  198. machineconfig/settings/shells/wt/settings.json +32 -17
  199. machineconfig/settings/shells/zsh/init.sh +89 -0
  200. machineconfig/settings/svim/linux/init.toml +0 -4
  201. machineconfig/settings/svim/windows/init.toml +0 -3
  202. machineconfig/settings/yazi/init.lua +57 -0
  203. machineconfig/settings/yazi/keymap_linux.toml +79 -0
  204. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  205. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  206. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  207. machineconfig/settings/yazi/yazi.toml +13 -0
  208. machineconfig/setup_linux/__init__.py +10 -0
  209. machineconfig/setup_linux/apps_desktop.sh +89 -0
  210. machineconfig/setup_linux/apps_gui.sh +64 -0
  211. machineconfig/setup_linux/{nix → others}/cli_installation.sh +9 -29
  212. machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
  213. machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
  214. machineconfig/setup_linux/uv.sh +15 -0
  215. machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
  216. machineconfig/setup_mac/__init__.py +16 -0
  217. machineconfig/setup_mac/apps_gui.sh +248 -0
  218. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  219. machineconfig/setup_mac/uv.sh +36 -0
  220. machineconfig/setup_windows/__init__.py +8 -0
  221. machineconfig/setup_windows/others/power_options.ps1 +7 -0
  222. machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
  223. machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
  224. machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
  225. machineconfig/setup_windows/uv.ps1 +10 -0
  226. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
  227. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +16 -0
  228. machineconfig/utils/accessories.py +7 -5
  229. machineconfig/utils/cloud/onedrive/README.md +139 -0
  230. machineconfig/utils/code.py +133 -106
  231. machineconfig/utils/files/art/fat_croco.txt +10 -0
  232. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  233. machineconfig/utils/files/art/happy_croco.txt +22 -0
  234. machineconfig/utils/files/art/water_croco.txt +11 -0
  235. machineconfig/utils/files/ascii_art.py +1 -1
  236. machineconfig/utils/files/dbms.py +257 -0
  237. machineconfig/utils/files/headers.py +11 -14
  238. machineconfig/utils/files/ouch/__init__.py +0 -0
  239. machineconfig/utils/files/ouch/decompress.py +45 -0
  240. machineconfig/utils/files/read.py +10 -18
  241. machineconfig/utils/installer_utils/installer_class.py +68 -126
  242. machineconfig/utils/installer_utils/{installer.py → installer_cli.py} +109 -117
  243. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +31 -81
  244. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +44 -74
  245. machineconfig/utils/io.py +77 -23
  246. machineconfig/utils/links.py +254 -162
  247. machineconfig/utils/meta.py +255 -0
  248. machineconfig/utils/notifications.py +1 -1
  249. machineconfig/utils/options.py +13 -3
  250. machineconfig/utils/path_extended.py +46 -100
  251. machineconfig/utils/path_helper.py +75 -22
  252. machineconfig/utils/procs.py +50 -70
  253. machineconfig/utils/scheduler.py +94 -97
  254. machineconfig/utils/scheduling.py +0 -3
  255. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  256. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  257. machineconfig/utils/source_of_truth.py +3 -6
  258. machineconfig/utils/ssh.py +742 -264
  259. machineconfig/utils/ssh_utils/utils.py +0 -0
  260. machineconfig/utils/terminal.py +2 -113
  261. machineconfig/utils/tst.py +20 -0
  262. machineconfig/utils/upgrade_packages.py +109 -28
  263. machineconfig/utils/ve.py +11 -4
  264. machineconfig-7.66.dist-info/METADATA +124 -0
  265. machineconfig-7.66.dist-info/RECORD +451 -0
  266. machineconfig-7.66.dist-info/entry_points.txt +15 -0
  267. machineconfig/cluster/sessions_managers/ffile.py +0 -4
  268. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
  269. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
  270. machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
  271. machineconfig/jobs/python/python_ve_symlink.py +0 -37
  272. machineconfig/jobs/python/vscode/api.py +0 -57
  273. machineconfig/jobs/python/vscode/sync_code.py +0 -73
  274. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
  275. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  276. machineconfig/jobs/windows/startup_file.cmd +0 -2
  277. machineconfig/profile/create.py +0 -303
  278. machineconfig/profile/shell.py +0 -176
  279. machineconfig/scripts/cloud/init.sh +0 -119
  280. machineconfig/scripts/linux/agents +0 -2
  281. machineconfig/scripts/linux/choose_wezterm_theme +0 -3
  282. machineconfig/scripts/linux/cloud_copy +0 -2
  283. machineconfig/scripts/linux/cloud_mount +0 -2
  284. machineconfig/scripts/linux/cloud_repo_sync +0 -2
  285. machineconfig/scripts/linux/cloud_sync +0 -2
  286. machineconfig/scripts/linux/croshell +0 -3
  287. machineconfig/scripts/linux/devops +0 -2
  288. machineconfig/scripts/linux/fire +0 -2
  289. machineconfig/scripts/linux/ftpx +0 -2
  290. machineconfig/scripts/linux/fzf2g +0 -21
  291. machineconfig/scripts/linux/fzffg +0 -25
  292. machineconfig/scripts/linux/gh_models +0 -2
  293. machineconfig/scripts/linux/initai +0 -2
  294. machineconfig/scripts/linux/kill_process +0 -2
  295. machineconfig/scripts/linux/scheduler +0 -2
  296. machineconfig/scripts/linux/sessions +0 -2
  297. machineconfig/scripts/linux/share_smb +0 -1
  298. machineconfig/scripts/linux/start_slidev +0 -2
  299. machineconfig/scripts/linux/start_terminals +0 -3
  300. machineconfig/scripts/linux/warp-cli.sh +0 -122
  301. machineconfig/scripts/linux/wifi_conn +0 -2
  302. machineconfig/scripts/linux/z_ls +0 -104
  303. machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
  304. machineconfig/scripts/python/cloud_repo_sync.py +0 -190
  305. machineconfig/scripts/python/count_lines_frontend.py +0 -16
  306. machineconfig/scripts/python/dotfile.py +0 -78
  307. machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
  308. machineconfig/scripts/python/get_zellij_cmd.py +0 -15
  309. machineconfig/scripts/python/gh_models.py +0 -104
  310. machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
  311. machineconfig/scripts/python/repos.py +0 -132
  312. machineconfig/scripts/python/repos_helper_action.py +0 -378
  313. machineconfig/scripts/python/snapshot.py +0 -25
  314. machineconfig/scripts/python/start_terminals.py +0 -121
  315. machineconfig/scripts/python/t4.py +0 -17
  316. machineconfig/scripts/windows/agents.ps1 +0 -1
  317. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  318. machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
  319. machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
  320. machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
  321. machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
  322. machineconfig/scripts/windows/croshell.ps1 +0 -1
  323. machineconfig/scripts/windows/devops.ps1 +0 -1
  324. machineconfig/scripts/windows/dotfile.ps1 +0 -1
  325. machineconfig/scripts/windows/fire.ps1 +0 -1
  326. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  327. machineconfig/scripts/windows/gpt.ps1 +0 -1
  328. machineconfig/scripts/windows/grep.ps1 +0 -2
  329. machineconfig/scripts/windows/initai.ps1 +0 -1
  330. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  331. machineconfig/scripts/windows/nano.ps1 +0 -3
  332. machineconfig/scripts/windows/pomodoro.ps1 +0 -1
  333. machineconfig/scripts/windows/reload_path.ps1 +0 -3
  334. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  335. machineconfig/scripts/windows/sessions.ps1 +0 -1
  336. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  337. machineconfig/scripts/windows/start_slidev.ps1 +0 -1
  338. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  339. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  340. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  341. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  342. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  343. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
  344. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
  345. machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
  346. machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
  347. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
  348. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
  349. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
  350. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  351. machineconfig-5.15.dist-info/METADATA +0 -188
  352. machineconfig-5.15.dist-info/RECORD +0 -415
  353. machineconfig-5.15.dist-info/entry_points.txt +0 -18
  354. machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
  355. machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  356. machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  357. machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  358. machineconfig/{jobs/python → scripts/python/helpers_agents}/__init__.py +0 -0
  359. machineconfig/scripts/python/{helpers → helpers_agents/agentic_frameworks}/__init__.py +0 -0
  360. machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
  361. machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
  362. machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_cloud/__init__.py} +0 -0
  363. machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
  364. /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
  365. /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_croshell/__init__.py} +0 -0
  366. /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
  367. /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
  368. /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
  369. /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
  370. /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_devops/__init__.py} +0 -0
  371. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/themes/__init__.py} +0 -0
  372. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  373. /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
  374. /machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/skrg +0 -0
  375. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfb.ps1 +0 -0
  376. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfg.ps1 +0 -0
  377. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfrga.bat +0 -0
  378. /machineconfig/scripts/{linux → python/nw}/mount_drive +0 -0
  379. /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
  380. /machineconfig/scripts/{linux → python/nw}/mount_smb +0 -0
  381. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  382. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  383. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  384. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  385. /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
  386. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
  387. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
  388. {machineconfig-5.15.dist-info → machineconfig-7.66.dist-info}/WHEEL +0 -0
  389. {machineconfig-5.15.dist-info → machineconfig-7.66.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,16 @@
1
- from machineconfig.utils.path_extended import PathExtended
2
- from machineconfig.utils.options import choose_from_options
3
1
  from machineconfig.utils.source_of_truth import EXCLUDE_DIRS
4
2
  from rich.console import Console
5
3
  from rich.panel import Panel
6
4
  import platform
7
5
  import subprocess
8
6
  from pathlib import Path
9
-
7
+ from typing import Optional
10
8
 
11
9
  console = Console()
12
10
 
13
11
 
14
- def sanitize_path(a_path: str) -> PathExtended:
15
- path = PathExtended(a_path)
12
+ def sanitize_path(a_path: str) -> Path:
13
+ path = Path(a_path)
16
14
  if Path.cwd() == Path.home() and not path.exists():
17
15
  result = input("Current working directory is home, and passed path is not full path, are you sure you want to continue, [y]/n? ") or "y"
18
16
  if result == "y":
@@ -23,13 +21,13 @@ def sanitize_path(a_path: str) -> PathExtended:
23
21
  if platform.system() == "Windows": # path copied from Linux/Mac to Windows
24
22
  # For Linux: /home/username, for Mac: /Users/username
25
23
  skip_parts = 3 if path.as_posix().startswith("/home") else 3 # Both have 3 parts to skip
26
- path = PathExtended.home().joinpath(*path.parts[skip_parts:])
24
+ path = Path.home().joinpath(*path.parts[skip_parts:])
27
25
  assert path.exists(), f"File not found: {path}"
28
26
  source_os = "Linux" if path.as_posix().startswith("/home") else "macOS"
29
27
  console.print(Panel(f"🔗 PATH MAPPING | {source_os} → Windows: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
30
- elif platform.system() in ["Linux", "Darwin"] and PathExtended.home().as_posix() not in path.as_posix(): # copied between Unix-like systems with different username
28
+ elif platform.system() in ["Linux", "Darwin"] and Path.home().as_posix() not in path.as_posix(): # copied between Unix-like systems with different username
31
29
  skip_parts = 3 # Both /home/username and /Users/username have 3 parts to skip
32
- path = PathExtended.home().joinpath(*path.parts[skip_parts:])
30
+ path = Path.home().joinpath(*path.parts[skip_parts:])
33
31
  assert path.exists(), f"File not found: {path}"
34
32
  current_os = "Linux" if platform.system() == "Linux" else "macOS"
35
33
  source_os = "Linux" if path.as_posix().startswith("/home") else "macOS"
@@ -37,12 +35,12 @@ def sanitize_path(a_path: str) -> PathExtended:
37
35
  elif path.as_posix().startswith("C:"):
38
36
  if platform.system() in ["Linux", "Darwin"]: # path copied from Windows to Linux/Mac
39
37
  xx = str(a_path).replace("\\\\", "/")
40
- path = PathExtended.home().joinpath(*PathExtended(xx).parts[3:]) # exclude C:\\Users\\username
38
+ path = Path.home().joinpath(*Path(xx).parts[3:]) # exclude C:\\Users\\username
41
39
  assert path.exists(), f"File not found: {path}"
42
40
  target_os = "Linux" if platform.system() == "Linux" else "macOS"
43
41
  console.print(Panel(f"🔗 PATH MAPPING | Windows → {target_os}: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
44
- elif platform.system() == "Windows" and PathExtended.home().as_posix() not in path.as_posix(): # copied from Windows to Windows with different username
45
- path = PathExtended.home().joinpath(*path.parts[2:])
42
+ elif platform.system() == "Windows" and Path.home().as_posix() not in path.as_posix(): # copied from Windows to Windows with different username
43
+ path = Path.home().joinpath(*path.parts[2:])
46
44
  assert path.exists(), f"File not found: {path}"
47
45
  console.print(Panel(f"🔗 PATH MAPPING | Windows → Windows: `{a_path}` ➡️ `{path}`", title="Path Mapping", expand=False))
48
46
  return path.expanduser().absolute()
@@ -67,49 +65,58 @@ def find_scripts(root: Path, name_substring: str, suffixes: set[str]) -> tuple[l
67
65
  return filename_matches, partial_path_matches
68
66
 
69
67
 
70
- def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[str]) -> PathExtended:
68
+ def match_file_name(sub_string: str, search_root: Path, suffixes: set[str]) -> Path:
71
69
  search_root_obj = search_root.absolute()
72
70
  # assume subscript is filename only, not a sub_path. There is no need to fzf over the paths.
73
71
  filename_matches, partial_path_matches = find_scripts(search_root_obj, sub_string, suffixes)
74
72
  if len(filename_matches) == 1:
75
- return PathExtended(filename_matches[0])
73
+ return Path(filename_matches[0])
76
74
  console.print(Panel(f"Partial filename {search_root_obj} match with case-insensitivity failed. This generated #{len(filename_matches)} results.", title="Search", expand=False))
77
75
  if len(filename_matches) < 20:
78
76
  print("\n".join([a_potential_match.as_posix() for a_potential_match in filename_matches]))
79
77
  if len(filename_matches) > 1:
80
- print("Try to narrow down filename_matches search by case-sensitivity.")
78
+ print(f"Try to narrow down filename_matches search by case-sensitivity, found {len(filename_matches)} results. First @ {filename_matches[0].as_posix()}")
81
79
  # let's see if avoiding .lower() helps narrowing down to one result
82
80
  reduced_scripts = [a_potential_match for a_potential_match in filename_matches if sub_string in a_potential_match.name]
83
81
  if len(reduced_scripts) == 1:
84
- return PathExtended(reduced_scripts[0])
82
+ return Path(reduced_scripts[0])
85
83
  elif len(reduced_scripts) > 1:
84
+ from machineconfig.utils.options import choose_from_options
86
85
  choice = choose_from_options(multi=False, msg="Multiple matches found", options=reduced_scripts, fzf=True)
87
- return PathExtended(choice)
86
+ return Path(choice)
88
87
  print(f"Result: This still generated {len(reduced_scripts)} results.")
89
88
  if len(reduced_scripts) < 10:
90
89
  print("\n".join([a_potential_match.as_posix() for a_potential_match in reduced_scripts]))
91
90
 
92
91
  console.print(Panel(f"Partial path match with case-insensitivity failed. This generated #{len(partial_path_matches)} results.", title="Search", expand=False))
93
92
  if len(partial_path_matches) == 1:
94
- return PathExtended(partial_path_matches[0])
93
+ return Path(partial_path_matches[0])
95
94
  elif len(partial_path_matches) > 1:
96
95
  print("Try to narrow down partial_path_matches search by case-sensitivity.")
97
96
  reduced_scripts = [a_potential_match for a_potential_match in partial_path_matches if sub_string in a_potential_match.as_posix()]
98
97
  if len(reduced_scripts) == 1:
99
- return PathExtended(reduced_scripts[0])
100
- print(f"Result: This still generated {len(reduced_scripts)} results.")
98
+ return Path(reduced_scripts[0])
99
+ print(f"Result: This still generated {len(reduced_scripts)} results.")
100
+
101
101
  try:
102
- fzf_cmd = f"cd '{search_root_obj}'; fd --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
102
+
103
+ if len(partial_path_matches) == 0:
104
+ print("No partial path matches found, trying to do fd with --no-ignore ...")
105
+ fzf_cmd = f"cd '{search_root_obj}'; fd --no-ignore --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
106
+ else:
107
+ fzf_cmd = f"cd '{search_root_obj}'; fd --type file --strip-cwd-prefix | fzf --ignore-case --exact --query={sub_string}"
103
108
  console.print(Panel(f"🔍 Second attempt: SEARCH STRATEGY | Using fd to search for '{sub_string}' in '{search_root_obj}' ...\n{fzf_cmd}", title="Search Strategy", expand=False))
104
109
  search_res_raw = subprocess.run(fzf_cmd, stdout=subprocess.PIPE, text=True, check=True, shell=True).stdout
105
- search_res = search_res_raw.strip().split("\\n")[:-1]
110
+ search_res = search_res_raw.strip().split("\n")
106
111
  except subprocess.CalledProcessError as cpe:
107
112
  console.print(Panel(f"❌ ERROR | FZF search failed with '{sub_string}' in '{search_root_obj}'.\n{cpe}", title="Error", expand=False))
108
113
  import sys
109
-
110
114
  sys.exit(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results.")
111
115
  if len(search_res) == 1:
112
116
  return search_root_obj.joinpath(search_res_raw)
117
+ elif len(search_res) == 0:
118
+ msg = Panel(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results", title="File Not Found", expand=False)
119
+ raise FileNotFoundError(msg)
113
120
 
114
121
  print(f"⚠️ WARNING | Multiple search results found for `{sub_string}`:\n'{search_res}'")
115
122
  cmd = f"cd '{search_root_obj}'; fd --type file | fzf --select-1 --query={sub_string}"
@@ -121,3 +128,49 @@ def match_file_name(sub_string: str, search_root: PathExtended, suffixes: set[st
121
128
  msg = Panel(f"💥 FILE NOT FOUND | Path {sub_string} does not exist @ root {search_root_obj}. No search results", title="File Not Found", expand=False)
122
129
  raise FileNotFoundError(msg) from cpe
123
130
  return search_root_obj.joinpath(res)
131
+
132
+
133
+ def search_for_files_of_interest(path_obj: Path, suffixes: set[str]) -> list[Path]:
134
+ if path_obj.is_file():
135
+ return [path_obj]
136
+ files: list[Path] = []
137
+ directories_to_visit: list[Path] = [path_obj]
138
+ while directories_to_visit:
139
+ current_dir = directories_to_visit.pop()
140
+ for entry in current_dir.iterdir():
141
+ if entry.is_dir():
142
+ if entry.name == ".venv":
143
+ continue
144
+ directories_to_visit.append(entry)
145
+ continue
146
+ if entry.suffix not in suffixes:
147
+ continue
148
+ if entry.suffix == ".py" and entry.name == "__init__.py":
149
+ continue
150
+ files.append(entry)
151
+ return files
152
+
153
+
154
+ def get_choice_file(path: str, suffixes: Optional[set[str]]):
155
+ path_obj = sanitize_path(path)
156
+ if suffixes is None:
157
+ import platform
158
+ if platform.system() == "Windows":
159
+ suffixes = {".py", ".ps1", ".sh"}
160
+ elif platform.system() in ["Linux", "Darwin"]:
161
+ suffixes = {".py", ".sh"}
162
+ else:
163
+ suffixes = {".py"}
164
+ if not path_obj.exists():
165
+ print(f"🔍 Searching for file matching `{path}` under `{Path.cwd()}`, but only if suffix matches {suffixes}")
166
+ choice_file = match_file_name(sub_string=path, search_root=Path.cwd(), suffixes=suffixes)
167
+ elif path_obj.is_dir():
168
+ print(f"🔍 Searching recursively for Python, PowerShell and Shell scripts in directory `{path_obj}`")
169
+ files = search_for_files_of_interest(path_obj, suffixes=suffixes)
170
+ print(f"🔍 Got #{len(files)} results.")
171
+ from machineconfig.utils.options import choose_from_options
172
+ choice_file = choose_from_options(multi=False, options=files, fzf=True, msg="Choose one option")
173
+ choice_file = Path(choice_file)
174
+ else:
175
+ choice_file = path_obj
176
+ return choice_file
@@ -2,12 +2,11 @@
2
2
 
3
3
  import psutil
4
4
  from rich.progress import Progress, SpinnerColumn, TextColumn
5
- from zoneinfo import ZoneInfo
6
5
  from machineconfig.utils.options import choose_from_options
7
- from typing import Optional, Any
6
+ from typing import Optional, TypedDict, List, Dict
8
7
  from rich.console import Console
9
8
  from rich.panel import Panel
10
- from datetime import datetime, timezone
9
+ from datetime import datetime
11
10
  from machineconfig.utils.accessories import pprint
12
11
 
13
12
  console = Console()
@@ -15,11 +14,29 @@ console = Console()
15
14
  BOX_WIDTH = 78 # width for box drawing
16
15
 
17
16
 
18
- def get_processes_accessing_file(path: str):
17
+ class ProcessInfo(TypedDict):
18
+ """TypedDict for process information."""
19
+ command: str
20
+ pid: int
21
+ name: str
22
+ username: str
23
+ cpu_percent: float
24
+ memory_usage_mb: float
25
+ status: str
26
+ create_time: datetime
27
+
28
+
29
+ class FileAccessInfo(TypedDict):
30
+ """TypedDict for file access information."""
31
+ pid: int
32
+ files: List[str]
33
+
34
+
35
+ def get_processes_accessing_file(path: str) -> List[FileAccessInfo]:
19
36
  # header for searching processes
20
37
  title = "🔍 SEARCHING FOR PROCESSES ACCESSING FILE"
21
38
  console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
22
- res: dict[int, list[str]] = {}
39
+ res: Dict[int, List[str]] = {}
23
40
 
24
41
  with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
25
42
  progress.add_task("🔎 Scanning processes...", total=None)
@@ -34,22 +51,22 @@ def get_processes_accessing_file(path: str):
34
51
  res[proc.pid] = tmp
35
52
 
36
53
  # Convert to list of dictionaries for consistent data structure
37
- result_data = [{"pid": pid, "files": files} for pid, files in res.items()]
54
+ result_data: List[FileAccessInfo] = [{"pid": pid, "files": files} for pid, files in res.items()]
38
55
  console.print(Panel(f"✅ Found {len(res)} processes accessing the specified file", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
39
56
  return result_data
40
57
 
41
58
 
42
59
  def kill_process(name: str):
43
- print(f"⚠️ Attempting to kill process: {name}...")
60
+ console.print(f"⚠️ Attempting to kill process: {name}...", style="yellow")
44
61
  killed = False
45
62
  for proc in psutil.process_iter():
46
63
  if proc.name() == name:
47
64
  proc.kill()
48
- print(f"💀 Process {name} (PID: {proc.pid}) terminated successfully")
65
+ console.print(f"💀 Process {name} (PID: {proc.pid}) terminated successfully", style="green")
49
66
  killed = True
50
67
  if not killed:
51
- print(f"❓ No process with name '{name}' was found")
52
- print(f"{'─' * 80}\n")
68
+ console.print(f"❓ No process with name '{name}' was found", style="red")
69
+ console.rule(style="dim")
53
70
 
54
71
 
55
72
  class ProcessManager:
@@ -57,15 +74,13 @@ class ProcessManager:
57
74
  # header for initializing process manager
58
75
  title = "📊 INITIALIZING PROCESS MANAGER"
59
76
  console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
60
- process_info = []
77
+ process_info: List[ProcessInfo] = []
61
78
  with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
62
79
  progress.add_task("🔍 Reading system processes...", total=None)
63
80
  for proc in psutil.process_iter():
64
81
  try:
65
82
  mem_usage_mb = proc.memory_info().rss / (1024 * 1024)
66
- # Convert create_time to local timezone
67
- create_time_utc = datetime.fromtimestamp(proc.create_time(), tz=timezone.utc)
68
- create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
83
+ create_time = datetime.fromtimestamp(proc.create_time(), tz=None)
69
84
 
70
85
  process_info.append(
71
86
  {
@@ -75,7 +90,7 @@ class ProcessManager:
75
90
  "cpu_percent": proc.cpu_percent(),
76
91
  "memory_usage_mb": mem_usage_mb,
77
92
  "status": proc.status(),
78
- "create_time": create_time_local,
93
+ "create_time": create_time,
79
94
  "command": " ".join(proc.cmdline()),
80
95
  }
81
96
  )
@@ -91,57 +106,51 @@ class ProcessManager:
91
106
  """Format process data as table string for display."""
92
107
  if not self.data:
93
108
  return ""
94
-
95
109
  # Create header
96
- _headers = ["PID", "Name", "Username", "CPU%", "Memory(MB)", "Status", "Create Time", "Command"]
97
- header_line = f"{'PID':<8} {'Name':<20} {'Username':<12} {'CPU%':<8} {'Memory(MB)':<12} {'Status':<12} {'Create Time':<20} {'Command':<50}"
110
+ _headers = ["Command", "PID", "Name", "Username", "CPU%", "Memory(MB)", "Status", "Create Time"]
111
+ header_line = f"{'Command':<50} {'PID':<8} {'Name':<20} {'Username':<12} {'CPU%':<8} {'Memory(MB)':<12} {'Status':<12} {'Create Time':<20}"
98
112
  separator = "-" * len(header_line)
99
-
100
113
  lines = [header_line, separator]
101
-
102
114
  for process in self.data:
103
115
  # Format create_time as string
104
116
  create_time_str = process["create_time"].strftime("%Y-%m-%d %H:%M:%S")
105
117
  # Truncate command if too long
106
118
  command = process["command"][:47] + "..." if len(process["command"]) > 50 else process["command"]
107
-
108
- line = f"{process['pid']:<8} {process['name'][:19]:<20} {process['username'][:11]:<12} {process['cpu_percent']:<8.1f} {process['memory_usage_mb']:<12.2f} {process['status'][:11]:<12} {create_time_str:<20} {command:<50}"
119
+ line = f"{command:<50} {process['pid']:<8} {process['name'][:19]:<20} {process['username'][:11]:<12} {process['cpu_percent']:<8.1f} {process['memory_usage_mb']:<12.2f} {process['status'][:11]:<12} {create_time_str:<20}"
109
120
  lines.append(line)
110
-
111
121
  return "\n".join(lines)
112
122
 
113
123
  def choose_and_kill(self):
114
124
  # header for interactive process selection
115
125
  title = "🎯 INTERACTIVE PROCESS SELECTION AND TERMINATION"
116
126
  console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
117
-
118
127
  # Format data as table for display
119
128
  formatted_data = self._format_process_table()
120
- options = formatted_data.split("\n")[1:] # Skip header
121
- res = choose_from_options(options=formatted_data.split("\n"), msg="📋 Select processes to manage:", fzf=True, multi=True)
122
- indices = [options.index(val) for val in res]
129
+ all_lines = formatted_data.split("\n")
130
+ header_and_separator = all_lines[:2] # First two lines: header and separator
131
+ options = all_lines[2:] # Skip header and separator, only process lines
132
+ res = choose_from_options(options=all_lines, msg="📋 Select processes to manage:", fzf=True, multi=True)
133
+ # Filter out header and separator if they were selected
134
+ selected_lines = [line for line in res if line not in header_and_separator]
135
+ indices = [options.index(val) for val in selected_lines]
123
136
  selected_processes = [self.data[i] for i in indices]
124
-
125
137
  print("\n📊 All Processes:")
126
138
  print(formatted_data)
127
139
  print("\n🎯 Selected Processes:")
128
140
  for process in selected_processes:
129
141
  print(f"PID: {process['pid']}, Name: {process['name']}, Memory: {process['memory_usage_mb']:.2f}MB")
130
-
131
142
  for idx, process in enumerate(selected_processes):
132
- pprint(process, f"📌 Process {idx}")
133
-
143
+ pprint(dict(process), f"📌 Process {idx}")
134
144
  kill_all = input("\n⚠️ Confirm killing ALL selected processes? y/[n] ").lower() == "y"
135
145
  if kill_all:
136
146
  self.kill(pids=[p["pid"] for p in selected_processes])
137
147
  return
138
-
139
148
  kill_by_index = input("\n🔫 Kill by index? (enter numbers separated by spaces, e.g. '1 4') or [n] to cancel: ")
140
149
  if kill_by_index != "" and kill_by_index != "n":
141
150
  indices = [int(val) for val in kill_by_index.split(" ")]
142
151
  target_processes = [selected_processes[i] for i in indices]
143
152
  for idx2, process in enumerate(target_processes):
144
- pprint(process, f"🎯 Target Process {idx2}")
153
+ pprint(dict(process), f"🎯 Target Process {idx2}")
145
154
  _ = self.kill(pids=[p["pid"] for p in target_processes]) if input("\n⚠️ Confirm termination? y/[n] ").lower() == "y" else None
146
155
  console.print(Panel("🔔 No processes were terminated.", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
147
156
 
@@ -149,12 +158,10 @@ class ProcessManager:
149
158
  # header for filtering processes by name
150
159
  title = "🔍 FILTERING AND TERMINATING PROCESSES BY NAME"
151
160
  console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
152
-
153
161
  # Filter processes by name
154
162
  filtered_processes = [p for p in self.data if p["name"] == name]
155
163
  # Sort by create_time (ascending)
156
164
  filtered_processes.sort(key=lambda x: x["create_time"])
157
-
158
165
  print(f"🎯 Found {len(filtered_processes)} processes matching name: '{name}'")
159
166
  self.kill(pids=[p["pid"] for p in filtered_processes])
160
167
  console.print(Panel("", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
@@ -171,69 +178,42 @@ class ProcessManager:
171
178
  pids = []
172
179
  if commands is None:
173
180
  commands = []
174
-
175
181
  killed_count = 0
176
-
177
182
  for name in names:
178
183
  matching_processes = [p for p in self.data if p["name"] == name]
179
184
  if len(matching_processes) > 0:
180
185
  for process in matching_processes:
181
186
  psutil.Process(process["pid"]).kill()
182
- print(f"💀 Killed process {name} with PID {process['pid']}. It lived {get_age(process['create_time'])}. RIP 🪦💐")
187
+ print(f"💀 Killed process {name} with PID {process['pid']}. It lived {get_age(process['create_time'])}. RIP 💐")
183
188
  killed_count += 1
184
189
  else:
185
190
  print(f'❓ No process named "{name}" found')
186
-
187
191
  for pid in pids:
188
192
  try:
189
193
  proc = psutil.Process(pid)
190
194
  proc_name = proc.name()
191
- proc_lifetime = get_age(proc.create_time())
195
+ proc_lifetime = get_age(datetime.fromtimestamp(proc.create_time(), tz=None))
192
196
  proc.kill()
193
- print(f'💀 Killed process with PID {pid} and name "{proc_name}". It lived {proc_lifetime}. RIP 🪦💐')
197
+ print(f'💀 Killed process with PID {pid} and name "{proc_name}". It lived {proc_lifetime}. RIP 💐')
194
198
  killed_count += 1
195
199
  except psutil.NoSuchProcess:
196
200
  print(f"❓ No process with PID {pid} found")
197
-
198
201
  for command in commands:
199
202
  matching_processes = [p for p in self.data if command in p["command"]]
200
203
  if len(matching_processes) > 0:
201
204
  for process in matching_processes:
202
205
  psutil.Process(process["pid"]).kill()
203
- print(f'💀 Killed process with "{command}" in its command & PID {process["pid"]}. It lived {get_age(process["create_time"])}. RIP 🪦💐')
206
+ print(f'💀 Killed process with "{command}" in its command & PID {process["pid"]}. It lived {get_age(process["create_time"])}. RIP 💐')
204
207
  killed_count += 1
205
208
  else:
206
209
  print(f'❓ No process has "{command}" in its command.')
207
-
208
210
  console.print(Panel(f"✅ Termination complete: {killed_count} processes terminated", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
209
211
 
210
212
 
211
- def get_age(create_time: Any) -> str:
212
- """Calculate age from create_time which can be either float timestamp or datetime object."""
213
- try:
214
- if isinstance(create_time, (int, float)):
215
- # Handle timestampz
216
- create_time_utc = datetime.fromtimestamp(create_time, tz=timezone.utc)
217
- create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
218
- else:
219
- # Already a datetime object
220
- create_time_local = create_time
221
-
222
- now_local = datetime.now(tz=ZoneInfo("Australia/Adelaide"))
223
- age = now_local - create_time_local
224
- return str(age)
225
- except Exception as e:
226
- try:
227
- # Fallback without timezone
228
- if isinstance(create_time, (int, float)):
229
- create_time_dt = datetime.fromtimestamp(create_time)
230
- else:
231
- create_time_dt = create_time.replace(tzinfo=None) if create_time.tzinfo else create_time
232
- now_dt = datetime.now()
233
- age = now_dt - create_time_dt
234
- return str(age)
235
- except Exception as ee:
236
- return f"unknown due to {ee} and {e}"
213
+ def get_age(create_time: datetime) -> str:
214
+ dtm_now = datetime.now()
215
+ delta = dtm_now - create_time
216
+ return str(delta).split(".")[0] # remove microseconds
237
217
 
238
218
 
239
219
  def main():