agsekit 1.7.3__tar.gz → 1.7.4__tar.gz

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.
Files changed (201) hide show
  1. {agsekit-1.7.3/agsekit.egg-info → agsekit-1.7.4}/PKG-INFO +1 -1
  2. {agsekit-1.7.3 → agsekit-1.7.4/agsekit.egg-info}/PKG-INFO +1 -1
  3. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit.egg-info/SOURCES.txt +3 -0
  4. agsekit-1.7.4/agsekit_cli/agent_version_sources.py +90 -0
  5. agsekit-1.7.4/agsekit_cli/agents_modules/aider.py +14 -0
  6. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agents_modules/base.py +6 -0
  7. agsekit-1.7.4/agsekit_cli/agents_modules/claude.py +15 -0
  8. agsekit-1.7.4/agsekit_cli/agents_modules/cline.py +15 -0
  9. agsekit-1.7.4/agsekit_cli/agents_modules/codex.py +14 -0
  10. agsekit-1.7.4/agsekit_cli/agents_modules/codex_glibc.py +15 -0
  11. agsekit-1.7.4/agsekit_cli/agents_modules/codex_glibc_prebuilt.py +23 -0
  12. agsekit-1.7.4/agsekit_cli/agents_modules/forgecode.py +16 -0
  13. agsekit-1.7.4/agsekit_cli/agents_modules/opencode.py +15 -0
  14. agsekit-1.7.4/agsekit_cli/agents_modules/qwen.py +14 -0
  15. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/codex-glibc-prebuilt.yml +4 -2
  16. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/codex-glibc.yml +3 -0
  17. agsekit-1.7.4/agsekit_cli/ansible/agents/codex_code_mode_host.yml +52 -0
  18. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/check_new_version.py +4 -4
  19. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/daemon.py +1 -1
  20. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/install_agents.py +51 -7
  21. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/locales/en.json +43 -38
  22. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/locales/ru.json +38 -33
  23. agsekit-1.7.4/agsekit_cli/state.py +356 -0
  24. {agsekit-1.7.3 → agsekit-1.7.4}/pyproject.toml +1 -1
  25. agsekit-1.7.4/tests/test_agent_latest_versions.py +95 -0
  26. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_ansible_agent_proxychains.py +32 -1
  27. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_daemon_command.py +2 -2
  28. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_install_agents_command.py +125 -4
  29. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_node_agent_installers.py +1 -1
  30. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_state.py +88 -0
  31. agsekit-1.7.3/agsekit_cli/agents_modules/aider.py +0 -8
  32. agsekit-1.7.3/agsekit_cli/agents_modules/claude.py +0 -9
  33. agsekit-1.7.3/agsekit_cli/agents_modules/cline.py +0 -9
  34. agsekit-1.7.3/agsekit_cli/agents_modules/codex.py +0 -8
  35. agsekit-1.7.3/agsekit_cli/agents_modules/codex_glibc.py +0 -7
  36. agsekit-1.7.3/agsekit_cli/agents_modules/codex_glibc_prebuilt.py +0 -7
  37. agsekit-1.7.3/agsekit_cli/agents_modules/forgecode.py +0 -8
  38. agsekit-1.7.3/agsekit_cli/agents_modules/opencode.py +0 -9
  39. agsekit-1.7.3/agsekit_cli/agents_modules/qwen.py +0 -8
  40. agsekit-1.7.3/agsekit_cli/state.py +0 -197
  41. {agsekit-1.7.3 → agsekit-1.7.4}/LICENSE +0 -0
  42. {agsekit-1.7.3 → agsekit-1.7.4}/MANIFEST.in +0 -0
  43. {agsekit-1.7.3 → agsekit-1.7.4}/README.md +0 -0
  44. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit.egg-info/dependency_links.txt +0 -0
  45. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit.egg-info/entry_points.txt +0 -0
  46. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit.egg-info/requires.txt +0 -0
  47. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit.egg-info/top_level.txt +0 -0
  48. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/__init__.py +0 -0
  49. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agent_scripts/claude-code.sh +0 -0
  50. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agent_scripts/codex-glibc.sh +0 -0
  51. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agent_scripts/codex.sh +0 -0
  52. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agent_scripts/proxychains_common.sh +0 -0
  53. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agent_scripts/qwen.sh +0 -0
  54. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agents.py +0 -0
  55. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/agents_modules/__init__.py +0 -0
  56. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/aider.yml +0 -0
  57. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/claude.yml +0 -0
  58. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/cline.yml +0 -0
  59. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/codex.yml +0 -0
  60. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/codex_logrotate.yml +0 -0
  61. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/forgecode.yml +0 -0
  62. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/opencode.yml +0 -0
  63. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/proxychains.yml +0 -0
  64. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/agents/qwen.yml +0 -0
  65. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/docker.yml +0 -0
  66. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/golang.yml +0 -0
  67. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/nodejs.yml +0 -0
  68. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/nvm.yml +0 -0
  69. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/pyenv.yml +0 -0
  70. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/python.yml +0 -0
  71. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/bundles/rust.yml +0 -0
  72. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/callback_plugins/agsekit_progress.py +0 -0
  73. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/callback_plugins/agsekit_rich.py +0 -0
  74. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/connection_plugins/agsekit_multipass.py +0 -0
  75. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/vm_packages.yml +0 -0
  76. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible/vm_ssh.yml +0 -0
  77. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible_runners.py +0 -0
  78. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/ansible_utils.py +0 -0
  79. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/backup.py +0 -0
  80. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/cli.py +0 -0
  81. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/cli_entry.py +0 -0
  82. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/codex_rust_toolchain_version.txt +0 -0
  83. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/__init__.py +0 -0
  84. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/addmount.py +0 -0
  85. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/backup_clean.py +0 -0
  86. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/backup_once.py +0 -0
  87. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/backup_repeated.py +0 -0
  88. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/config_example.py +0 -0
  89. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/config_gen.py +0 -0
  90. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/create_vm.py +0 -0
  91. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/destroy_vm.py +0 -0
  92. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/doctor.py +0 -0
  93. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/down.py +0 -0
  94. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/list_bundles.py +0 -0
  95. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/mounts.py +0 -0
  96. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/pip_upgrade.py +0 -0
  97. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/portforward.py +0 -0
  98. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/prepare.py +0 -0
  99. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/removemount.py +0 -0
  100. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/restart_vm.py +0 -0
  101. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/run.py +0 -0
  102. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/shell.py +0 -0
  103. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/ssh.py +0 -0
  104. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/start_vm.py +0 -0
  105. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/status.py +0 -0
  106. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/stop.py +0 -0
  107. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/systemd.py +0 -0
  108. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/up.py +0 -0
  109. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/commands/version.py +0 -0
  110. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/config.py +0 -0
  111. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/daemon_backends.py +0 -0
  112. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/debug.py +0 -0
  113. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/host_tools.py +0 -0
  114. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/i18n.py +0 -0
  115. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/interactive.py +0 -0
  116. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/mounts.py +0 -0
  117. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/prebuilt.py +0 -0
  118. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/prepare_strategies.py +0 -0
  119. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/progress.py +0 -0
  120. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/provision_handlers.py +0 -0
  121. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/run_agent.sh +0 -0
  122. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/run_with_http_proxy.sh +0 -0
  123. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/run_with_proxychains.sh +0 -0
  124. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/systemd/agsekit-portforward.service +0 -0
  125. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/systemd_backend.py +0 -0
  126. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/tui_prompts.py +0 -0
  127. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/versioning.py +0 -0
  128. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm.py +0 -0
  129. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_bundle_definitions.py +0 -0
  130. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_bundles.py +0 -0
  131. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/docker.sh +0 -0
  132. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/golang.sh +0 -0
  133. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/nodejs.sh +0 -0
  134. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/nvm.sh +0 -0
  135. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/pyenv.sh +0 -0
  136. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/python.sh +0 -0
  137. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_installers/rust.sh +0 -0
  138. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_local_control_node.py +0 -0
  139. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_prepare.py +0 -0
  140. {agsekit-1.7.3 → agsekit-1.7.4}/agsekit_cli/vm_ssh_bootstrap.py +0 -0
  141. {agsekit-1.7.3 → agsekit-1.7.4}/config-example.yaml +0 -0
  142. {agsekit-1.7.3 → agsekit-1.7.4}/prebuilt-agents/codex-glibc/.dockerignore +0 -0
  143. {agsekit-1.7.3 → agsekit-1.7.4}/prebuilt-agents/codex-glibc/Dockerfile +0 -0
  144. {agsekit-1.7.3 → agsekit-1.7.4}/prebuilt-agents/codex-glibc/build-codex-glibc.sh +0 -0
  145. {agsekit-1.7.3 → agsekit-1.7.4}/prebuilt-agents/codex-glibc/build.sh +0 -0
  146. {agsekit-1.7.3 → agsekit-1.7.4}/setup.cfg +0 -0
  147. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_addmount_command.py +0 -0
  148. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_agents.py +0 -0
  149. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_agents_modules.py +0 -0
  150. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_ansible_multipass_connection.py +0 -0
  151. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_ansible_utils.py +0 -0
  152. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_ansible_vm_bundles.py +0 -0
  153. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_backup_clean_command.py +0 -0
  154. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_backup_lock.py +0 -0
  155. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_backup_progress.py +0 -0
  156. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_backup_repeated.py +0 -0
  157. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_backup_repeated_commands.py +0 -0
  158. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_build_backfill_github_releases.py +0 -0
  159. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_build_check_pypi_version.py +0 -0
  160. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_build_extract_changelog.py +0 -0
  161. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_check_new_version_command.py +0 -0
  162. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_codex_logrotate_installers.py +0 -0
  163. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_config_agents.py +0 -0
  164. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_config_gen_command.py +0 -0
  165. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_config_main.py +0 -0
  166. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_config_mounts.py +0 -0
  167. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_config_vms.py +0 -0
  168. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_create_vm_command.py +0 -0
  169. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_debug.py +0 -0
  170. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_doctor_command.py +0 -0
  171. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_down_command.py +0 -0
  172. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_host_tools.py +0 -0
  173. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_i18n.py +0 -0
  174. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_install_script.py +0 -0
  175. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_interactive_mode.py +0 -0
  176. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_launchd_backend.py +0 -0
  177. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_make_single_backup.py +0 -0
  178. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_mount_commands.py +0 -0
  179. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_mounts.py +0 -0
  180. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_pip_upgrade_command.py +0 -0
  181. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_portforward.py +0 -0
  182. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_portforward_command.py +0 -0
  183. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_prebuilt.py +0 -0
  184. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_prepare_command.py +0 -0
  185. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_progress.py +0 -0
  186. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_provision_handlers.py +0 -0
  187. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_removemount_command.py +0 -0
  188. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_restart_vm_command.py +0 -0
  189. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_run_command.py +0 -0
  190. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_shell_command.py +0 -0
  191. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_ssh_command.py +0 -0
  192. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_start_vm_command.py +0 -0
  193. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_status_command.py +0 -0
  194. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_stop_vm_command.py +0 -0
  195. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_systemd_command.py +0 -0
  196. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_up_command.py +0 -0
  197. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_version_command.py +0 -0
  198. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_vm_compare.py +0 -0
  199. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_vm_launch.py +0 -0
  200. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_vm_local_control_node.py +0 -0
  201. {agsekit-1.7.3 → agsekit-1.7.4}/tests/test_vm_proxychains.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agsekit
