apm-cli 0.12.4__tar.gz → 0.14.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.12.4 → apm_cli-0.14.0}/NOTICE +1 -1
- {apm_cli-0.12.4/src/apm_cli.egg-info → apm_cli-0.14.0}/PKG-INFO +5 -3
- {apm_cli-0.12.4 → apm_cli-0.14.0}/README.md +1 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/pyproject.toml +15 -3
- apm_cli-0.14.0/src/apm_cli/adapters/client/base.py +451 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/codex.py +14 -102
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/copilot.py +176 -194
- apm_cli-0.14.0/src/apm_cli/adapters/client/cursor.py +240 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/gemini.py +42 -19
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/opencode.py +3 -13
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/local_bundle.py +18 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/plugin_exporter.py +43 -9
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/unpacker.py +16 -4
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/git_cache.py +3 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cli.py +4 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/_apm_yml_writer.py +12 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/_helpers.py +1 -24
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/audit.py +15 -7
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/compile/cli.py +83 -2
- apm_cli-0.14.0/src/apm_cli/commands/compile/watcher.py +249 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/config.py +6 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/deps/cli.py +43 -34
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/init.py +64 -5
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/install.py +243 -119
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/__init__.py +53 -27
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/doctor.py +59 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/init.py +2 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/outdated.py +34 -1
- apm_cli-0.14.0/src/apm_cli/commands/pack.py +765 -0
- apm_cli-0.14.0/src/apm_cli/commands/plugin/__init__.py +21 -0
- apm_cli-0.14.0/src/apm_cli/commands/plugin/init.py +44 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/policy.py +3 -3
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/run.py +1 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/runtime.py +1 -1
- apm_cli-0.12.4/src/apm_cli/commands/update.py → apm_cli-0.14.0/src/apm_cli/commands/self_update.py +17 -8
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/uninstall/cli.py +14 -6
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/uninstall/engine.py +222 -12
- apm_cli-0.14.0/src/apm_cli/commands/update.py +353 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/claude_formatter.py +4 -15
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/distributed_compiler.py +4 -13
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/template_builder.py +40 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/apm_yml.py +10 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/auth.py +254 -88
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/build_orchestrator.py +59 -18
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/command_logger.py +20 -2
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/errors.py +30 -4
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/script_runner.py +11 -11
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/token_manager.py +149 -7
- apm_cli-0.14.0/src/apm_cli/deps/_shared.py +40 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/apm_resolver.py +83 -15
- apm_cli-0.14.0/src/apm_cli/deps/artifactory_orchestrator.py +309 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/bare_cache.py +252 -7
- apm_cli-0.14.0/src/apm_cli/deps/clone_engine.py +342 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/download_strategies.py +475 -126
- apm_cli-0.14.0/src/apm_cli/deps/git_auth_env.py +152 -0
- apm_cli-0.14.0/src/apm_cli/deps/git_reference_resolver.py +417 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/github_downloader.py +213 -927
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/github_downloader_validation.py +13 -0
- apm_cli-0.14.0/src/apm_cli/deps/host_backends.py +623 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/package_validator.py +47 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/registry_proxy.py +14 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/shared_clone_cache.py +75 -0
- apm_cli-0.14.0/src/apm_cli/deps/tiered_ref_resolver.py +491 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/context.py +1 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/errors.py +23 -0
- apm_cli-0.14.0/src/apm_cli/install/gitlab_resolver.py +41 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/local_bundle_handler.py +180 -3
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/command.py +5 -2
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/entry.py +5 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/writer.py +5 -0
- apm_cli-0.14.0/src/apm_cli/install/package_resolution.py +162 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/resolve.py +26 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/targets.py +14 -4
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/pipeline.py +145 -35
- apm_cli-0.14.0/src/apm_cli/install/plan.py +425 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/request.py +15 -2
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/service.py +65 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/services.py +129 -14
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/validation.py +113 -32
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/agent_integrator.py +102 -43
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/base_integrator.py +181 -5
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/command_integrator.py +17 -10
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/hook_integrator.py +190 -11
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/instruction_integrator.py +12 -10
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/mcp_integrator.py +166 -545
- apm_cli-0.14.0/src/apm_cli/integration/mcp_integrator_install.py +601 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/prompt_integrator.py +27 -12
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/targets.py +35 -7
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/__init__.py +2 -0
- apm_cli-0.14.0/src/apm_cli/marketplace/_shared.py +48 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/builder.py +271 -308
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/client.py +80 -48
- apm_cli-0.14.0/src/apm_cli/marketplace/diagnostics.py +13 -0
- apm_cli-0.14.0/src/apm_cli/marketplace/drift_check.py +258 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/init_template.py +22 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/models.py +3 -3
- apm_cli-0.14.0/src/apm_cli/marketplace/output_mappers.py +342 -0
- apm_cli-0.14.0/src/apm_cli/marketplace/output_profiles.py +100 -0
- apm_cli-0.14.0/src/apm_cli/marketplace/resolver.py +770 -0
- apm_cli-0.14.0/src/apm_cli/marketplace/version_check.py +248 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/yml_schema.py +356 -4
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/apm_package.py +49 -5
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/dependency/reference.py +395 -50
- apm_cli-0.14.0/src/apm_cli/policy/_shared.py +40 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/ci_checks.py +40 -22
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/discovery.py +6 -6
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/inheritance.py +63 -6
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/matcher.py +1 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/models.py +1 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/parser.py +28 -10
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/policy_checks.py +11 -23
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/schema.py +34 -7
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/registry/client.py +206 -64
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/base.py +40 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/codex_runtime.py +4 -3
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/copilot_runtime.py +4 -24
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/llm_runtime.py +2 -20
- apm_cli-0.14.0/src/apm_cli/runtime/utils.py +66 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/console.py +22 -4
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/github_host.py +203 -13
- {apm_cli-0.12.4 → apm_cli-0.14.0/src/apm_cli.egg-info}/PKG-INFO +5 -3
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli.egg-info/SOURCES.txt +22 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli.egg-info/requires.txt +3 -1
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_github_downloader.py +576 -30
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_token_manager.py +270 -18
- apm_cli-0.12.4/src/apm_cli/adapters/client/base.py +0 -198
- apm_cli-0.12.4/src/apm_cli/adapters/client/cursor.py +0 -144
- apm_cli-0.12.4/src/apm_cli/commands/compile/watcher.py +0 -170
- apm_cli-0.12.4/src/apm_cli/commands/pack.py +0 -388
- apm_cli-0.12.4/src/apm_cli/marketplace/resolver.py +0 -370
- {apm_cli-0.12.4 → apm_cli-0.14.0}/AUTHORS +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/LICENSE +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/setup.cfg +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/claude.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/vscode.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/client/windsurf.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/package_manager/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/package_manager/base.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/adapters/package_manager/default_manager.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/lockfile_enrichment.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/bundle/packer.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/http_cache.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/integrity.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/locking.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/paths.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/cache/url_normalize.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/cache.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/compile/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/deps/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/deps/_utils.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/experimental.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/list_cmd.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/check.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/migrate.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/outdated.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/plugin/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/plugin/add.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/plugin/remove.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/plugin/set.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/publish.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/marketplace/validate.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/mcp.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/prune.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/targets.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/uninstall/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/commands/view.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/agents_compiler.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/build_id.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/constants.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/constitution.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/constitution_block.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/context_optimizer.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/gemini_formatter.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/injector.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/link_resolver.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/compilation/output_writer.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/config.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/constants.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/azure_cli.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/conflict_detector.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/docker_args.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/experimental.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/null_logger.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/operations.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/safe_installer.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/scope.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/core/target_detection.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/aggregator.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/artifactory_entry.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/dependency_graph.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/git_remote_ops.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/installed_package.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/lockfile.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/plugin_parser.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/transport_selection.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/deps/verifier.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/drift.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/factory.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/cache_pin.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/drift.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/heals/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/heals/base.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/heals/branch_ref_drift.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/heals/buggy_lockfile_recovery.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/helpers/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/helpers/security_scan.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/insecure_policy.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/args.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/conflicts.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/registry.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/mcp/warnings.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/cleanup.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/download.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/finalize.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/heal.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/integrate.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/local_content.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/lockfile.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/policy_gate.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/policy_target_check.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/phases/post_deps_local.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/presentation/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/presentation/dry_run.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/skill_path_migration.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/sources.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/summary.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/install/template.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/cleanup.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/copilot_cowork_paths.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/coverage.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/dispatch.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/skill_integrator.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/skill_transformer.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/integration/utils.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/_git_utils.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/_io.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/errors.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/git_stderr.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/migration.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/pr_integration.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/publisher.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/ref_resolver.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/registry.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/semver.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/shadow_detector.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/tag_pattern.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/validator.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/version_pins.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/marketplace/yml_editor.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/dependency/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/dependency/mcp.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/dependency/types.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/plugin.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/results.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/models/validation.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/output/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/output/formatters.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/output/models.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/output/script_formatters.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/_help_text.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/install_preflight.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/outcome_routing.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/policy/project_config.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/primitives/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/primitives/discovery.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/primitives/models.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/primitives/parser.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/registry/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/registry/integration.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/registry/operations.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/factory.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/runtime/manager.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/security/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/security/audit_report.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/security/content_scanner.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/security/file_scanner.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/security/gate.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/update_policy.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/atomic_io.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/content_hash.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/diagnostics.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/exclude.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/file_ops.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/git_env.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/guards.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/helpers.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/install_tui.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/normalization.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/path_security.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/paths.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/reflink.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/short_sha.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/subprocess_env.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/version_checker.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/utils/yaml_io.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/version.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/workflow/__init__.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/workflow/discovery.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/workflow/parser.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli/workflow/runner.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli.egg-info/dependency_links.txt +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli.egg-info/entry_points.txt +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/src/apm_cli.egg-info/top_level.txt +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_apm_package_models.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_apm_resolver.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_codex_docker_args_fix.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_codex_empty_string_and_defaults.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_collision_integration.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_console.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_distributed_compilation.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_empty_string_and_defaults.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_enhanced_discovery.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_github_downloader_token_precedence.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_lockfile.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_runnable_prompts.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_runtime_manager_token_precedence.py +0 -0
- {apm_cli-0.12.4 → apm_cli-0.14.0}/tests/test_virtual_package_multi_install.py +0 -0
|
@@ -139,7 +139,7 @@ SOFTWARE.
|
|
|
139
139
|
|
|
140
140
|
## Component. requests
|
|
141
141
|
|
|
142
|
-
- Version requirement: `>=2.
|
|
142
|
+
- Version requirement: `>=2.31.0`
|
|
143
143
|
- Upstream: https://github.com/psf/requests
|
|
144
144
|
- SPDX: `Apache-2.0`
|
|
145
145
|
- Notes: Apache-2.0 requires forwarding the upstream NOTICE file verbatim.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apm-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: MCP configuration tool
|
|
5
5
|
Author-email: Daniel Meppiel <user@example.com>
|
|
6
6
|
License: MIT License
|
|
@@ -40,7 +40,7 @@ License-File: AUTHORS
|
|
|
40
40
|
Requires-Dist: click>=8.0.0
|
|
41
41
|
Requires-Dist: colorama>=0.4.6
|
|
42
42
|
Requires-Dist: pyyaml>=6.0.0
|
|
43
|
-
Requires-Dist: requests>=2.
|
|
43
|
+
Requires-Dist: requests>=2.31.0
|
|
44
44
|
Requires-Dist: python-frontmatter>=1.0.0
|
|
45
45
|
Requires-Dist: llm>=0.17.0
|
|
46
46
|
Requires-Dist: llm-github-models>=0.1.0
|
|
@@ -56,9 +56,11 @@ Provides-Extra: dev
|
|
|
56
56
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
57
57
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
58
58
|
Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
|
|
59
|
+
Requires-Dist: pytest-split>=0.9.0; extra == "dev"
|
|
59
60
|
Requires-Dist: ruff>=0.11.0; extra == "dev"
|
|
60
61
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
61
62
|
Requires-Dist: jsonschema>=4.0.0; extra == "dev"
|
|
63
|
+
Requires-Dist: pylint>=3.0.0; extra == "dev"
|
|
62
64
|
Provides-Extra: build
|
|
63
65
|
Requires-Dist: pyinstaller>=6.0.0; extra == "build"
|
|
64
66
|
Dynamic: license-file
|
|
@@ -133,7 +135,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
|
|
|
133
135
|
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.
|
|
134
136
|
|
|
135
137
|
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf
|
|
136
|
-
- **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, any git host
|
|
138
|
+
- **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, Gitea, Gogs, any git host
|
|
137
139
|
- **[Transitive dependencies](https://microsoft.github.io/apm/guides/dependencies/)** — packages can depend on packages; APM resolves the full tree
|
|
138
140
|
- **[Author plugins](https://microsoft.github.io/apm/guides/plugins/)** — build Copilot, Claude, and Cursor plugins with dependency management, then export standard `plugin.json`
|
|
139
141
|
- **[Marketplaces](https://microsoft.github.io/apm/guides/marketplaces/)** — install plugins from curated registries in one command, deployed across all targets and locked
|
|
@@ -68,7 +68,7 @@ One command, no configuration -- VS Code and GitHub Copilot read the file automa
|
|
|
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
70
|
- **[One manifest for everything](https://microsoft.github.io/apm/reference/primitive-types/)** — declared once, deployed across Copilot, Claude, Cursor, OpenCode, Codex, Gemini, Windsurf
|
|
71
|
-
- **[Install from anywhere](https://microsoft.github.io/apm/guides/dependencies/)** — GitHub, GitLab, Bitbucket, Azure DevOps, GitHub Enterprise, any git host
|
|
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`
|
|
74
74
|
- **[Marketplaces](https://microsoft.github.io/apm/guides/marketplaces/)** — install plugins from curated registries in one command, deployed across all targets and locked
|
|
@@ -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.14.0"
|
|
8
8
|
description = "MCP configuration tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -25,7 +25,7 @@ dependencies = [
|
|
|
25
25
|
"click>=8.0.0",
|
|
26
26
|
"colorama>=0.4.6",
|
|
27
27
|
"pyyaml>=6.0.0",
|
|
28
|
-
"requests>=2.
|
|
28
|
+
"requests>=2.31.0",
|
|
29
29
|
"python-frontmatter>=1.0.0",
|
|
30
30
|
"llm>=0.17.0",
|
|
31
31
|
"llm-github-models>=0.1.0",
|
|
@@ -44,9 +44,11 @@ dev = [
|
|
|
44
44
|
"pytest>=7.0.0",
|
|
45
45
|
"pytest-cov>=4.0.0",
|
|
46
46
|
"pytest-xdist>=3.0.0",
|
|
47
|
+
"pytest-split>=0.9.0",
|
|
47
48
|
"ruff>=0.11.0",
|
|
48
49
|
"mypy>=1.0.0",
|
|
49
50
|
"jsonschema>=4.0.0",
|
|
51
|
+
"pylint>=3.0.0",
|
|
50
52
|
]
|
|
51
53
|
build = [
|
|
52
54
|
"pyinstaller>=6.0.0",
|
|
@@ -128,11 +130,21 @@ warn_return_any = true
|
|
|
128
130
|
warn_unused_configs = true
|
|
129
131
|
|
|
130
132
|
[tool.pytest.ini_options]
|
|
131
|
-
addopts = "-m 'not benchmark'"
|
|
133
|
+
addopts = "-m 'not benchmark and not live'"
|
|
132
134
|
markers = [
|
|
133
135
|
"integration: marks tests as integration tests that may require network access",
|
|
134
136
|
"live: marks tests that hit real GitHub repos (requires network + optional GITHUB_TOKEN)",
|
|
135
137
|
"slow: marks tests as slow running tests",
|
|
136
138
|
"benchmark: marks performance benchmark tests (deselected by default, run with -m benchmark)",
|
|
139
|
+
"requires_e2e_mode: requires APM_E2E_TESTS=1",
|
|
140
|
+
"requires_github_token: requires GITHUB_APM_PAT or GITHUB_TOKEN",
|
|
141
|
+
"requires_ado_pat: requires ADO_APM_PAT",
|
|
142
|
+
"requires_ado_bearer: requires az CLI logged in + APM_TEST_ADO_BEARER=1",
|
|
143
|
+
"requires_network_integration: requires APM_RUN_INTEGRATION_TESTS=1",
|
|
144
|
+
"requires_apm_binary: requires built apm binary on PATH (or APM_BINARY_PATH)",
|
|
145
|
+
"requires_runtime_codex: requires codex runtime installed",
|
|
146
|
+
"requires_runtime_copilot: requires GitHub Copilot CLI runtime installed",
|
|
147
|
+
"requires_runtime_llm: requires llm runtime installed",
|
|
148
|
+
"requires_inference: requires APM_RUN_INFERENCE_TESTS=1 + model API access",
|
|
137
149
|
]
|
|
138
150
|
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"""Base adapter interface for MCP clients."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from ...utils.console import _rich_error, _rich_warning
|
|
9
|
+
|
|
10
|
+
_INPUT_VAR_RE = re.compile(r"\$\{input:([^}]+)\}")
|
|
11
|
+
|
|
12
|
+
# Matches ${VAR} and ${env:VAR}, capturing VAR. Intentionally does NOT match
|
|
13
|
+
# ${input:VAR} (the optional ``env:`` group cannot also satisfy ``input:``),
|
|
14
|
+
# nor GitHub Actions ``${{ ... }}`` templates (the second ``{`` fails the
|
|
15
|
+
# identifier class). This keeps env-var handling fully disjoint from input
|
|
16
|
+
# variable handling, so existing _INPUT_VAR_RE call sites are unaffected.
|
|
17
|
+
_ENV_VAR_RE = re.compile(r"\$\{(?:env:)?([A-Za-z_][A-Za-z0-9_]*)\}")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MCPClientAdapter(ABC):
|
|
21
|
+
"""Base adapter for MCP clients."""
|
|
22
|
+
|
|
23
|
+
# Identifier matching the corresponding ``KNOWN_TARGETS`` entry name.
|
|
24
|
+
# Subclasses MUST override this so target-aware code can look up
|
|
25
|
+
# per-target metadata via ``KNOWN_TARGETS[adapter.target_name]``
|
|
26
|
+
# instead of sniffing class names. The ``vscode`` adapter is the
|
|
27
|
+
# only MCP-only pseudo-target (no entry in ``KNOWN_TARGETS``), so
|
|
28
|
+
# downstream code that joins on this field must tolerate misses.
|
|
29
|
+
target_name: str = ""
|
|
30
|
+
|
|
31
|
+
# Top-level config key under which this adapter's MCP server entries
|
|
32
|
+
# live (``"mcpServers"``, ``"mcp_servers"``, ``"servers"``, ...).
|
|
33
|
+
# Subclasses MUST override this; ``MCPConflictDetector`` reads it to
|
|
34
|
+
# extract existing server configs without classname dispatch.
|
|
35
|
+
# The adapter is the canonical owner of its config schema, so this
|
|
36
|
+
# field lives here rather than on ``TargetProfile`` (which is
|
|
37
|
+
# primitive-focused) and applies uniformly to MCP-only adapters
|
|
38
|
+
# (e.g. ``VSCodeClientAdapter``) that have no ``KNOWN_TARGETS`` entry.
|
|
39
|
+
mcp_servers_key: str = ""
|
|
40
|
+
|
|
41
|
+
# Whether this adapter's config path is user/global-scoped (e.g.
|
|
42
|
+
# ``~/.copilot/``) rather than workspace-scoped (e.g. ``.vscode/``).
|
|
43
|
+
# Adapters that target a global path should override this to ``True``
|
|
44
|
+
# so that ``apm install --global`` can install MCP servers to them.
|
|
45
|
+
supports_user_scope: bool = False
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
project_root: Path | str | None = None,
|
|
50
|
+
user_scope: bool = False,
|
|
51
|
+
):
|
|
52
|
+
"""Initialize the adapter with optional scope-aware path context.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
project_root: Project root used to resolve project-local config paths.
|
|
56
|
+
When not provided, adapters fall back to the current working
|
|
57
|
+
directory for project-scoped paths.
|
|
58
|
+
user_scope: Whether the adapter should resolve user-scope config
|
|
59
|
+
paths instead of project-local paths when supported.
|
|
60
|
+
"""
|
|
61
|
+
self._project_root = Path(project_root) if project_root is not None else None
|
|
62
|
+
self.user_scope = user_scope
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def project_root(self) -> Path:
|
|
66
|
+
"""Return the explicit project root or the current working directory."""
|
|
67
|
+
if self._project_root is not None:
|
|
68
|
+
return self._project_root
|
|
69
|
+
return Path(os.getcwd())
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def get_config_path(self):
|
|
73
|
+
"""Get the path to the MCP configuration file."""
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def update_config(self, config_updates) -> bool | None:
|
|
78
|
+
"""Update the MCP configuration.
|
|
79
|
+
|
|
80
|
+
Returns ``False`` or ``None`` when the config write was skipped
|
|
81
|
+
(for example because the existing file could not be parsed safely).
|
|
82
|
+
"""
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def get_current_config(self):
|
|
87
|
+
"""Get the current MCP configuration."""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def configure_mcp_server(
|
|
92
|
+
self,
|
|
93
|
+
server_url,
|
|
94
|
+
server_name=None,
|
|
95
|
+
enabled=True,
|
|
96
|
+
env_overrides=None,
|
|
97
|
+
server_info_cache=None,
|
|
98
|
+
runtime_vars=None,
|
|
99
|
+
):
|
|
100
|
+
"""Configure an MCP server in the client configuration.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
server_url (str): URL of the MCP server.
|
|
104
|
+
server_name (str, optional): Name of the server. Defaults to None.
|
|
105
|
+
enabled (bool, optional): Whether to enable the server. Defaults to True.
|
|
106
|
+
env_overrides (dict, optional): Environment variable overrides. Defaults to None.
|
|
107
|
+
server_info_cache (dict, optional): Pre-fetched server info to avoid duplicate registry calls.
|
|
108
|
+
runtime_vars (dict, optional): Runtime variable values. Defaults to None.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
bool: True if successful, False otherwise.
|
|
112
|
+
"""
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def _infer_registry_name(package):
|
|
117
|
+
"""Infer the registry type from package metadata.
|
|
118
|
+
|
|
119
|
+
The MCP registry API often returns empty ``registry_name``. This
|
|
120
|
+
method derives the registry from explicit fields first, then falls
|
|
121
|
+
back to heuristics on the package name.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
package (dict): A single package entry from the registry.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
str: Inferred registry name (e.g. "npm", "pypi", "docker") or "".
|
|
128
|
+
"""
|
|
129
|
+
if not package:
|
|
130
|
+
return ""
|
|
131
|
+
|
|
132
|
+
explicit = package.get("registry_name", "")
|
|
133
|
+
if explicit:
|
|
134
|
+
return explicit
|
|
135
|
+
|
|
136
|
+
name = package.get("name", "")
|
|
137
|
+
runtime_hint = package.get("runtime_hint", "")
|
|
138
|
+
|
|
139
|
+
# Infer from runtime_hint
|
|
140
|
+
if runtime_hint in ("npx", "npm"):
|
|
141
|
+
return "npm"
|
|
142
|
+
if runtime_hint in ("uvx", "pip", "pipx"):
|
|
143
|
+
return "pypi"
|
|
144
|
+
if runtime_hint == "docker":
|
|
145
|
+
return "docker"
|
|
146
|
+
if runtime_hint in ("dotnet", "dnx"):
|
|
147
|
+
return "nuget"
|
|
148
|
+
|
|
149
|
+
# Infer from package name patterns
|
|
150
|
+
if name.startswith("@") and "/" in name:
|
|
151
|
+
return "npm" # scoped npm package, e.g. @azure/mcp
|
|
152
|
+
if name.startswith(("ghcr.io/", "mcr.microsoft.com/", "docker.io/")):
|
|
153
|
+
return "docker"
|
|
154
|
+
if name.startswith("https://") and name.endswith(".mcpb"):
|
|
155
|
+
return "mcpb"
|
|
156
|
+
# PascalCase with dots usually means nuget (e.g. Azure.Mcp)
|
|
157
|
+
if "." in name and not name.startswith("http") and name[0].isupper():
|
|
158
|
+
return "nuget"
|
|
159
|
+
|
|
160
|
+
return ""
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def _warn_input_variables(mapping, server_name, runtime_label):
|
|
164
|
+
"""Emit a warning for each ``${input:...}`` reference found in *mapping*.
|
|
165
|
+
|
|
166
|
+
Runtimes that do not support VS Code-style input prompts (Copilot CLI,
|
|
167
|
+
Codex CLI, etc.) should call this so users know their placeholders
|
|
168
|
+
will not be resolved at runtime.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
mapping (dict): Header or env dict to scan.
|
|
172
|
+
server_name (str): Server name for the warning message.
|
|
173
|
+
runtime_label (str): Human-readable runtime name (e.g. "Copilot CLI").
|
|
174
|
+
"""
|
|
175
|
+
if not mapping:
|
|
176
|
+
return
|
|
177
|
+
seen: set = set()
|
|
178
|
+
for value in mapping.values():
|
|
179
|
+
if not isinstance(value, str):
|
|
180
|
+
continue
|
|
181
|
+
for match in _INPUT_VAR_RE.finditer(value):
|
|
182
|
+
var_id = match.group(1)
|
|
183
|
+
if var_id in seen:
|
|
184
|
+
continue
|
|
185
|
+
seen.add(var_id)
|
|
186
|
+
_rich_warning(
|
|
187
|
+
f"${{input:{var_id}}} in server "
|
|
188
|
+
f"'{server_name}' will not be resolved -- "
|
|
189
|
+
f"{runtime_label} does not support input variable prompts"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def normalize_project_arg(self, value):
|
|
193
|
+
"""Normalize workspace placeholders for project-local runtimes."""
|
|
194
|
+
if (
|
|
195
|
+
not self.user_scope
|
|
196
|
+
and isinstance(value, str)
|
|
197
|
+
and value in {"${workspaceFolder}", "${projectRoot}", "${workspaceRoot}"}
|
|
198
|
+
):
|
|
199
|
+
return "."
|
|
200
|
+
return value
|
|
201
|
+
|
|
202
|
+
# ------------------------------------------------------------------
|
|
203
|
+
# Shared server-info helpers (used by all adapter subclasses)
|
|
204
|
+
# ------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
def _fetch_server_info(self, server_url: str, server_info_cache: dict | None) -> dict | None:
|
|
207
|
+
"""Look up *server_url* in *server_info_cache* or fetch from registry.
|
|
208
|
+
|
|
209
|
+
Prints a user-visible error and returns ``None`` when the server is
|
|
210
|
+
not found, so callers can do a simple ``if server_info is None: return False``
|
|
211
|
+
guard and the error message stays consistent across adapters.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
server_url: Registry reference (``owner/repo`` or full URL).
|
|
215
|
+
server_info_cache: Optional pre-fetched cache; ``None`` skips
|
|
216
|
+
the cache lookup.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Server-info dict on success; ``None`` when not found.
|
|
220
|
+
"""
|
|
221
|
+
if server_info_cache and server_url in server_info_cache:
|
|
222
|
+
return server_info_cache[server_url]
|
|
223
|
+
server_info = self.registry_client.find_server_by_reference(server_url)
|
|
224
|
+
if not server_info:
|
|
225
|
+
_rich_error(f"Error: MCP server '{server_url}' not found in registry")
|
|
226
|
+
return None
|
|
227
|
+
return server_info
|
|
228
|
+
|
|
229
|
+
@staticmethod
|
|
230
|
+
def _determine_config_key(server_url: str, server_name: str) -> str:
|
|
231
|
+
"""Return the configuration key to use for *server_url*/*server_name*.
|
|
232
|
+
|
|
233
|
+
The caller-supplied *server_name* takes precedence; if empty the last
|
|
234
|
+
path segment of *server_url* is used as a fallback, which mirrors the
|
|
235
|
+
convention ``owner/repo -> repo``.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
server_url: Registry reference used as fallback source.
|
|
239
|
+
server_name: Explicit caller-supplied name (may be empty string).
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Non-empty configuration key string.
|
|
243
|
+
"""
|
|
244
|
+
if server_name:
|
|
245
|
+
return server_name
|
|
246
|
+
if "/" in server_url:
|
|
247
|
+
return server_url.split("/")[-1]
|
|
248
|
+
return server_url
|
|
249
|
+
|
|
250
|
+
@staticmethod
|
|
251
|
+
def _apply_pypi_homebrew_generic_config(
|
|
252
|
+
config: dict,
|
|
253
|
+
registry_name: str,
|
|
254
|
+
package_name: str,
|
|
255
|
+
runtime_hint: str,
|
|
256
|
+
processed_runtime_args: list,
|
|
257
|
+
processed_package_args: list,
|
|
258
|
+
resolved_env: dict,
|
|
259
|
+
) -> None:
|
|
260
|
+
"""Apply pypi / homebrew / generic (uvx / brew / npx) run config to *config*.
|
|
261
|
+
|
|
262
|
+
Mutates *config* in-place with ``command``, ``args``, and optionally
|
|
263
|
+
``env`` keys appropriate for the detected registry type.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
config: Mutable server-config dict to populate.
|
|
267
|
+
registry_name: Registry identifier (``"pypi"``, ``"homebrew"``,
|
|
268
|
+
``"npm"``, or any other string treated as generic).
|
|
269
|
+
package_name: Base package / formula / module name.
|
|
270
|
+
runtime_hint: Caller-specified runtime hint (e.g. ``"uvx"``).
|
|
271
|
+
processed_runtime_args: Fully resolved positional args for the
|
|
272
|
+
runtime launcher.
|
|
273
|
+
processed_package_args: Fully resolved positional args appended
|
|
274
|
+
after the package name.
|
|
275
|
+
resolved_env: Pre-resolved environment variables dict; an empty
|
|
276
|
+
dict is omitted.
|
|
277
|
+
"""
|
|
278
|
+
if registry_name == "pypi":
|
|
279
|
+
launcher = runtime_hint or "uvx"
|
|
280
|
+
config["command"] = launcher
|
|
281
|
+
config["args"] = [package_name] + processed_runtime_args + processed_package_args # noqa: RUF005
|
|
282
|
+
elif registry_name == "homebrew":
|
|
283
|
+
formula_name = package_name.split("/")[-1] if "/" in package_name else package_name
|
|
284
|
+
config["command"] = formula_name
|
|
285
|
+
config["args"] = processed_runtime_args + processed_package_args
|
|
286
|
+
else:
|
|
287
|
+
# Generic / npm-compatible fallback
|
|
288
|
+
config["command"] = "npx"
|
|
289
|
+
config["args"] = processed_runtime_args + ["-y", package_name] + processed_package_args # noqa: RUF005
|
|
290
|
+
if resolved_env:
|
|
291
|
+
config["env"] = resolved_env
|
|
292
|
+
|
|
293
|
+
def _apply_auth_and_headers_impl(
|
|
294
|
+
self,
|
|
295
|
+
config: dict,
|
|
296
|
+
remote: dict,
|
|
297
|
+
server_info: dict,
|
|
298
|
+
env_overrides: dict,
|
|
299
|
+
runtime_label: str,
|
|
300
|
+
token_manager_class,
|
|
301
|
+
) -> None:
|
|
302
|
+
"""Core implementation of GitHub-token injection and header merging.
|
|
303
|
+
|
|
304
|
+
Factored out so that each concrete adapter subclass can supply its own
|
|
305
|
+
*token_manager_class* (looked up from the subclass module's namespace),
|
|
306
|
+
allowing :func:`unittest.mock.patch` to intercept the class at the
|
|
307
|
+
right module scope in tests.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
config: Mutable config dict updated in place.
|
|
311
|
+
remote: Registry remote entry (may contain a ``"headers"`` list).
|
|
312
|
+
server_info: Registry server metadata used for name / URL lookup.
|
|
313
|
+
env_overrides: Caller-supplied env-var override mapping.
|
|
314
|
+
runtime_label: Label for diagnostic messages.
|
|
315
|
+
token_manager_class: The ``GitHubTokenManager`` class (or mock) to
|
|
316
|
+
instantiate. Passed by the caller so tests can patch the right
|
|
317
|
+
module-level name.
|
|
318
|
+
"""
|
|
319
|
+
server_name = server_info.get("name", "")
|
|
320
|
+
is_github_server = self._is_github_server(server_name, remote.get("url", ""))
|
|
321
|
+
local_token_injected = False
|
|
322
|
+
if is_github_server:
|
|
323
|
+
_tm = token_manager_class()
|
|
324
|
+
github_token = _tm.get_token_for_purpose("copilot") or os.getenv(
|
|
325
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN"
|
|
326
|
+
)
|
|
327
|
+
if github_token:
|
|
328
|
+
config["headers"] = {"Authorization": f"Bearer {github_token}"}
|
|
329
|
+
local_token_injected = True
|
|
330
|
+
headers = remote.get("headers", [])
|
|
331
|
+
if headers:
|
|
332
|
+
if "headers" not in config:
|
|
333
|
+
config["headers"] = {}
|
|
334
|
+
for header in headers:
|
|
335
|
+
header_name = header.get("name", "")
|
|
336
|
+
header_value = header.get("value", "")
|
|
337
|
+
if header_name and header_value:
|
|
338
|
+
if header_name == "Authorization" and local_token_injected:
|
|
339
|
+
continue
|
|
340
|
+
resolved_value = self._resolve_env_variable(
|
|
341
|
+
header_name, header_value, env_overrides
|
|
342
|
+
)
|
|
343
|
+
config["headers"][header_name] = resolved_value
|
|
344
|
+
if config.get("headers"):
|
|
345
|
+
self._warn_input_variables(
|
|
346
|
+
config["headers"], server_info.get("name", ""), runtime_label
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
@staticmethod
|
|
350
|
+
def _resolve_env_vars_with_prompting(
|
|
351
|
+
env_vars: list,
|
|
352
|
+
env_overrides: dict,
|
|
353
|
+
default_github_env: dict,
|
|
354
|
+
) -> dict:
|
|
355
|
+
"""Resolve *env_vars* from overrides, environment, or interactive prompts.
|
|
356
|
+
|
|
357
|
+
Identical logic shared between
|
|
358
|
+
:meth:`CopilotClientAdapter._process_environment_variables` and
|
|
359
|
+
:meth:`CodexClientAdapter._process_environment_variables`.
|
|
360
|
+
|
|
361
|
+
All imports are deferred so that ``rich.prompt`` (an optional
|
|
362
|
+
dependency) is never imported at module load time.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
env_vars: List of env-var descriptor dicts from the registry.
|
|
366
|
+
env_overrides: Pre-collected ``{name: value}`` overrides (empty
|
|
367
|
+
dict when none).
|
|
368
|
+
default_github_env: Mapping of well-known GitHub variable names
|
|
369
|
+
to their preferred environment-variable lookup names.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
``resolved`` dict mapping each env-var name to its resolved value
|
|
373
|
+
(empty string when unresolvable).
|
|
374
|
+
"""
|
|
375
|
+
import sys
|
|
376
|
+
|
|
377
|
+
env_overrides = env_overrides or {}
|
|
378
|
+
resolved: dict = {}
|
|
379
|
+
|
|
380
|
+
# Determine whether interactive prompting is available.
|
|
381
|
+
# If env_overrides is provided the CLI has already collected variables -- never prompt again.
|
|
382
|
+
skip_prompting = (
|
|
383
|
+
bool(env_overrides)
|
|
384
|
+
or bool(os.getenv("CI"))
|
|
385
|
+
or bool(os.getenv("APM_E2E_TESTS"))
|
|
386
|
+
or not sys.stdout.isatty()
|
|
387
|
+
or not sys.stdin.isatty()
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# First pass: identify variables with empty values to warn the user.
|
|
391
|
+
empty_value_vars = [ev for ev in env_vars if ev.get("required") and not ev.get("value")]
|
|
392
|
+
if empty_value_vars and skip_prompting:
|
|
393
|
+
var_names = [ev.get("name") for ev in empty_value_vars]
|
|
394
|
+
_rich_warning(
|
|
395
|
+
f"Warning: The following required environment variables have no default "
|
|
396
|
+
f"value and cannot be prompted in non-interactive mode: {var_names}"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
for env_var in env_vars:
|
|
400
|
+
name = env_var.get("name", "")
|
|
401
|
+
if not name:
|
|
402
|
+
continue
|
|
403
|
+
|
|
404
|
+
# Priority 1: caller-supplied override
|
|
405
|
+
if name in env_overrides:
|
|
406
|
+
resolved[name] = env_overrides[name]
|
|
407
|
+
continue
|
|
408
|
+
|
|
409
|
+
# Priority 2: check GitHub-specific defaults (values are literal defaults, not env-var names)
|
|
410
|
+
if name in default_github_env:
|
|
411
|
+
resolved[name] = os.getenv(name) or default_github_env[name]
|
|
412
|
+
continue
|
|
413
|
+
|
|
414
|
+
# Priority 3: environment variable with the same name
|
|
415
|
+
env_val = os.getenv(name, "")
|
|
416
|
+
if env_val:
|
|
417
|
+
resolved[name] = env_val
|
|
418
|
+
continue
|
|
419
|
+
|
|
420
|
+
# Priority 4: interactive prompt
|
|
421
|
+
default_value = env_var.get("value", "")
|
|
422
|
+
required = env_var.get("required", False)
|
|
423
|
+
|
|
424
|
+
if not skip_prompting:
|
|
425
|
+
from rich.prompt import Prompt
|
|
426
|
+
|
|
427
|
+
description = env_var.get("description", "")
|
|
428
|
+
prompt_text = f"Enter value for {name}"
|
|
429
|
+
if description:
|
|
430
|
+
prompt_text += f" ({description})"
|
|
431
|
+
is_secret = "token" in name.lower() or "key" in name.lower()
|
|
432
|
+
user_input = Prompt.ask(
|
|
433
|
+
prompt_text,
|
|
434
|
+
default=default_value,
|
|
435
|
+
password=True # noqa: SIM210
|
|
436
|
+
if is_secret
|
|
437
|
+
else False,
|
|
438
|
+
)
|
|
439
|
+
resolved[name] = user_input
|
|
440
|
+
elif default_value:
|
|
441
|
+
resolved[name] = default_value
|
|
442
|
+
elif required:
|
|
443
|
+
_rich_warning(
|
|
444
|
+
f"Warning: Required environment variable '{name}' could not be resolved. "
|
|
445
|
+
f"The MCP server may not function correctly."
|
|
446
|
+
)
|
|
447
|
+
resolved[name] = ""
|
|
448
|
+
else:
|
|
449
|
+
resolved[name] = default_value
|
|
450
|
+
|
|
451
|
+
return resolved
|