apm-cli 0.20.0__tar.gz → 0.22.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.22.0}/PKG-INFO +4 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/README.md +3 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/pyproject.toml +4 -1
- apm_cli-0.22.0/src/apm_cli/adapters/client/antigravity.py +54 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/base.py +33 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/codex.py +16 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/copilot.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/cursor.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/gemini.py +36 -19
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/kiro.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/vscode.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/lockfile_enrichment.py +7 -9
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/plugin_exporter.py +7 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/unpacker.py +24 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cli.py +3 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/_apm_yml_writer.py +41 -10
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/_helpers.py +2 -2
- apm_cli-0.22.0/src/apm_cli/commands/approve.py +505 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/audit.py +79 -4
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/compile/cli.py +153 -4
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/config.py +139 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/deps/cli.py +7 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/doctor.py +3 -5
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/install.py +71 -58
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/lock.py +140 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/__init__.py +1 -240
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/check.py +83 -4
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/doctor.py +87 -66
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/outdated.py +19 -6
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/pack.py +16 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/policy.py +21 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/publish.py +15 -9
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/self_update.py +65 -5
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/update.py +3 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/view.py +140 -13
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/__init__.py +4 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/agents_compiler.py +11 -2
- apm_cli-0.22.0/src/apm_cli/compilation/user_root_context.py +305 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/config.py +125 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/errors.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/experimental.py +12 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/target_detection.py +44 -5
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/dependency_graph.py +13 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/installed_package.py +4 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/lockfile.py +82 -13
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/extractor.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/outdated.py +22 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/resolver.py +38 -15
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/drift.py +9 -4
- apm_cli-0.22.0/src/apm_cli/export/__init__.py +13 -0
- apm_cli-0.22.0/src/apm_cli/export/authoring.py +55 -0
- apm_cli-0.22.0/src/apm_cli/export/declared_license.py +79 -0
- apm_cli-0.22.0/src/apm_cli/export/formats.py +15 -0
- apm_cli-0.22.0/src/apm_cli/export/purl.py +153 -0
- apm_cli-0.22.0/src/apm_cli/export/sbom.py +178 -0
- apm_cli-0.22.0/src/apm_cli/export/spdx.py +168 -0
- apm_cli-0.22.0/src/apm_cli/export/spdx_data.py +841 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/factory.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/artifactory_resolver.py +7 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/cache_pin.py +2 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/context.py +24 -2
- apm_cli-0.22.0/src/apm_cli/install/deployed_paths.py +70 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/drift.py +40 -2
- apm_cli-0.22.0/src/apm_cli/install/exec_gate.py +167 -0
- apm_cli-0.22.0/src/apm_cli/install/integrity.py +59 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/local_bundle_handler.py +2 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/package_resolution.py +51 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/cleanup.py +24 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/finalize.py +69 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/integrate.py +100 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/local_content.py +1 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/lockfile.py +32 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/resolve.py +17 -7
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/targets.py +18 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/pipeline.py +47 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/plan.py +5 -1
- apm_cli-0.22.0/src/apm_cli/install/registry_wiring.py +145 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/services.py +270 -145
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/skill_path_migration.py +6 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/sources.py +61 -2
- apm_cli-0.22.0/src/apm_cli/install/target_filter.py +33 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/template.py +61 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/agent_integrator.py +15 -5
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/base_integrator.py +95 -14
- apm_cli-0.22.0/src/apm_cli/integration/canvas_integrator.py +509 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/cleanup.py +236 -23
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/command_integrator.py +5 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/dispatch.py +7 -0
- apm_cli-0.22.0/src/apm_cli/integration/hook_file_routing.py +120 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/hook_integrator.py +230 -99
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/instruction_integrator.py +32 -9
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/kiro_hook_integrator.py +10 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/lsp_integrator.py +3 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/mcp_integrator.py +25 -4
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/prompt_integrator.py +5 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/skill_integrator.py +84 -33
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/skill_transformer.py +2 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/targets.py +62 -6
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/__init__.py +0 -16
- apm_cli-0.22.0/src/apm_cli/marketplace/auth_helpers.py +53 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/builder.py +45 -32
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/client.py +170 -10
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/git_stderr.py +1 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/models.py +6 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/resolver.py +62 -4
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/validator.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/version_check.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/yml_schema.py +1 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/apm_package.py +40 -6
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/mcp.py +46 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/reference.py +14 -21
- apm_cli-0.22.0/src/apm_cli/models/dependency/subsets.py +94 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/validation.py +31 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/_help_text.py +3 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/discovery.py +227 -11
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/inheritance.py +75 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/matcher.py +19 -6
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/models.py +1 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/parser.py +84 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/policy_checks.py +233 -27
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/schema.py +63 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/__init__.py +8 -0
- apm_cli-0.22.0/src/apm_cli/security/executables.py +1157 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/atomic_io.py +25 -2
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/github_host.py +72 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/version_checker.py +42 -12
- {apm_cli-0.20.0 → apm_cli-0.22.0/src/apm_cli.egg-info}/PKG-INFO +4 -1
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli.egg-info/SOURCES.txt +20 -3
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_lockfile.py +242 -0
- 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.22.0}/AUTHORS +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/LICENSE +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/NOTICE +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/setup.cfg +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/prune.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/uninstall/cli.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/commands/uninstall/engine.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/distributed_compiler.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/apm_yml.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/auth.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/build_orchestrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/script_runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/apm_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/bare_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/clone_engine.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/download_strategies.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/git_auth_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/github_downloader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/host_backends.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/errors.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/command.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/_skip_logic.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/request.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/service.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/install/validation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/mcp_integrator_install.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/audit.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/drift_check.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/output_profiles.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/identity.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/ci_checks.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/patterns.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli.egg-info/requires.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_console.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_github_downloader.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.20.0 → apm_cli-0.22.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.22.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.22.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``
|
|
@@ -10,6 +10,7 @@ import toml
|
|
|
10
10
|
from ...registry.client import SimpleRegistryClient
|
|
11
11
|
from ...registry.integration import RegistryIntegration
|
|
12
12
|
from ...utils.console import _rich_success, _rich_warning
|
|
13
|
+
from ...utils.path_security import PathTraversalError
|
|
13
14
|
from ._mcp_runtime_args import process_v01_value_hint_arg
|
|
14
15
|
from .base import MCPClientAdapter
|
|
15
16
|
|
|
@@ -49,13 +50,22 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
49
50
|
self.registry_client = SimpleRegistryClient(registry_url)
|
|
50
51
|
self.registry_integration = RegistryIntegration(registry_url)
|
|
51
52
|
|
|
52
|
-
def _get_codex_dir(self):
|
|
53
|
+
def _get_codex_dir(self) -> Path:
|
|
53
54
|
"""Return the root directory used for Codex config in the current scope."""
|
|
54
55
|
if self.user_scope:
|
|
56
|
+
codex_home = os.environ.get("CODEX_HOME", "")
|
|
57
|
+
if codex_home.strip():
|
|
58
|
+
codex_home_path = Path(codex_home).expanduser()
|
|
59
|
+
if not codex_home_path.is_absolute():
|
|
60
|
+
raise PathTraversalError(
|
|
61
|
+
"CODEX_HOME is set to a non-absolute path; cannot locate the "
|
|
62
|
+
"Codex CLI configuration directory."
|
|
63
|
+
)
|
|
64
|
+
return codex_home_path
|
|
55
65
|
return Path.home() / ".codex"
|
|
56
66
|
return self.project_root / ".codex"
|
|
57
67
|
|
|
58
|
-
def get_config_path(self):
|
|
68
|
+
def get_config_path(self) -> str:
|
|
59
69
|
"""Get the path to the Codex CLI MCP configuration file.
|
|
60
70
|
|
|
61
71
|
Returns:
|
|
@@ -219,6 +229,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
219
229
|
return self.normalize_project_arg(arg)
|
|
220
230
|
|
|
221
231
|
config["args"] = [_process_stdio_arg(arg) for arg in raw.get("args") or []]
|
|
232
|
+
self._merge_extra(config, server_info)
|
|
222
233
|
return config
|
|
223
234
|
|
|
224
235
|
# Remote MCP handling.
|
|
@@ -273,6 +284,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
273
284
|
if http_headers:
|
|
274
285
|
remote_config["http_headers"] = http_headers
|
|
275
286
|
self._warn_input_variables(http_headers, server_name, "Codex CLI")
|
|
287
|
+
self._merge_extra(remote_config, server_info)
|
|
276
288
|
return remote_config
|
|
277
289
|
|
|
278
290
|
if not packages:
|
|
@@ -320,7 +332,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
320
332
|
all_args = processed_runtime_args + processed_package_args
|
|
321
333
|
if all_args:
|
|
322
334
|
# If runtime_arguments already include the package (bare or
|
|
323
|
-
# versioned), use them as-is
|
|
335
|
+
# versioned), use them as-is -- they are authoritative from
|
|
324
336
|
# the registry and may carry a version pin.
|
|
325
337
|
has_pkg = any(
|
|
326
338
|
a == package_name or a.startswith(f"{package_name}@") for a in all_args
|
|
@@ -361,6 +373,7 @@ class CodexClientAdapter(MCPClientAdapter):
|
|
|
361
373
|
resolved_env,
|
|
362
374
|
)
|
|
363
375
|
|
|
376
|
+
self._merge_extra(config, server_info)
|
|
364
377
|
return config
|
|
365
378
|
|
|
366
379
|
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
|
|
@@ -13,12 +13,10 @@ from ..integration.targets import KNOWN_TARGETS
|
|
|
13
13
|
# .github/ is the canonical interop prefix -- install always creates it, so
|
|
14
14
|
# all non-github targets map FROM .github/. The copilot target additionally
|
|
15
15
|
# maps FROM .claude/ for the common case of Claude-first projects packing
|
|
16
|
-
# for Copilot. Cursor
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# into the windsurf skill envelope), so .github/agents/ maps to
|
|
21
|
-
# .windsurf/skills/.
|
|
16
|
+
# for Copilot. Cursor, opencode, and windsurf skills converge on the
|
|
17
|
+
# shared .agents/skills/ convention rather than bespoke per-target paths.
|
|
18
|
+
# Windsurf agents still collapse into .windsurf/skills/ because the target
|
|
19
|
+
# has no distinct agent envelope.
|
|
22
20
|
_CROSS_TARGET_MAPS: dict[str, dict[str, str]] = {
|
|
23
21
|
"claude": {
|
|
24
22
|
".github/skills/": ".claude/skills/",
|
|
@@ -33,11 +31,11 @@ _CROSS_TARGET_MAPS: dict[str, dict[str, str]] = {
|
|
|
33
31
|
".claude/agents/": ".github/agents/",
|
|
34
32
|
},
|
|
35
33
|
"cursor": {
|
|
36
|
-
".github/skills/": ".
|
|
34
|
+
".github/skills/": ".agents/skills/",
|
|
37
35
|
".github/agents/": ".cursor/agents/",
|
|
38
36
|
},
|
|
39
37
|
"opencode": {
|
|
40
|
-
".github/skills/": ".
|
|
38
|
+
".github/skills/": ".agents/skills/",
|
|
41
39
|
".github/agents/": ".opencode/agents/",
|
|
42
40
|
},
|
|
43
41
|
"codex": {
|
|
@@ -45,7 +43,7 @@ _CROSS_TARGET_MAPS: dict[str, dict[str, str]] = {
|
|
|
45
43
|
".github/agents/": ".codex/agents/",
|
|
46
44
|
},
|
|
47
45
|
"windsurf": {
|
|
48
|
-
".github/skills/": ".
|
|
46
|
+
".github/skills/": ".agents/skills/",
|
|
49
47
|
".github/agents/": ".windsurf/skills/",
|
|
50
48
|
},
|
|
51
49
|
"agent-skills": {
|
|
@@ -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
|
+
# approves the package via allowExecutables / ``apm approve`` 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
|
|
|
@@ -163,6 +164,27 @@ def unpack_bundle(
|
|
|
163
164
|
if dep_files:
|
|
164
165
|
dep_file_map[dep_key] = dep_files
|
|
165
166
|
|
|
167
|
+
# Security + feature gate: canvas extensions are executable Node
|
|
168
|
+
# bundles (``extension.mjs``). ``apm unpack`` (deprecated) copies
|
|
169
|
+
# deployed files verbatim WITHOUT routing through ``CanvasIntegrator``.
|
|
170
|
+
# When the canvas feature flag is OFF, drop paths silently.
|
|
171
|
+
# When ON, canvas files are allowed (apm unpack has no project context
|
|
172
|
+
# so no allowExecutables enforcement is available; the user is assumed
|
|
173
|
+
# to understand what they are unpacking for this deprecated command).
|
|
174
|
+
canvas_blocked = 0
|
|
175
|
+
from ..core.experimental import is_enabled
|
|
176
|
+
from ..integration.canvas_integrator import is_canvas_bundle_path
|
|
177
|
+
|
|
178
|
+
if not is_enabled("canvas"):
|
|
179
|
+
_blocked = {f for f in unique_files if is_canvas_bundle_path(f)}
|
|
180
|
+
if _blocked:
|
|
181
|
+
canvas_blocked = len(_blocked)
|
|
182
|
+
unique_files = [f for f in unique_files if f not in _blocked]
|
|
183
|
+
for _k in list(dep_file_map):
|
|
184
|
+
dep_file_map[_k] = [f for f in dep_file_map[_k] if f not in _blocked]
|
|
185
|
+
if not dep_file_map[_k]:
|
|
186
|
+
del dep_file_map[_k]
|
|
187
|
+
|
|
166
188
|
# 3. Verify completeness
|
|
167
189
|
verified = True
|
|
168
190
|
if not skip_verify:
|
|
@@ -211,6 +233,7 @@ def unpack_bundle(
|
|
|
211
233
|
dependency_files=dep_file_map,
|
|
212
234
|
security_warnings=security_warnings,
|
|
213
235
|
security_critical=security_critical,
|
|
236
|
+
canvas_blocked=canvas_blocked,
|
|
214
237
|
pack_meta=pack_meta,
|
|
215
238
|
)
|
|
216
239
|
|
|
@@ -254,6 +277,7 @@ def unpack_bundle(
|
|
|
254
277
|
skipped_count=skipped,
|
|
255
278
|
security_warnings=security_warnings,
|
|
256
279
|
security_critical=security_critical,
|
|
280
|
+
canvas_blocked=canvas_blocked,
|
|
257
281
|
pack_meta=pack_meta,
|
|
258
282
|
)
|
|
259
283
|
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``
|