3
- Version: 1.7.3
3
+ Version: 1.7.4
4
4
  Summary: Agent Safety Kit command-line utilities
5
5
  Author-email: Mihanentalpo <mihanentalpo@yandex.ru>
6
6
  License: MIT License
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agsekit
3
- Version: 1.7.3
3
+ Version: 1.7.4
4
4
  Summary: Agent Safety Kit command-line utilities
5
5
  Author-email: Mihanentalpo <mihanentalpo@yandex.ru>
6
6
  License: MIT License
@@ -10,6 +10,7 @@ agsekit.egg-info/entry_points.txt
10
10
  agsekit.egg-info/requires.txt
11
11
  agsekit.egg-info/top_level.txt
12
12
  agsekit_cli/__init__.py
13
+ agsekit_cli/agent_version_sources.py
13
14
  agsekit_cli/agents.py
14
15
  agsekit_cli/ansible_runners.py
15
16
  agsekit_cli/ansible_utils.py
@@ -65,6 +66,7 @@ agsekit_cli/ansible/agents/cline.yml
65
66
  agsekit_cli/ansible/agents/codex-glibc-prebuilt.yml
66
67
  agsekit_cli/ansible/agents/codex-glibc.yml
67
68
  agsekit_cli/ansible/agents/codex.yml
