apm-cli 0.27.0__tar.gz → 0.28.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.27.0/src/apm_cli.egg-info → apm_cli-0.28.0}/PKG-INFO +3 -3
- {apm_cli-0.27.0 → apm_cli-0.28.0}/README.md +2 -2
- {apm_cli-0.27.0 → apm_cli-0.28.0}/pyproject.toml +1 -1
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/base.py +89 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/vscode.py +108 -82
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/lockfile_enrichment.py +17 -13
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/_helpers.py +5 -16
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/deps/cli.py +2 -1
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/init.py +19 -6
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/install.py +35 -43
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/audit.py +27 -5
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +5 -3
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/plugin/add.py +11 -3
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/outdated.py +9 -2
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/pack.py +38 -10
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/uninstall/engine.py +25 -17
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/context_optimizer.py +186 -82
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/distributed_compiler.py +43 -32
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/build_orchestrator.py +9 -11
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/experimental.py +6 -0
- apm_cli-0.28.0/src/apm_cli/core/project_name.py +19 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/script_runner.py +2 -1
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/target_catalog.py +14 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/target_detection.py +23 -5
- apm_cli-0.28.0/src/apm_cli/install/argv.py +34 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/local_bundle_handler.py +12 -0
- apm_cli-0.28.0/src/apm_cli/install/local_bundle_paths.py +89 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/package_resolution.py +96 -6
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/_skip_logic.py +13 -2
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/integrate.py +1 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/targets.py +23 -37
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/services.py +24 -41
- apm_cli-0.28.0/src/apm_cli/install/target_hints.py +53 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/agent_integrator.py +259 -18
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_integrator.py +52 -39
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/instruction_integrator.py +16 -16
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/mcp_integrator_install.py +24 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/targets.py +36 -2
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/audit.py +48 -3
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/builder.py +18 -9
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/drift_check.py +12 -18
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/output_profiles.py +39 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/resolver.py +32 -10
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/version_check.py +91 -11
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/yml_schema.py +11 -10
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/reference.py +21 -90
- apm_cli-0.28.0/src/apm_cli/models/dependency/registry_entry.py +119 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/discovery.py +3 -22
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/primitives/parser.py +3 -29
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/registry/operations.py +43 -9
- apm_cli-0.28.0/src/apm_cli/utils/patterns.py +185 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0/src/apm_cli.egg-info}/PKG-INFO +3 -3
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli.egg-info/SOURCES.txt +5 -0
- apm_cli-0.27.0/src/apm_cli/utils/patterns.py +0 -91
- {apm_cli-0.27.0 → apm_cli-0.28.0}/AUTHORS +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/LICENSE +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/NOTICE +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/setup.cfg +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/_mcp_runtime_args.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/antigravity.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/codex.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/copilot.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/cursor.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/gemini.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/hermes.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/intellij.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/kiro.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/opencode.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bootstrap_mirror.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/attest.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/local_bundle.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/plugin_exporter.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/plugin_layout.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/bundle/unpacker.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/git_cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/cli.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/_apm_yml_writer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/approve.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/audit.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/compile/cli.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/compile/watcher.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/config.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/deps/why.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/doctor.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/find.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/lifecycle.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/lock.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/check.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/doctor.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/init.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/plugin/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/plugin/init.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/policy.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/prune.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/publish.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/run.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/runtime.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/self_update.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/uninstall/cli.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/uninstall/lockfile_state.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/update.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/claude_formatter.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/managed_section.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/template_builder.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/compilation/user_root_context.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/_child_tls/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/_child_tls/_apm_tls.pth +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/_child_tls/_apm_tls_bootstrap.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/apm_yml.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/auth.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/command_logger.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/deployment_ledger.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/deployment_state.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/errors.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/host_providers.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/install_audit.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/lifecycle_scripts.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/output_mode.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/plugin_manifest.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/script_executors.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/script_trust.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/tls_trust.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/core/token_manager.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/_shared.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/apm_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/artifactory_orchestrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/bare_cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/clone_engine.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/dependency_graph.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/download_strategies.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/git_auth_env.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/git_file_transport.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/git_reference_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/git_semver_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/github_downloader.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/github_downloader_validation.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/github_rate_limit.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/host_backends.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/lockfile.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/outdated_ref_cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/outdated_row.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/package_validator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/path_anchoring.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/reachability.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/auth.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/client.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/config_loader.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/extractor.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/feature_gate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/outdated.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry/semver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/registry_proxy.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/revision_pins.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/shared_clone_cache.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/tiered_ref_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/deps/why_walker.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/drift.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/authoring.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/declared_license.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/formats.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/purl.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/sbom.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/spdx.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/export/spdx_data.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/artifactory_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/audit_replay.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/context.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/deployed_paths.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/drift.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/drift_render.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/errors.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/exec_gate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/gitlab_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/helpers/no_work.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/helpers/ref_reuse.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/helpers/ref_seed.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/integrity.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/lsp/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/lsp/integration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/manifest_reconcile.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/command.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/entry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/integration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/ownership.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/mcp/writer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/outcome.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/package_selection.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/_redownload.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/audit.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/cleanup.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/finalize.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/lockfile.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/phases/resolve.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/pipeline.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/plan.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/registry_wiring.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/request.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/resolution_staging.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/root_redirect.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/service.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/service_integration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/sources.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/target_filter.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/target_warnings.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/template.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/transaction.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/install/validation.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/_hook_dropped_targets.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/_shared.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/base_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/canvas_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/cleanup.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/command_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/copilot_app_db.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/copilot_app_project.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/copilot_app_workflow_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/copilot_app_ws.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_bundle.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_file_routing.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_ir.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_native_formats.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/hook_ownership.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/kiro_hook_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/lsp_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/mcp_config_view.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/mcp_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/opencode_frontmatter.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/prompt_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/skill_integrator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/_shared.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/auth_helpers.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/client.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/diagnostics.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/init_template.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/models.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/output_mappers.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/version_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/apm_package.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/identity.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/lsp.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/materialization.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/mcp.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/object_fields.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/provider_coordinates.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/selection.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/subsets.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/format_detection.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/manifest_contract.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/models/validation.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/_constraint_pinning.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/_shared.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/ci_checks.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/inheritance.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/matcher.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/models.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/parser.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/policy_checks.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/policy/schema.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/registry/client.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/base.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/codex_runtime.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/copilot_runtime.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/llm_runtime.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/registry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/runtime/utils.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/executables.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/base.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/gate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/generic_sarif.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/options.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/registry.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/runner.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/sarif_ingest.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/external/skillspector.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/archive.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/console.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/git_sparse.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/github_host.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/perf_stats.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli.egg-info/requires.txt +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_console.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_github_downloader.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_gitlab_git_transport.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_lockfile.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.0}/tests/test_token_manager.py +0 -0
- {apm_cli-0.27.0 → apm_cli-0.28.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.28.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -76,7 +76,7 @@ Dynamic: license-file
|
|
|
76
76
|
|
|
77
77
|
Think `package.json`, `requirements.txt`, or `Cargo.toml` — but for AI agent configuration.
|
|
78
78
|
|
|
79
|
-
GitHub Copilot
|
|
79
|
+
GitHub Copilot | Claude Code | Grok Build | Cursor | OpenCode | Codex | Gemini | Windsurf | Kiro
|
|
80
80
|
|
|
81
81
|
**[Documentation](https://microsoft.github.io/apm/)** · **[Quick Start](https://microsoft.github.io/apm/getting-started/quick-start/)** · **[CLI Reference](https://microsoft.github.io/apm/reference/cli-commands/)** · **[Roadmap](https://github.com/orgs/microsoft/projects/2304)**
|
|
82
82
|
|
|
@@ -139,7 +139,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
|
|
|
139
139
|
|
|
140
140
|
One `apm.yml` describes every primitive your agents need — instructions, skills, prompts, agents, hooks, plugins, MCP servers — and `apm install` reproduces the exact same setup across every client on every machine. `apm.lock.yaml` pins the resolved tree the way `package-lock.json` does for npm.
|
|
141
141
|
|
|
142
|
-
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)**
|
|
142
|
+
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** -- declared once, deployed across Copilot, Claude, Grok Build, Cursor, OpenCode, Codex, Gemini, Windsurf, Kiro
|
|
143
143
|
- **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, Gitea, Gogs, any git host
|
|
144
144
|
- **[Transitive dependencies](https://microsoft.github.io/apm/guides/dependencies/)** — packages can depend on packages; APM resolves the full tree
|
|
145
145
|
- **[Author plugins](https://microsoft.github.io/apm/guides/plugins/)** — build Copilot, Claude, and Cursor plugins with dependency management, then export standard `plugin.json`
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Think `package.json`, `requirements.txt`, or `Cargo.toml` — but for AI agent configuration.
|
|
6
6
|
|
|
7
|
-
GitHub Copilot
|
|
7
|
+
GitHub Copilot | Claude Code | Grok Build | Cursor | OpenCode | Codex | Gemini | Windsurf | Kiro
|
|
8
8
|
|
|
9
9
|
**[Documentation](https://microsoft.github.io/apm/)** · **[Quick Start](https://microsoft.github.io/apm/getting-started/quick-start/)** · **[CLI Reference](https://microsoft.github.io/apm/reference/cli-commands/)** · **[Roadmap](https://github.com/orgs/microsoft/projects/2304)**
|
|
10
10
|
|
|
@@ -67,7 +67,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
|
|
|
67
67
|
|
|
68
68
|
One `apm.yml` describes every primitive your agents need — instructions, skills, prompts, agents, hooks, plugins, MCP servers — and `apm install` reproduces the exact same setup across every client on every machine. `apm.lock.yaml` pins the resolved tree the way `package-lock.json` does for npm.
|
|
69
69
|
|
|
70
|
-
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)**
|
|
70
|
+
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** -- declared once, deployed across Copilot, Claude, Grok Build, Cursor, OpenCode, Codex, Gemini, Windsurf, Kiro
|
|
71
71
|
- **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, Gitea, Gogs, any git host
|
|
72
72
|
- **[Transitive dependencies](https://microsoft.github.io/apm/guides/dependencies/)** — packages can depend on packages; APM resolves the full tree
|
|
73
73
|
- **[Author plugins](https://microsoft.github.io/apm/guides/plugins/)** — build Copilot, Claude, and Cursor plugins with dependency management, then export standard `plugin.json`
|
|
@@ -29,6 +29,7 @@ _ENV_PLACEHOLDER_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>|" + _ENV_VAR_RE.pattern)
|
|
|
29
29
|
# Detects the legacy ``<VAR>`` placeholder syntax only. Used to aggregate
|
|
30
30
|
# deprecation warnings across all servers in a single install run.
|
|
31
31
|
_LEGACY_ANGLE_VAR_RE = re.compile(r"<([A-Z_][A-Z0-9_]*)>")
|
|
32
|
+
_RUNTIME_TEMPLATE_VARIABLE_RE = re.compile(r"(?<!\$)\{([a-zA-Z_][a-zA-Z0-9_]*)\}")
|
|
32
33
|
|
|
33
34
|
# MCP Registry v0.1 names the container registry type ``oci``; the adapters
|
|
34
35
|
# below key their launcher dispatch on ``docker`` (the vocabulary the legacy
|
|
@@ -656,6 +657,94 @@ class MCPClientAdapter(ABC):
|
|
|
656
657
|
None,
|
|
657
658
|
)
|
|
658
659
|
|
|
660
|
+
@staticmethod
|
|
661
|
+
def _package_runtime_variable_metadata(
|
|
662
|
+
package: dict[str, Any] | None,
|
|
663
|
+
) -> dict[str, dict] | None:
|
|
664
|
+
"""Return one validated runtime-variable declaration map for a package.
|
|
665
|
+
|
|
666
|
+
Registry metadata may declare a variable on one argument and reference it
|
|
667
|
+
later without repeating the declaration. Keeping this map package-scoped
|
|
668
|
+
makes those references resolve consistently while rejecting malformed
|
|
669
|
+
secret metadata before an adapter can render a collected value.
|
|
670
|
+
"""
|
|
671
|
+
metadata_by_name: dict[str, dict] = {}
|
|
672
|
+
for field_name in ("runtime_arguments", "package_arguments"):
|
|
673
|
+
for argument in (package or {}).get(field_name) or []:
|
|
674
|
+
if not isinstance(argument, dict):
|
|
675
|
+
continue
|
|
676
|
+
variables = argument.get("variables")
|
|
677
|
+
if variables is None:
|
|
678
|
+
continue
|
|
679
|
+
if not isinstance(variables, dict):
|
|
680
|
+
return None
|
|
681
|
+
for name, metadata in variables.items():
|
|
682
|
+
if not isinstance(name, str) or not isinstance(metadata, dict):
|
|
683
|
+
return None
|
|
684
|
+
secret_marker = metadata.get("isSecret", metadata.get("is_secret", False))
|
|
685
|
+
if not isinstance(secret_marker, bool):
|
|
686
|
+
return None
|
|
687
|
+
existing = metadata_by_name.get(name)
|
|
688
|
+
if existing is not None and existing != metadata:
|
|
689
|
+
return None
|
|
690
|
+
metadata_by_name[name] = metadata
|
|
691
|
+
return metadata_by_name
|
|
692
|
+
|
|
693
|
+
@staticmethod
|
|
694
|
+
def _substitute_runtime_variables(
|
|
695
|
+
template: str,
|
|
696
|
+
variables: dict[object, object] | None,
|
|
697
|
+
runtime_vars: dict[str, object] | None,
|
|
698
|
+
runtime_variable_fallbacks: dict[str, str] | None = None,
|
|
699
|
+
secret_variable_fallbacks: dict[str, str] | None = None,
|
|
700
|
+
) -> str | None:
|
|
701
|
+
"""Resolve every APM runtime variable in one registry argument template.
|
|
702
|
+
|
|
703
|
+
Variable metadata may appear on an earlier argument while later
|
|
704
|
+
arguments reference the same value. Collected values therefore apply to
|
|
705
|
+
every template, not only the metadata-bearing entry. Target-specific
|
|
706
|
+
fallbacks are used only for declared variables with no collected value.
|
|
707
|
+
"""
|
|
708
|
+
secret_fallbacks = secret_variable_fallbacks or {}
|
|
709
|
+
values: dict[str, str] = dict(secret_fallbacks)
|
|
710
|
+
for name, value in (runtime_vars or {}).items():
|
|
711
|
+
if (
|
|
712
|
+
isinstance(name, str)
|
|
713
|
+
and name not in secret_fallbacks
|
|
714
|
+
and value is not None
|
|
715
|
+
and str(value) != ""
|
|
716
|
+
):
|
|
717
|
+
values[name] = str(value)
|
|
718
|
+
|
|
719
|
+
fallbacks = runtime_variable_fallbacks or {}
|
|
720
|
+
for name, metadata in (variables or {}).items():
|
|
721
|
+
if not isinstance(name, str) or not isinstance(metadata, dict):
|
|
722
|
+
return None
|
|
723
|
+
placeholder = f"{{{name}}}"
|
|
724
|
+
if placeholder not in template or name in values:
|
|
725
|
+
continue
|
|
726
|
+
secret_marker = metadata.get("isSecret", metadata.get("is_secret", False))
|
|
727
|
+
if not isinstance(secret_marker, bool):
|
|
728
|
+
return None
|
|
729
|
+
if secret_marker is True:
|
|
730
|
+
return None
|
|
731
|
+
fallback = fallbacks.get(name)
|
|
732
|
+
if fallback is not None:
|
|
733
|
+
values[name] = fallback
|
|
734
|
+
continue
|
|
735
|
+
configured = metadata.get("value", metadata.get("default"))
|
|
736
|
+
if isinstance(configured, str) and configured:
|
|
737
|
+
values[name] = configured
|
|
738
|
+
elif configured is not None:
|
|
739
|
+
return None
|
|
740
|
+
|
|
741
|
+
for name, value in values.items():
|
|
742
|
+
template = template.replace(f"{{{name}}}", value)
|
|
743
|
+
|
|
744
|
+
if _RUNTIME_TEMPLATE_VARIABLE_RE.search(template):
|
|
745
|
+
return None
|
|
746
|
+
return template
|
|
747
|
+
|
|
659
748
|
@staticmethod
|
|
660
749
|
def _processed_non_container_argument_groups(
|
|
661
750
|
arguments: list[object],
|
|
@@ -5,6 +5,7 @@ following the official documentation at:
|
|
|
5
5
|
https://code.visualstudio.com/docs/copilot/chat/mcp-servers
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import hashlib
|
|
8
9
|
import json
|
|
9
10
|
import re
|
|
10
11
|
from pathlib import Path
|
|
@@ -13,7 +14,13 @@ from ...core.docker_args import DockerArgsProcessor
|
|
|
13
14
|
from ...registry.client import SimpleRegistryClient
|
|
14
15
|
from ...registry.integration import RegistryIntegration
|
|
15
16
|
from ...utils.console import _rich_warning
|
|
16
|
-
from .base import
|
|
17
|
+
from .base import (
|
|
18
|
+
_ENV_VAR_RE,
|
|
19
|
+
_INPUT_VAR_RE,
|
|
20
|
+
_RUNTIME_TEMPLATE_VARIABLE_RE,
|
|
21
|
+
MCPClientAdapter,
|
|
22
|
+
registry_field_is_required,
|
|
23
|
+
)
|
|
17
24
|
|
|
18
25
|
# Legacy ``<VAR>`` placeholder (Copilot CLI / Codex only). VS Code does not
|
|
19
26
|
# resolve angle-bracket placeholders, so emitting them produces literal
|
|
@@ -298,7 +305,8 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
298
305
|
existing_server_config=existing_server_config,
|
|
299
306
|
)
|
|
300
307
|
secret_fallbacks, argument_inputs = self._declared_vscode_argument_secret_inputs(
|
|
301
|
-
package
|
|
308
|
+
package,
|
|
309
|
+
server_name=server_info.get("name", ""),
|
|
302
310
|
)
|
|
303
311
|
seen_input_ids = {item.get("id") for item in input_vars}
|
|
304
312
|
for input_definition in (*declared_inputs, *argument_inputs):
|
|
@@ -342,19 +350,29 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
342
350
|
|
|
343
351
|
# Handle docker packages
|
|
344
352
|
elif is_docker:
|
|
345
|
-
|
|
353
|
+
docker_kwargs = (
|
|
354
|
+
{"secret_variable_fallbacks": secret_fallbacks} if secret_fallbacks else {}
|
|
355
|
+
)
|
|
356
|
+
unresolved_variables: list[str] = []
|
|
357
|
+
args = self._docker_run_args(
|
|
358
|
+
package,
|
|
359
|
+
runtime_vars,
|
|
360
|
+
unresolved_variables=unresolved_variables,
|
|
361
|
+
**docker_kwargs,
|
|
362
|
+
)
|
|
346
363
|
if args is None:
|
|
347
364
|
if package.get("runtime_arguments") or package.get("package_arguments"):
|
|
365
|
+
variable_name = (
|
|
366
|
+
unresolved_variables[0] if unresolved_variables else "unknown"
|
|
367
|
+
)
|
|
348
368
|
_rich_warning(
|
|
349
|
-
"Could not resolve container run
|
|
350
|
-
f"'{package.get('name', '')}';
|
|
351
|
-
"
|
|
352
|
-
"'apm install'."
|
|
369
|
+
"Could not resolve required container run option "
|
|
370
|
+
f"'{variable_name}' for '{package.get('name', '')}'; "
|
|
371
|
+
"target configuration was not changed. Set the required "
|
|
372
|
+
"registry runtime variables and rerun 'apm install'."
|
|
353
373
|
)
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
package.get("name"),
|
|
357
|
-
)
|
|
374
|
+
return {}, []
|
|
375
|
+
args = self._ensure_docker_image_arg(["run", "-i", "--rm"], package.get("name"))
|
|
358
376
|
|
|
359
377
|
server_config = {"type": "stdio", "command": "docker", "args": args}
|
|
360
378
|
|
|
@@ -547,50 +565,50 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
547
565
|
return env_config, input_vars
|
|
548
566
|
|
|
549
567
|
@staticmethod
|
|
550
|
-
def
|
|
568
|
+
def _vscode_argument_secret_input_id(server_name: str, variable_name: str) -> str:
|
|
569
|
+
"""Return a collision-safe VS Code input ID for one server variable."""
|
|
570
|
+
server_digest = hashlib.sha256(server_name.encode("utf-8")).hexdigest()[:12]
|
|
571
|
+
return f"mcp-{server_digest}-{variable_name.encode('utf-8').hex()}"
|
|
572
|
+
|
|
573
|
+
@classmethod
|
|
574
|
+
def _declared_vscode_argument_secret_inputs(cls, package, *, server_name: str):
|
|
551
575
|
"""Return VS Code input indirections for secret argument variables."""
|
|
552
576
|
if not package:
|
|
553
577
|
return {}, []
|
|
578
|
+
package_variables = cls._package_runtime_variable_metadata(package)
|
|
579
|
+
if package_variables is None:
|
|
580
|
+
raise ValueError("MCP package argument variable metadata must be valid")
|
|
554
581
|
fallbacks = {}
|
|
555
582
|
input_vars = []
|
|
583
|
+
templates = []
|
|
556
584
|
for field_name in ("runtime_arguments", "package_arguments"):
|
|
557
585
|
for argument in package.get(field_name) or []:
|
|
558
586
|
if not isinstance(argument, dict):
|
|
559
587
|
continue
|
|
560
|
-
variables = argument.get("variables")
|
|
561
|
-
if not isinstance(variables, dict):
|
|
562
|
-
continue
|
|
563
588
|
template = argument.get(
|
|
564
589
|
"value",
|
|
565
590
|
argument.get("default", argument.get("value_hint", "")),
|
|
566
591
|
)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
"description": variable_info.get(
|
|
588
|
-
"description",
|
|
589
|
-
f"{variable_name} for MCP server",
|
|
590
|
-
),
|
|
591
|
-
"password": True,
|
|
592
|
-
}
|
|
593
|
-
)
|
|
592
|
+
if isinstance(template, str):
|
|
593
|
+
templates.append(template)
|
|
594
|
+
for variable_name, variable_info in package_variables.items():
|
|
595
|
+
if not any(f"{{{variable_name}}}" in template for template in templates):
|
|
596
|
+
continue
|
|
597
|
+
if not variable_info.get("isSecret", variable_info.get("is_secret", False)):
|
|
598
|
+
continue
|
|
599
|
+
input_id = cls._vscode_argument_secret_input_id(server_name, variable_name)
|
|
600
|
+
fallbacks[variable_name] = f"${{input:{input_id}}}"
|
|
601
|
+
input_vars.append(
|
|
602
|
+
{
|
|
603
|
+
"type": "promptString",
|
|
604
|
+
"id": input_id,
|
|
605
|
+
"description": variable_info.get(
|
|
606
|
+
"description",
|
|
607
|
+
f"{variable_name} for MCP server",
|
|
608
|
+
),
|
|
609
|
+
"password": True,
|
|
610
|
+
}
|
|
611
|
+
)
|
|
594
612
|
return fallbacks, input_vars
|
|
595
613
|
|
|
596
614
|
@staticmethod
|
|
@@ -776,7 +794,14 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
776
794
|
return extracted
|
|
777
795
|
|
|
778
796
|
@classmethod
|
|
779
|
-
def _docker_run_args(
|
|
797
|
+
def _docker_run_args(
|
|
798
|
+
cls,
|
|
799
|
+
package: dict,
|
|
800
|
+
runtime_vars: dict | None = None,
|
|
801
|
+
*,
|
|
802
|
+
secret_variable_fallbacks: dict[str, str] | None = None,
|
|
803
|
+
unresolved_variables: list[str] | None = None,
|
|
804
|
+
) -> list[str] | None:
|
|
780
805
|
"""Build ``docker run`` arguments from a container package's metadata.
|
|
781
806
|
|
|
782
807
|
Container packages retain a dedicated assembler because Docker requires
|
|
@@ -813,10 +838,27 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
813
838
|
"""
|
|
814
839
|
if not package:
|
|
815
840
|
return None
|
|
816
|
-
|
|
841
|
+
package_variables = cls._package_runtime_variable_metadata(package)
|
|
842
|
+
if package_variables is None:
|
|
843
|
+
if unresolved_variables is not None:
|
|
844
|
+
unresolved_variables.append("invalid metadata")
|
|
845
|
+
return None
|
|
846
|
+
run_options = cls._docker_arg_values(
|
|
847
|
+
package.get("runtime_arguments"),
|
|
848
|
+
runtime_vars,
|
|
849
|
+
secret_variable_fallbacks,
|
|
850
|
+
package_variables,
|
|
851
|
+
unresolved_variables,
|
|
852
|
+
)
|
|
817
853
|
if run_options is None:
|
|
818
854
|
return None
|
|
819
|
-
package_args = cls._docker_arg_values(
|
|
855
|
+
package_args = cls._docker_arg_values(
|
|
856
|
+
package.get("package_arguments"),
|
|
857
|
+
runtime_vars,
|
|
858
|
+
secret_variable_fallbacks,
|
|
859
|
+
package_variables,
|
|
860
|
+
unresolved_variables,
|
|
861
|
+
)
|
|
820
862
|
if package_args is None:
|
|
821
863
|
return None
|
|
822
864
|
if not run_options and package_args and package_args[0] == "run":
|
|
@@ -855,7 +897,12 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
855
897
|
|
|
856
898
|
@classmethod
|
|
857
899
|
def _docker_arg_values(
|
|
858
|
-
cls,
|
|
900
|
+
cls,
|
|
901
|
+
entries: list | None,
|
|
902
|
+
runtime_vars: dict | None,
|
|
903
|
+
secret_variable_fallbacks: dict[str, str] | None,
|
|
904
|
+
package_variables: dict[str, dict],
|
|
905
|
+
unresolved_variables: list[str] | None,
|
|
859
906
|
) -> list[str] | None:
|
|
860
907
|
"""Resolve one registry argument list into CLI argument strings.
|
|
861
908
|
|
|
@@ -903,47 +950,26 @@ class VSCodeClientAdapter(MCPClientAdapter):
|
|
|
903
950
|
continue
|
|
904
951
|
|
|
905
952
|
template = str(raw)
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
953
|
+
substituted = cls._substitute_runtime_variables(
|
|
954
|
+
template,
|
|
955
|
+
package_variables,
|
|
956
|
+
runtime_vars,
|
|
957
|
+
{"workspaceFolder": "${workspaceFolder}"},
|
|
958
|
+
secret_variable_fallbacks,
|
|
959
|
+
)
|
|
960
|
+
if substituted is None:
|
|
961
|
+
if required:
|
|
962
|
+
if unresolved_variables is not None:
|
|
963
|
+
match = _RUNTIME_TEMPLATE_VARIABLE_RE.search(template)
|
|
964
|
+
unresolved_variables.append(match.group(1) if match else "unknown")
|
|
965
|
+
return None
|
|
966
|
+
continue
|
|
967
|
+
template = substituted
|
|
914
968
|
if arg_type == "named" and arg.get("name"):
|
|
915
969
|
args.append(str(arg["name"]))
|
|
916
970
|
args.append(template)
|
|
917
971
|
return args
|
|
918
972
|
|
|
919
|
-
@staticmethod
|
|
920
|
-
def _substitute_runtime_variables(
|
|
921
|
-
template: str, variables: dict, runtime_vars: dict | None
|
|
922
|
-
) -> str | None:
|
|
923
|
-
"""Substitute ``{var}`` placeholders, or return None if unresolvable.
|
|
924
|
-
|
|
925
|
-
``workspaceFolder`` resolves to VS Code's own ``${workspaceFolder}``
|
|
926
|
-
token, which the editor expands at server start. Any other name that
|
|
927
|
-
this install did not collect a value for has no such fallback, so the
|
|
928
|
-
caller is told to decline rather than write a literal ``${name}`` into
|
|
929
|
-
a mount path.
|
|
930
|
-
"""
|
|
931
|
-
for var_name in variables:
|
|
932
|
-
placeholder = f"{{{var_name}}}"
|
|
933
|
-
# A descriptor the template never references cannot make it
|
|
934
|
-
# unresolvable; declining on one would drop a usable argument.
|
|
935
|
-
if placeholder not in template:
|
|
936
|
-
continue
|
|
937
|
-
supplied = (runtime_vars or {}).get(var_name)
|
|
938
|
-
if supplied is not None and str(supplied) != "":
|
|
939
|
-
replacement = str(supplied)
|
|
940
|
-
elif var_name == "workspaceFolder":
|
|
941
|
-
replacement = "${workspaceFolder}"
|
|
942
|
-
else:
|
|
943
|
-
return None
|
|
944
|
-
template = template.replace(placeholder, replacement)
|
|
945
|
-
return template
|
|
946
|
-
|
|
947
973
|
@staticmethod
|
|
948
974
|
def _select_remote_with_url(remotes):
|
|
949
975
|
"""Return the first remote entry that has a non-empty URL.
|
|
@@ -46,6 +46,13 @@ _CROSS_TARGET_MAPS: dict[str, dict[str, str]] = {
|
|
|
46
46
|
".github/skills/": ".agents/skills/",
|
|
47
47
|
".github/agents/": ".windsurf/skills/",
|
|
48
48
|
},
|
|
49
|
+
"grok-cloud": {
|
|
50
|
+
".github/skills/": ".grok/skills/",
|
|
51
|
+
},
|
|
52
|
+
"grok-build": {
|
|
53
|
+
".github/skills/": ".grok/skills/",
|
|
54
|
+
".github/agents/": ".grok/agents/",
|
|
55
|
+
},
|
|
49
56
|
"agent-skills": {
|
|
50
57
|
".github/skills/": ".agents/skills/",
|
|
51
58
|
},
|
|
@@ -131,32 +138,30 @@ def _filter_files_by_target(
|
|
|
131
138
|
if p not in seen_prefixes:
|
|
132
139
|
seen_prefixes.add(p)
|
|
133
140
|
prefixes.append(p)
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
# is benign -- common multi-target combos (e.g. claude+copilot)
|
|
138
|
-
# match prefixes directly without needing cross-maps.
|
|
139
|
-
cross_map: dict[str, str] = {}
|
|
141
|
+
# Preserve every selected target's cross-map so one source path can
|
|
142
|
+
# intentionally fan out to multiple target-specific destinations.
|
|
143
|
+
cross_maps: list[tuple[str, str]] = []
|
|
140
144
|
for t in target:
|
|
141
|
-
|
|
145
|
+
cross_maps.extend(_CROSS_TARGET_MAPS.get(t, {}).items())
|
|
142
146
|
else:
|
|
143
147
|
prefixes = _get_target_prefixes(target)
|
|
144
|
-
|
|
148
|
+
cross_maps = list(_CROSS_TARGET_MAPS.get(target, {}).items())
|
|
145
149
|
|
|
146
150
|
direct = [f for f in deployed_files if any(f.startswith(p) for p in prefixes)]
|
|
147
151
|
|
|
148
152
|
path_mappings: dict[str, str] = {}
|
|
149
|
-
if
|
|
153
|
+
if cross_maps:
|
|
150
154
|
direct_set = set(direct)
|
|
151
155
|
for f in deployed_files:
|
|
152
156
|
if f in direct_set:
|
|
153
157
|
continue
|
|
154
|
-
for src_prefix, dst_prefix in
|
|
158
|
+
for src_prefix, dst_prefix in cross_maps:
|
|
155
159
|
if f.startswith(src_prefix):
|
|
156
160
|
mapped = dst_prefix + f[len(src_prefix) :]
|
|
157
161
|
# Containment guard: normalise the remapped path and
|
|
158
|
-
# reject any result that escapes the destination prefix
|
|
159
|
-
#
|
|
162
|
+
# reject any result that escapes the destination prefix.
|
|
163
|
+
# The ".." check catches root-level escapes; the prefix
|
|
164
|
+
# check below is the authoritative containment barrier.
|
|
160
165
|
normalised = posixpath.normpath(mapped)
|
|
161
166
|
if ".." in normalised.split("/"):
|
|
162
167
|
continue
|
|
@@ -170,7 +175,6 @@ def _filter_files_by_target(
|
|
|
170
175
|
direct.append(mapped)
|
|
171
176
|
direct_set.add(mapped)
|
|
172
177
|
path_mappings[mapped] = f
|
|
173
|
-
break
|
|
174
178
|
|
|
175
179
|
return direct, path_mappings
|
|
176
180
|
|
|
@@ -19,6 +19,7 @@ from ..constants import (
|
|
|
19
19
|
APM_YML_FILENAME,
|
|
20
20
|
GITIGNORE_FILENAME,
|
|
21
21
|
)
|
|
22
|
+
from ..core import project_name as _project_name
|
|
22
23
|
from ..update_policy import get_update_hint_message, is_self_update_enabled
|
|
23
24
|
from ..utils.atomic_io import (
|
|
24
25
|
atomic_write_text as _atomic_write, # noqa: F401 -- re-exported; tests import from apm_cli.commands._helpers
|
|
@@ -29,6 +30,10 @@ from ..utils.version_checker import check_for_updates
|
|
|
29
30
|
from ..version import get_build_sha, get_version
|
|
30
31
|
from .deps._utils import _scan_installed_packages
|
|
31
32
|
|
|
33
|
+
# Thin compatibility aliases only; core/project_name.py remains the AC18 owner.
|
|
34
|
+
_resolve_bootstrap_project_name = _project_name.resolve_bootstrap_project_name
|
|
35
|
+
_validate_project_name = _project_name.validate_project_name
|
|
36
|
+
|
|
32
37
|
# CRITICAL: Shadow Click commands at module level to prevent namespace collision
|
|
33
38
|
# When Click commands like 'config set' are defined, calling set() can invoke the command
|
|
34
39
|
# instead of the Python built-in. This affects ALL functions in this module.
|
|
@@ -617,22 +622,6 @@ def _validate_plugin_name(name):
|
|
|
617
622
|
return bool(re.match(r"^[a-z][a-z0-9-]{0,63}$", name))
|
|
618
623
|
|
|
619
624
|
|
|
620
|
-
def _validate_project_name(name):
|
|
621
|
-
"""Validate that a project name is safe to use as a directory name.
|
|
622
|
-
|
|
623
|
-
Project names are used directly as directory names and must not contain
|
|
624
|
-
'/' or '\' so the name is not interpreted as a filesystem path,
|
|
625
|
-
and must not be '..' to prevent directory traversal.
|
|
626
|
-
|
|
627
|
-
Returns True if valid, False otherwise.
|
|
628
|
-
"""
|
|
629
|
-
if "/" in name or "\\" in name:
|
|
630
|
-
return False
|
|
631
|
-
if name == "..": # noqa: SIM103
|
|
632
|
-
return False
|
|
633
|
-
return True
|
|
634
|
-
|
|
635
|
-
|
|
636
625
|
def _create_plugin_json(config):
|
|
637
626
|
"""Create plugin.json file with package metadata.
|
|
638
627
|
|
|
@@ -11,6 +11,7 @@ import click
|
|
|
11
11
|
# Import existing APM components
|
|
12
12
|
from ...constants import APM_MODULES_DIR, APM_YML_FILENAME, SKILL_MD_FILENAME
|
|
13
13
|
from ...core.command_logger import CommandLogger
|
|
14
|
+
from ...core.project_name import DEFAULT_BOOTSTRAP_PROJECT_NAME
|
|
14
15
|
from ...core.target_detection import TargetParamType
|
|
15
16
|
from ...deps.lockfile import LockedDependency
|
|
16
17
|
from ...models.apm_package import APMPackage
|
|
@@ -644,7 +645,7 @@ def _build_dep_tree(apm_dir):
|
|
|
644
645
|
apm_modules_path = apm_dir / APM_MODULES_DIR
|
|
645
646
|
|
|
646
647
|
# Load project info
|
|
647
|
-
project_name =
|
|
648
|
+
project_name = DEFAULT_BOOTSTRAP_PROJECT_NAME
|
|
648
649
|
try:
|
|
649
650
|
apm_yml_path = apm_dir / APM_YML_FILENAME
|
|
650
651
|
if apm_yml_path.exists():
|
|
@@ -10,6 +10,10 @@ import click
|
|
|
10
10
|
from ..bundle.plugin_layout import find_plugin_root_sources
|
|
11
11
|
from ..constants import APM_YML_FILENAME
|
|
12
12
|
from ..core.command_logger import CommandLogger
|
|
13
|
+
from ..core.project_name import (
|
|
14
|
+
resolve_bootstrap_project_name as _resolve_bootstrap_project_name,
|
|
15
|
+
)
|
|
16
|
+
from ..core.project_name import validate_project_name as _validate_project_name
|
|
13
17
|
from ..core.target_detection import (
|
|
14
18
|
EXPLICIT_ONLY_TARGETS,
|
|
15
19
|
TargetParamType,
|
|
@@ -29,7 +33,6 @@ from ._helpers import (
|
|
|
29
33
|
_get_default_config,
|
|
30
34
|
_rich_blank_line,
|
|
31
35
|
_validate_plugin_name,
|
|
32
|
-
_validate_project_name,
|
|
33
36
|
)
|
|
34
37
|
|
|
35
38
|
|
|
@@ -146,10 +149,11 @@ def _perform_init(
|
|
|
146
149
|
project_name = None
|
|
147
150
|
|
|
148
151
|
# Reject names containing path separators before any filesystem use
|
|
149
|
-
if project_name and not _validate_project_name(project_name):
|
|
152
|
+
if project_name is not None and not _validate_project_name(project_name):
|
|
150
153
|
logger.error(
|
|
151
154
|
f"Invalid project name '{project_name}': "
|
|
152
|
-
"project names must not
|
|
155
|
+
"project names must not be empty or whitespace-only and must not contain "
|
|
156
|
+
"path separators ('/' or '\\\\') or be '..'."
|
|
153
157
|
)
|
|
154
158
|
sys.exit(1)
|
|
155
159
|
|
|
@@ -162,7 +166,14 @@ def _perform_init(
|
|
|
162
166
|
final_project_name = project_name
|
|
163
167
|
else:
|
|
164
168
|
project_dir = Path.cwd()
|
|
165
|
-
|
|
169
|
+
# A filesystem root has no directory name, so resolve a valid fallback.
|
|
170
|
+
derived_project_name = project_dir.name
|
|
171
|
+
final_project_name = _resolve_bootstrap_project_name(derived_project_name)
|
|
172
|
+
if final_project_name != derived_project_name:
|
|
173
|
+
logger.verbose_detail(
|
|
174
|
+
f'Using default project name "{final_project_name}" because '
|
|
175
|
+
f"derived name {derived_project_name!a} is invalid"
|
|
176
|
+
)
|
|
166
177
|
project_root = Path.cwd()
|
|
167
178
|
|
|
168
179
|
# Validate plugin name early
|
|
@@ -395,7 +406,8 @@ def _interactive_project_setup(default_name, logger):
|
|
|
395
406
|
break
|
|
396
407
|
console.print(
|
|
397
408
|
f"[error]Invalid project name '{name}': "
|
|
398
|
-
"project names must not
|
|
409
|
+
"project names must not be empty or whitespace-only and must not contain "
|
|
410
|
+
"path separators ('/' or '\\\\') or be '..'.[/error]"
|
|
399
411
|
)
|
|
400
412
|
|
|
401
413
|
version = Prompt.ask("Version", default="1.0.0").strip()
|
|
@@ -412,7 +424,8 @@ def _interactive_project_setup(default_name, logger):
|
|
|
412
424
|
break
|
|
413
425
|
click.echo(
|
|
414
426
|
f"{ERROR}Invalid project name '{name}': "
|
|
415
|
-
f"project names must not
|
|
427
|
+
f"project names must not be empty or whitespace-only and must not contain "
|
|
428
|
+
f"path separators ('/' or '\\\\') or be '..'.{RESET}"
|
|
416
429
|
)
|
|
417
430
|
|
|
418
431
|
version = click.prompt("Version", default="1.0.0").strip()
|