apm-cli 0.18.0__tar.gz → 0.20.0__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 (396) hide show
  1. {apm_cli-0.18.0 → apm_cli-0.20.0}/AUTHORS +1 -0
  2. {apm_cli-0.18.0/src/apm_cli.egg-info → apm_cli-0.20.0}/PKG-INFO +4 -4
  3. {apm_cli-0.18.0 → apm_cli-0.20.0}/README.md +3 -3
  4. {apm_cli-0.18.0 → apm_cli-0.20.0}/pyproject.toml +1 -1
  5. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/base.py +26 -16
  6. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/claude.py +1 -6
  7. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/codex.py +1 -13
  8. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/copilot.py +11 -15
  9. apm_cli-0.20.0/src/apm_cli/adapters/client/hermes.py +210 -0
  10. apm_cli-0.20.0/src/apm_cli/adapters/client/kiro.py +226 -0
  11. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/vscode.py +115 -30
  12. apm_cli-0.20.0/src/apm_cli/bootstrap_mirror.py +101 -0
  13. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/local_bundle.py +57 -62
  14. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/lockfile_enrichment.py +6 -0
  15. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/packer.py +25 -7
  16. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/plugin_exporter.py +21 -13
  17. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/unpacker.py +46 -29
  18. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cli.py +57 -1
  19. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/audit.py +82 -23
  20. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/compile/cli.py +25 -6
  21. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/deps/cli.py +7 -2
  22. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/experimental.py +2 -2
  23. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/install.py +16 -16
  24. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/__init__.py +151 -22
  25. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/outdated.py +57 -6
  26. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/pack.py +79 -5
  27. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/publish.py +34 -34
  28. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/self_update.py +87 -26
  29. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/update.py +203 -28
  30. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/agents_compiler.py +215 -13
  31. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/claude_formatter.py +14 -7
  32. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/distributed_compiler.py +241 -26
  33. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/apm_yml.py +1 -0
  34. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/auth.py +213 -28
  35. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/build_orchestrator.py +2 -0
  36. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/experimental.py +20 -0
  37. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/safe_installer.py +2 -0
  38. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/target_detection.py +64 -5
  39. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/apm_resolver.py +155 -43
  40. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/download_strategies.py +263 -57
  41. apm_cli-0.20.0/src/apm_cli/deps/git_file_transport.py +246 -0
  42. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/git_reference_resolver.py +18 -3
  43. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/git_remote_ops.py +24 -3
  44. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/github_downloader.py +22 -4
  45. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/github_downloader_validation.py +5 -1
  46. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/host_backends.py +18 -6
  47. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/lockfile.py +64 -5
  48. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/path_anchoring.py +4 -4
  49. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/plugin_parser.py +123 -15
  50. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/client.py +9 -9
  51. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/extractor.py +7 -33
  52. apm_cli-0.20.0/src/apm_cli/deps/revision_pins.py +262 -0
  53. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/factory.py +4 -0
  54. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/drift.py +19 -2
  55. apm_cli-0.20.0/src/apm_cli/install/manifest_reconcile.py +112 -0
  56. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/local_content.py +116 -20
  57. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/lockfile.py +66 -10
  58. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/post_deps_local.py +17 -3
  59. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/targets.py +297 -266
  60. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/services.py +88 -4
  61. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/validation.py +8 -1
  62. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/base_integrator.py +7 -1
  63. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/hook_integrator.py +170 -5
  64. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/instruction_integrator.py +135 -21
  65. apm_cli-0.20.0/src/apm_cli/integration/kiro_hook_integrator.py +322 -0
  66. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/mcp_integrator.py +24 -3
  67. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/mcp_integrator_install.py +142 -111
  68. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/skill_integrator.py +33 -7
  69. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/targets.py +193 -12
  70. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/builder.py +225 -46
  71. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/client.py +250 -15
  72. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/models.py +48 -4
  73. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/output_mappers.py +118 -55
  74. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/resolver.py +18 -0
  75. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/yml_editor.py +19 -22
  76. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/yml_schema.py +122 -17
  77. apm_cli-0.20.0/src/apm_cli/models/dependency/identity.py +112 -0
  78. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/dependency/mcp.py +29 -1
  79. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/dependency/reference.py +160 -46
  80. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/dependency/types.py +2 -1
  81. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/policy_checks.py +1 -0
  82. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/registry/operations.py +47 -18
  83. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/skillspector.py +18 -5
  84. apm_cli-0.20.0/src/apm_cli/utils/archive.py +380 -0
  85. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/github_host.py +24 -5
  86. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/version_checker.py +66 -21
  87. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/yaml_io.py +40 -0
  88. {apm_cli-0.18.0 → apm_cli-0.20.0/src/apm_cli.egg-info}/PKG-INFO +4 -4
  89. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli.egg-info/SOURCES.txt +10 -0
  90. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_apm_resolver.py +141 -1
  91. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_github_downloader.py +123 -41
  92. apm_cli-0.20.0/tests/test_gitlab_git_transport.py +663 -0
  93. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_lockfile.py +71 -1
  94. {apm_cli-0.18.0 → apm_cli-0.20.0}/LICENSE +0 -0
  95. {apm_cli-0.18.0 → apm_cli-0.20.0}/NOTICE +0 -0
  96. {apm_cli-0.18.0 → apm_cli-0.20.0}/setup.cfg +0 -0
  97. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/__init__.py +0 -0
  98. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/__init__.py +0 -0
  99. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/__init__.py +0 -0
  100. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
  101. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/cursor.py +0 -0
  102. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/gemini.py +0 -0
  103. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/intellij.py +0 -0
  104. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/opencode.py +0 -0
  105. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
  106. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
  107. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
  108. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
  109. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/bundle/__init__.py +0 -0
  110. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/__init__.py +0 -0
  111. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/git_cache.py +0 -0
  112. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/http_cache.py +0 -0
  113. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/integrity.py +0 -0
  114. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/locking.py +0 -0
  115. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/paths.py +0 -0
  116. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/cache/url_normalize.py +0 -0
  117. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/__init__.py +0 -0
  118. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
  119. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/_helpers.py +0 -0
  120. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/cache.py +0 -0
  121. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/compile/__init__.py +0 -0
  122. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/compile/watcher.py +0 -0
  123. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/config.py +0 -0
  124. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/deps/__init__.py +0 -0
  125. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/deps/_utils.py +0 -0
  126. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/deps/why.py +0 -0
  127. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/doctor.py +0 -0
  128. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/find.py +0 -0
  129. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/init.py +0 -0
  130. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/list_cmd.py +0 -0
  131. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/lock.py +0 -0
  132. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
  133. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/check.py +0 -0
  134. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
  135. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/init.py +0 -0
  136. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
  137. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
  138. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
  139. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
  140. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
  141. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
  142. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/publish.py +0 -0
  143. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
  144. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/mcp.py +0 -0
  145. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
  146. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/plugin/init.py +0 -0
  147. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/policy.py +0 -0
  148. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/prune.py +0 -0
  149. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/run.py +0 -0
  150. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/runtime.py +0 -0
  151. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/targets.py +0 -0
  152. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
  153. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/uninstall/cli.py +0 -0
  154. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/uninstall/engine.py +0 -0
  155. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/commands/view.py +0 -0
  156. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/__init__.py +0 -0
  157. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/build_id.py +0 -0
  158. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/constants.py +0 -0
  159. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/constitution.py +0 -0
  160. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/constitution_block.py +0 -0
  161. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
  162. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
  163. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/injector.py +0 -0
  164. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/link_resolver.py +0 -0
  165. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/managed_section.py +0 -0
  166. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/output_writer.py +0 -0
  167. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/compilation/template_builder.py +0 -0
  168. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/config.py +0 -0
  169. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/constants.py +0 -0
  170. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/__init__.py +0 -0
  171. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/azure_cli.py +0 -0
  172. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/command_logger.py +0 -0
  173. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/conflict_detector.py +0 -0
  174. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/docker_args.py +0 -0
  175. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/errors.py +0 -0
  176. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/install_audit.py +0 -0
  177. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/null_logger.py +0 -0
  178. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/operations.py +0 -0
  179. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/plugin_manifest.py +0 -0
  180. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/scope.py +0 -0
  181. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/script_runner.py +0 -0
  182. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/core/token_manager.py +0 -0
  183. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/__init__.py +0 -0
  184. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/_shared.py +0 -0
  185. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/aggregator.py +0 -0
  186. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
  187. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
  188. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/bare_cache.py +0 -0
  189. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/clone_engine.py +0 -0
  190. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/dependency_graph.py +0 -0
  191. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/git_auth_env.py +0 -0
  192. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
  193. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/installed_package.py +0 -0
  194. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/outdated_row.py +0 -0
  195. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/package_validator.py +0 -0
  196. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/__init__.py +0 -0
  197. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/auth.py +0 -0
  198. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
  199. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
  200. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/outdated.py +0 -0
  201. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/resolver.py +0 -0
  202. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry/semver.py +0 -0
  203. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/registry_proxy.py +0 -0
  204. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
  205. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
  206. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/transport_selection.py +0 -0
  207. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/verifier.py +0 -0
  208. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/deps/why_walker.py +0 -0
  209. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/drift.py +0 -0
  210. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/__init__.py +0 -0
  211. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
  212. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/cache_pin.py +0 -0
  213. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/context.py +0 -0
  214. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/errors.py +0 -0
  215. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
  216. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/heals/__init__.py +0 -0
  217. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/heals/base.py +0 -0
  218. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
  219. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
  220. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/helpers/__init__.py +0 -0
  221. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
  222. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/insecure_policy.py +0 -0
  223. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
  224. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/lsp/__init__.py +0 -0
  225. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/lsp/integration.py +0 -0
  226. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/__init__.py +0 -0
  227. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/args.py +0 -0
  228. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/command.py +0 -0
  229. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
  230. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/entry.py +0 -0
  231. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/registry.py +0 -0
  232. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/warnings.py +0 -0
  233. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/mcp/writer.py +0 -0
  234. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/package_resolution.py +0 -0
  235. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/package_selection.py +0 -0
  236. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/__init__.py +0 -0
  237. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/_redownload.py +0 -0
  238. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
  239. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/audit.py +0 -0
  240. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/cleanup.py +0 -0
  241. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/download.py +0 -0
  242. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/finalize.py +0 -0
  243. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/heal.py +0 -0
  244. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/integrate.py +0 -0
  245. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
  246. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
  247. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/phases/resolve.py +0 -0
  248. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/pipeline.py +0 -0
  249. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/plan.py +0 -0
  250. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/presentation/__init__.py +0 -0
  251. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
  252. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/registry_wiring.py +0 -0
  253. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/request.py +0 -0
  254. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/root_redirect.py +0 -0
  255. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/service.py +0 -0
  256. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/skill_path_migration.py +0 -0
  257. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/sources.py +0 -0
  258. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/summary.py +0 -0
  259. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/install/template.py +0 -0
  260. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/__init__.py +0 -0
  261. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/_shared.py +0 -0
  262. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/agent_integrator.py +0 -0
  263. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/cleanup.py +0 -0
  264. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/command_integrator.py +0 -0
  265. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
  266. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
  267. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
  268. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
  269. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
  270. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/coverage.py +0 -0
  271. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/dispatch.py +0 -0
  272. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
  273. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
  274. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
  275. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/skill_transformer.py +0 -0
  276. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/integration/utils.py +0 -0
  277. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/__init__.py +0 -0
  278. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
  279. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/_io.py +0 -0
  280. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/_shared.py +0 -0
  281. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/audit.py +0 -0
  282. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
  283. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/drift_check.py +0 -0
  284. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/errors.py +0 -0
  285. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
  286. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/init_template.py +0 -0
  287. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/migration.py +0 -0
  288. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
  289. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/pr_integration.py +0 -0
  290. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/publisher.py +0 -0
  291. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
  292. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/registry.py +0 -0
  293. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/semver.py +0 -0
  294. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
  295. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
  296. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/validator.py +0 -0
  297. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/version_check.py +0 -0
  298. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/version_pins.py +0 -0
  299. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
  300. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/__init__.py +0 -0
  301. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/apm_package.py +0 -0
  302. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/dependency/__init__.py +0 -0
  303. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/dependency/lsp.py +0 -0
  304. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/format_detection.py +0 -0
  305. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/plugin.py +0 -0
  306. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/results.py +0 -0
  307. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/models/validation.py +0 -0
  308. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/output/__init__.py +0 -0
  309. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/output/formatters.py +0 -0
  310. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/output/models.py +0 -0
  311. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/output/script_formatters.py +0 -0
  312. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/__init__.py +0 -0
  313. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
  314. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/_help_text.py +0 -0
  315. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/_shared.py +0 -0
  316. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/ci_checks.py +0 -0
  317. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/discovery.py +0 -0
  318. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/inheritance.py +0 -0
  319. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/install_preflight.py +0 -0
  320. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/matcher.py +0 -0
  321. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/models.py +0 -0
  322. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/outcome_routing.py +0 -0
  323. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/parser.py +0 -0
  324. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/project_config.py +0 -0
  325. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/policy/schema.py +0 -0
  326. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/primitives/__init__.py +0 -0
  327. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/primitives/discovery.py +0 -0
  328. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/primitives/models.py +0 -0
  329. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/primitives/parser.py +0 -0
  330. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/registry/__init__.py +0 -0
  331. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/registry/client.py +0 -0
  332. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/registry/integration.py +0 -0
  333. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/__init__.py +0 -0
  334. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/base.py +0 -0
  335. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
  336. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
  337. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/factory.py +0 -0
  338. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
  339. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/manager.py +0 -0
  340. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/runtime/utils.py +0 -0
  341. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/__init__.py +0 -0
  342. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/audit_report.py +0 -0
  343. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/content_scanner.py +0 -0
  344. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/__init__.py +0 -0
  345. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/base.py +0 -0
  346. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/gate.py +0 -0
  347. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
  348. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/options.py +0 -0
  349. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/registry.py +0 -0
  350. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/runner.py +0 -0
  351. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
  352. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/file_scanner.py +0 -0
  353. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/security/gate.py +0 -0
  354. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/update_policy.py +0 -0
  355. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/__init__.py +0 -0
  356. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/atomic_io.py +0 -0
  357. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/console.py +0 -0
  358. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/content_hash.py +0 -0
  359. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/diagnostics.py +0 -0
  360. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/exclude.py +0 -0
  361. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/file_ops.py +0 -0
  362. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/git_env.py +0 -0
  363. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/git_sparse.py +0 -0
  364. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/guards.py +0 -0
  365. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/helpers.py +0 -0
  366. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/install_tui.py +0 -0
  367. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/normalization.py +0 -0
  368. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/path_security.py +0 -0
  369. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/paths.py +0 -0
  370. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/patterns.py +0 -0
  371. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/perf_stats.py +0 -0
  372. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/reflink.py +0 -0
  373. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/short_sha.py +0 -0
  374. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/utils/subprocess_env.py +0 -0
  375. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/version.py +0 -0
  376. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/workflow/__init__.py +0 -0
  377. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/workflow/discovery.py +0 -0
  378. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/workflow/parser.py +0 -0
  379. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli/workflow/runner.py +0 -0
  380. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
  381. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
  382. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli.egg-info/requires.txt +0 -0
  383. {apm_cli-0.18.0 → apm_cli-0.20.0}/src/apm_cli.egg-info/top_level.txt +0 -0
  384. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_apm_package_models.py +0 -0
  385. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_codex_docker_args_fix.py +0 -0
  386. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
  387. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_collision_integration.py +0 -0
  388. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_console.py +0 -0
  389. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_distributed_compilation.py +0 -0
  390. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_empty_string_and_defaults.py +0 -0
  391. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_enhanced_discovery.py +0 -0
  392. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_github_downloader_token_precedence.py +0 -0
  393. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_runnable_prompts.py +0 -0
  394. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_runtime_manager_token_precedence.py +0 -0
  395. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_token_manager.py +0 -0
  396. {apm_cli-0.18.0 → apm_cli-0.20.0}/tests/test_virtual_package_multi_install.py +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  * Daniel Meppiel (@danielmeppiel) — Microsoft