69
+ agsekit_cli/ansible/agents/codex_code_mode_host.yml
68
70
  agsekit_cli/ansible/agents/codex_logrotate.yml
69
71
  agsekit_cli/ansible/agents/forgecode.yml
70
72
  agsekit_cli/ansible/agents/opencode.yml
@@ -125,6 +127,7 @@ prebuilt-agents/codex-glibc/Dockerfile
125
127
  prebuilt-agents/codex-glibc/build-codex-glibc.sh
126
128
  prebuilt-agents/codex-glibc/build.sh
127
129
  tests/test_addmount_command.py
130
+ tests/test_agent_latest_versions.py
128
131
  tests/test_agents.py
129
132
  tests/test_agents_modules.py
130
133
  tests/test_ansible_agent_proxychains.py
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ from typing import Any, Dict, Iterable, Optional
6
+ from urllib.error import HTTPError, URLError
7
+ from urllib.parse import quote
8
+ from urllib.request import Request, urlopen
9
+
10
+ from packaging.version import InvalidVersion, Version
11
+
12
+
13
+ class AgentVersionCheckError(RuntimeError):
14
+ """Raised when an upstream agent version cannot be resolved."""
15
+
16
+
17
+ def _headers() -> Dict[str, str]:
18
+ headers = {"Accept": "application/json", "User-Agent": "agsekit-agent-version-check"}
19
+ token = os.getenv("AGSEKIT_GITHUB_TOKEN") or os.getenv("GITHUB_TOKEN")
20
+ if token:
21
+ headers["Authorization"] = f"Bearer {token}"
22
+ return headers
23
+
24
+
25
+ def fetch_json(url: str, *, timeout: float = 30.0) -> Any:
26
+ request = Request(url, headers=_headers())
27
+ try:
28
+ with urlopen(request, timeout=timeout) as response:
29
+ return json.load(response)
30
+ except HTTPError as exc:
31
+ raise AgentVersionCheckError(f"Version request failed for {url}: HTTP {exc.code}") from exc
32
+ except URLError as exc:
33
+ raise AgentVersionCheckError(f"Version request failed for {url}: {exc.reason}") from exc
34
+ except (OSError, ValueError) as exc:
35
+ raise AgentVersionCheckError(f"Invalid version response from {url}: {exc}") from exc
36
+
37
+
38
+ def latest_npm_version(package_name: str, *, timeout: float = 30.0) -> str:
39
+ payload = fetch_json(
40
+ f"https://registry.npmjs.org/{quote(package_name, safe='')}/latest",
41
+ timeout=timeout,
42
+ )
43
+ version = payload.get("version") if isinstance(payload, dict) else None
44
+ if not isinstance(version, str) or not version.strip():
45
+ raise AgentVersionCheckError(f"npm did not report a latest version for {package_name}")
46
+ return version.strip()
47
+
48
+
49
+ def latest_pypi_version(package_name: str, *, timeout: float = 30.0) -> str:
50
+ payload = fetch_json(f"https://pypi.org/pypi/{quote(package_name, safe='')}/json", timeout=timeout)
51
+ info = payload.get("info") if isinstance(payload, dict) else None
52
+ version = info.get("version") if isinstance(info, dict) else None
53
+ if not isinstance(version, str) or not version.strip():
54
+ raise AgentVersionCheckError(f"PyPI did not report a latest version for {package_name}")
55
+ return version.strip()
56
+
57
+
58
+ def _stable_versions(values: Iterable[str]) -> Iterable[Version]:
59
+ for value in values:
60
+ try:
61
+ parsed = Version(value)
62
+ except InvalidVersion:
63
+ continue
64
+ if not parsed.is_prerelease and not parsed.is_devrelease:
65
+ yield parsed
66
+
67
+
68
+ def latest_github_release_version(
69
+ repo: str,
70
+ *,
71
+ tag_prefix: str,
72
+ timeout: float = 30.0,
73
+ ) -> str:
74
+ payload = fetch_json(f"https://api.github.com/repos/{repo}/releases?per_page=100", timeout=timeout)
75
+ if not isinstance(payload, list):
76
+ raise AgentVersionCheckError(f"GitHub did not report releases for {repo}")
77
+
78
+ candidates = []
79
+ for release in payload:
80
+ if not isinstance(release, dict) or release.get("draft") or release.get("prerelease"):
81
+ continue
82
+ tag = release.get("tag_name")
83
+ if not isinstance(tag, str) or not tag.startswith(tag_prefix):
84
+ continue
85
+ candidates.append(tag[len(tag_prefix):])
86
+
87
+ versions = list(_stable_versions(candidates))
88
+ if not versions:
89
+ raise AgentVersionCheckError(f"GitHub did not report a stable {tag_prefix} release for {repo}")
90
+ return str(max(versions))
@@ -0,0 +1,14 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_pypi_version
3
+
4
+
5
+ class AiderAgent(BaseAgent):
6
+ type_name = "aider"
7
+ runtime_binary = "aider"
8
+ default_version = "0.86.2"
9
+ default_env = {"AIDER_CHECK_UPDATE": "false"}
10
+
11
+ @classmethod
12
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
13
+ del architecture
14
+ return cls.normalize_version(latest_pypi_version("aider-chat", timeout=timeout))
@@ -33,6 +33,12 @@ class BaseAgent:
33
33
  def needs_nvm(cls) -> bool:
