apm-cli 0.26.0__tar.gz → 0.27.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.
- {apm_cli-0.26.0/src/apm_cli.egg-info → apm_cli-0.27.0}/PKG-INFO +1 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/pyproject.toml +1 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/base.py +574 -6
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/codex.py +24 -7
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/copilot.py +54 -17
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/gemini.py +5 -7
- apm_cli-0.27.0/src/apm_cli/adapters/client/intellij.py +281 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/vscode.py +411 -124
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cli.py +1 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/audit.py +45 -11
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/install.py +103 -64
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/lock.py +7 -6
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/check.py +7 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/outdated.py +5 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/policy.py +10 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/self_update.py +90 -40
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/uninstall/cli.py +145 -40
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/uninstall/engine.py +392 -66
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/uninstall/lockfile_state.py +16 -2
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/update.py +105 -17
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/link_resolver.py +8 -11
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/apm_yml.py +19 -16
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/auth.py +448 -64
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/deployment_ledger.py +45 -3
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/host_providers.py +22 -3
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/operations.py +8 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/safe_installer.py +3 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/scope.py +5 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/target_detection.py +178 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/apm_resolver.py +37 -9
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/bare_cache.py +8 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/clone_engine.py +126 -30
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/dependency_graph.py +9 -9
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/download_strategies.py +268 -36
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/git_auth_env.py +14 -8
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/git_reference_resolver.py +142 -37
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/github_downloader.py +134 -10
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/github_downloader_validation.py +166 -30
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/host_backends.py +6 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/lockfile.py +80 -17
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/tiered_ref_resolver.py +101 -9
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/drift.py +9 -0
- apm_cli-0.27.0/src/apm_cli/install/audit_replay.py +112 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/context.py +4 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/drift.py +251 -148
- apm_cli-0.27.0/src/apm_cli/install/drift_render.py +100 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/errors.py +4 -0
- apm_cli-0.27.0/src/apm_cli/install/helpers/no_work.py +34 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/helpers/ref_reuse.py +11 -3
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/helpers/ref_seed.py +4 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/lsp/integration.py +36 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/manifest_reconcile.py +74 -2
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/command.py +75 -7
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/integration.py +78 -16
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/ownership.py +22 -2
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/outcome.py +1 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/cleanup.py +4 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/lockfile.py +37 -5
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/post_deps_local.py +3 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/resolve.py +139 -43
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/targets.py +27 -36
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/pipeline.py +62 -65
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/request.py +4 -1
- apm_cli-0.27.0/src/apm_cli/install/resolution_staging.py +126 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/service.py +64 -5
- apm_cli-0.27.0/src/apm_cli/install/service_integration.py +126 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/services.py +62 -21
- apm_cli-0.27.0/src/apm_cli/install/target_filter.py +131 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/validation.py +55 -17
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/base_integrator.py +8 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/cleanup.py +9 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/hook_bundle.py +23 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/hook_integrator.py +238 -252
- apm_cli-0.27.0/src/apm_cli/integration/hook_ownership.py +296 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/lsp_integrator.py +69 -10
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/mcp_config_view.py +88 -7
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/mcp_integrator.py +140 -47
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/mcp_integrator_install.py +365 -89
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/targets.py +25 -2
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/auth_helpers.py +1 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/builder.py +30 -2
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/client.py +45 -12
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/models.py +29 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/output_mappers.py +12 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/ref_resolver.py +51 -23
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/resolver.py +57 -37
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/tag_pattern.py +33 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/version_resolver.py +15 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/yml_schema.py +7 -6
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/apm_package.py +12 -15
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/identity.py +29 -9
- apm_cli-0.27.0/src/apm_cli/models/dependency/materialization.py +351 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/reference.py +62 -117
- apm_cli-0.27.0/src/apm_cli/models/dependency/selection.py +105 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/results.py +7 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/ci_checks.py +91 -46
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/discovery.py +181 -40
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/registry/operations.py +46 -19
- apm_cli-0.27.0/src/apm_cli/security/file_scanner.py +238 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/gate.py +22 -6
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/atomic_io.py +8 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/github_host.py +220 -9
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/paths.py +16 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/version_checker.py +1 -4
- {apm_cli-0.26.0 → apm_cli-0.27.0/src/apm_cli.egg-info}/PKG-INFO +1 -1
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli.egg-info/SOURCES.txt +7 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_apm_package_models.py +6 -5
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_codex_docker_args_fix.py +13 -7
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_lockfile.py +5 -0
- apm_cli-0.26.0/src/apm_cli/adapters/client/intellij.py +0 -104
- apm_cli-0.26.0/src/apm_cli/install/resolution_staging.py +0 -59
- apm_cli-0.26.0/src/apm_cli/install/target_filter.py +0 -33
- apm_cli-0.26.0/src/apm_cli/security/file_scanner.py +0 -89
- {apm_cli-0.26.0 → apm_cli-0.27.0}/AUTHORS +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/LICENSE +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/NOTICE +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/README.md +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/setup.cfg +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/cursor.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/kiro.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/attest.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/plugin_exporter.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/bundle/unpacker.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/_helpers.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/approve.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/compile/cli.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/deps/cli.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/doctor.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/init.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/lifecycle.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/pack.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/prune.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/publish.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/compilation/user_root_context.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/_child_tls/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/_child_tls/_apm_tls.pth +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/deployment_state.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/errors.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/experimental.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/output_mode.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/script_executors.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/script_runner.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/script_trust.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/target_catalog.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/tls_trust.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/github_rate_limit.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/reachability.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/extractor.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/outdated.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/resolver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/authoring.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/declared_license.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/formats.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/purl.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/sbom.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/spdx.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/export/spdx_data.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/deployed_paths.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/exec_gate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/integrity.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/local_bundle_handler.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/package_resolution.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/finalize.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/integrate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/plan.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/registry_wiring.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/sources.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/target_warnings.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/template.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/install/transaction.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/_hook_dropped_targets.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/agent_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/hook_ir.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/hook_native_formats.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/instruction_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/skill_integrator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/version_check.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/mcp.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/object_fields.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/provider_coordinates.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/subsets.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/manifest_contract.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/models/validation.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/inheritance.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/matcher.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/models.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/parser.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/policy_checks.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/policy/schema.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/base.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/registry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/executables.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli.egg-info/requires.txt +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_console.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_github_downloader.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.26.0 → apm_cli-0.27.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import re
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
|
+
from dataclasses import dataclass
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import Any, ClassVar
|
|
8
9
|
|
|
@@ -29,6 +30,153 @@ _ENV_PLACEHOLDER_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>|" + _ENV_VAR_RE.pattern)
|
|
|
29
30
|
# deprecation warnings across all servers in a single install run.
|
|
30
31
|
_LEGACY_ANGLE_VAR_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>")
|
|
31
32
|
|
|
33
|
+
# MCP Registry v0.1 names the container registry type ``oci``; the adapters
|
|
34
|
+
# below key their launcher dispatch on ``docker`` (the vocabulary the legacy
|
|
35
|
+
# registry shape used, and what ``_infer_registry_name`` derives from a
|
|
36
|
+
# ``docker`` runtime hint or an image-shaped package name). Without this
|
|
37
|
+
# mapping an ``oci`` package matches no launcher branch and falls through to
|
|
38
|
+
# the generic ``npx`` default, which hands the image reference to npm as a
|
|
39
|
+
# package name -- a dependency-confusion exposure, not just a broken config
|
|
40
|
+
# (#2376). Keyed on the lowercased registry type; unlisted values pass through
|
|
41
|
+
# untouched.
|
|
42
|
+
_REGISTRY_TYPE_ALIASES = {"oci": "docker"}
|
|
43
|
+
_DOCKER_RUN_OPTIONS_WITH_VALUES = frozenset(
|
|
44
|
+
{
|
|
45
|
+
"--add-host",
|
|
46
|
+
"--annotation",
|
|
47
|
+
"--attach",
|
|
48
|
+
"--blkio-weight",
|
|
49
|
+
"--blkio-weight-device",
|
|
50
|
+
"--cap-add",
|
|
51
|
+
"--cap-drop",
|
|
52
|
+
"--cgroup-parent",
|
|
53
|
+
"--cgroupns",
|
|
54
|
+
"--cidfile",
|
|
55
|
+
"--cpu-count",
|
|
56
|
+
"--cpu-percent",
|
|
57
|
+
"--cpu-period",
|
|
58
|
+
"--cpu-quota",
|
|
59
|
+
"--cpu-rt-period",
|
|
60
|
+
"--cpu-rt-runtime",
|
|
61
|
+
"--cpu-shares",
|
|
62
|
+
"--cpus",
|
|
63
|
+
"--cpuset-cpus",
|
|
64
|
+
"--cpuset-mems",
|
|
65
|
+
"--detach-keys",
|
|
66
|
+
"--device",
|
|
67
|
+
"--device-cgroup-rule",
|
|
68
|
+
"--device-read-bps",
|
|
69
|
+
"--device-read-iops",
|
|
70
|
+
"--device-write-bps",
|
|
71
|
+
"--device-write-iops",
|
|
72
|
+
"--dns",
|
|
73
|
+
"--dns-opt",
|
|
74
|
+
"--dns-option",
|
|
75
|
+
"--dns-search",
|
|
76
|
+
"--domainname",
|
|
77
|
+
"--entrypoint",
|
|
78
|
+
"--env",
|
|
79
|
+
"--env-file",
|
|
80
|
+
"--expose",
|
|
81
|
+
"--gpus",
|
|
82
|
+
"--group-add",
|
|
83
|
+
"--health-cmd",
|
|
84
|
+
"--health-interval",
|
|
85
|
+
"--health-retries",
|
|
86
|
+
"--health-start-interval",
|
|
87
|
+
"--health-start-period",
|
|
88
|
+
"--health-timeout",
|
|
89
|
+
"--hostname",
|
|
90
|
+
"--io-maxbandwidth",
|
|
91
|
+
"--io-maxiops",
|
|
92
|
+
"--ip",
|
|
93
|
+
"--ip6",
|
|
94
|
+
"--ipc",
|
|
95
|
+
"--isolation",
|
|
96
|
+
"--kernel-memory",
|
|
97
|
+
"--label",
|
|
98
|
+
"--label-file",
|
|
99
|
+
"--link",
|
|
100
|
+
"--link-local-ip",
|
|
101
|
+
"--log-driver",
|
|
102
|
+
"--log-opt",
|
|
103
|
+
"--mac-address",
|
|
104
|
+
"--memory",
|
|
105
|
+
"--memory-reservation",
|
|
106
|
+
"--memory-swap",
|
|
107
|
+
"--memory-swappiness",
|
|
108
|
+
"--mount",
|
|
109
|
+
"--name",
|
|
110
|
+
"--net",
|
|
111
|
+
"--net-alias",
|
|
112
|
+
"--network",
|
|
113
|
+
"--network-alias",
|
|
114
|
+
"--oom-score-adj",
|
|
115
|
+
"--pid",
|
|
116
|
+
"--pids-limit",
|
|
117
|
+
"--platform",
|
|
118
|
+
"--publish",
|
|
119
|
+
"--pull",
|
|
120
|
+
"--restart",
|
|
121
|
+
"--runtime",
|
|
122
|
+
"--security-opt",
|
|
123
|
+
"--shm-size",
|
|
124
|
+
"--stop-signal",
|
|
125
|
+
"--stop-timeout",
|
|
126
|
+
"--storage-opt",
|
|
127
|
+
"--sysctl",
|
|
128
|
+
"--tmpfs",
|
|
129
|
+
"--ulimit",
|
|
130
|
+
"--user",
|
|
131
|
+
"--userns",
|
|
132
|
+
"--uts",
|
|
133
|
+
"--volume",
|
|
134
|
+
"--volume-driver",
|
|
135
|
+
"--volumes-from",
|
|
136
|
+
"--workdir",
|
|
137
|
+
"-a",
|
|
138
|
+
"-c",
|
|
139
|
+
"-e",
|
|
140
|
+
"-h",
|
|
141
|
+
"-l",
|
|
142
|
+
"-m",
|
|
143
|
+
"-p",
|
|
144
|
+
"-u",
|
|
145
|
+
"-v",
|
|
146
|
+
"-w",
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _docker_image_repository(reference: str) -> str:
|
|
152
|
+
"""Return the repository component of a container image reference.
|
|
153
|
+
|
|
154
|
+
Drops an ``@sha256:...`` digest and a trailing ``:tag`` so that two
|
|
155
|
+
references to the same repository compare equal regardless of how each
|
|
156
|
+
side is pinned. A ``host:port/`` prefix is preserved, since a tag can
|
|
157
|
+
only appear in the final path segment.
|
|
158
|
+
|
|
159
|
+
Docker Hub is also folded to its short form: a registry commonly
|
|
160
|
+
publishes a fully qualified ``identifier`` while the run arguments it
|
|
161
|
+
ships use the implicit spelling, and treating those as different
|
|
162
|
+
repositories would append a second image operand.
|
|
163
|
+
"""
|
|
164
|
+
repository = reference.split("@", 1)[0]
|
|
165
|
+
last_segment = repository.rsplit("/", 1)[-1]
|
|
166
|
+
tag_at = last_segment.find(":")
|
|
167
|
+
if tag_at != -1:
|
|
168
|
+
repository = repository[: len(repository) - len(last_segment) + tag_at]
|
|
169
|
+
for default_registry in ("docker.io/", "index.docker.io/"):
|
|
170
|
+
if repository.startswith(default_registry):
|
|
171
|
+
repository = repository[len(default_registry) :]
|
|
172
|
+
break
|
|
173
|
+
# Only meaningful once the implicit registry is stripped: ``library/`` is
|
|
174
|
+
# where Docker Hub keeps official images, so ``library/redis`` is ``redis``.
|
|
175
|
+
if repository.startswith("library/"):
|
|
176
|
+
repository = repository[len("library/") :]
|
|
177
|
+
return repository
|
|
178
|
+
|
|
179
|
+
|
|
32
180
|
# Config keys that ``_extra`` passthrough must NEVER set on a rendered harness
|
|
33
181
|
# config. Covers the modeled MCP fields (imported single-source from the model)
|
|
34
182
|
# plus harness-specific aliases that mirror a modeled field under a different
|
|
@@ -39,6 +187,14 @@ _LEGACY_ANGLE_VAR_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>")
|
|
|
39
187
|
_EXTRA_DENYLIST = _RESERVED_EXTRA_KEYS | frozenset({"http_headers"})
|
|
40
188
|
|
|
41
189
|
|
|
190
|
+
@dataclass(frozen=True)
|
|
191
|
+
class _MCPLauncherArgumentGroup:
|
|
192
|
+
"""One atomic registry argument and its rendered argv values."""
|
|
193
|
+
|
|
194
|
+
kind: str
|
|
195
|
+
values: tuple[str, ...]
|
|
196
|
+
|
|
197
|
+
|
|
42
198
|
def registry_field_is_required(field: dict[str, Any]) -> bool:
|
|
43
199
|
"""Return True unless registry metadata explicitly marks a field optional."""
|
|
44
200
|
return field.get("required", field.get("is_required", True)) is not False
|
|
@@ -280,13 +436,25 @@ class MCPClientAdapter(ABC):
|
|
|
280
436
|
|
|
281
437
|
Returns:
|
|
282
438
|
str: Inferred registry name (e.g. "npm", "pypi", "docker") or "".
|
|
439
|
+
Spec spellings that name the same registry as an APM launcher
|
|
440
|
+
branch are canonicalized via ``_REGISTRY_TYPE_ALIASES`` (v0.1
|
|
441
|
+
``oci`` -> ``docker``). Malformed explicit values fail closed
|
|
442
|
+
before any package-manager launcher is selected.
|
|
283
443
|
"""
|
|
284
444
|
if not package:
|
|
285
445
|
return ""
|
|
286
446
|
|
|
287
447
|
explicit = package.get("registry_name", "")
|
|
448
|
+
if not isinstance(explicit, str):
|
|
449
|
+
# Registry payloads are untrusted. A malformed explicit value must
|
|
450
|
+
# fail closed rather than miss every launcher branch and reach the
|
|
451
|
+
# generic npx fallback with an untrusted package name.
|
|
452
|
+
raise ValueError("MCP package registry_name must be a string")
|
|
453
|
+
if explicit and not explicit.strip():
|
|
454
|
+
raise ValueError("MCP package registry_name must not be whitespace")
|
|
288
455
|
if explicit:
|
|
289
|
-
|
|
456
|
+
canonical = explicit.strip().lower()
|
|
457
|
+
return _REGISTRY_TYPE_ALIASES.get(canonical, canonical)
|
|
290
458
|
|
|
291
459
|
name = package.get("name", "")
|
|
292
460
|
runtime_hint = package.get("runtime_hint", "")
|
|
@@ -314,6 +482,382 @@ class MCPClientAdapter(ABC):
|
|
|
314
482
|
|
|
315
483
|
return ""
|
|
316
484
|
|
|
485
|
+
def _parse_non_container_argument_groups(
|
|
486
|
+
self,
|
|
487
|
+
arguments: object,
|
|
488
|
+
*,
|
|
489
|
+
resolved_env: dict[str, str] | None = None,
|
|
490
|
+
runtime_vars: dict[str, object] | None = None,
|
|
491
|
+
runtime_variable_fallbacks: dict[str, str] | None = None,
|
|
492
|
+
secret_variable_fallbacks: dict[str, str] | None = None,
|
|
493
|
+
package_name: str = "",
|
|
494
|
+
) -> list[_MCPLauncherArgumentGroup]:
|
|
495
|
+
"""Parse registry arguments without losing named-group boundaries.
|
|
496
|
+
|
|
497
|
+
Typed v0.1 entries read ``value`` while untyped legacy entries read
|
|
498
|
+
``value_hint``. Named arguments remain one atomic group so package
|
|
499
|
+
identity matching cannot confuse a flag value with the package operand.
|
|
500
|
+
Optional groups with unresolved variables are omitted as a whole;
|
|
501
|
+
malformed or unresolved required entries fail closed.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
arguments: Raw ``runtime_arguments`` or ``package_arguments`` value.
|
|
505
|
+
resolved_env: Target-native environment placeholder mapping.
|
|
506
|
+
runtime_vars: Values collected for registry argument variables.
|
|
507
|
+
runtime_variable_fallbacks: Target-native fallbacks for variables
|
|
508
|
+
such as VS Code's ``workspaceFolder``.
|
|
509
|
+
secret_variable_fallbacks: Target-native indirections for secret
|
|
510
|
+
values that must not be written literally.
|
|
511
|
+
package_name: Package identity included in actionable diagnostics.
|
|
512
|
+
|
|
513
|
+
Returns:
|
|
514
|
+
Ordered atomic launcher argument groups.
|
|
515
|
+
|
|
516
|
+
Raises:
|
|
517
|
+
ValueError: If registry argument metadata is malformed or a required
|
|
518
|
+
variable cannot be resolved.
|
|
519
|
+
"""
|
|
520
|
+
if arguments is None:
|
|
521
|
+
return []
|
|
522
|
+
if not isinstance(arguments, list):
|
|
523
|
+
raise ValueError("MCP package arguments must be a list")
|
|
524
|
+
|
|
525
|
+
groups: list[_MCPLauncherArgumentGroup] = []
|
|
526
|
+
for entry in arguments:
|
|
527
|
+
if not isinstance(entry, dict):
|
|
528
|
+
raise ValueError("MCP package argument entries must be objects")
|
|
529
|
+
|
|
530
|
+
raw_type = entry.get("type", "")
|
|
531
|
+
if not isinstance(raw_type, str):
|
|
532
|
+
raise ValueError("MCP package argument type must be a string")
|
|
533
|
+
arg_type = raw_type.strip().lower()
|
|
534
|
+
if arg_type not in ("", "positional", "named"):
|
|
535
|
+
raise ValueError("MCP package argument type must be 'positional' or 'named'")
|
|
536
|
+
|
|
537
|
+
required_marker = entry.get(
|
|
538
|
+
"is_required",
|
|
539
|
+
entry.get("isRequired", entry.get("required")),
|
|
540
|
+
)
|
|
541
|
+
if required_marker is not None and not isinstance(required_marker, bool):
|
|
542
|
+
raise ValueError("MCP package argument required marker must be a boolean")
|
|
543
|
+
required = True if required_marker is None else required_marker
|
|
544
|
+
|
|
545
|
+
variables = entry.get("variables")
|
|
546
|
+
if variables is not None and not isinstance(variables, dict):
|
|
547
|
+
raise ValueError("MCP package argument variables must be an object")
|
|
548
|
+
if not required and "variables" not in entry:
|
|
549
|
+
continue
|
|
550
|
+
|
|
551
|
+
if arg_type:
|
|
552
|
+
raw_value = entry.get("value", entry.get("default"))
|
|
553
|
+
else:
|
|
554
|
+
raw_value = entry.get(
|
|
555
|
+
"value_hint",
|
|
556
|
+
entry.get("value", entry.get("default")),
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
name = entry.get("name")
|
|
560
|
+
if arg_type == "named" and not isinstance(name, str):
|
|
561
|
+
raise ValueError("MCP package argument name must be a string")
|
|
562
|
+
if arg_type == "named" and not name:
|
|
563
|
+
raise ValueError("MCP package argument name must not be empty")
|
|
564
|
+
|
|
565
|
+
if raw_value is None or raw_value == "":
|
|
566
|
+
if arg_type == "named" and name:
|
|
567
|
+
if required:
|
|
568
|
+
groups.append(_MCPLauncherArgumentGroup("named", (name,)))
|
|
569
|
+
elif required:
|
|
570
|
+
raise ValueError(
|
|
571
|
+
f"MCP package argument for '{package_name or 'unknown'}' "
|
|
572
|
+
"is missing a required positional value"
|
|
573
|
+
)
|
|
574
|
+
continue
|
|
575
|
+
if not isinstance(raw_value, str):
|
|
576
|
+
raise ValueError("MCP package argument value must be a string")
|
|
577
|
+
|
|
578
|
+
rendered, unresolved_variable = self._resolve_non_container_argument_value(
|
|
579
|
+
raw_value,
|
|
580
|
+
variables=variables or {},
|
|
581
|
+
resolved_env=resolved_env or {},
|
|
582
|
+
runtime_vars=runtime_vars or {},
|
|
583
|
+
runtime_variable_fallbacks=runtime_variable_fallbacks or {},
|
|
584
|
+
secret_variable_fallbacks=secret_variable_fallbacks or {},
|
|
585
|
+
)
|
|
586
|
+
if rendered is None:
|
|
587
|
+
if required:
|
|
588
|
+
raise ValueError(
|
|
589
|
+
"Could not resolve required MCP package argument variable "
|
|
590
|
+
f"'{unresolved_variable or 'unknown'}' for "
|
|
591
|
+
f"'{package_name or 'unknown'}'"
|
|
592
|
+
)
|
|
593
|
+
continue
|
|
594
|
+
|
|
595
|
+
if arg_type == "named" and name:
|
|
596
|
+
groups.append(_MCPLauncherArgumentGroup("named", (name, rendered)))
|
|
597
|
+
else:
|
|
598
|
+
kind = "positional" if arg_type == "positional" else "legacy"
|
|
599
|
+
groups.append(_MCPLauncherArgumentGroup(kind, (rendered,)))
|
|
600
|
+
return groups
|
|
601
|
+
|
|
602
|
+
def _resolve_non_container_argument_value(
|
|
603
|
+
self,
|
|
604
|
+
template: str,
|
|
605
|
+
*,
|
|
606
|
+
variables: dict[object, object],
|
|
607
|
+
resolved_env: dict[str, str],
|
|
608
|
+
runtime_vars: dict[str, object],
|
|
609
|
+
runtime_variable_fallbacks: dict[str, str],
|
|
610
|
+
secret_variable_fallbacks: dict[str, str],
|
|
611
|
+
) -> tuple[str | None, str | None]:
|
|
612
|
+
"""Resolve one argument value and identify any absent variable."""
|
|
613
|
+
for variable_name, variable_info in variables.items():
|
|
614
|
+
if not isinstance(variable_name, str):
|
|
615
|
+
raise ValueError("MCP package argument variable names must be strings")
|
|
616
|
+
if not isinstance(variable_info, dict):
|
|
617
|
+
raise ValueError("MCP package argument variable metadata must be an object")
|
|
618
|
+
placeholder = f"{{{variable_name}}}"
|
|
619
|
+
if placeholder not in template:
|
|
620
|
+
continue
|
|
621
|
+
secret_marker = variable_info.get(
|
|
622
|
+
"isSecret",
|
|
623
|
+
variable_info.get("is_secret", False),
|
|
624
|
+
)
|
|
625
|
+
if not isinstance(secret_marker, bool):
|
|
626
|
+
raise ValueError("MCP package argument variable isSecret marker must be a boolean")
|
|
627
|
+
if secret_marker:
|
|
628
|
+
replacement = secret_variable_fallbacks.get(variable_name)
|
|
629
|
+
if replacement is None and self._supports_runtime_env_substitution:
|
|
630
|
+
replacement = self._format_runtime_env_placeholder(variable_name)
|
|
631
|
+
else:
|
|
632
|
+
supplied = runtime_vars.get(variable_name)
|
|
633
|
+
if supplied is not None and str(supplied) != "":
|
|
634
|
+
replacement = str(supplied)
|
|
635
|
+
else:
|
|
636
|
+
configured = variable_info.get(
|
|
637
|
+
"value",
|
|
638
|
+
variable_info.get("default"),
|
|
639
|
+
)
|
|
640
|
+
if configured is not None and not isinstance(configured, str):
|
|
641
|
+
raise ValueError("MCP package argument variable value must be a string")
|
|
642
|
+
replacement = configured or runtime_variable_fallbacks.get(variable_name)
|
|
643
|
+
if replacement is None:
|
|
644
|
+
return None, variable_name
|
|
645
|
+
template = template.replace(placeholder, replacement)
|
|
646
|
+
|
|
647
|
+
string_runtime_vars = {
|
|
648
|
+
key: str(value) for key, value in runtime_vars.items() if value is not None
|
|
649
|
+
}
|
|
650
|
+
return (
|
|
651
|
+
self._resolve_variable_placeholders(
|
|
652
|
+
template,
|
|
653
|
+
resolved_env,
|
|
654
|
+
string_runtime_vars,
|
|
655
|
+
),
|
|
656
|
+
None,
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
@staticmethod
|
|
660
|
+
def _processed_non_container_argument_groups(
|
|
661
|
+
arguments: list[object],
|
|
662
|
+
) -> list[_MCPLauncherArgumentGroup]:
|
|
663
|
+
"""Wrap already-processed compatibility inputs as positional groups."""
|
|
664
|
+
return [_MCPLauncherArgumentGroup("legacy", (str(argument),)) for argument in arguments]
|
|
665
|
+
|
|
666
|
+
@staticmethod
|
|
667
|
+
def _flatten_non_container_argument_groups(
|
|
668
|
+
groups: list[_MCPLauncherArgumentGroup],
|
|
669
|
+
) -> list[str]:
|
|
670
|
+
"""Flatten ordered atomic groups without changing their contents."""
|
|
671
|
+
return [value for group in groups for value in group.values]
|
|
672
|
+
|
|
673
|
+
@staticmethod
|
|
674
|
+
def _build_non_container_launcher_argv(
|
|
675
|
+
package_name: str,
|
|
676
|
+
runtime_groups: list[_MCPLauncherArgumentGroup],
|
|
677
|
+
package_groups: list[_MCPLauncherArgumentGroup],
|
|
678
|
+
*,
|
|
679
|
+
launcher_prefix: tuple[str, ...] = (),
|
|
680
|
+
) -> list[str]:
|
|
681
|
+
"""Merge one package identity into a typed non-container launcher argv.
|
|
682
|
+
|
|
683
|
+
Package detection is semantic and type-aware. The first non-option
|
|
684
|
+
typed positional group can satisfy package identity; named groups are
|
|
685
|
+
atomic and their values never count. Untyped legacy runtime argv are
|
|
686
|
+
searched for the identifier because their historical shape carries no
|
|
687
|
+
stronger type signal. Package groups never satisfy launcher identity;
|
|
688
|
+
they are arguments to the package binary. This preserves a legitimate
|
|
689
|
+
flag value equal to the package name while avoiding duplicate package
|
|
690
|
+
operands.
|
|
691
|
+
|
|
692
|
+
Args:
|
|
693
|
+
package_name: Registry package identifier.
|
|
694
|
+
runtime_groups: Ordered runtime argument groups.
|
|
695
|
+
package_groups: Ordered package argument groups appended last.
|
|
696
|
+
launcher_prefix: Default launcher operands preceding the package,
|
|
697
|
+
such as npm's ``-y``.
|
|
698
|
+
|
|
699
|
+
Returns:
|
|
700
|
+
Complete ordered launcher argv.
|
|
701
|
+
|
|
702
|
+
Raises:
|
|
703
|
+
ValueError: If the package identifier is missing or malformed.
|
|
704
|
+
"""
|
|
705
|
+
if not isinstance(package_name, str) or not package_name:
|
|
706
|
+
raise ValueError("MCP package name must be a non-empty string")
|
|
707
|
+
|
|
708
|
+
identity_present = any(
|
|
709
|
+
group.kind == "legacy"
|
|
710
|
+
and len(group.values) == 1
|
|
711
|
+
and MCPClientAdapter._package_identity_matches(
|
|
712
|
+
group.values[0],
|
|
713
|
+
package_name,
|
|
714
|
+
)
|
|
715
|
+
for group in runtime_groups
|
|
716
|
+
)
|
|
717
|
+
for group in runtime_groups:
|
|
718
|
+
if identity_present:
|
|
719
|
+
break
|
|
720
|
+
if group.kind != "positional" or len(group.values) != 1:
|
|
721
|
+
continue
|
|
722
|
+
candidate = group.values[0]
|
|
723
|
+
if candidate in launcher_prefix or candidate.startswith("-"):
|
|
724
|
+
continue
|
|
725
|
+
if MCPClientAdapter._package_identity_matches(candidate, package_name):
|
|
726
|
+
identity_present = True
|
|
727
|
+
break
|
|
728
|
+
|
|
729
|
+
leading_prefix_groups = 0
|
|
730
|
+
for expected, group in zip(launcher_prefix, runtime_groups, strict=False):
|
|
731
|
+
if group.kind == "named" or group.values != (expected,):
|
|
732
|
+
break
|
|
733
|
+
leading_prefix_groups += 1
|
|
734
|
+
has_leading_prefix = leading_prefix_groups == len(launcher_prefix)
|
|
735
|
+
|
|
736
|
+
runtime_values = MCPClientAdapter._flatten_non_container_argument_groups(runtime_groups)
|
|
737
|
+
package_values = MCPClientAdapter._flatten_non_container_argument_groups(package_groups)
|
|
738
|
+
if identity_present:
|
|
739
|
+
if launcher_prefix and not has_leading_prefix:
|
|
740
|
+
runtime_values = [*launcher_prefix, *runtime_values]
|
|
741
|
+
elif launcher_prefix and has_leading_prefix:
|
|
742
|
+
insertion = len(launcher_prefix)
|
|
743
|
+
runtime_values = [
|
|
744
|
+
*runtime_values[:insertion],
|
|
745
|
+
package_name,
|
|
746
|
+
*runtime_values[insertion:],
|
|
747
|
+
]
|
|
748
|
+
else:
|
|
749
|
+
runtime_values = [
|
|
750
|
+
*launcher_prefix,
|
|
751
|
+
package_name,
|
|
752
|
+
*runtime_values,
|
|
753
|
+
]
|
|
754
|
+
return [*runtime_values, *package_values]
|
|
755
|
+
|
|
756
|
+
@staticmethod
|
|
757
|
+
def _package_identity_matches(candidate: str, package_name: str) -> bool:
|
|
758
|
+
"""Return whether a positional operand identifies the package."""
|
|
759
|
+
if candidate == package_name:
|
|
760
|
+
return True
|
|
761
|
+
version_prefix = f"{package_name}@"
|
|
762
|
+
return candidate.startswith(version_prefix) and len(candidate) > len(version_prefix)
|
|
763
|
+
|
|
764
|
+
@staticmethod
|
|
765
|
+
def _docker_image_references_match(left: Any, right: Any) -> bool:
|
|
766
|
+
"""Return whether two strings name the same image repository."""
|
|
767
|
+
return (
|
|
768
|
+
isinstance(left, str)
|
|
769
|
+
and isinstance(right, str)
|
|
770
|
+
and _docker_image_repository(left) == _docker_image_repository(right)
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
@staticmethod
|
|
774
|
+
def _docker_option_requires_value(argument: Any) -> bool:
|
|
775
|
+
"""Return whether a Docker run option needs a separate value."""
|
|
776
|
+
if not isinstance(argument, str) or "=" in argument:
|
|
777
|
+
return False
|
|
778
|
+
if argument.startswith("--"):
|
|
779
|
+
return argument in _DOCKER_RUN_OPTIONS_WITH_VALUES
|
|
780
|
+
if not argument.startswith("-") or argument == "-":
|
|
781
|
+
return False
|
|
782
|
+
short_options = argument[1:]
|
|
783
|
+
for index, short_name in enumerate(short_options):
|
|
784
|
+
if f"-{short_name}" in _DOCKER_RUN_OPTIONS_WITH_VALUES:
|
|
785
|
+
return index == len(short_options) - 1
|
|
786
|
+
return False
|
|
787
|
+
|
|
788
|
+
@classmethod
|
|
789
|
+
def _docker_image_arg_index(
|
|
790
|
+
cls,
|
|
791
|
+
runtime_args: list[Any],
|
|
792
|
+
image: str | None,
|
|
793
|
+
) -> int | None:
|
|
794
|
+
"""Return the matching Docker image operand index, or None."""
|
|
795
|
+
if not image or not runtime_args or runtime_args[0] != "run":
|
|
796
|
+
return None
|
|
797
|
+
index = 1
|
|
798
|
+
while index < len(runtime_args):
|
|
799
|
+
argument = runtime_args[index]
|
|
800
|
+
if argument == "--":
|
|
801
|
+
index += 1
|
|
802
|
+
break
|
|
803
|
+
if isinstance(argument, str) and argument.startswith("--"):
|
|
804
|
+
option = argument.split("=", 1)[0]
|
|
805
|
+
consumes_next = "=" not in argument and option in _DOCKER_RUN_OPTIONS_WITH_VALUES
|
|
806
|
+
if consumes_next and index + 1 >= len(runtime_args):
|
|
807
|
+
raise ValueError(f"Docker run option '{option}' requires a value")
|
|
808
|
+
index += 2 if consumes_next else 1
|
|
809
|
+
continue
|
|
810
|
+
if isinstance(argument, str) and argument.startswith("-") and argument != "-":
|
|
811
|
+
consumes_next = cls._docker_option_requires_value(argument)
|
|
812
|
+
if consumes_next and index + 1 >= len(runtime_args):
|
|
813
|
+
raise ValueError(f"Docker run option '{argument}' requires a value")
|
|
814
|
+
index += 2 if consumes_next else 1
|
|
815
|
+
continue
|
|
816
|
+
break
|
|
817
|
+
if index >= len(runtime_args):
|
|
818
|
+
return None
|
|
819
|
+
candidate = runtime_args[index]
|
|
820
|
+
if cls._docker_image_references_match(candidate, image):
|
|
821
|
+
return index
|
|
822
|
+
return None
|
|
823
|
+
|
|
824
|
+
@classmethod
|
|
825
|
+
def _ensure_docker_image_arg(
|
|
826
|
+
cls,
|
|
827
|
+
runtime_args: list[Any],
|
|
828
|
+
image: str | None,
|
|
829
|
+
) -> list[Any]:
|
|
830
|
+
"""Return *runtime_args* with the container image operand present.
|
|
831
|
+
|
|
832
|
+
``docker run [OPTIONS] IMAGE`` needs the image after the run options.
|
|
833
|
+
Registries that list it as the last ``runtime_arguments`` entry already
|
|
834
|
+
satisfy that; registries that expose it only as the package
|
|
835
|
+
``identifier`` leave the resolved args ending at the last option, which
|
|
836
|
+
would render an image-less ``docker run`` that fails on invocation
|
|
837
|
+
(#2376).
|
|
838
|
+
|
|
839
|
+
The image is appended only when no argument already references the same
|
|
840
|
+
repository. Comparison is on the repository component, so a digest- or
|
|
841
|
+
tag-pinned identifier still matches a differently-pinned argument
|
|
842
|
+
instead of being appended a second time -- a duplicate operand would be
|
|
843
|
+
parsed by Docker as the container command and break a launcher that
|
|
844
|
+
previously worked.
|
|
845
|
+
|
|
846
|
+
Args:
|
|
847
|
+
runtime_args (list): Resolved registry runtime arguments.
|
|
848
|
+
image (str): Container image reference from the package entry.
|
|
849
|
+
|
|
850
|
+
Returns:
|
|
851
|
+
list: A new list of ``docker run`` arguments.
|
|
852
|
+
"""
|
|
853
|
+
runtime_args = list(runtime_args)
|
|
854
|
+
if not image:
|
|
855
|
+
return runtime_args
|
|
856
|
+
if cls._docker_image_arg_index(runtime_args, image) is not None:
|
|
857
|
+
return runtime_args
|
|
858
|
+
runtime_args.append(image)
|
|
859
|
+
return runtime_args
|
|
860
|
+
|
|
317
861
|
@classmethod
|
|
318
862
|
def _select_best_package(cls, packages):
|
|
319
863
|
"""Select the best package for installation from available packages.
|
|
@@ -707,8 +1251,9 @@ class MCPClientAdapter(ABC):
|
|
|
707
1251
|
return server_url.split("/")[-1]
|
|
708
1252
|
return server_url
|
|
709
1253
|
|
|
710
|
-
@
|
|
1254
|
+
@classmethod
|
|
711
1255
|
def _apply_pypi_homebrew_generic_config(
|
|
1256
|
+
cls,
|
|
712
1257
|
config: dict,
|
|
713
1258
|
registry_name: str,
|
|
714
1259
|
package_name: str,
|
|
@@ -716,6 +1261,8 @@ class MCPClientAdapter(ABC):
|
|
|
716
1261
|
processed_runtime_args: list,
|
|
717
1262
|
processed_package_args: list,
|
|
718
1263
|
resolved_env: dict,
|
|
1264
|
+
runtime_argument_groups: list[_MCPLauncherArgumentGroup] | None = None,
|
|
1265
|
+
package_argument_groups: list[_MCPLauncherArgumentGroup] | None = None,
|
|
719
1266
|
) -> None:
|
|
720
1267
|
"""Apply pypi / homebrew / generic (uvx / brew / npx) run config to *config*.
|
|
721
1268
|
|
|
@@ -734,19 +1281,40 @@ class MCPClientAdapter(ABC):
|
|
|
734
1281
|
after the package name.
|
|
735
1282
|
resolved_env: Pre-resolved environment variables dict; an empty
|
|
736
1283
|
dict is omitted.
|
|
1284
|
+
runtime_argument_groups: Optional typed runtime groups. Compatibility
|
|
1285
|
+
callers may omit them and supply processed strings only.
|
|
1286
|
+
package_argument_groups: Optional typed package groups appended
|
|
1287
|
+
after runtime groups.
|
|
737
1288
|
"""
|
|
1289
|
+
runtime_groups = runtime_argument_groups
|
|
1290
|
+
if runtime_groups is None:
|
|
1291
|
+
runtime_groups = cls._processed_non_container_argument_groups(processed_runtime_args)
|
|
1292
|
+
package_groups = package_argument_groups
|
|
1293
|
+
if package_groups is None:
|
|
1294
|
+
package_groups = cls._processed_non_container_argument_groups(processed_package_args)
|
|
1295
|
+
|
|
738
1296
|
if registry_name == "pypi":
|
|
739
1297
|
launcher = runtime_hint or "uvx"
|
|
740
1298
|
config["command"] = launcher
|
|
741
|
-
config["args"] =
|
|
1299
|
+
config["args"] = cls._build_non_container_launcher_argv(
|
|
1300
|
+
package_name,
|
|
1301
|
+
runtime_groups,
|
|
1302
|
+
package_groups,
|
|
1303
|
+
)
|
|
742
1304
|
elif registry_name == "homebrew":
|
|
743
1305
|
formula_name = package_name.split("/")[-1] if "/" in package_name else package_name
|
|
744
1306
|
config["command"] = formula_name
|
|
745
1307
|
config["args"] = processed_runtime_args + processed_package_args
|
|
746
1308
|
else:
|
|
747
|
-
|
|
748
|
-
config["command"] =
|
|
749
|
-
|
|
1309
|
+
launcher = runtime_hint or "npx"
|
|
1310
|
+
config["command"] = launcher
|
|
1311
|
+
prefix = ("-y",) if launcher in ("npx", "bunx") else ()
|
|
1312
|
+
config["args"] = cls._build_non_container_launcher_argv(
|
|
1313
|
+
package_name,
|
|
1314
|
+
runtime_groups,
|
|
1315
|
+
package_groups,
|
|
1316
|
+
launcher_prefix=prefix,
|
|
1317
|
+
)
|
|
750
1318
|
if resolved_env:
|
|
751
1319
|
config["env"] = resolved_env
|
|
752
1320
|
|