6
6
  * Sergio Sisternes (@sergio-sisternes-epam) — EPAM Systems
7
+ * Nadav Yogev (@nadav-y) — JFrog
7
8
 
8
9
  Maintainers' work on APM is supported by their employers. Project
9
10
  decisions are made in the interest of APM and its users, independent
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apm-cli
3
- Version: 0.18.0
3
+ Version: 0.20.0
4
4
  Summary: MCP configuration tool
5
5
  Author-email: Daniel Meppiel <user@example.com>
6
6
  License: MIT License
@@ -72,7 +72,7 @@ Dynamic: license-file
72
72
 
73
73
  Think `package.json`, `requirements.txt`, or `Cargo.toml` — but for AI agent configuration.
74
74
 
75
- GitHub Copilot · Claude Code · Cursor · OpenCode · Codex · Gemini · Windsurf
75
+ GitHub Copilot · Claude Code · Cursor · OpenCode · Codex · Gemini · Windsurf · Kiro
76
76
 
77
77
  **[Documentation](https://microsoft.github.io/apm/)** · **[Quick Start](https://microsoft.github.io/apm/getting-started/quick-start/)** · **[CLI Reference](https://microsoft.github.io/apm/reference/cli-commands/)** · **[Roadmap](https://github.com/orgs/microsoft/projects/2304)**
78
78
 
@@ -135,7 +135,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
135
135
 
136
136
  One `apm.yml` describes every primitive your agents need — instructions, skills, prompts, agents, hooks, plugins, MCP servers — and `apm install` reproduces the exact same setup across every client on every machine. `apm.lock.yaml` pins the resolved tree the way `package-lock.json` does for npm.
137
137
 
138
- - **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf
138
+ - **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf, Kiro
139
139
  - **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, Gitea, Gogs, any git host
140
140
  - **[Transitive dependencies](https://microsoft.github.io/apm/guides/dependencies/)** — packages can depend on packages; APM resolves the full tree
141
141
  - **[Author plugins](https://microsoft.github.io/apm/guides/plugins/)** — build Copilot, Claude, and Cursor plugins with dependency management, then export standard `plugin.json`
@@ -214,7 +214,7 @@ apm marketplace add github/awesome-copilot
214
214
  apm install azure-cloud-development@awesome-copilot
215
215
  ```
216
216
 
217
- Or add an MCP server (wired into Copilot, Claude, Cursor, Codex, OpenCode, Gemini, and Windsurf):
217
+ Or add an MCP server (wired into Copilot, Claude, Cursor, Codex, OpenCode, Gemini, Windsurf, and Kiro):
218
218
 
219
219
  ```bash
220
220
  apm install --mcp io.github.github/github-mcp-server --transport http # connects over HTTPS
@@ -4,7 +4,7 @@
4
4
 
5
5
  Think `package.json`, `requirements.txt`, or `Cargo.toml` — but for AI agent configuration.
6
6
 
7
- GitHub Copilot · Claude Code · Cursor · OpenCode · Codex · Gemini · Windsurf
7
+ GitHub Copilot · Claude Code · Cursor · OpenCode · Codex · Gemini · Windsurf · Kiro
8
8
 
9
9
  **[Documentation](https://microsoft.github.io/apm/)** · **[Quick Start](https://microsoft.github.io/apm/getting-started/quick-start/)** · **[CLI Reference](https://microsoft.github.io/apm/reference/cli-commands/)** · **[Roadmap](https://github.com/orgs/microsoft/projects/2304)**
10
10
 
@@ -67,7 +67,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
67
67
 
68
68
  One `apm.yml` describes every primitive your agents need — instructions, skills, prompts, agents, hooks, plugins, MCP servers — and `apm install` reproduces the exact same setup across every client on every machine. `apm.lock.yaml` pins the resolved tree the way `package-lock.json` does for npm.
69
69
 
70
- - **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf
70
+ - **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf, Kiro
71
71
  - **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, Gitea, Gogs, any git host
72
72
  - **[Transitive dependencies](https://microsoft.github.io/apm/guides/dependencies/)** — packages can depend on packages; APM resolves the full tree
73
73
  - **[Author plugins](https://microsoft.github.io/apm/guides/plugins/)** — build Copilot, Claude, and Cursor plugins with dependency management, then export standard `plugin.json`
@@ -146,7 +146,7 @@ apm marketplace add github/awesome-copilot
146
146
  apm install azure-cloud-development@awesome-copilot
147
147
  ```
148
148
 
149
- Or add an MCP server (wired into Copilot, Claude, Cursor, Codex, OpenCode, Gemini, and Windsurf):
149
+ Or add an MCP server (wired into Copilot, Claude, Cursor, Codex, OpenCode, Gemini, Windsurf, and Kiro):
150
150
 
151
151
  ```bash
152
152
  apm install --mcp io.github.github/github-mcp-server --transport http # connects over HTTPS
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "apm-cli"
7
- version = "0.18.0"
7
+ version = "0.20.0"
8
8
  description = "MCP configuration tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -4,7 +4,7 @@ import os
4
4
  import re
5
5
  from abc import ABC, abstractmethod
6
6
  from pathlib import Path
7
- from typing import ClassVar
7
+ from typing import Any, ClassVar
8
8
 
9
9
  from ...utils.console import _rich_error, _rich_warning
10
10
 
@@ -29,6 +29,11 @@ _ENV_PLACEHOLDER_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>|" + _ENV_VAR_RE.pattern)
29
29
  _LEGACY_ANGLE_VAR_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>")
30
30
 
31
31
 
32
+ def registry_field_is_required(field: dict[str, Any]) -> bool:
33
+ """Return True unless registry metadata explicitly marks a field optional."""
34
+ return field.get("required", field.get("is_required", True)) is not False
35
+
36
+
32
37
  def _translate_env_placeholder(value):
33
38
  """Pure-textual translation of env-var placeholders to the canonical
34
39
  ``${VAR}`` runtime-substitution syntax.
@@ -481,7 +486,7 @@ class MCPClientAdapter(ABC):
481
486
  name = env_var.get("name", "")
482
487
  if not name:
483
488
  continue
484
- required = env_var.get("required", True)
489
+ required = registry_field_is_required(env_var)
485
490
 
486
491
  value = env_overrides.get(name) or os.getenv(name)
487
492
  if not value and required and not skip_prompting:
@@ -633,22 +638,25 @@ class MCPClientAdapter(ABC):
633
638
  return server_info
634
639
 
635
640
  @staticmethod
636
- def _determine_config_key(server_url: str, server_name: str) -> str:
641
+ def _determine_config_key(server_url: str, server_name: str | None) -> str:
637
642
  """Return the configuration key to use for *server_url*/*server_name*.
638
643
 
639
- The caller-supplied *server_name* takes precedence; if empty the last
640
- path segment of *server_url* is used as a fallback, which mirrors the
641
- convention ``owner/repo -> repo``.
644
+ The caller-supplied *server_name* takes precedence. If it is absent,
645
+ preserve npm-style scoped names such as ``@scope/name`` (one slash by
646
+ npm convention) while keeping the historical ``owner/repo -> repo``
647
+ fallback for registry paths.
642
648
 
643
649
  Args:
644
650
  server_url: Registry reference used as fallback source.
645
- server_name: Explicit caller-supplied name (may be empty string).
651
+ server_name: Explicit caller-supplied name, if any.
646
652
 
647
653
  Returns:
648
654
  Non-empty configuration key string.
649
655
  """
650
656
  if server_name:
651
657
  return server_name
658
+ if server_url.startswith("@") and server_url.count("/") == 1:
659
+ return server_url
652
660
  if "/" in server_url:
653
661
  return server_url.split("/")[-1]
654
662
  return server_url
@@ -794,12 +802,15 @@ class MCPClientAdapter(ABC):
794
802
  )
795
803
 
796
804
  # First pass: identify variables with empty values to warn the user.
797
- empty_value_vars = [ev for ev in env_vars if ev.get("required") and not ev.get("value")]
805
+ empty_value_vars = [
806
+ ev for ev in env_vars if registry_field_is_required(ev) and not ev.get("value")
807
+ ]
798
808
  if empty_value_vars and skip_prompting:
799
809
  var_names = [ev.get("name") for ev in empty_value_vars]
800
810
  _rich_warning(
801
- f"Warning: The following required environment variables have no default "
802
- f"value and cannot be prompted in non-interactive mode: {var_names}"
811
+ f"Required environment variables have no default value and cannot be "
812
+ f"prompted in non-interactive mode: {var_names}. Set them in your "
813
+ "environment and rerun `apm install`."
803
814
  )
804
815
 
805
816
  for env_var in env_vars:
@@ -834,9 +845,9 @@ class MCPClientAdapter(ABC):
834
845
 
835
846
  # Priority 4: interactive prompt
836
847
  default_value = env_var.get("value", "")
837
- required = env_var.get("required", False)
848
+ required = registry_field_is_required(env_var)
838
849
 
839
- if not skip_prompting:
850
+ if not skip_prompting and required:
840
851
  from rich.prompt import Prompt
841
852
 
842
853
  description = env_var.get("description", "")
@@ -856,11 +867,10 @@ class MCPClientAdapter(ABC):
856
867
  resolved[name] = default_value
857
868
  elif required:
858
869
  _rich_warning(
859
- f"Warning: Required environment variable '{name}' could not be resolved. "
860
- f"The MCP server may not function correctly."
870
+ f"Required environment variable '{name}' could not be resolved. "
871
+ f"The MCP server may not function correctly. Set {name} in your "
872
+ "environment and rerun `apm install`."
861
873
  )
862
874
  resolved[name] = ""
863
- else:
864
- resolved[name] = default_value
865
875
 
866
876
  return resolved
@@ -239,12 +239,7 @@ class ClaudeClientAdapter(CopilotClientAdapter):
239
239
  _rich_error(f"MCP server '{server_url}' not found in registry")
240
240
  return False
241
241
 
242
- if server_name:
243
- config_key = server_name
244
- elif "/" in server_url:
245
- config_key = server_url.split("/")[-1]
246
- else:
247
- config_key = server_url
242
+ config_key = self._determine_config_key(server_url, server_name)
248
243
 
249
244
  server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
250
245
  ok = self.update_config({config_key: server_config})
@@ -150,19 +150,7 @@ class CodexClientAdapter(MCPClientAdapter):
150
150
  if server_info is None:
151
151
  return False
152
152
 
153
- # Determine the server name for configuration key
154
- if server_name:
155
- # Use explicitly provided server name
156
- config_key = server_name
157
- else: # noqa: PLR5501
158
- # Extract name from server_url (part after last slash)
159
- # For URLs like "microsoft/azure-devops-mcp" -> "azure-devops-mcp"
160
- # For URLs like "github/github-mcp-server" -> "github-mcp-server"
161
- if "/" in server_url: # noqa: SIM108
162
- config_key = server_url.split("/")[-1]
163
- else:
164
- # Fallback to full server_url if no slash
165
- config_key = server_url
153
+ config_key = self._determine_config_key(server_url, server_name)
166
154
 
167
155
  # Generate server configuration with environment variable resolution
168
156
  server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
@@ -26,6 +26,7 @@ from .base import (
26
26
  _extract_legacy_angle_vars,
27
27
  _has_env_placeholder,
28
28
  _stringify_env_literal,
29
+ registry_field_is_required,
29
30
  )
30
31
  from .base import (
31
32
  _translate_env_placeholder as _translate_env_placeholder,
@@ -206,19 +207,7 @@ class CopilotClientAdapter(MCPClientAdapter):
206
207
  # Generate server configuration with environment and runtime variable resolution
207
208
  server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
208
209
 
209
- # Determine the server name for configuration key
210
- if server_name:
211
- # Use explicitly provided server name
212
- config_key = server_name
213
- else: # noqa: PLR5501
214
- # Extract name from server_url (part after last slash)
215
- # For URLs like "microsoft/azure-devops-mcp" -> "azure-devops-mcp"
216
- # For URLs like "github/github-mcp-server" -> "github-mcp-server"
217
- if "/" in server_url: # noqa: SIM108
218
- config_key = server_url.split("/")[-1]
219
- else:
220
- # Fallback to full server_url if no slash
221
- config_key = server_url
210
+ config_key = self._determine_config_key(server_url, server_name)
222
211
 
223
212
  # Update configuration using the chosen key
224
213
  self.update_config({config_key: server_config})
@@ -710,6 +699,7 @@ class CopilotClientAdapter(MCPClientAdapter):
710
699
  return translated
711
700
 
712
701
  if self._supports_runtime_env_substitution:
702
+ env_overrides = env_overrides or {}
713
703
  resolved = {}
714
704
  placeholder_keys = []
715
705
  for env_var in env_vars:
@@ -718,12 +708,18 @@ class CopilotClientAdapter(MCPClientAdapter):
718
708
  name = env_var.get("name", "")
719
709
  if not name:
720
710
  continue
711
+ required = registry_field_is_required(env_var)
712
+ override_value = env_overrides.get(name)
713
+ has_override = bool(
714
+ override_value.strip() if isinstance(override_value, str) else override_value
715
+ )
721
716
  if name in default_github_env:
722
717
  # Non-secret literal default -- preserve as-is.
723
718
  resolved[name] = default_github_env[name]
724
- else:
719
+ elif required or has_override:
725
720
  # Emit a runtime-substitution placeholder; APM never reads
726
- # or stores the value.
721
+ # or stores the value. Optional variables are included only
722
+ # when install-time collection observed a value.
727
723
  resolved[name] = self._format_runtime_env_placeholder(name)
728
724
  placeholder_keys.append(name)
729
725
  # Record for the post-install summary line and the
@@ -0,0 +1,210 @@
1
+ """Hermes agent MCP client adapter.
2
+
3
+ Hermes (Nous Research) reads MCP servers from a YAML ``mcp_servers:`` block
4
+ in ``~/.hermes/config.yaml`` (snake_case key -- distinct from the JSON
5
+ ``mcpServers`` schema used by Claude/Copilot). ``$HERMES_HOME`` overrides
6
+ the home directory (default ``~/.hermes``).
7
+
8
+ Scope: Hermes has a single home-directory config, so MCP writes are always
9
+ user-scope -- ``config.yaml`` is the same file regardless of whether the
10
+ install was triggered at project or user scope. Unrelated top-level config
11
+ keys (model provider, telegram settings, ...) are preserved on every write;
12
+ a malformed existing file is left untouched rather than overwritten.
13
+
14
+ Per-server shape:
15
+ * stdio -> ``command`` / ``args`` / ``env`` (+ ``enabled``)
16
+ * http -> ``url`` / ``headers`` (+ ``enabled``)
17
+
18
+ YAML serialization goes through ``utils.yaml_io`` (lint forbids raw
19
+ ``yaml.dump``); the document is written atomically with ``0o600`` perms via
20
+ ``utils.atomic_io`` because ``config.yaml`` carries literal credentials.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import contextlib
26
+ import os
27
+ from pathlib import Path
28
+
29
+ import yaml
30
+
31
+ from ...utils.atomic_io import atomic_write_text
32
+ from ...utils.console import _rich_error, _rich_success
33
+ from ...utils.yaml_io import load_yaml, yaml_to_str
34
+ from .copilot import CopilotClientAdapter
35
+
36
+ # Credential-bearing config file mode: owner read/write only. Hermes' config.yaml
37
+ # holds literal MCP env values plus native model-provider keys / messaging tokens,
38
+ # so it must never be group/world-readable (parity with claude/codex/gemini/cursor).
39
+ _CONFIG_FILE_MODE = 0o600
40
+
41
+
42
+ class _MalformedHermesConfig(Exception):
43
+ """Raised when ``config.yaml`` exists but is not a YAML mapping.
44
+
45
+ Signals write paths to refuse the overwrite so a user's native Hermes
46
+ credentials (model-provider keys, Telegram tokens) are never discarded.
47
+ """
48
+
49
+
50
+ class HermesClientAdapter(CopilotClientAdapter):
51
+ """MCP configuration for the Hermes agent (YAML ``mcp_servers`` schema).
52
+
53
+ Registry formatting reuses :class:`CopilotClientAdapter`, then entries are
54
+ converted to Hermes' on-disk shape via :meth:`_to_hermes_format`.
55
+ """
56
+
57
+ supports_user_scope: bool = True
58
+ target_name: str = "hermes"
59
+ mcp_servers_key: str = "mcp_servers"
60
+
61
+ # Hermes' config.yaml does NOT support runtime env-var substitution; the
62
+ # value in ``env`` must be a literal string, so install-time resolution
63
+ # is kept (mirrors Claude -- see #1152 supply-chain analysis).
64
+ _supports_runtime_env_substitution: bool = False
65
+
66
+ def _config_path(self) -> Path:
67
+ """Resolve ``<hermes-home>/config.yaml`` honouring ``$HERMES_HOME``."""
68
+ from ...integration.targets import resolve_hermes_root
69
+
70
+ return resolve_hermes_root() / "config.yaml"
71
+
72
+ @staticmethod
73
+ def _to_hermes_format(copilot_entry: dict, *, enabled: bool = True) -> dict:
74
+ """Convert a Copilot-format server entry to Hermes' on-disk shape.
75
+
76
+ Drops Copilot-CLI-only fields (``type: "local"``, default
77
+ ``tools: ["*"]``, empty ``id``) and stamps an explicit ``enabled``.
78
+ Required transport fields (``url`` for remote, ``command`` for stdio)
79
+ are only emitted when truthy so a malformed entry never serializes as
80
+ ``url: null`` / ``command: null`` into Hermes' config.
81
+ """
82
+ if not isinstance(copilot_entry, dict):
83
+ return copilot_entry
84
+
85
+ url = copilot_entry.get("url")
86
+ t = copilot_entry.get("type")
87
+ is_remote = bool(url) or t in ("http", "sse", "streamable-http")
88
+
89
+ out: dict = {}
90
+ if is_remote:
91
+ if url:
92
+ out["url"] = url
93
+ headers = copilot_entry.get("headers")
94
+ if headers:
95
+ out["headers"] = headers
96
+ else:
97
+ command = copilot_entry.get("command")
98
+ if command:
99
+ out["command"] = command
100
+ args = copilot_entry.get("args")
101
+ if args:
102
+ out["args"] = list(args)
103
+ env = copilot_entry.get("env")
104
+ if env:
105
+ out["env"] = dict(env)
106
+ out["enabled"] = enabled
107
+ return out
108
+
109
+ def get_config_path(self):
110
+ """Path to the Hermes config file (``<hermes-home>/config.yaml``)."""
111
+ return str(self._config_path())
112
+
113
+ def _load_document(self) -> dict:
114
+ """Load the full ``config.yaml`` document (preserving siblings).
115
+
116
+ Returns ``{}`` when the file is absent or empty. Raises
117
+ :class:`_MalformedHermesConfig` when the file exists but is not a YAML
118
+ mapping (parse error or non-dict root) so write paths can refuse to
119
+ overwrite and silently discard the user's native Hermes credentials.
120
+ """
121
+ path = self._config_path()
122
+ if not path.is_file():
123
+ return {}
124
+ try:
125
+ data = load_yaml(path)
126
+ except (OSError, yaml.YAMLError) as exc:
127
+ raise _MalformedHermesConfig(str(path)) from exc
128
+ if data is None:
129
+ return {}
130
+ if not isinstance(data, dict):
131
+ raise _MalformedHermesConfig(str(path))
132
+ return data
133
+
134
+ def get_current_config(self):
135
+ """Return ``{"mcp_servers": {...}}`` for the on-disk config."""
136
+ try:
137
+ data = self._load_document()
138
+ except _MalformedHermesConfig:
139
+ return {self.mcp_servers_key: {}}
140
+ servers = data.get(self.mcp_servers_key)
141
+ return {self.mcp_servers_key: dict(servers) if isinstance(servers, dict) else {}}
142
+
143
+ def update_config(self, config_updates, enabled=True):
144
+ """Merge *config_updates* into the ``mcp_servers:`` block.
145
+
146
+ Entries are normalized to Hermes' shape. Per-server entries are
147
+ replaced on key conflict; unrelated servers and all other top-level
148
+ config keys are preserved. The file is written atomically with
149
+ ``0o600`` permissions so the credential-bearing config is never left
150
+ group/world-readable. A malformed existing ``config.yaml`` is left
151
+ untouched (returns ``False``) rather than overwritten.
152
+ """
153
+ path = self._config_path()
154
+ try:
155
+ data = self._load_document()
156
+ except _MalformedHermesConfig:
157
+ _rich_error(
158
+ f"{path} is malformed YAML; refusing to overwrite. "
159
+ "Fix or remove the file manually, then retry."
160
+ )
161
+ return False
162
+ try:
163
+ servers = data.get(self.mcp_servers_key)
164
+ if not isinstance(servers, dict):
165
+ servers = {}
166
+ for name, cfg in config_updates.items():
167
+ servers[name] = self._to_hermes_format(cfg, enabled=enabled)
168
+ data[self.mcp_servers_key] = servers
169
+ path.parent.mkdir(parents=True, exist_ok=True)
170
+ atomic_write_text(path, yaml_to_str(data), new_file_mode=_CONFIG_FILE_MODE)
171
+ # Tighten perms even when the file pre-existed with a looser mode
172
+ # (atomic_write_text only applies new_file_mode on first create).
173
+ with contextlib.suppress(OSError, NotImplementedError):
174
+ os.chmod(path, _CONFIG_FILE_MODE)
175
+ return True
176
+ except OSError:
177
+ return False
178
+
179
+ def configure_mcp_server(
180
+ self,
181
+ server_url,
182
+ server_name=None,
183
+ enabled=True,
184
+ env_overrides=None,
185
+ server_info_cache=None,
186
+ runtime_vars=None,
187
+ ):
188
+ if not server_url:
189
+ _rich_error("server_url cannot be empty")
190
+ return False
191
+
192
+ try:
193
+ server_info = self._fetch_server_info(server_url, server_info_cache)
194
+ if server_info is None:
195
+ return False
196
+
197
+ config_key = self._determine_config_key(server_url, server_name)
198
+ server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
199
+ ok = self.update_config({config_key: server_config}, enabled=enabled)
200
+ if not ok:
201
+ _rich_error(f"Failed to write MCP config for '{config_key}' to Hermes")
202
+ return False
203
+
204
+ _rich_success(f"Successfully configured MCP server '{config_key}' for Hermes")
205
+ return True
206
+ except Exception:
207
+ # Do not interpolate the exception message: registry URLs and
208
+ # other inputs may carry embedded credentials.
209
+ _rich_error("Error configuring MCP server")
210
+ return False