34
34
  return bool(cls._needs_nvm)
35
35
 
36
+ @classmethod
37
+ def check_latest_version(cls, *, architecture: Optional[str] = None, timeout: float = 30.0) -> str:
38
+ del architecture
39
+ del timeout
40
+ raise NotImplementedError(f"Latest-version lookup is not implemented for {cls.type_name}")
41
+
36
42
  @classmethod
37
43
  def playbook_name(cls) -> str:
38
44
  if cls.installer_playbook:
@@ -0,0 +1,15 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_npm_version
3
+
4
+
5
+ class ClaudeAgent(BaseAgent):
6
+ type_name = "claude"
7
+ runtime_binary = "claude"
8
+ default_version = "2.1.141"
9
+ default_env = {"DISABLE_AUTOUPDATER": "1"}
10
+ _needs_nvm = True
11
+
12
+ @classmethod
13
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
14
+ del architecture
15
+ return cls.normalize_version(latest_npm_version("@anthropic-ai/claude-code", timeout=timeout))
@@ -0,0 +1,15 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_npm_version
3
+
4
+
5
+ class ClineAgent(BaseAgent):
6
+ type_name = "cline"
7
+ runtime_binary = "cline"
8
+ default_version = "2.17.0"
9
+ default_env = {"CLINE_NO_AUTO_UPDATE": "1"}
10
+ _needs_nvm = True
11
+
12
+ @classmethod
13
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
14
+ del architecture
15
+ return cls.normalize_version(latest_npm_version("cline", timeout=timeout))
@@ -0,0 +1,14 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_npm_version
3
+
4
+
5
+ class CodexAgent(BaseAgent):
6
+ type_name = "codex"
7
+ runtime_binary = "codex"
8
+ default_version = "0.130.0"
9
+ _needs_nvm = True
10
+
11
+ @classmethod
12
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
13
+ del architecture
14
+ return cls.normalize_version(latest_npm_version("@openai/codex", timeout=timeout))
@@ -0,0 +1,15 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_github_release_version
3
+
4
+
5
+ class CodexGlibcAgent(BaseAgent):
6
+ type_name = "codex-glibc"
7
+ runtime_binary = "codex-glibc"
8
+ default_version = "0.130.0"
9
+
10
+ @classmethod
11
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
12
+ del architecture
13
+ return cls.normalize_version(
14
+ latest_github_release_version("openai/codex", tag_prefix="rust-v", timeout=timeout)
15
+ )
@@ -0,0 +1,23 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import AgentVersionCheckError
3
+ from ..prebuilt import PrebuiltReleaseError, resolve_codex_glibc_prebuilt_release
4
+
5
+
6
+ class CodexGlibcPrebuiltAgent(BaseAgent):
7
+ type_name = "codex-glibc-prebuilt"
8
+ runtime_binary = "codex-glibc-prebuilt"
9
+ default_version = "0.130.0"
10
+
11
+ @classmethod
12
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
13
+ del timeout
14
+ if not architecture:
15
+ raise AgentVersionCheckError("Current architecture is required for codex-glibc-prebuilt")
16
+ try:
17
+ release = resolve_codex_glibc_prebuilt_release(arch=architecture)
18
+ except PrebuiltReleaseError as exc:
19
+ raise AgentVersionCheckError(str(exc)) from exc
20
+ prefix = "codex-glibc-rust-v"
21
+ if not release.tag.startswith(prefix):
22
+ raise AgentVersionCheckError(f"Unexpected codex-glibc prebuilt tag: {release.tag}")
23
+ return cls.normalize_version(release.tag[len(prefix):])
@@ -0,0 +1,16 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_github_release_version
3
+
4
+
5
+ class ForgecodeAgent(BaseAgent):
6
+ type_name = "forgecode"
7
+ runtime_binary = "forge"
8
+ default_version = "2.12.14"
9
+ default_env = {"FORGE_TRACKER": "false"}
10
+
11
+ @classmethod
12
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
13
+ del architecture
14
+ return cls.normalize_version(
15
+ latest_github_release_version("tailcallhq/forgecode", tag_prefix="v", timeout=timeout)
16
+ )
@@ -0,0 +1,15 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_npm_version
3
+
4
+
5
+ class OpencodeAgent(BaseAgent):
6
+ type_name = "opencode"
7
+ runtime_binary = "opencode"
8
+ default_version = "1.14.50"
9
+ default_env = {"OPENCODE_DISABLE_AUTOUPDATE": "true"}
10
+ _needs_nvm = True
11
+
12
+ @classmethod
13
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
14
+ del architecture
15
+ return cls.normalize_version(latest_npm_version("opencode-ai", timeout=timeout))
@@ -0,0 +1,14 @@
1
+ from .base import BaseAgent
2
+ from ..agent_version_sources import latest_npm_version
3
+
4
+
5
+ class QwenAgent(BaseAgent):
6
+ type_name = "qwen"
7
+ runtime_binary = "qwen"
8
+ default_version = "0.15.11"
9
+ _needs_nvm = True
10
+
11
+ @classmethod
12
+ def check_latest_version(cls, *, architecture=None, timeout=30.0):
13
+ del architecture
14
+ return cls.normalize_version(latest_npm_version("@qwen-code/qwen-code", timeout=timeout))
@@ -52,8 +52,7 @@
52
52
  (ansible_playbook_python | quote)
