machineconfig 3.7__py3-none-any.whl → 7.69__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/__init__.py +0 -28
- machineconfig/cluster/remote/distribute.py +0 -1
- machineconfig/cluster/remote/file_manager.py +0 -2
- machineconfig/cluster/remote/script_execution.py +1 -2
- machineconfig/cluster/sessions_managers/{enhanced_command_runner.py → helpers/enhanced_command_runner.py} +4 -6
- machineconfig/cluster/sessions_managers/helpers/load_balancer_helper.py +145 -0
- machineconfig/cluster/sessions_managers/utils/load_balancer.py +53 -0
- machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
- machineconfig/cluster/sessions_managers/wt_local.py +128 -330
- machineconfig/cluster/sessions_managers/wt_local_manager.py +53 -187
- machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +49 -197
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +22 -172
- machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
- machineconfig/jobs/{python → installer}/check_installations.py +7 -21
- machineconfig/jobs/installer/custom/boxes.py +61 -0
- machineconfig/jobs/installer/custom/gh.py +128 -0
- machineconfig/jobs/{python_custom_installers → installer/custom}/hx.py +84 -18
- machineconfig/jobs/installer/custom_dev/alacritty.py +86 -0
- machineconfig/jobs/installer/custom_dev/brave.py +82 -0
- machineconfig/jobs/installer/custom_dev/bypass_paywall.py +59 -0
- machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/custom_dev/code.py +63 -0
- machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/cursor.py +7 -7
- machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
- machineconfig/jobs/installer/custom_dev/espanso.py +117 -0
- machineconfig/jobs/installer/custom_dev/goes.py +68 -0
- machineconfig/jobs/installer/custom_dev/lvim.py +89 -0
- machineconfig/jobs/installer/custom_dev/nerdfont.py +111 -0
- machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +149 -0
- machineconfig/jobs/installer/custom_dev/redis.py +88 -0
- machineconfig/jobs/installer/custom_dev/sysabc.py +145 -0
- machineconfig/jobs/installer/custom_dev/wezterm.py +92 -0
- machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/winget.py +2 -3
- machineconfig/jobs/installer/installer_data.json +3440 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/brave.sh +4 -14
- machineconfig/jobs/{python_custom_installers/scripts/linux/warp-cli.sh → installer/linux_scripts/cloudflare_warp_cli.sh} +5 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/docker.sh +6 -18
- machineconfig/jobs/installer/linux_scripts/docker_start.sh +37 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/edge.sh +3 -11
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/nerdfont.sh +5 -17
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/ngrok.sh +6 -0
- machineconfig/jobs/installer/linux_scripts/q.sh +9 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/redis.sh +6 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/vscode.sh +5 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/wezterm.sh +4 -12
- machineconfig/jobs/installer/package_groups.py +255 -0
- machineconfig/logger.py +0 -1
- machineconfig/profile/backup.toml +49 -0
- machineconfig/profile/bash_shell_profiles.md +11 -0
- machineconfig/profile/create_helper.py +74 -0
- machineconfig/profile/create_links.py +288 -0
- machineconfig/profile/create_links_export.py +100 -0
- machineconfig/profile/create_shell_profile.py +136 -0
- machineconfig/profile/mapper.toml +258 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
- machineconfig/scripts/linux/wrap_mcfg +47 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +198 -0
- machineconfig/scripts/python/ai/command_runner/command_runner.sh +9 -0
- machineconfig/scripts/python/ai/command_runner/prompt.txt +9 -0
- machineconfig/scripts/python/ai/generate_files.py +307 -42
- machineconfig/scripts/python/ai/{mcinit.py → initai.py} +3 -38
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +114 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +88 -22
- machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +4 -1
- machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
- machineconfig/scripts/python/ai/solutions/gemini/settings.json +1 -1
- machineconfig/scripts/python/ai/solutions/generic.py +27 -4
- machineconfig/scripts/python/ai/vscode_tasks.py +37 -0
- machineconfig/scripts/python/cloud.py +29 -0
- machineconfig/scripts/python/croshell.py +129 -198
- machineconfig/scripts/python/define.py +31 -0
- machineconfig/scripts/python/devops.py +45 -131
- machineconfig/scripts/python/devops_navigator.py +6 -0
- machineconfig/scripts/python/env_manager/__init__.py +1 -0
- machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
- machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
- machineconfig/scripts/python/fire_jobs.py +166 -235
- machineconfig/scripts/python/ftpx.py +164 -100
- machineconfig/scripts/python/helpers/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +37 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +42 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +110 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +34 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_load_balancer.py +22 -0
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
- machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
- machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
- machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +52 -39
- machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +13 -18
- machineconfig/scripts/python/helpers_cloud/cloud_sync.py +81 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +3 -3
- machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
- machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -1
- machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +32 -20
- machineconfig/scripts/python/helpers_devops/cli_config.py +95 -0
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
- machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
- machineconfig/scripts/python/helpers_devops/cli_nw.py +134 -0
- machineconfig/scripts/python/helpers_devops/cli_repos.py +182 -0
- machineconfig/scripts/python/helpers_devops/cli_self.py +134 -0
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +141 -0
- machineconfig/scripts/python/helpers_devops/cli_terminal.py +156 -0
- machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
- machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
- machineconfig/scripts/python/helpers_devops/devops_status.py +511 -0
- machineconfig/scripts/python/helpers_devops/devops_update_repos.py +269 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
- machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +2 -2
- machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -2
- machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +57 -89
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +145 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +110 -0
- machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfag +1 -1
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +1 -1
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfrga +1 -1
- machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
- machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
- machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
- machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
- machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
- machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
- machineconfig/scripts/python/helpers_repos/action.py +209 -0
- machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
- machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +6 -7
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
- machineconfig/scripts/python/helpers_repos/count_lines.py +348 -0
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +17 -0
- machineconfig/scripts/python/helpers_repos/entrypoint.py +77 -0
- machineconfig/scripts/python/helpers_repos/grource.py +340 -0
- machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +7 -4
- machineconfig/scripts/python/helpers_repos/sync.py +66 -0
- machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +58 -0
- machineconfig/scripts/python/helpers_utils/download.py +152 -0
- machineconfig/scripts/python/helpers_utils/path.py +108 -0
- machineconfig/scripts/python/interactive.py +187 -0
- machineconfig/scripts/python/mcfg_entry.py +63 -0
- machineconfig/scripts/python/msearch.py +40 -0
- machineconfig/scripts/python/{devops_add_identity.py → nw/devops_add_identity.py} +1 -3
- machineconfig/scripts/python/{devops_add_ssh_key.py → nw/devops_add_ssh_key.py} +74 -44
- machineconfig/scripts/{linux → python/nw}/mount_nfs +1 -1
- machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +19 -16
- machineconfig/scripts/{linux → python/nw}/mount_nw_drive +1 -2
- machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +7 -8
- machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -1
- machineconfig/scripts/python/nw/ssh_debug_linux.py +391 -0
- machineconfig/scripts/python/nw/ssh_debug_windows.py +338 -0
- machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +1 -51
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +67 -0
- machineconfig/scripts/python/sessions.py +167 -0
- machineconfig/scripts/python/terminal.py +127 -0
- machineconfig/scripts/python/utils.py +66 -0
- machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
- machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
- machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
- machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
- machineconfig/scripts/windows/wrap_mcfg.ps1 +60 -0
- machineconfig/settings/broot/br.sh +0 -4
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
- machineconfig/settings/lf/linux/lfrc +10 -12
- machineconfig/settings/lf/windows/fzf_edit.ps1 +2 -2
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +18 -38
- machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
- machineconfig/settings/marimo/marimo.toml +80 -0
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/pistol/pistol.conf +1 -1
- machineconfig/settings/shells/bash/init.sh +55 -31
- machineconfig/settings/shells/nushell/config.nu +1 -34
- machineconfig/settings/shells/nushell/init.nu +127 -0
- machineconfig/settings/shells/pwsh/init.ps1 +61 -43
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/wt/settings.json +32 -17
- machineconfig/settings/shells/zsh/init.sh +89 -0
- machineconfig/settings/svim/linux/init.toml +0 -4
- machineconfig/settings/svim/windows/init.toml +0 -3
- machineconfig/settings/yazi/init.lua +57 -0
- machineconfig/settings/yazi/keymap_linux.toml +79 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/yazi.toml +14 -1
- machineconfig/setup_linux/__init__.py +10 -0
- machineconfig/setup_linux/apps_desktop.sh +89 -0
- machineconfig/setup_linux/apps_gui.sh +64 -0
- machineconfig/setup_linux/{nix → others}/cli_installation.sh +9 -29
- machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
- machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
- machineconfig/setup_linux/uv.sh +15 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +28 -203
- machineconfig/setup_mac/__init__.py +16 -0
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
- machineconfig/setup_mac/uv.sh +36 -0
- machineconfig/setup_windows/__init__.py +8 -0
- machineconfig/setup_windows/others/power_options.ps1 +7 -0
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
- machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
- machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
- machineconfig/setup_windows/uv.ps1 +17 -0
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -189
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +37 -23
- machineconfig/utils/accessories.py +52 -12
- machineconfig/utils/cloud/onedrive/README.md +139 -0
- machineconfig/utils/code.py +140 -93
- machineconfig/utils/files/art/fat_croco.txt +10 -0
- machineconfig/utils/files/art/halfwit_croco.txt +9 -0
- machineconfig/utils/files/art/happy_croco.txt +22 -0
- machineconfig/utils/files/art/water_croco.txt +11 -0
- machineconfig/utils/files/ascii_art.py +118 -0
- machineconfig/utils/files/dbms.py +257 -0
- machineconfig/utils/files/headers.py +68 -0
- machineconfig/utils/files/ouch/decompress.py +45 -0
- machineconfig/utils/files/read.py +95 -0
- machineconfig/utils/installer_utils/github_release_bulk.py +188 -0
- machineconfig/utils/installer_utils/install_from_url.py +180 -0
- machineconfig/utils/installer_utils/installer_class.py +239 -316
- machineconfig/utils/installer_utils/installer_cli.py +186 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +90 -5
- machineconfig/utils/installer_utils/installer_runner.py +191 -0
- machineconfig/utils/io.py +77 -24
- machineconfig/utils/links.py +309 -100
- machineconfig/utils/meta.py +255 -0
- machineconfig/utils/notifications.py +1 -1
- machineconfig/utils/options.py +19 -47
- machineconfig/utils/path_extended.py +111 -121
- machineconfig/utils/path_helper.py +75 -22
- machineconfig/utils/procs.py +50 -74
- machineconfig/utils/scheduler.py +94 -97
- machineconfig/utils/scheduling.py +0 -3
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +5 -17
- machineconfig/utils/schemas/installer/installer_types.py +28 -6
- machineconfig/utils/schemas/layouts/layout_types.py +34 -1
- machineconfig/utils/source_of_truth.py +3 -6
- machineconfig/utils/ssh.py +742 -254
- machineconfig/utils/ssh_utils/utils.py +0 -0
- machineconfig/utils/terminal.py +3 -140
- machineconfig/utils/tst.py +20 -0
- machineconfig/utils/upgrade_packages.py +109 -28
- machineconfig/utils/ve.py +13 -5
- machineconfig-7.69.dist-info/METADATA +124 -0
- machineconfig-7.69.dist-info/RECORD +454 -0
- machineconfig-7.69.dist-info/entry_points.txt +15 -0
- machineconfig/cluster/templates/cli_click.py +0 -102
- machineconfig/cluster/templates/cli_gooey.py +0 -115
- machineconfig/cluster/templates/utils.py +0 -51
- machineconfig/jobs/linux/msc/cli_agents.sh +0 -32
- machineconfig/jobs/python/create_bootable_media.py +0 -16
- machineconfig/jobs/python/python_cargo_build_share.py +0 -59
- machineconfig/jobs/python/python_ve_symlink.py +0 -29
- machineconfig/jobs/python/tasks.py +0 -3
- machineconfig/jobs/python/vscode/api.py +0 -48
- machineconfig/jobs/python/vscode/link_ve.py +0 -63
- machineconfig/jobs/python/vscode/select_interpreter.py +0 -87
- machineconfig/jobs/python/vscode/sync_code.py +0 -58
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +0 -63
- machineconfig/jobs/python_custom_installers/dev/aider.py +0 -37
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +0 -65
- machineconfig/jobs/python_custom_installers/dev/brave.py +0 -71
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +0 -50
- machineconfig/jobs/python_custom_installers/dev/code.py +0 -51
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +0 -78
- machineconfig/jobs/python_custom_installers/dev/espanso.py +0 -90
- machineconfig/jobs/python_custom_installers/dev/goes.py +0 -55
- machineconfig/jobs/python_custom_installers/dev/lvim.py +0 -77
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +0 -68
- machineconfig/jobs/python_custom_installers/dev/redis.py +0 -65
- machineconfig/jobs/python_custom_installers/dev/reverse_proxy.md +0 -31
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +0 -70
- machineconfig/jobs/python_custom_installers/docker.py +0 -74
- machineconfig/jobs/python_custom_installers/gh.py +0 -97
- machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +0 -45
- machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +0 -49
- machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +0 -85
- machineconfig/jobs/python_custom_installers/warp-cli.py +0 -71
- machineconfig/jobs/python_generic_installers/config.json +0 -603
- machineconfig/jobs/python_generic_installers/config.json.bak +0 -414
- machineconfig/jobs/python_generic_installers/dev/config.archive.json +0 -18
- machineconfig/jobs/python_generic_installers/dev/config.json +0 -825
- machineconfig/jobs/python_generic_installers/dev/config.json.bak +0 -565
- machineconfig/jobs/python_linux_installers/archive/config.json +0 -18
- machineconfig/jobs/python_linux_installers/archive/config.json.bak +0 -10
- machineconfig/jobs/python_linux_installers/config.json +0 -145
- machineconfig/jobs/python_linux_installers/config.json.bak +0 -110
- machineconfig/jobs/python_linux_installers/dev/config.json +0 -276
- machineconfig/jobs/python_linux_installers/dev/config.json.bak +0 -206
- machineconfig/jobs/python_windows_installers/archive/file.json +0 -11
- machineconfig/jobs/python_windows_installers/config.json +0 -82
- machineconfig/jobs/python_windows_installers/config.json.bak +0 -56
- machineconfig/jobs/python_windows_installers/dev/config.json +0 -4
- machineconfig/jobs/python_windows_installers/dev/config.json.bak +0 -3
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
- machineconfig/jobs/windows/start_terminal.ps1 +0 -6
- machineconfig/jobs/windows/startup_file.cmd +0 -2
- machineconfig/profile/create.py +0 -169
- machineconfig/profile/shell.py +0 -176
- machineconfig/scripts/cloud/init.sh +0 -119
- machineconfig/scripts/linux/choose_wezterm_theme +0 -3
- machineconfig/scripts/linux/cloud_copy +0 -2
- machineconfig/scripts/linux/cloud_mount +0 -2
- machineconfig/scripts/linux/cloud_repo_sync +0 -2
- machineconfig/scripts/linux/cloud_sync +0 -2
- machineconfig/scripts/linux/croshell +0 -3
- machineconfig/scripts/linux/devops +0 -2
- machineconfig/scripts/linux/fire +0 -2
- machineconfig/scripts/linux/fire_agents +0 -2
- machineconfig/scripts/linux/ftpx +0 -2
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/gh_models +0 -2
- machineconfig/scripts/linux/kill_process +0 -2
- machineconfig/scripts/linux/mcinit +0 -2
- machineconfig/scripts/linux/programs +0 -21
- machineconfig/scripts/linux/repos +0 -2
- machineconfig/scripts/linux/scheduler +0 -2
- machineconfig/scripts/linux/share_smb +0 -1
- machineconfig/scripts/linux/start_slidev +0 -2
- machineconfig/scripts/linux/start_terminals +0 -3
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/wifi_conn +0 -2
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
- machineconfig/scripts/python/archive/im2text.py +0 -34
- machineconfig/scripts/python/archive/tmate_conn.py +0 -41
- machineconfig/scripts/python/archive/tmate_start.py +0 -44
- machineconfig/scripts/python/cloud_repo_sync.py +0 -192
- machineconfig/scripts/python/cloud_sync.py +0 -85
- machineconfig/scripts/python/devops_devapps_install.py +0 -202
- machineconfig/scripts/python/devops_update_repos.py +0 -180
- machineconfig/scripts/python/dotfile.py +0 -52
- machineconfig/scripts/python/fire_agents.py +0 -176
- machineconfig/scripts/python/fire_agents_help_launch.py +0 -143
- machineconfig/scripts/python/fire_agents_load_balancer.py +0 -50
- machineconfig/scripts/python/fire_jobs_args_helper.py +0 -84
- machineconfig/scripts/python/fire_jobs_layout_helper.py +0 -66
- machineconfig/scripts/python/get_zellij_cmd.py +0 -15
- machineconfig/scripts/python/gh_models.py +0 -104
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -114
- machineconfig/scripts/python/repos.py +0 -160
- machineconfig/scripts/python/snapshot.py +0 -25
- machineconfig/scripts/python/start_terminals.py +0 -121
- machineconfig/scripts/python/wsl_windows_transfer.py +0 -72
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
- machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
- machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
- machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
- machineconfig/scripts/windows/croshell.ps1 +0 -1
- machineconfig/scripts/windows/devops.ps1 +0 -1
- machineconfig/scripts/windows/dotfile.ps1 +0 -1
- machineconfig/scripts/windows/fire.ps1 +0 -1
- machineconfig/scripts/windows/ftpx.ps1 +0 -1
- machineconfig/scripts/windows/gpt.ps1 +0 -1
- machineconfig/scripts/windows/grep.ps1 +0 -2
- machineconfig/scripts/windows/kill_process.ps1 +0 -1
- machineconfig/scripts/windows/mcinit.ps1 +0 -1
- machineconfig/scripts/windows/nano.ps1 +0 -3
- machineconfig/scripts/windows/pomodoro.ps1 +0 -1
- machineconfig/scripts/windows/reload_path.ps1 +0 -3
- machineconfig/scripts/windows/repos.ps1 +0 -1
- machineconfig/scripts/windows/scheduler.ps1 +0 -1
- machineconfig/scripts/windows/snapshot.ps1 +0 -1
- machineconfig/scripts/windows/start_slidev.ps1 +0 -1
- machineconfig/scripts/windows/start_terminals.ps1 +0 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
- machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
- machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
- machineconfig/setup_linux/web_shortcuts/ascii_art.sh +0 -93
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
- machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
- machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
- machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
- machineconfig/setup_windows/wt_and_pwsh/install_nerd_fonts.py +0 -100
- machineconfig/utils/ai/generate_file_checklist.py +0 -68
- machineconfig/utils/installer.py +0 -255
- machineconfig-3.7.dist-info/METADATA +0 -165
- machineconfig-3.7.dist-info/RECORD +0 -432
- machineconfig-3.7.dist-info/entry_points.txt +0 -18
- machineconfig/cluster/{templates → remote}/run_cloud.py +0 -0
- machineconfig/cluster/{templates → remote}/run_cluster.py +0 -0
- machineconfig/cluster/{templates → remote}/run_remote.py +0 -0
- machineconfig/jobs/{python → installer}/__init__.py +0 -0
- machineconfig/jobs/{python_custom_installers → installer/custom_dev}/__init__.py +0 -0
- machineconfig/{setup_windows/wt_and_pwsh → jobs/installer/powershell_scripts}/install_fonts.ps1 +0 -0
- machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
- machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
- machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
- machineconfig/{jobs/python_generic_installers → scripts/python/helpers_agents}/__init__.py +0 -0
- machineconfig/{jobs/python_linux_installers → scripts/python/helpers_agents/agentic_frameworks}/__init__.py +0 -0
- machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
- machineconfig/{jobs/python_linux_installers/dev → scripts/python/helpers_cloud}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
- /machineconfig/{jobs/python_windows_installers → scripts/python/helpers_croshell}/__init__.py +0 -0
- /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
- /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
- /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
- /machineconfig/{jobs/python_windows_installers/archive → scripts/python/helpers_devops}/__init__.py +0 -0
- /machineconfig/{jobs/python_windows_installers/dev → scripts/python/helpers_devops/themes}/__init__.py +0 -0
- /machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
- /machineconfig/scripts/python/{helpers → helpers_fire_command}/__init__.py +0 -0
- /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/skrg +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfb.ps1 +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfg.ps1 +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfrga.bat +0 -0
- /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_sessions/__init__.py} +0 -0
- /machineconfig/scripts/{windows/share_nfs.ps1 → python/nw/__init__.py} +0 -0
- /machineconfig/scripts/{linux → python/nw}/mount_drive +0 -0
- /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
- /machineconfig/scripts/{linux → python/nw}/mount_smb +0 -0
- /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
- /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
- /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
- /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
- /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
- /machineconfig/{settings/yazi/keymap.toml → utils/files/ouch/__init__.py} +0 -0
- {machineconfig-3.7.dist-info → machineconfig-7.69.dist-info}/WHEEL +0 -0
- {machineconfig-3.7.dist-info → machineconfig-7.69.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import shlex
|
|
3
|
+
import subprocess
|
|
4
|
+
import random
|
|
5
|
+
import string
|
|
6
|
+
import psutil
|
|
7
|
+
import logging
|
|
8
|
+
from typing import List
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from machineconfig.cluster.sessions_managers.zellij_utils.monitoring_types import CommandStatus, ZellijSessionStatus
|
|
12
|
+
from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig, TabConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def generate_random_suffix(length: int) -> str:
|
|
19
|
+
"""Generate a random string suffix for unique layout file names."""
|
|
20
|
+
return "".join(random.choices(string.ascii_lowercase + string.digits, k=length))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def parse_command(command: str) -> tuple[str, List[str]]:
|
|
24
|
+
"""Parse a command string into executable and arguments."""
|
|
25
|
+
try:
|
|
26
|
+
parts = shlex.split(command)
|
|
27
|
+
if not parts:
|
|
28
|
+
raise ValueError("Empty command provided")
|
|
29
|
+
return parts[0], parts[1:] if len(parts) > 1 else []
|
|
30
|
+
except ValueError as e:
|
|
31
|
+
logger.error(f"Error parsing command '{command}': {e}")
|
|
32
|
+
parts = command.split()
|
|
33
|
+
return parts[0] if parts else "", parts[1:] if len(parts) > 1 else []
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def format_args_for_kdl(args: List[str]) -> str:
|
|
37
|
+
"""Format command arguments for KDL layout format."""
|
|
38
|
+
if not args:
|
|
39
|
+
return ""
|
|
40
|
+
formatted_args = []
|
|
41
|
+
for arg in args:
|
|
42
|
+
if " " in arg or '"' in arg or "'" in arg:
|
|
43
|
+
escaped_arg = arg.replace('"', '\\"')
|
|
44
|
+
formatted_args.append(f'"{escaped_arg}"')
|
|
45
|
+
else:
|
|
46
|
+
formatted_args.append(f'"{arg}"')
|
|
47
|
+
return " ".join(formatted_args)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def create_tab_section(tab_config: TabConfig) -> str:
|
|
51
|
+
"""Create a KDL tab section from tab configuration."""
|
|
52
|
+
tab_name = tab_config["tabName"]
|
|
53
|
+
cwd = tab_config["startDir"]
|
|
54
|
+
command = tab_config["command"]
|
|
55
|
+
cmd, args = parse_command(command)
|
|
56
|
+
args_str = format_args_for_kdl(args)
|
|
57
|
+
tab_cwd = cwd or "~"
|
|
58
|
+
escaped_tab_name = tab_name.replace('"', '\\"')
|
|
59
|
+
tab_section = f' tab name="{escaped_tab_name}" cwd="{tab_cwd}" {{\n'
|
|
60
|
+
tab_section += f' pane command="{cmd}" {{\n'
|
|
61
|
+
if args_str:
|
|
62
|
+
tab_section += f" args {args_str}\n"
|
|
63
|
+
tab_section += " }\n }\n"
|
|
64
|
+
return tab_section
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def validate_layout_config(layout_config: LayoutConfig) -> None:
|
|
68
|
+
"""Validate layout configuration."""
|
|
69
|
+
if not layout_config["layoutTabs"]:
|
|
70
|
+
raise ValueError("Layout must contain at least one tab")
|
|
71
|
+
for tab in layout_config["layoutTabs"]:
|
|
72
|
+
if not tab["tabName"].strip():
|
|
73
|
+
raise ValueError(f"Invalid tab name: {tab['tabName']}")
|
|
74
|
+
if not tab["command"].strip():
|
|
75
|
+
raise ValueError(f"Invalid command for tab '{tab['tabName']}': {tab['command']}")
|
|
76
|
+
if not tab["startDir"].strip():
|
|
77
|
+
raise ValueError(f"Invalid startDir for tab '{tab['tabName']}': {tab['startDir']}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def check_command_status(tab_name: str, layout_config: LayoutConfig) -> CommandStatus:
|
|
81
|
+
"""Check the running status of a command for a specific tab."""
|
|
82
|
+
# Find the tab with the given name
|
|
83
|
+
tab_config = None
|
|
84
|
+
for tab in layout_config["layoutTabs"]:
|
|
85
|
+
if tab["tabName"] == tab_name:
|
|
86
|
+
tab_config = tab
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
if tab_config is None:
|
|
90
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in layout config", "running": False, "command": "", "cwd": "", "tab_name": tab_name, "processes": []}
|
|
91
|
+
|
|
92
|
+
command = tab_config["command"]
|
|
93
|
+
cwd = tab_config["startDir"]
|
|
94
|
+
cmd, args = parse_command(command)
|
|
95
|
+
try:
|
|
96
|
+
shells = {"bash", "sh", "zsh", "fish"}
|
|
97
|
+
matching_processes = []
|
|
98
|
+
for proc in psutil.process_iter(["pid", "name", "cmdline", "status", "ppid", "create_time", "memory_info"]):
|
|
99
|
+
try:
|
|
100
|
+
info = proc.info
|
|
101
|
+
proc_cmdline: list[str] | None = info.get("cmdline") # type: ignore[assignment]
|
|
102
|
+
if not proc_cmdline:
|
|
103
|
+
continue
|
|
104
|
+
if info.get("status") in ["zombie", "dead", "stopped"]:
|
|
105
|
+
continue
|
|
106
|
+
proc_name = info.get("name", "")
|
|
107
|
+
is_match = False
|
|
108
|
+
joined_cmdline = " ".join(proc_cmdline)
|
|
109
|
+
# Primary matching heuristics - more precise matching
|
|
110
|
+
if proc_name == cmd and cmd not in shells:
|
|
111
|
+
# For non-shell commands, match if args appear in cmdline
|
|
112
|
+
if not args or any(arg in joined_cmdline for arg in args):
|
|
113
|
+
is_match = True
|
|
114
|
+
elif proc_name == cmd and cmd in shells:
|
|
115
|
+
# For shell commands, require more precise matching to avoid false positives
|
|
116
|
+
if args:
|
|
117
|
+
# Check if all args appear as separate cmdline arguments (not just substrings)
|
|
118
|
+
args_found = 0
|
|
119
|
+
for arg in args:
|
|
120
|
+
for cmdline_arg in proc_cmdline[1:]: # Skip shell name
|
|
121
|
+
if arg == cmdline_arg or (len(arg) > 3 and arg in cmdline_arg):
|
|
122
|
+
args_found += 1
|
|
123
|
+
break
|
|
124
|
+
# Require at least as many args found as we're looking for
|
|
125
|
+
if args_found >= len(args):
|
|
126
|
+
is_match = True
|
|
127
|
+
elif cmd in proc_cmdline[0] and cmd not in shells:
|
|
128
|
+
# Non-shell command in first argument
|
|
129
|
+
is_match = True
|
|
130
|
+
|
|
131
|
+
# Additional shell wrapper filter - be more restrictive for shells
|
|
132
|
+
if is_match and proc_name in shells and args:
|
|
133
|
+
# For shell processes, ensure the match is actually meaningful
|
|
134
|
+
# Don't match generic shell sessions just because they contain common paths
|
|
135
|
+
meaningful_match = False
|
|
136
|
+
for arg in args:
|
|
137
|
+
# Only consider it meaningful if the arg is substantial (not just a common path)
|
|
138
|
+
if len(arg) > 10 and any(arg == cmdline_arg for cmdline_arg in proc_cmdline[1:]):
|
|
139
|
+
meaningful_match = True
|
|
140
|
+
break
|
|
141
|
+
# Or if it's an exact script name match
|
|
142
|
+
elif arg.endswith(".py") or arg.endswith(".sh") or arg.endswith(".rb"):
|
|
143
|
+
if any(arg in cmdline_arg for cmdline_arg in proc_cmdline[1:]):
|
|
144
|
+
meaningful_match = True
|
|
145
|
+
break
|
|
146
|
+
if not meaningful_match:
|
|
147
|
+
is_match = False
|
|
148
|
+
if not is_match:
|
|
149
|
+
continue
|
|
150
|
+
try:
|
|
151
|
+
proc_obj = psutil.Process(info["pid"]) # type: ignore[index]
|
|
152
|
+
if proc_obj.status() not in ["running", "sleeping"]:
|
|
153
|
+
continue
|
|
154
|
+
mem_info = None
|
|
155
|
+
try:
|
|
156
|
+
mem = proc_obj.memory_info()
|
|
157
|
+
mem_info = mem.rss / (1024 * 1024)
|
|
158
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
159
|
+
pass
|
|
160
|
+
matching_processes.append(
|
|
161
|
+
{
|
|
162
|
+
"pid": info["pid"], # type: ignore[index]
|
|
163
|
+
"name": proc_name,
|
|
164
|
+
"cmdline": proc_cmdline,
|
|
165
|
+
"status": info.get("status", "unknown"),
|
|
166
|
+
"cmdline_str": joined_cmdline,
|
|
167
|
+
"create_time": info.get("create_time", 0.0),
|
|
168
|
+
**({"memory_mb": float(mem_info)} if mem_info is not None else {}),
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
172
|
+
continue
|
|
173
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
174
|
+
continue
|
|
175
|
+
|
|
176
|
+
# Second-pass filtering: remove idle wrapper shells that have no meaningful (non-shell) descendants
|
|
177
|
+
filtered_active = []
|
|
178
|
+
for proc_info in matching_processes:
|
|
179
|
+
try:
|
|
180
|
+
proc_obj = psutil.Process(proc_info["pid"]) # type: ignore[index]
|
|
181
|
+
if not proc_obj.is_running():
|
|
182
|
+
continue
|
|
183
|
+
status_val = proc_obj.status()
|
|
184
|
+
if status_val not in ["running", "sleeping"]:
|
|
185
|
+
continue
|
|
186
|
+
proc_name = proc_info.get("name", "")
|
|
187
|
+
if proc_name in shells:
|
|
188
|
+
descendants = proc_obj.children(recursive=True)
|
|
189
|
+
# Keep shell only if there exists a non-shell alive descendant OR descendant cmdline still includes our command token
|
|
190
|
+
meaningful = False
|
|
191
|
+
for child in descendants:
|
|
192
|
+
try:
|
|
193
|
+
if not child.is_running():
|
|
194
|
+
continue
|
|
195
|
+
child_name = child.name()
|
|
196
|
+
child_cmdline = " ".join(child.cmdline())
|
|
197
|
+
if child_name not in shells:
|
|
198
|
+
meaningful = True
|
|
199
|
+
break
|
|
200
|
+
if cmd in child_cmdline or any(arg in child_cmdline for arg in args):
|
|
201
|
+
meaningful = True
|
|
202
|
+
break
|
|
203
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
204
|
+
continue
|
|
205
|
+
if not meaningful:
|
|
206
|
+
continue # discard idle wrapper shell
|
|
207
|
+
filtered_active.append(proc_info)
|
|
208
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
209
|
+
continue
|
|
210
|
+
|
|
211
|
+
if filtered_active:
|
|
212
|
+
# Heuristic: if the only remaining processes are wrapper shells invoking a script that already completed, mark as not running.
|
|
213
|
+
# Case: layout launches 'bash <script.sh>' where script finishes and leaves an idle shell whose cmdline still shows the script path.
|
|
214
|
+
try:
|
|
215
|
+
if all(p.get("name") in shells for p in filtered_active):
|
|
216
|
+
script_paths = [arg for arg in args if arg.endswith(".sh")]
|
|
217
|
+
shell_only = True
|
|
218
|
+
stale_script_overall = False
|
|
219
|
+
for p in filtered_active:
|
|
220
|
+
proc_shell = psutil.Process(p["pid"]) # type: ignore[index]
|
|
221
|
+
create_time = getattr(proc_shell, "create_time", lambda: None)()
|
|
222
|
+
cmdline_joined = " ".join(p.get("cmdline", []))
|
|
223
|
+
stale_script = False
|
|
224
|
+
for spath in script_paths:
|
|
225
|
+
script_file = Path(spath)
|
|
226
|
+
if script_file.exists():
|
|
227
|
+
try:
|
|
228
|
+
# If script mtime older than process start AND no non-shell descendants -> likely finished
|
|
229
|
+
if create_time and script_file.stat().st_mtime < create_time:
|
|
230
|
+
stale_script = True
|
|
231
|
+
except OSError:
|
|
232
|
+
pass
|
|
233
|
+
if spath not in cmdline_joined:
|
|
234
|
+
stale_script = False
|
|
235
|
+
# If shell has any alive non-shell descendants, treat as running
|
|
236
|
+
descendants = proc_shell.children(recursive=True)
|
|
237
|
+
for d in descendants:
|
|
238
|
+
try:
|
|
239
|
+
if d.is_running() and d.name() not in shells:
|
|
240
|
+
shell_only = False
|
|
241
|
+
break
|
|
242
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
243
|
+
continue
|
|
244
|
+
if not shell_only:
|
|
245
|
+
break
|
|
246
|
+
if stale_script:
|
|
247
|
+
stale_script_overall = True
|
|
248
|
+
if shell_only and stale_script_overall:
|
|
249
|
+
return {"status": "not_running", "running": False, "processes": [], "command": command, "cwd": cwd, "tab_name": tab_name}
|
|
250
|
+
except Exception:
|
|
251
|
+
pass
|
|
252
|
+
return {"status": "running", "running": True, "processes": filtered_active, "command": command, "cwd": cwd, "tab_name": tab_name}
|
|
253
|
+
return {"status": "not_running", "running": False, "processes": [], "command": command, "cwd": cwd, "tab_name": tab_name}
|
|
254
|
+
|
|
255
|
+
except Exception as e:
|
|
256
|
+
logger.error(f"Error checking command status for tab '{tab_name}': {e}")
|
|
257
|
+
return {"status": "error", "error": str(e), "running": False, "command": command, "cwd": cwd, "tab_name": tab_name, "processes": []}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def check_zellij_session_status(session_name: str) -> ZellijSessionStatus:
|
|
261
|
+
"""Check if a Zellij session is running."""
|
|
262
|
+
try:
|
|
263
|
+
# Run zellij list-sessions command
|
|
264
|
+
result = subprocess.run(["zellij", "list-sessions"], capture_output=True, text=True, timeout=10)
|
|
265
|
+
|
|
266
|
+
if result.returncode == 0:
|
|
267
|
+
sessions = result.stdout.strip().split("\n") if result.stdout.strip() else []
|
|
268
|
+
session_running = any(session_name in session for session in sessions)
|
|
269
|
+
|
|
270
|
+
return {"zellij_running": True, "session_exists": session_running, "session_name": session_name, "all_sessions": sessions}
|
|
271
|
+
else:
|
|
272
|
+
return {"zellij_running": False, "session_exists": False, "session_name": session_name, "all_sessions": [], "error": result.stderr}
|
|
273
|
+
|
|
274
|
+
except subprocess.TimeoutExpired:
|
|
275
|
+
return {"zellij_running": False, "session_exists": False, "session_name": session_name, "all_sessions": [], "error": "Timeout while checking Zellij sessions"}
|
|
276
|
+
except FileNotFoundError:
|
|
277
|
+
return {"zellij_running": False, "session_exists": False, "session_name": session_name, "all_sessions": [], "error": "Zellij not found in PATH"}
|
|
278
|
+
except Exception as e:
|
|
279
|
+
return {"zellij_running": False, "session_exists": False, "session_name": session_name, "all_sessions": [], "error": str(e)}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def get_layout_preview(layout_config: LayoutConfig, layout_template: str | None) -> str:
|
|
283
|
+
"""Generate a preview of the layout configuration."""
|
|
284
|
+
if layout_template is None:
|
|
285
|
+
layout_template = """layout {
|
|
286
|
+
default_tab_template {
|
|
287
|
+
// the default zellij tab-bar and status bar plugins
|
|
288
|
+
pane size=1 borderless=true {
|
|
289
|
+
plugin location="zellij:compact-bar"
|
|
290
|
+
}
|
|
291
|
+
children
|
|
292
|
+
}
|
|
293
|
+
"""
|
|
294
|
+
validate_layout_config(layout_config)
|
|
295
|
+
layout_content = layout_template
|
|
296
|
+
for tab in layout_config["layoutTabs"]:
|
|
297
|
+
layout_content += "\n" + create_tab_section(tab)
|
|
298
|
+
return layout_content + "\n}\n"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import subprocess
|
|
3
|
+
import time
|
|
4
|
+
import logging
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def restart_tab_process(tab_name: str, layout_config: LayoutConfig, session_name: str) -> bool:
|
|
15
|
+
"""Restart the process running in a specific Zellij tab without changing the layout.
|
|
16
|
+
|
|
17
|
+
This function will:
|
|
18
|
+
1. Navigate to the specified tab
|
|
19
|
+
2. Send Ctrl+C to stop the running process
|
|
20
|
+
3. Clear the screen
|
|
21
|
+
4. Re-execute the original command
|
|
22
|
+
|
|
23
|
+
The tab layout and configuration remain unchanged - only the process is restarted.
|
|
24
|
+
"""
|
|
25
|
+
if not layout_config:
|
|
26
|
+
logger.error("No layout config available. Cannot restart tab.")
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
tab_config = None
|
|
30
|
+
for tab in layout_config["layoutTabs"]:
|
|
31
|
+
if tab["tabName"] == tab_name:
|
|
32
|
+
tab_config = tab
|
|
33
|
+
break
|
|
34
|
+
|
|
35
|
+
if tab_config is None:
|
|
36
|
+
logger.error(f"Tab '{tab_name}' not found in layout config.")
|
|
37
|
+
console.print(f"[bold red]❌ Tab '{tab_name}' not found in layout[/bold red]")
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
command = tab_config.get("command", "")
|
|
41
|
+
if not command:
|
|
42
|
+
logger.warning(f"No command configured for tab '{tab_name}'")
|
|
43
|
+
console.print(f"[bold yellow]⚠️ No command to restart for tab '{tab_name}'[/bold yellow]")
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
console.print(f"[bold cyan]🔄 Restarting tab[/bold cyan] [yellow]'{tab_name}'[/yellow]")
|
|
47
|
+
console.print(f"[dim]Command: {command}[/dim]")
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
session_arg = f"--session {session_name}" if session_name else ""
|
|
51
|
+
|
|
52
|
+
subprocess.run(f"zellij {session_arg} action go-to-tab-name '{tab_name}'", shell=True, check=True, capture_output=True, text=True)
|
|
53
|
+
time.sleep(0.5)
|
|
54
|
+
|
|
55
|
+
subprocess.run(f"zellij {session_arg} action write-chars '\\u0003'", shell=True, check=True, capture_output=True, text=True)
|
|
56
|
+
time.sleep(0.3)
|
|
57
|
+
|
|
58
|
+
subprocess.run(f"zellij {session_arg} action write-chars 'clear'", shell=True, check=True, capture_output=True, text=True)
|
|
59
|
+
subprocess.run(f"zellij {session_arg} action write-chars '\\n'", shell=True, check=True, capture_output=True, text=True)
|
|
60
|
+
time.sleep(0.2)
|
|
61
|
+
|
|
62
|
+
escaped_command = command.replace("'", "'\\''")
|
|
63
|
+
subprocess.run(f"zellij {session_arg} action write-chars '{escaped_command}'", shell=True, check=True, capture_output=True, text=True)
|
|
64
|
+
subprocess.run(f"zellij {session_arg} action write-chars '\\n'", shell=True, check=True, capture_output=True, text=True)
|
|
65
|
+
|
|
66
|
+
console.print(f"[bold green]✅ Tab '{tab_name}' restarted successfully[/bold green]")
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
except subprocess.CalledProcessError as e:
|
|
70
|
+
logger.error(f"Failed to restart tab '{tab_name}': {e}")
|
|
71
|
+
console.print(f"[bold red]❌ Failed to restart tab '{tab_name}'[/bold red]")
|
|
72
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
73
|
+
return False
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.error(f"Unexpected error while restarting tab '{tab_name}': {e}")
|
|
76
|
+
console.print(f"[bold red]❌ Unexpected error: {e}[/bold red]")
|
|
77
|
+
return False
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Helper functions for generating Zellij KDL layouts with support for multiple panes per tab.
|
|
4
|
+
This module extends the basic layout functionality to organize multiple commands into panes within a single tab.
|
|
5
|
+
"""
|
|
6
|
+
import shlex
|
|
7
|
+
import random
|
|
8
|
+
import string
|
|
9
|
+
import logging
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Literal
|
|
12
|
+
|
|
13
|
+
from machineconfig.utils.schemas.layouts.layout_types import LayoutConfig, TabConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def generate_random_suffix(length: int) -> str:
|
|
20
|
+
"""Generate a random string suffix for unique layout file names."""
|
|
21
|
+
return "".join(random.choices(string.ascii_lowercase + string.digits, k=length))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def parse_command(command: str) -> tuple[str, list[str]]:
|
|
25
|
+
"""Parse a command string into executable and arguments."""
|
|
26
|
+
try:
|
|
27
|
+
parts = shlex.split(command)
|
|
28
|
+
if not parts:
|
|
29
|
+
raise ValueError("Empty command provided")
|
|
30
|
+
return parts[0], parts[1:] if len(parts) > 1 else []
|
|
31
|
+
except ValueError as e:
|
|
32
|
+
logger.error(f"Error parsing command '{command}': {e}")
|
|
33
|
+
parts = command.split()
|
|
34
|
+
return parts[0] if parts else "", parts[1:] if len(parts) > 1 else []
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def format_args_for_kdl(args: list[str]) -> str:
|
|
38
|
+
"""Format command arguments for KDL layout format."""
|
|
39
|
+
if not args:
|
|
40
|
+
return ""
|
|
41
|
+
formatted_args = []
|
|
42
|
+
for arg in args:
|
|
43
|
+
if " " in arg or '"' in arg or "'" in arg:
|
|
44
|
+
escaped_arg = arg.replace('"', '\\"')
|
|
45
|
+
formatted_args.append(f'"{escaped_arg}"')
|
|
46
|
+
else:
|
|
47
|
+
formatted_args.append(f'"{arg}"')
|
|
48
|
+
return " ".join(formatted_args)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def create_pane_kdl(tab_config: TabConfig, indent_level: int) -> str:
|
|
52
|
+
"""Create a KDL pane definition from a tab configuration."""
|
|
53
|
+
indent = " " * indent_level
|
|
54
|
+
cmd, args = parse_command(tab_config["command"])
|
|
55
|
+
args_str = format_args_for_kdl(args)
|
|
56
|
+
pane_content = f'{indent}pane command="{cmd}" {{\n'
|
|
57
|
+
if args_str:
|
|
58
|
+
pane_content += f'{indent} args {args_str}\n'
|
|
59
|
+
pane_content += f'{indent}}}\n'
|
|
60
|
+
return pane_content
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def create_tab_with_panes(
|
|
64
|
+
tab_configs: list[TabConfig],
|
|
65
|
+
tab_name: str,
|
|
66
|
+
common_cwd: str,
|
|
67
|
+
split_direction: Literal["vertical", "horizontal"] = "vertical",
|
|
68
|
+
) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Create a KDL tab section with multiple panes from multiple tab configurations.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
tab_configs: List of TabConfig objects to be organized as panes within one tab
|
|
74
|
+
tab_name: Name for the tab (derived from configs)
|
|
75
|
+
common_cwd: Common working directory for the tab
|
|
76
|
+
split_direction: Direction to split panes ('vertical' or 'horizontal')
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
KDL formatted string for the tab with multiple panes
|
|
80
|
+
"""
|
|
81
|
+
escaped_tab_name = tab_name.replace('"', '\\"')
|
|
82
|
+
tab_section = f' tab name="{escaped_tab_name}" cwd="{common_cwd}" {{\n'
|
|
83
|
+
if len(tab_configs) == 1:
|
|
84
|
+
cmd, args = parse_command(tab_configs[0]["command"])
|
|
85
|
+
args_str = format_args_for_kdl(args)
|
|
86
|
+
tab_section += f' pane command="{cmd}" {{\n'
|
|
87
|
+
if args_str:
|
|
88
|
+
tab_section += f" args {args_str}\n"
|
|
89
|
+
tab_section += " }\n"
|
|
90
|
+
else:
|
|
91
|
+
tab_section += f' pane split_direction="{split_direction}" {{\n'
|
|
92
|
+
for config in tab_configs:
|
|
93
|
+
tab_section += create_pane_kdl(config, indent_level=3)
|
|
94
|
+
tab_section += " }\n"
|
|
95
|
+
tab_section += " }\n"
|
|
96
|
+
return tab_section
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def generate_tab_name(tab_configs: list[TabConfig], tab_index: int) -> str:
|
|
100
|
+
"""
|
|
101
|
+
Generate a meaningful tab name from a list of tab configurations.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
tab_configs: List of TabConfig objects in this tab
|
|
105
|
+
tab_index: Index of the tab (1-based)
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
A descriptive tab name
|
|
109
|
+
"""
|
|
110
|
+
if len(tab_configs) == 1:
|
|
111
|
+
return tab_configs[0]["tabName"]
|
|
112
|
+
first_name = tab_configs[0]["tabName"].strip()
|
|
113
|
+
if first_name.startswith("🤖") or first_name.startswith("📊") or first_name.startswith("📝"):
|
|
114
|
+
base_name = first_name[:2]
|
|
115
|
+
return f"{base_name}Group{tab_index}"
|
|
116
|
+
words = first_name.split()
|
|
117
|
+
if words:
|
|
118
|
+
first_word = words[0].strip(":")
|
|
119
|
+
return f"{first_word}×{len(tab_configs)}"
|
|
120
|
+
return f"Tab{tab_index}[{len(tab_configs)}]"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def determine_common_cwd(tab_configs: list[TabConfig]) -> str:
|
|
124
|
+
"""
|
|
125
|
+
Determine the common working directory for a group of tab configs.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
tab_configs: List of TabConfig objects
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
The most common directory or the first one if no commonality
|
|
132
|
+
"""
|
|
133
|
+
if not tab_configs:
|
|
134
|
+
return "~"
|
|
135
|
+
dirs = [config["startDir"] for config in tab_configs]
|
|
136
|
+
if len(set(dirs)) == 1:
|
|
137
|
+
return dirs[0]
|
|
138
|
+
return dirs[0]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def create_zellij_layout_with_panes(
|
|
142
|
+
layout_config: LayoutConfig,
|
|
143
|
+
output_path: str,
|
|
144
|
+
panes_per_tab: int = 1,
|
|
145
|
+
split_direction: Literal["vertical", "horizontal"] = "vertical",
|
|
146
|
+
) -> str:
|
|
147
|
+
"""
|
|
148
|
+
Create a Zellij KDL layout file with support for multiple panes per tab.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
layout_config: The LayoutConfig object containing all tabs/commands
|
|
152
|
+
panes_per_tab: Number of panes to group into each tab (default: 1 = same as original behavior)
|
|
153
|
+
split_direction: Direction to split panes within a tab ('vertical' or 'horizontal')
|
|
154
|
+
output_path: Path to save the layout file (directory or full file path)
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Absolute path to the created layout file
|
|
158
|
+
|
|
159
|
+
Example:
|
|
160
|
+
>>> layout = {"layoutName": "MyLayout", "layoutTabs": [...]}
|
|
161
|
+
>>> path = create_zellij_layout_with_panes(layout, panes_per_tab=2, split_direction="vertical", output_path="/tmp/layout.kdl")
|
|
162
|
+
"""
|
|
163
|
+
if panes_per_tab < 1:
|
|
164
|
+
raise ValueError("panes_per_tab must be at least 1")
|
|
165
|
+
layout_tabs = layout_config["layoutTabs"]
|
|
166
|
+
if not layout_tabs:
|
|
167
|
+
raise ValueError("Layout must contain at least one tab")
|
|
168
|
+
layout_template = """layout {
|
|
169
|
+
default_tab_template {
|
|
170
|
+
// the default zellij tab-bar and status bar plugins
|
|
171
|
+
pane size=1 borderless=true {
|
|
172
|
+
plugin location="zellij:compact-bar"
|
|
173
|
+
}
|
|
174
|
+
children
|
|
175
|
+
}
|
|
176
|
+
"""
|
|
177
|
+
layout_content = layout_template
|
|
178
|
+
grouped_tabs: list[list[TabConfig]] = []
|
|
179
|
+
for i in range(0, len(layout_tabs), panes_per_tab):
|
|
180
|
+
group = layout_tabs[i : i + panes_per_tab]
|
|
181
|
+
grouped_tabs.append(group)
|
|
182
|
+
for tab_index, group in enumerate(grouped_tabs, start=1):
|
|
183
|
+
tab_name = generate_tab_name(group, tab_index)
|
|
184
|
+
common_cwd = determine_common_cwd(group)
|
|
185
|
+
layout_content += "\n" + create_tab_with_panes(group, tab_name, common_cwd, split_direction)
|
|
186
|
+
layout_content += "\n}\n"
|
|
187
|
+
try:
|
|
188
|
+
path_obj = Path(output_path)
|
|
189
|
+
if path_obj.is_dir():
|
|
190
|
+
raise ValueError("Output path must be a file path ending with .kdl, not a directory")
|
|
191
|
+
if path_obj.suffix == ".kdl":
|
|
192
|
+
layout_file = path_obj
|
|
193
|
+
layout_file.parent.mkdir(parents=True, exist_ok=True)
|
|
194
|
+
else:
|
|
195
|
+
raise ValueError("Output path must end with .kdl")
|
|
196
|
+
layout_file.write_text(layout_content, encoding="utf-8")
|
|
197
|
+
logger.info(f"Created Zellij layout file: {layout_file.absolute()}")
|
|
198
|
+
return str(layout_file.absolute())
|
|
199
|
+
except OSError as e:
|
|
200
|
+
logger.error(f"Failed to create layout file: {e}")
|
|
201
|
+
raise
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
sample_layout: LayoutConfig = {
|
|
206
|
+
"layoutName": "TestMultiPane",
|
|
207
|
+
"layoutTabs": [
|
|
208
|
+
{"tabName": "🤖Bot1", "startDir": "~/code/project1", "command": "python bot1.py"},
|
|
209
|
+
{"tabName": "🤖Bot2", "startDir": "~/code/project1", "command": "python bot2.py"},
|
|
210
|
+
{"tabName": "🤖Bot3", "startDir": "~/code/project1", "command": "python bot3.py"},
|
|
211
|
+
{"tabName": "🤖Bot4", "startDir": "~/code/project2", "command": "python bot4.py"},
|
|
212
|
+
{"tabName": "📊Monitor", "startDir": "~", "command": "htop"},
|
|
213
|
+
{"tabName": "📝Logs", "startDir": "/var/log", "command": "tail -f /var/log/app.log"},
|
|
214
|
+
],
|
|
215
|
+
}
|
|
216
|
+
print("=" * 80)
|
|
217
|
+
print("DEMO 1: panes_per_tab=1 (same as original behavior)")
|
|
218
|
+
print("=" * 80)
|
|
219
|
+
layout_path_1 = create_zellij_layout_with_panes(sample_layout, "/tmp/zellij_test_123.kdl", panes_per_tab=1)
|
|
220
|
+
print(f"✅ Layout created: {layout_path_1}")
|
|
221
|
+
layout_path_2 = create_zellij_layout_with_panes(layout_config=sample_layout, output_path="/tmp/zellij_test_1234.kdl", panes_per_tab=2, split_direction="vertical")
|
|
222
|
+
print(f"✅ Layout created: {layout_path_2}")
|
|
223
|
+
print("DEMO 3: panes_per_tab=3 (three panes per tab, horizontal split)")
|
|
224
|
+
layout_path_3 = create_zellij_layout_with_panes(layout_config=sample_layout, output_path="/tmp/zellij_test_12345.kdl", panes_per_tab=3, split_direction="horizontal")
|
|
225
|
+
print(f"✅ Layout created: {layout_path_3}")
|
|
226
|
+
|
|
227
|
+
from machineconfig.cluster.sessions_managers.helpers.enhanced_command_runner import enhanced_zellij_session_start
|
|
228
|
+
enhanced_zellij_session_start(session_name="tmp", layout_path=layout_path_3)
|