apm-cli 0.20.0__tar.gz → 0.21.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.20.0/src/apm_cli.egg-info → apm_cli-0.21.0}/PKG-INFO +4 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/README.md +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/pyproject.toml +4 -1
- apm_cli-0.21.0/src/apm_cli/adapters/client/antigravity.py +54 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/base.py +33 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/codex.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/copilot.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/cursor.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/gemini.py +36 -19
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/kiro.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/vscode.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/plugin_exporter.py +7 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/unpacker.py +30 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cli.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/_helpers.py +2 -2
- apm_cli-0.21.0/src/apm_cli/commands/approve.py +265 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/audit.py +79 -4
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/compile/cli.py +12 -4
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/deps/cli.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/doctor.py +3 -5
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/install.py +65 -52
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/lock.py +140 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/__init__.py +0 -240
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/check.py +83 -4
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/doctor.py +7 -66
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/outdated.py +19 -6
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/pack.py +34 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/publish.py +15 -9
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/update.py +3 -3
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/agents_compiler.py +9 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/errors.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/experimental.py +12 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/target_detection.py +14 -3
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/lockfile.py +13 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/extractor.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/outdated.py +22 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/resolver.py +27 -13
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/drift.py +9 -4
- apm_cli-0.21.0/src/apm_cli/export/__init__.py +13 -0
- apm_cli-0.21.0/src/apm_cli/export/authoring.py +55 -0
- apm_cli-0.21.0/src/apm_cli/export/declared_license.py +79 -0
- apm_cli-0.21.0/src/apm_cli/export/formats.py +15 -0
- apm_cli-0.21.0/src/apm_cli/export/purl.py +153 -0
- apm_cli-0.21.0/src/apm_cli/export/sbom.py +178 -0
- apm_cli-0.21.0/src/apm_cli/export/spdx.py +168 -0
- apm_cli-0.21.0/src/apm_cli/export/spdx_data.py +841 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/factory.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/cache_pin.py +2 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/context.py +13 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/drift.py +34 -0
- apm_cli-0.21.0/src/apm_cli/install/exec_gate.py +139 -0
- apm_cli-0.21.0/src/apm_cli/install/integrity.py +59 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/local_bundle_handler.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/package_resolution.py +51 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/integrate.py +53 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/local_content.py +1 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/lockfile.py +14 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/targets.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/pipeline.py +49 -1
- apm_cli-0.21.0/src/apm_cli/install/registry_wiring.py +145 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/request.py +6 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/service.py +1 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/services.py +204 -91
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/sources.py +22 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/template.py +3 -0
- apm_cli-0.21.0/src/apm_cli/integration/canvas_integrator.py +508 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/cleanup.py +236 -23
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/dispatch.py +7 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/hook_integrator.py +154 -35
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/instruction_integrator.py +13 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/mcp_integrator.py +20 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/skill_integrator.py +61 -14
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/targets.py +48 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/__init__.py +0 -16
- apm_cli-0.21.0/src/apm_cli/marketplace/auth_helpers.py +53 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/builder.py +15 -21
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/git_stderr.py +1 -3
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/resolver.py +30 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/validator.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/version_check.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/yml_schema.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/apm_package.py +40 -6
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/mcp.py +46 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/validation.py +31 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/discovery.py +1 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/inheritance.py +54 -2
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/matcher.py +19 -6
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/parser.py +35 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/policy_checks.py +155 -17
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/schema.py +25 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/__init__.py +8 -0
- apm_cli-0.21.0/src/apm_cli/security/executables.py +435 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0/src/apm_cli.egg-info}/PKG-INFO +4 -1
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli.egg-info/SOURCES.txt +15 -3
- apm_cli-0.20.0/src/apm_cli/commands/marketplace/publish.py +0 -239
- apm_cli-0.20.0/src/apm_cli/install/registry_wiring.py +0 -63
- apm_cli-0.20.0/src/apm_cli/marketplace/pr_integration.py +0 -498
- apm_cli-0.20.0/src/apm_cli/marketplace/publisher.py +0 -922
- {apm_cli-0.20.0 → apm_cli-0.21.0}/AUTHORS +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/LICENSE +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/NOTICE +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/setup.cfg +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/policy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/prune.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/self_update.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/uninstall/cli.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/uninstall/engine.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/apm_yml.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/auth.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/script_runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/apm_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/bare_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/clone_engine.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/dependency_graph.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/download_strategies.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/git_auth_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/github_downloader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/host_backends.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/errors.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/command.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/cleanup.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/finalize.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/phases/resolve.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/plan.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/install/validation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/agent_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/base_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/mcp_integrator_install.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/client.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/identity.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/reference.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/ci_checks.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/github_host.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli.egg-info/requires.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_console.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_github_downloader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_lockfile.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.21.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apm-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -149,6 +149,7 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
|
|
|
149
149
|
|
|
150
150
|
- **[Content security](https://microsoft.github.io/apm/enterprise/security/)** — `apm install` blocks compromised packages before agents read them; `apm audit` runs the same checks on demand
|
|
151
151
|
- **[Lockfile integrity](https://microsoft.github.io/apm/enterprise/governance/)** — `apm.lock` records resolved sources and content hashes for full provenance
|
|
152
|
+
- **[SBOM export](https://microsoft.github.io/apm/reference/cli/lock/)** — `apm lock export --format cyclonedx|spdx` emits a standard inventory of what reached disk, straight from the lockfile — provenance for procurement, not a compliance attestation
|
|
152
153
|
- **[Drift detection](https://microsoft.github.io/apm/guides/drift-detection/)** — `apm audit` rebuilds your agent context in scratch and diffs it against your working tree to catch hand-edits before they ship
|
|
153
154
|
- **[MCP trust boundaries](https://microsoft.github.io/apm/guides/mcp-servers/)** — transitive MCP servers require explicit consent
|
|
154
155
|
|
|
@@ -156,6 +157,8 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
|
|
|
156
157
|
|
|
157
158
|
`apm-policy.yml` lets a security team say *"these are the only sources, scopes, and primitives this org will allow"* and have every `apm install` enforce it — with tighten-only inheritance from enterprise to org to repo, a published bypass contract, and audit-mode CI gates.
|
|
158
159
|
|
|
160
|
+
apm-policy.yml governs what gets installed; your agent harness governs what runs. The two planes do not overlap.
|
|
161
|
+
|
|
159
162
|
- **[Governance Guide](https://microsoft.github.io/apm/enterprise/governance-guide/)** — the canonical enterprise reference: enforcement points, bypass contract, air-gapped story, failure semantics, rollout playbook
|
|
160
163
|
- **[Policy reference](https://microsoft.github.io/apm/enterprise/policy-reference/)** — every check, every field, every default
|
|
161
164
|
- **[Adoption playbook](https://microsoft.github.io/apm/enterprise/adoption-playbook/)** — staged rollout from warn to block across hundreds of repos
|
|
@@ -81,6 +81,7 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
|
|
|
81
81
|
|
|
82
82
|
- **[Content security](https://microsoft.github.io/apm/enterprise/security/)** — `apm install` blocks compromised packages before agents read them; `apm audit` runs the same checks on demand
|
|
83
83
|
- **[Lockfile integrity](https://microsoft.github.io/apm/enterprise/governance/)** — `apm.lock` records resolved sources and content hashes for full provenance
|
|
84
|
+
- **[SBOM export](https://microsoft.github.io/apm/reference/cli/lock/)** — `apm lock export --format cyclonedx|spdx` emits a standard inventory of what reached disk, straight from the lockfile — provenance for procurement, not a compliance attestation
|
|
84
85
|
- **[Drift detection](https://microsoft.github.io/apm/guides/drift-detection/)** — `apm audit` rebuilds your agent context in scratch and diffs it against your working tree to catch hand-edits before they ship
|
|
85
86
|
- **[MCP trust boundaries](https://microsoft.github.io/apm/guides/mcp-servers/)** — transitive MCP servers require explicit consent
|
|
86
87
|
|
|
@@ -88,6 +89,8 @@ Agent context is executable in effect — a prompt is a program for an LLM. APM
|
|
|
88
89
|
|
|
89
90
|
`apm-policy.yml` lets a security team say *"these are the only sources, scopes, and primitives this org will allow"* and have every `apm install` enforce it — with tighten-only inheritance from enterprise to org to repo, a published bypass contract, and audit-mode CI gates.
|
|
90
91
|
|
|
92
|
+
apm-policy.yml governs what gets installed; your agent harness governs what runs. The two planes do not overlap.
|
|
93
|
+
|
|
91
94
|
- **[Governance Guide](https://microsoft.github.io/apm/enterprise/governance-guide/)** — the canonical enterprise reference: enforcement points, bypass contract, air-gapped story, failure semantics, rollout playbook
|
|
92
95
|
- **[Policy reference](https://microsoft.github.io/apm/enterprise/policy-reference/)** — every check, every field, every default
|
|
93
96
|
- **[Adoption playbook](https://microsoft.github.io/apm/enterprise/adoption-playbook/)** — staged rollout from warn to block across hundreds of repos
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apm-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.21.0"
|
|
8
8
|
description = "MCP configuration tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -105,6 +105,9 @@ max-returns = 12 # Stage 1 (was 18)
|
|
|
105
105
|
# Stage 1 (was 100). Stage 2 target: <=20 (McCabe industry standard).
|
|
106
106
|
max-complexity = 50
|
|
107
107
|
|
|
108
|
+
[tool.ruff.lint.isort]
|
|
109
|
+
known-first-party = ["apm_cli"]
|
|
110
|
+
|
|
108
111
|
[tool.ruff.lint.per-file-ignores]
|
|
109
112
|
# Subprocess calls are intentional in a CLI tool
|
|
110
113
|
"src/apm_cli/**" = ["S603", "S607"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Antigravity CLI (agy) implementation of MCP client adapter.
|
|
2
|
+
|
|
3
|
+
Antigravity CLI is Google's Gemini-derived agentic CLI. Unlike Gemini
|
|
4
|
+
CLI (which stores MCP servers in ``settings.json``), Antigravity reads a
|
|
5
|
+
dedicated ``mcp_config.json`` with an ``mcpServers`` key -- the same JSON
|
|
6
|
+
schema, a different file:
|
|
7
|
+
|
|
8
|
+
.. code-block:: json
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
"mcpServers": {
|
|
12
|
+
"server-name": {
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "@modelcontextprotocol/server-foo"],
|
|
15
|
+
"env": { "KEY": "value" }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Scope resolution: project scope writes to
|
|
21
|
+
``<project_root>/.agents/mcp_config.json`` (opt-in -- the directory must
|
|
22
|
+
already exist). User scope writes to ``~/.gemini/config/mcp_config.json``
|
|
23
|
+
unconditionally, creating the directory if needed.
|
|
24
|
+
|
|
25
|
+
Ref: https://antigravity.google/docs/mcp
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
from .gemini import GeminiClientAdapter
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AntigravityClientAdapter(GeminiClientAdapter):
|
|
34
|
+
"""Antigravity CLI MCP client adapter.
|
|
35
|
+
|
|
36
|
+
Reuses GeminiClientAdapter's ``_format_server_config`` and
|
|
37
|
+
``configure_mcp_server`` (identical ``mcpServers`` JSON schema) and
|
|
38
|
+
overrides only the config directory, the config filename, and the
|
|
39
|
+
display name. Antigravity writes MCP servers to a dedicated
|
|
40
|
+
``mcp_config.json`` rather than ``settings.json``.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
supports_user_scope: bool = True
|
|
44
|
+
target_name: str = "antigravity"
|
|
45
|
+
|
|
46
|
+
def _get_config_dir(self) -> Path:
|
|
47
|
+
"""Return the ``.agents`` or ``~/.gemini/config`` directory."""
|
|
48
|
+
if self.user_scope:
|
|
49
|
+
return Path.home() / ".gemini" / "config"
|
|
50
|
+
return self.project_root / ".agents"
|
|
51
|
+
|
|
52
|
+
def get_config_path(self):
|
|
53
|
+
"""Return the path to ``mcp_config.json`` for the active scope."""
|
|
54
|
+
return str(self._get_config_dir() / "mcp_config.json")
|
|
@@ -6,6 +6,7 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any, ClassVar
|
|
8
8
|
|
|
9
|
+
from ...models.dependency.mcp import _RESERVED_EXTRA_KEYS
|
|
9
10
|
from ...utils.console import _rich_error, _rich_warning
|
|
10
11
|
|
|
11
12
|
_INPUT_VAR_RE = re.compile(r"\$\{input:([^}]+)\}")
|
|
@@ -28,6 +29,15 @@ _ENV_PLACEHOLDER_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>|" + _ENV_VAR_RE.pattern)
|
|
|
28
29
|
# deprecation warnings across all servers in a single install run.
|
|
29
30
|
_LEGACY_ANGLE_VAR_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>")
|
|
30
31
|
|
|
32
|
+
# Config keys that ``_extra`` passthrough must NEVER set on a rendered harness
|
|
33
|
+
# config. Covers the modeled MCP fields (imported single-source from the model)
|
|
34
|
+
# plus harness-specific aliases that mirror a modeled field under a different
|
|
35
|
+
# name -- e.g. Codex emits ``http_headers`` for remote auth headers, which must
|
|
36
|
+
# not be injectable via passthrough. Enforced unconditionally per adapter path
|
|
37
|
+
# (NOT guarded by "key absent from config"), so it also closes paths that do not
|
|
38
|
+
# pre-set the key. Security boundary for PR #1765 / issue #1670.
|
|
39
|
+
_EXTRA_DENYLIST = _RESERVED_EXTRA_KEYS | frozenset({"http_headers"})
|
|
40
|
+
|
|
31
41
|
|
|
32
42
|
def registry_field_is_required(field: dict[str, Any]) -> bool:
|
|
33
43
|
"""Return True unless registry metadata explicitly marks a field optional."""
|
|
@@ -118,6 +128,29 @@ class MCPClientAdapter(ABC):
|
|
|
118
128
|
# (e.g. ``VSCodeClientAdapter``) that have no ``KNOWN_TARGETS`` entry.
|
|
119
129
|
mcp_servers_key: str = ""
|
|
120
130
|
|
|
131
|
+
@staticmethod
|
|
132
|
+
def _merge_extra(config: dict, server_info: dict) -> dict:
|
|
133
|
+
"""Merge harness-specific ``_extra`` keys from server_info into config.
|
|
134
|
+
|
|
135
|
+
Two guards apply:
|
|
136
|
+
|
|
137
|
+
* Denylist (unconditional): a key naming a modeled MCP field -- or a
|
|
138
|
+
harness alias of one (see ``_EXTRA_DENYLIST``) -- is dropped on EVERY
|
|
139
|
+
path, even when the config does not already carry it. This stops a
|
|
140
|
+
passthrough value from shadowing/redirecting a modeled field on
|
|
141
|
+
adapter paths that start empty or set only a subset of keys.
|
|
142
|
+
* Shadow guard: a non-reserved key is appended only when absent, so it
|
|
143
|
+
never overwrites a value the adapter set itself.
|
|
144
|
+
"""
|
|
145
|
+
extra = server_info.get("_extra")
|
|
146
|
+
if extra and isinstance(extra, dict):
|
|
147
|
+
for k, v in extra.items():
|
|
148
|
+
if k in _EXTRA_DENYLIST:
|
|
149
|
+
continue
|
|
150
|
+
if k not in config:
|
|
151
|
+
config[k] = v
|
|
152
|
+
return config
|
|
153
|
+
|
|
121
154
|
# Whether this adapter's config path is user/global-scoped (e.g.
|
|
122
155
|
# ``~/.copilot/``) rather than workspace-scoped (e.g. ``.vscode/``).
|
|
123
156
|
# Adapters that target a global path should override this to ``True``
|
|
@@ -219,6 +219,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
219
219
|
return self.normalize_project_arg(arg)
|
|
220
220
|
|
|
221
221
|
config["args"] = [_process_stdio_arg(arg) for arg in raw.get("args") or []]
|
|
222
|
+
self._merge_extra(config, server_info)
|
|
222
223
|
return config
|
|
223
224
|
|
|
224
225
|
# Remote MCP handling.
|
|
@@ -273,6 +274,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
273
274
|
if http_headers:
|
|
274
275
|
remote_config["http_headers"] = http_headers
|
|
275
276
|
self._warn_input_variables(http_headers, server_name, "Codex CLI")
|
|
277
|
+
self._merge_extra(remote_config, server_info)
|
|
276
278
|
return remote_config
|
|
277
279
|
|
|
278
280
|
if not packages:
|
|
@@ -361,6 +363,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
361
363
|
resolved_env,
|
|
362
364
|
)
|
|
363
365
|
|
|
366
|
+
self._merge_extra(config, server_info)
|
|
364
367
|
return config
|
|
365
368
|
|
|
366
369
|
def _process_arguments( # pylint: disable=duplicate-code # structural similarity with copilot adapter is intentional
|
|
@@ -442,6 +442,7 @@ class CopilotClientAdapter(MCPClientAdapter):
|
|
|
442
442
|
tools_override = server_info.get("_apm_tools_override")
|
|
443
443
|
if tools_override:
|
|
444
444
|
config["tools"] = tools_override
|
|
445
|
+
self._merge_extra(config, server_info)
|
|
445
446
|
return config
|
|
446
447
|
|
|
447
448
|
# Check for remote endpoints first (registry-defined priority)
|
|
@@ -484,6 +485,7 @@ class CopilotClientAdapter(MCPClientAdapter):
|
|
|
484
485
|
if tools_override:
|
|
485
486
|
config["tools"] = tools_override
|
|
486
487
|
|
|
488
|
+
self._merge_extra(config, server_info)
|
|
487
489
|
return config
|
|
488
490
|
|
|
489
491
|
# Get packages from server info
|
|
@@ -507,6 +509,7 @@ class CopilotClientAdapter(MCPClientAdapter):
|
|
|
507
509
|
if tools_override:
|
|
508
510
|
config["tools"] = tools_override
|
|
509
511
|
|
|
512
|
+
self._merge_extra(config, server_info)
|
|
510
513
|
return config
|
|
511
514
|
|
|
512
515
|
def _apply_auth_and_headers(
|
|
@@ -148,6 +148,7 @@ class CursorClientAdapter(CopilotClientAdapter):
|
|
|
148
148
|
else arg
|
|
149
149
|
for arg in args
|
|
150
150
|
]
|
|
151
|
+
self._merge_extra(config, server_info)
|
|
151
152
|
return config
|
|
152
153
|
|
|
153
154
|
# --- remote endpoints ---
|
|
@@ -169,6 +170,7 @@ class CursorClientAdapter(CopilotClientAdapter):
|
|
|
169
170
|
config["url"] = (remote.get("url") or "").strip()
|
|
170
171
|
|
|
171
172
|
self._apply_auth_and_headers(config, remote, server_info, env_overrides, "Cursor")
|
|
173
|
+
self._merge_extra(config, server_info)
|
|
172
174
|
return config
|
|
173
175
|
|
|
174
176
|
# --- local packages ---
|
|
@@ -194,6 +196,7 @@ class CursorClientAdapter(CopilotClientAdapter):
|
|
|
194
196
|
f"{[p.get('registry_name', 'unknown') for p in packages]}."
|
|
195
197
|
)
|
|
196
198
|
|
|
199
|
+
self._merge_extra(config, server_info)
|
|
197
200
|
return config
|
|
198
201
|
|
|
199
202
|
# ------------------------------------------------------------------ #
|
|
@@ -61,7 +61,7 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
61
61
|
# revisit in a follow-up.
|
|
62
62
|
_supports_runtime_env_substitution: bool = False
|
|
63
63
|
|
|
64
|
-
def
|
|
64
|
+
def _get_config_dir(self) -> Path:
|
|
65
65
|
"""Return the ``.gemini`` directory for the active scope."""
|
|
66
66
|
if self.user_scope:
|
|
67
67
|
return Path.home() / ".gemini"
|
|
@@ -69,22 +69,24 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
69
69
|
|
|
70
70
|
def get_config_path(self):
|
|
71
71
|
"""Return the path to ``settings.json`` for the active scope."""
|
|
72
|
-
return str(self.
|
|
72
|
+
return str(self._get_config_dir() / "settings.json")
|
|
73
73
|
|
|
74
74
|
def update_config(self, config_updates):
|
|
75
75
|
"""Merge *config_updates* into the ``mcpServers`` section of settings.json.
|
|
76
76
|
|
|
77
|
-
Project scope is opt-in: if
|
|
77
|
+
Project scope is opt-in: if the target config directory does not
|
|
78
78
|
exist, this method returns silently. User scope always writes,
|
|
79
|
-
creating
|
|
79
|
+
creating the directory if needed.
|
|
80
80
|
|
|
81
81
|
Preserves all other top-level keys in settings.json (theme, tools,
|
|
82
82
|
hooks, etc.).
|
|
83
83
|
"""
|
|
84
|
-
|
|
85
|
-
if not self.user_scope and not
|
|
84
|
+
config_dir = self._get_config_dir()
|
|
85
|
+
if not self.user_scope and not config_dir.is_dir():
|
|
86
86
|
logger.debug(
|
|
87
|
-
"Skipping
|
|
87
|
+
"Skipping %s project-scope write -- %s does not exist (opt-in)",
|
|
88
|
+
self.target_name,
|
|
89
|
+
config_dir,
|
|
88
90
|
)
|
|
89
91
|
return
|
|
90
92
|
|
|
@@ -97,7 +99,9 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
97
99
|
current_config["mcpServers"][name] = entry
|
|
98
100
|
|
|
99
101
|
if not config_path.parent.is_dir():
|
|
100
|
-
logger.debug(
|
|
102
|
+
logger.debug(
|
|
103
|
+
"Creating %s for %s user configuration", config_path.parent, self.target_name
|
|
104
|
+
)
|
|
101
105
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
102
106
|
with open(config_path, "w", encoding="utf-8") as f:
|
|
103
107
|
json.dump(current_config, f, indent=2)
|
|
@@ -151,13 +155,16 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
151
155
|
raw["env"], env_overrides=env_overrides
|
|
152
156
|
)
|
|
153
157
|
config["env"] = resolved_env_for_args
|
|
154
|
-
self._warn_input_variables(
|
|
158
|
+
self._warn_input_variables(
|
|
159
|
+
raw["env"], server_info.get("name", ""), self.target_name
|
|
160
|
+
)
|
|
155
161
|
config["args"] = [
|
|
156
162
|
self._resolve_variable_placeholders(arg, resolved_env_for_args, runtime_vars)
|
|
157
163
|
if isinstance(arg, str)
|
|
158
164
|
else arg
|
|
159
165
|
for arg in raw.get("args") or []
|
|
160
166
|
]
|
|
167
|
+
self._merge_extra(config, server_info)
|
|
161
168
|
return config
|
|
162
169
|
|
|
163
170
|
# --- remote endpoints ---
|
|
@@ -170,7 +177,7 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
170
177
|
transport = "http"
|
|
171
178
|
elif transport not in ("sse", "http", "streamable-http"):
|
|
172
179
|
raise ValueError(
|
|
173
|
-
f"Unsupported remote transport '{transport}' for
|
|
180
|
+
f"Unsupported remote transport '{transport}' for {self.target_name}. "
|
|
174
181
|
f"Server: {server_info.get('name', 'unknown')}. "
|
|
175
182
|
f"Supported transports: http, sse, streamable-http."
|
|
176
183
|
)
|
|
@@ -192,9 +199,10 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
192
199
|
|
|
193
200
|
if config.get("headers"):
|
|
194
201
|
self._warn_input_variables(
|
|
195
|
-
config["headers"], server_info.get("name", ""),
|
|
202
|
+
config["headers"], server_info.get("name", ""), self.target_name
|
|
196
203
|
)
|
|
197
204
|
|
|
205
|
+
self._merge_extra(config, server_info)
|
|
198
206
|
return config
|
|
199
207
|
|
|
200
208
|
# --- local packages ---
|
|
@@ -208,6 +216,7 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
208
216
|
|
|
209
217
|
package = self._select_best_package(packages)
|
|
210
218
|
if not package:
|
|
219
|
+
self._merge_extra(config, server_info)
|
|
211
220
|
return config
|
|
212
221
|
|
|
213
222
|
registry_name = self._infer_registry_name(package)
|
|
@@ -245,6 +254,7 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
245
254
|
if resolved_env:
|
|
246
255
|
config["env"] = resolved_env
|
|
247
256
|
|
|
257
|
+
self._merge_extra(config, server_info)
|
|
248
258
|
return config
|
|
249
259
|
|
|
250
260
|
def configure_mcp_server(
|
|
@@ -256,19 +266,20 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
256
266
|
server_info_cache=None,
|
|
257
267
|
runtime_vars=None,
|
|
258
268
|
):
|
|
259
|
-
"""Configure an MCP server in
|
|
269
|
+
"""Configure an MCP server in the target's ``settings.json``.
|
|
260
270
|
|
|
261
271
|
Delegates to the parent for config formatting, then writes to
|
|
262
|
-
the
|
|
272
|
+
the target CLI settings file.
|
|
263
273
|
"""
|
|
264
274
|
if not server_url:
|
|
265
275
|
_rich_error("server_url cannot be empty", symbol="error")
|
|
266
276
|
return False
|
|
267
277
|
|
|
268
|
-
if not self.user_scope and not self.
|
|
278
|
+
if not self.user_scope and not self._get_config_dir().is_dir():
|
|
269
279
|
logger.debug(
|
|
270
|
-
"
|
|
271
|
-
self.
|
|
280
|
+
"%s opt-in gate: %s absent, skipping configure_mcp_server",
|
|
281
|
+
self.target_name,
|
|
282
|
+
self._get_config_dir(),
|
|
272
283
|
)
|
|
273
284
|
return True
|
|
274
285
|
|
|
@@ -292,10 +303,16 @@ class GeminiClientAdapter(CopilotClientAdapter):
|
|
|
292
303
|
server_config = self._format_server_config(server_info, env_overrides, runtime_vars)
|
|
293
304
|
self.update_config({config_key: server_config})
|
|
294
305
|
|
|
295
|
-
_rich_success(
|
|
306
|
+
_rich_success(
|
|
307
|
+
f"Configured MCP server '{config_key}' for {self.target_name}",
|
|
308
|
+
symbol="success",
|
|
309
|
+
)
|
|
296
310
|
return True
|
|
297
311
|
|
|
298
312
|
except Exception as e:
|
|
299
|
-
logger.debug("
|
|
300
|
-
_rich_error(
|
|
313
|
+
logger.debug("%s MCP configuration failed: %s", self.target_name, e)
|
|
314
|
+
_rich_error(
|
|
315
|
+
f"Failed to configure MCP server for {self.target_name}",
|
|
316
|
+
symbol="error",
|
|
317
|
+
)
|
|
301
318
|
return False
|
|
@@ -130,6 +130,7 @@ class KiroClientAdapter(CopilotClientAdapter):
|
|
|
130
130
|
for arg in raw.get("args") or []
|
|
131
131
|
]
|
|
132
132
|
self._copy_kiro_extensions(config, server_info)
|
|
133
|
+
self._merge_extra(config, server_info)
|
|
133
134
|
return config
|
|
134
135
|
|
|
135
136
|
remotes = server_info.get("remotes", [])
|
|
@@ -157,6 +158,7 @@ class KiroClientAdapter(CopilotClientAdapter):
|
|
|
157
158
|
config["headers"] = headers
|
|
158
159
|
self._warn_input_variables(headers, server_info.get("name", ""), "Kiro")
|
|
159
160
|
self._copy_kiro_extensions(config, server_info)
|
|
161
|
+
self._merge_extra(config, server_info)
|
|
160
162
|
return config
|
|
161
163
|
|
|
162
164
|
packages = server_info.get("packages", [])
|
|
@@ -180,6 +182,7 @@ class KiroClientAdapter(CopilotClientAdapter):
|
|
|
180
182
|
f"Server: {server_info.get('name', 'unknown')}."
|
|
181
183
|
)
|
|
182
184
|
self._copy_kiro_extensions(config, server_info)
|
|
185
|
+
self._merge_extra(config, server_info)
|
|
183
186
|
return config
|
|
184
187
|
|
|
185
188
|
def configure_mcp_server(
|
|
@@ -281,6 +281,7 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
281
281
|
input_vars.extend(
|
|
282
282
|
self._extract_input_variables(env_translated, server_info.get("name", ""))
|
|
283
283
|
)
|
|
284
|
+
self._merge_extra(server_config, server_info)
|
|
284
285
|
return server_config, input_vars
|
|
285
286
|
|
|
286
287
|
# Check for packages information
|
|
@@ -448,6 +449,7 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
448
449
|
f"Server: {server_info.get('name', 'unknown')}"
|
|
449
450
|
)
|
|
450
451
|
|
|
452
|
+
self._merge_extra(server_config, server_info)
|
|
451
453
|
return server_config, input_vars
|
|
452
454
|
|
|
453
455
|
@staticmethod
|
|
@@ -108,6 +108,12 @@ def _collect_apm_components(apm_dir: Path) -> list[tuple[Path, str]]:
|
|
|
108
108
|
# commands/ -> commands/
|
|
109
109
|
_collect_recursive(apm_dir / "commands", "commands", components)
|
|
110
110
|
|
|
111
|
+
# extensions/ -> extensions/ (canvas extensions, experimental Copilot-only).
|
|
112
|
+
# Preserved verbatim so an offline bundle can carry a canvas; the files are
|
|
113
|
+
# inert until the consumer enables the ``canvas`` experimental flag AND
|
|
114
|
+
# passes ``--trust-canvas-extensions`` at install time.
|
|
115
|
+
_collect_recursive(apm_dir / "extensions", "extensions", components)
|
|
116
|
+
|
|
111
117
|
return components
|
|
112
118
|
|
|
113
119
|
|
|
@@ -118,7 +124,7 @@ def _collect_root_plugin_components(project_root: Path) -> list[tuple[Path, str]
|
|
|
118
124
|
``skills/``, etc. at the repo root) have their files picked up here.
|
|
119
125
|
"""
|
|
120
126
|
components: list[tuple[Path, str]] = []
|
|
121
|
-
for dir_name in ("agents", "skills", "commands", "instructions"):
|
|
127
|
+
for dir_name in ("agents", "skills", "commands", "instructions", "extensions"):
|
|
122
128
|
_collect_recursive(project_root / dir_name, dir_name, components)
|
|
123
129
|
return components
|
|
124
130
|
|
|
@@ -30,6 +30,7 @@ class UnpackResult:
|
|
|
30
30
|
skipped_count: int = 0
|
|
31
31
|
security_warnings: int = 0
|
|
32
32
|
security_critical: int = 0
|
|
33
|
+
canvas_blocked: int = 0
|
|
33
34
|
pack_meta: dict = field(default_factory=dict)
|
|
34
35
|
|
|
35
36
|
|
|
@@ -39,6 +40,7 @@ def unpack_bundle(
|
|
|
39
40
|
skip_verify: bool = False,
|
|
40
41
|
dry_run: bool = False,
|
|
41
42
|
force: bool = False,
|
|
43
|
+
trust_canvas: bool = False,
|
|
42
44
|
) -> UnpackResult:
|
|
43
45
|
"""Extract and apply an APM bundle to a project directory.
|
|
44
46
|
|
|
@@ -52,6 +54,10 @@ def unpack_bundle(
|
|
|
52
54
|
skip_verify: If *True*, skip completeness verification against the lockfile.
|
|
53
55
|
dry_run: If *True*, resolve the file list but write nothing to disk.
|
|
54
56
|
force: If *True*, deploy even when critical hidden characters are found.
|
|
57
|
+
trust_canvas: If *True*, allow executable canvas extension files
|
|
58
|
+
(``.github/extensions/<name>/extension.mjs``) to be unpacked.
|
|
59
|
+
Defaults to *False* (fail closed) so a vendored bundle cannot
|
|
60
|
+
smuggle executable canvas code past the trust gate.
|
|
55
61
|
|
|
56
62
|
Returns:
|
|
57
63
|
:class:`UnpackResult` describing what was (or would be) extracted.
|
|
@@ -163,6 +169,28 @@ def unpack_bundle(
|
|
|
163
169
|
if dep_files:
|
|
164
170
|
dep_file_map[dep_key] = dep_files
|
|
165
171
|
|
|
172
|
+
# Security + feature gate: canvas extensions are executable Node
|
|
173
|
+
# bundles (``extension.mjs``). ``apm unpack`` copies deployed files
|
|
174
|
+
# verbatim WITHOUT routing through ``CanvasIntegrator``, so neither
|
|
175
|
+
# the experimental feature flag nor its trust gate would otherwise
|
|
176
|
+
# apply. Require BOTH gates -- the ``canvas`` experimental flag ON
|
|
177
|
+
# (feature availability) AND ``trust_canvas`` (executable-code trust)
|
|
178
|
+
# -- before unpacking canvas paths. Fail closed: drop them when
|
|
179
|
+
# either gate is missing.
|
|
180
|
+
canvas_blocked = 0
|
|
181
|
+
from ..core.experimental import is_enabled
|
|
182
|
+
from ..integration.canvas_integrator import is_canvas_bundle_path
|
|
183
|
+
|
|
184
|
+
if not (is_enabled("canvas") and trust_canvas):
|
|
185
|
+
_blocked = {f for f in unique_files if is_canvas_bundle_path(f)}
|
|
186
|
+
if _blocked:
|
|
187
|
+
canvas_blocked = len(_blocked)
|
|
188
|
+
unique_files = [f for f in unique_files if f not in _blocked]
|
|
189
|
+
for _k in list(dep_file_map):
|
|
190
|
+
dep_file_map[_k] = [f for f in dep_file_map[_k] if f not in _blocked]
|
|
191
|
+
if not dep_file_map[_k]:
|
|
192
|
+
del dep_file_map[_k]
|
|
193
|
+
|
|
166
194
|
# 3. Verify completeness
|
|
167
195
|
verified = True
|
|
168
196
|
if not skip_verify:
|
|
@@ -211,6 +239,7 @@ def unpack_bundle(
|
|
|
211
239
|
dependency_files=dep_file_map,
|
|
212
240
|
security_warnings=security_warnings,
|
|
213
241
|
security_critical=security_critical,
|
|
242
|
+
canvas_blocked=canvas_blocked,
|
|
214
243
|
pack_meta=pack_meta,
|
|
215
244
|
)
|
|
216
245
|
|
|
@@ -254,6 +283,7 @@ def unpack_bundle(
|
|
|
254
283
|
skipped_count=skipped,
|
|
255
284
|
security_warnings=security_warnings,
|
|
256
285
|
security_critical=security_critical,
|
|
286
|
+
canvas_blocked=canvas_blocked,
|
|
257
287
|
pack_meta=pack_meta,
|
|
258
288
|
)
|
|
259
289
|
finally:
|
|
@@ -18,6 +18,7 @@ from apm_cli.commands._helpers import (
|
|
|
18
18
|
_check_and_notify_updates,
|
|
19
19
|
print_version,
|
|
20
20
|
)
|
|
21
|
+
from apm_cli.commands.approve import approve_cmd, deny_cmd
|
|
21
22
|
from apm_cli.commands.audit import audit
|
|
22
23
|
from apm_cli.commands.cache import cache
|
|
23
24
|
from apm_cli.commands.compile import compile as compile_cmd
|
|
@@ -147,8 +148,10 @@ def cli(ctx, verbose: bool) -> None:
|
|
|
147
148
|
|
|
148
149
|
|
|
149
150
|
# Register command groups
|
|
151
|
+
cli.add_command(approve_cmd, name="approve")
|
|
150
152
|
cli.add_command(audit)
|
|
151
153
|
cli.add_command(cache)
|
|
154
|
+
cli.add_command(deny_cmd, name="deny")
|
|
152
155
|
cli.add_command(deps)
|
|
153
156
|
cli.add_command(view_cmd)
|
|
154
157
|
# Hidden backward-compatible alias: ``apm info`` → ``apm view``
|
|
@@ -710,8 +710,8 @@ def _create_minimal_apm_yml(config, plugin=False, target_path=None):
|
|
|
710
710
|
targets_comment = (
|
|
711
711
|
"# Which agent platforms to deploy to.\n"
|
|
712
712
|
"# Resolution order: --target flag > this field > auto-detect from filesystem.\n"
|
|
713
|
-
"# Accepted values: copilot, claude, cursor, opencode, codex
|
|
714
|
-
"windsurf, all\n"
|
|
713
|
+
"# Accepted values: vscode, agents, copilot, claude, cursor, opencode, codex,\n"
|
|
714
|
+
"# gemini, antigravity, windsurf, kiro, agent-skills, all\n"
|
|
715
715
|
)
|
|
716
716
|
content = content.replace("targets:", targets_comment + "targets:", 1)
|
|
717
717
|
else:
|