53
53
  ~ ' -m agsekit_cli.prebuilt resolve-codex-glibc-prebuilt --arch '
54
54
  ~ (codex_prebuilt_arch | quote)
55
- ~ ' --tag '
56
- ~ (('--tag ' ~ ('codex-glibc-rust-v' ~ requested_agent_version)) if requested_agent_version else '')
55
+ ~ ((' --tag ' ~ ('codex-glibc-rust-v' ~ requested_agent_version)) if requested_agent_version else '')
57
56
  ) | from_json
58
57
  }}
59
58
 
@@ -149,3 +148,6 @@
149
148
  ansible.builtin.command: "{{ codex_install_path }} --version"
150
149
  register: codex_version_check
151
150
  changed_when: false
151
+
152
+ - name: Install version-matched Codex Code Mode host
153
+ ansible.builtin.include_tasks: "{{ playbook_dir }}/codex_code_mode_host.yml"
@@ -263,6 +263,9 @@
263
263
  register: codex_version_check
264
264
  changed_when: false
265
265
 
266
+ - name: Install version-matched Codex Code Mode host
267
+ ansible.builtin.include_tasks: "{{ playbook_dir }}/codex_code_mode_host.yml"
268
+
266
269
  - name: Cleanup rust and cargo toolchains used for build
267
270
  ansible.builtin.shell: |
268
271
  set -euo pipefail
@@ -0,0 +1,52 @@
1
+ ---
2
+ - name: Extract installed Codex version for Code Mode host
3
+ ansible.builtin.set_fact:
4
+ codex_code_mode_host_version: >-
5
+ {{ codex_version_check.stdout | regex_search('[0-9]+\.[0-9]+\.[0-9]+(?:[-+][0-9A-Za-z.-]+)?') }}
6
+
7
+ - name: Fail when installed Codex version cannot be determined
8
+ ansible.builtin.fail:
9
+ msg: >-
10
+ Could not determine the installed Codex version from: {{ codex_version_check.stdout }}
11
+ when: not codex_code_mode_host_version
12
+
13
+ - name: Determine Codex Code Mode host release target
14
+ ansible.builtin.set_fact:
15
+ codex_code_mode_host_target: >-
16
+ {{ 'aarch64-unknown-linux-musl' if ansible_architecture in ['aarch64', 'arm64'] else 'x86_64-unknown-linux-musl' }}
17
+ codex_code_mode_host_path: "{{ codex_install_path | dirname }}/codex-code-mode-host"
18
+
19
+ - name: Remove previous Codex Code Mode host download
20
+ ansible.builtin.file:
21
+ path: /tmp/codex-code-mode-host.tar.gz
22
+ state: absent
23
+
24
+ - name: Download version-matched Codex Code Mode host
25
+ ansible.builtin.command: >-
26
+ {{ proxychains_prefix }}curl -fsSL --write-out %{http_code}
27
+ "https://github.com/openai/codex/releases/download/rust-v{{ codex_code_mode_host_version }}/codex-code-mode-host-{{ codex_code_mode_host_target }}.tar.gz"
28
+ -o /tmp/codex-code-mode-host.tar.gz
29
+ register: codex_code_mode_host_download
30
+ changed_when: codex_code_mode_host_download.rc == 0
31
+ failed_when:
32
+ - codex_code_mode_host_download.rc != 0
33
+ - codex_code_mode_host_download.stdout | trim != "404"
34
+
35
+ - name: Install Codex Code Mode host beside Codex binary
36
+ ansible.builtin.shell: |
37
+ set -euo pipefail
38
+ rm -rf /tmp/codex-code-mode-host-extract
39
+ mkdir -p /tmp/codex-code-mode-host-extract
40
+ tar -xzf /tmp/codex-code-mode-host.tar.gz -C /tmp/codex-code-mode-host-extract
41
+ helper="/tmp/codex-code-mode-host-extract/codex-code-mode-host-{{ codex_code_mode_host_target }}"
42
+ test -f "$helper"
43
+ {{ 'sudo ' if codex_install_mode == 'system' else '' }}install -m 0755 "$helper" "{{ codex_code_mode_host_path }}"
44
+ rm -rf /tmp/codex-code-mode-host-extract /tmp/codex-code-mode-host.tar.gz
45
+ args:
46
+ executable: /bin/bash
47
+ when: codex_code_mode_host_download.rc == 0
48
+
49
+ - name: Verify Codex Code Mode host works
50
+ ansible.builtin.command: "{{ codex_code_mode_host_path }} --help"
51
+ changed_when: false
52
+ when: codex_code_mode_host_download.rc == 0
@@ -5,7 +5,7 @@ from typing import Optional
5
5
 
6
6
  import click
7
7
 
8
- from ..config import resolve_config_path
8
+ from ..config import ConfigError, resolve_config_path
9
9
  from ..i18n import tr
10
10
  from ..state import CHANGELOG_URL, get_state_manager, initialize_state, run_check_new_version
11
11
  from ..versioning import is_newer_version
@@ -24,7 +24,7 @@ from . import debug_option, non_interactive_option
24
24
  help=tr("config.option_path"),
25
25
  )
26
26
  def check_new_version_command(config_path: Optional[str], non_interactive: bool, debug: bool) -> None:
27
- """Check PyPI through pip, update state.yaml, and report whether a newer version exists."""
27
+ """Refresh cached agsekit and configured-agent versions in state.yaml."""
28
28
  del non_interactive
29
29
  del debug
30
30
 
@@ -32,8 +32,8 @@ def check_new_version_command(config_path: Optional[str], non_interactive: bool,
32
32
  initialize_state(resolved_path)
33
33
  manager = get_state_manager()
34
34
  try:
35
- latest = run_check_new_version()
36
- except RuntimeError as exc:
35
+ latest = run_check_new_version(resolved_path)
36
+ except (ConfigError, RuntimeError) as exc:
37
37
  raise click.ClickException(tr("check_new_version.failed", error=str(exc)))
38
38
 
39
39
  if is_newer_version(latest, manager.current_version):
@@ -77,7 +77,7 @@ def run_daemon_status() -> None:
77
77
 
78
78
  @click.group(name="daemon", help=tr("daemon.group_help"))
79
79
  def daemon_group() -> None:
80
- """Commands for managing the portforward daemon."""
80
+ """Commands for managing the agsekit background daemon."""
81
81
 
82
82
 
83
83
  @daemon_group.command(name="install", help=tr("daemon.install_help"))
@@ -34,6 +34,7 @@ from ..interactive import is_interactive_terminal
34
34
  from ..i18n import tr
35
35
  from ..progress import ProgressManager
36
36
  from ..provision_handlers import PreparedVmSsh, choose_provision_handler
37
+ from ..state import initialize_state, refresh_agent_versions
37
38
  from ..vm import MultipassError, ensure_multipass_available, resolve_proxychains
38
39
  from ..vm_prepare import _ensure_vm_ssh_access, _fetch_vm_ips, ensure_host_ssh_keypair, vm_ssh_ansible_vars
39
40
  from . import debug_option, non_interactive_option
@@ -246,6 +247,8 @@ def run_install_agents(
246
247
  debug: bool,
247
248
  interactive: bool,
248
249
  progress: Optional[ProgressManager] = None,
250
+ upgrade: bool = False,
251
+ force_check_versions: bool = False,
249
252
  ) -> None:
250
253
  with debug_scope(debug):
251
254
  if not progress:
@@ -253,6 +256,8 @@ def run_install_agents(
253
256
 
254
257
  if all_agents and agent_name:
255
258
  raise click.ClickException(tr("install_agents.agent_conflict"))
259
+ if force_check_versions and not upgrade:
260
+ raise click.ClickException(tr("install_agents.force_check_requires_upgrade"))
256
261
 
257
262
  resolved_path = resolve_config_path(Path(config_path) if config_path else None)
258
263
  try:
@@ -307,6 +312,31 @@ def run_install_agents(
307
312
  raise click.ClickException(tr("install_agents.vm_missing", vm_name=target_vm_name))
308
313
  targets.append((agent.name, vms_config[target_vm_name]))
309
314
 
315
+ upgrade_versions: Dict[str, str] = {}
316
+ if upgrade:
317
+ state_manager = initialize_state(resolved_path)
318
+ selected_agent_types = {
319
+ find_agent(agents_config, target_agent_name).type
320
+ for target_agent_name, _target_vm in targets
321
+ }
322
+ if force_check_versions:
323
+ errors = refresh_agent_versions(selected_agent_types, force=True)
324
+ if errors:
325
+ details = "; ".join(
326
+ f"{agent_type}: {message}" for agent_type, message in sorted(errors.items())
327
+ )
328
+ raise click.ClickException(
329
+ tr("install_agents.force_check_failed", errors=details)
330
+ )
331
+ for target_agent_name in dict.fromkeys(name for name, _vm in targets):
332
+ target_agent = find_agent(agents_config, target_agent_name)
333
+ cached = state_manager.get_agent_version(target_agent.type)
334
+ if cached is None:
335
+ raise click.ClickException(
336
+ tr("install_agents.upgrade_version_missing", agent_type=target_agent.type)
337
+ )
338
+ upgrade_versions[target_agent.type] = cached.latest_version
339
+
310
340
  if progress is None:
311
341
  with ProgressManager(debug=debug) as owned_progress:
312
342
  _run_install_targets(
@@ -317,6 +347,7 @@ def run_install_agents(
317
347
  debug=debug,
318
348
  progress=owned_progress,
319
349
  show_overall_task=True,
350
+ upgrade_versions=upgrade_versions,
320
351
  )
321
352
  _emit_install_success(targets)
322
353
  return
@@ -329,6 +360,7 @@ def run_install_agents(
329
360
  debug=debug,
330
361
  progress=progress,
331
362
  show_overall_task=False,
363
+ upgrade_versions=upgrade_versions,
332
364
  )
333
365
 
334
366
 
@@ -341,6 +373,7 @@ def _run_install_targets(
341
373
  debug: bool,
342
374
  progress: ProgressManager,
343
375
  show_overall_task: bool,
376
+ upgrade_versions: Optional[Dict[str, str]] = None,
344
377
  ) -> None:
345
378
  overall_task = progress.add_task(tr("progress.install_agents_title"), total=len(targets)) if show_overall_task else None
346
379
  node_ready_vms: set[str] = set()
@@ -349,8 +382,9 @@ def _run_install_targets(
349
382
  agent = find_agent(agents_config, target_agent_name)
350
383
  agent_cls = get_agent_class(agent.type)
351
384
  playbook_path = _playbook_for(agent)
385
+ requested_version = upgrade_versions.get(agent.type) if upgrade_versions else agent.version
352
386
  installed_version = _installed_agent_version(agent, target_vm, debug=debug)
353
- if agent.version is None and installed_version is not None:
387
+ if requested_version is None and installed_version is not None:
354
388
  click.echo(
355
389
  tr(
356
390
  "install_agents.version_unpinned",
@@ -363,14 +397,14 @@ def _run_install_targets(
363
397
  if overall_task is not None:
364
398
  progress.advance(overall_task)
365
399
  continue
366
- if agent.version is not None and installed_version == agent.version:
400
+ if requested_version is not None and installed_version == requested_version:
367
401
  click.echo(
368
402
  tr(
369
403
  "install_agents.version_ok",
370
404
  agent_name=agent.name,
371
405
  agent_type=agent.type,
372
406
  vm_name=target_vm.name,
373
- version=agent.version or "latest",
407
+ version=requested_version or "latest",
374
408
  )
375
409
  )
376
410
  if overall_task is not None:
@@ -384,7 +418,7 @@ def _run_install_targets(
384
418
  agent_name=agent.name,
385
419
  agent_type=agent.type,
386
420
  vm_name=target_vm.name,
387
- version=agent.version or "latest",
421
+ version=requested_version or "latest",
388
422
  )
389
423
  )
390
424
  else:
@@ -395,7 +429,7 @@ def _run_install_targets(
395
429
  agent_type=agent.type,
396
430
  vm_name=target_vm.name,
397
431
  current_version=installed_version,
398
- required_version=agent.version or "latest",
432
+ required_version=requested_version or "latest",
399
433
  )
400
434
  )
401
435
  if debug:
@@ -405,7 +439,7 @@ def _run_install_targets(
405
439
  agent_name=agent.name,
406
440
  agent_type=agent.type,
407
441
  vm_name=target_vm.name,
408
- version=agent.version or "latest",
442
+ version=requested_version or "latest",
409
443
  script=playbook_path.name,
410
444
  )
411
445
  )
@@ -422,7 +456,7 @@ def _run_install_targets(
422
456
  if overall_task is not None:
423
457
  progress.update(overall_task, description=install_label)
424
458
  extra_vars_overrides: Dict[str, object] = {
425
- "agent_version": agent.version,
459
+ "agent_version": requested_version,
426
460
  "force_reinstall": force_reinstall,
427
461
  }
428
462
  if agent_cls.needs_nvm() and target_vm.name in node_ready_vms:
@@ -467,6 +501,12 @@ def _run_install_targets(
467
501
  @click.argument("vm", required=False)
468
502
  @click.option("--all-vms", is_flag=True, help=tr("install_agents.option_all_vms"))
469
503
  @click.option("--all-agents", is_flag=True, help=tr("install_agents.option_all_agents"))
504
+ @click.option("--upgrade", is_flag=True, help=tr("install_agents.option_upgrade"))
505
+ @click.option(
506
+ "--force-check-versions",
507
+ is_flag=True,
508
+ help=tr("install_agents.option_force_check_versions"),
509
+ )
470
510
  @click.option(
471
511
  "config_path",
472
512
  "--config",
@@ -487,6 +527,8 @@ def install_agents_command(
487
527
  vm: Optional[str],
488
528
  all_vms: bool,
489
529
  all_agents: bool,
530
+ upgrade: bool,
531
+ force_check_versions: bool,
490
532
  config_path: Optional[str],
491
533
  proxychains: Optional[str],
492
534
  debug: bool,
@@ -503,4 +545,6 @@ def install_agents_command(
503
545
  proxychains=proxychains,
504
546
  debug=debug,
505
547
  interactive=interactive,
548
+ upgrade=upgrade,
549
+ force_check_versions=force_check_versions,
506
550
  )