Skip to content

Conversation

danielmeppiel
Copy link
Collaborator

This pull request introduces APM (Agent Package Manager) integration into the project, providing new functionality for managing modular context packages and files. It adds a new apm subcommand to the CLI, updates README.md to reflect these changes, and brings in a set of new dependencies and Python modules to support APM features.

  • specify init modified to also add basic apm scaffolding (apm.yml)
  • specify apm install to install APM modules from apm.yml
  • specify apm compile to trigger the context compiler and generated optimal nested agents.md files
  • specify apm deps for operations related to APM module dependencies

@Copilot Copilot AI review requested due to automatic review settings September 15, 2025 21:47
@danielmeppiel danielmeppiel self-assigned this Sep 15, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces comprehensive APM (Agent Package Manager) functionality into the project, adding a new CLI subcommand system for managing modular context packages and files. The PR implements a complete APM ecosystem including dependency management, context compilation, and package discovery.

Key Changes:

  • Added complete APM CLI integration with specify apm subcommands (init, install, compile, deps)
  • Implemented distributed context compilation system with optimization engine
  • Added GitHub package downloader with authentication and dependency resolution
  • Enhanced specify init to include APM scaffolding setup

Reviewed Changes

Copilot reviewed 64 out of 64 changed files in this pull request and generated 4 comments.

File Description
src/specify_cli/init.py Main CLI integration adding APM subcommands and wrapper functions
templates/apm/hello-world/apm.yml Template configuration file with project metadata and dependencies
src/apm_cli/ Complete APM CLI implementation with workflow, registry, deps, and compilation modules

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

self.adapter = ClientFactory.create_client(runtime)
self.conflict_detector = MCPConflictDetector(self.adapter)

def install_servers(self, server_references: List[str], env_overrides: Dict[str, str] = None, server_info_cache: Dict[str, Any] = None, runtime_vars: Dict[str, str] = None) -> InstallationSummary:
Copy link
Preview

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method signature has too many optional parameters with mutable defaults. Consider using Optional[Dict[str, str]] instead of Dict[str, str] = None for type safety, and consider grouping related parameters into a configuration object.

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would postpone for later due to breadth of changes needed

@localden localden added the merge-candidate Reasonable change that is going to be merged after a review. label Sep 16, 2025
…s (APM packages with same repo name different owner are now handled well)
@danielmeppiel
Copy link
Collaborator Author

@localden changed to specify init --with-apm in commit 6e4f287

@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 10:51
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 64 out of 65 changed files in this pull request and generated 4 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +531 to +540
original_argv = sys.argv.copy()
try:
sys.argv = ["apm"] + args
try:
apm_click.main(args, standalone_mode=False)
except SystemExit as e:
if e.code != 0:
raise typer.Exit(e.code)
finally:
sys.argv = original_argv
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifying sys.argv globally is a risky pattern that could cause issues in concurrent environments or testing. Consider using Click's context passing or subprocess execution for better isolation.

Suggested change
original_argv = sys.argv.copy()
try:
sys.argv = ["apm"] + args
try:
apm_click.main(args, standalone_mode=False)
except SystemExit as e:
if e.code != 0:
raise typer.Exit(e.code)
finally:
sys.argv = original_argv
try:
apm_click.main(args, standalone_mode=False)
except SystemExit as e:
if e.code != 0:
raise typer.Exit(e.code)

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High effort and no easy way to do this without breaking either output formatting, argument passing, etc

@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 11:56
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 65 out of 66 changed files in this pull request and generated 4 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +95 to +97
# Use GitHub Enterprise x-access-token format for authenticated access
# This is the standard format for GitHub Actions and Enterprise environments
return f"https://x-access-token:{self.github_token}@github.com/{repo_ref}.git"
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GitHub token is being embedded directly in the URL, which could be logged or exposed in error messages. Consider using Git credential helpers or environment variables that Git can access securely instead of embedding tokens in URLs.

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code already implements some security measures:

  • Error Sanitization: The _sanitize_git_error() method specifically removes tokens from error messages using regex patterns
  • Environment Control: The code sets GIT_TERMINAL_PROMPT='0' and GIT_ASKPASS='echo' to prevent interactive prompts

Alternative auth methods had been explored but complex to implement in headless / non-interactive scripts. I'd rather go for the simple approach with the above mitigation as phase 1.

@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 11:59
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 65 out of 66 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/apm_cli/deps/github_downloader.py:1

  • The urllib.parse import should be moved to the top of the file with other imports rather than being imported within a method for better code organization and to avoid repeated imports.
"""GitHub package downloader for APM dependencies."""

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +128 to +135
def _get_available_tokens(self, env: Dict[str, str]) -> Dict[str, str]:
"""Get all available GitHub tokens from environment."""
tokens = {}
for purpose, token_vars in self.TOKEN_PRECEDENCE.items():
for token_var in token_vars:
if token_var in env and env[token_var]:
tokens[token_var] = env[token_var]
return tokens
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method returns a flat dictionary of token variables, but it's designed to return available tokens by purpose. The method should return Dict[str, Optional[str]] mapping purposes to their best available tokens, not all token variables.

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would mean a complex re-architecture of auth mechanisms, so I'd leave this for later

@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 14:51
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 65 out of 66 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/apm_cli/deps/github_downloader.py:1

  • The hostname validation should use case-insensitive comparison since hostnames are case-insensitive. Use parsed_url.netloc.lower() != 'github.com' to prevent bypass with different casing.
"""GitHub package downloader for APM dependencies."""

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +374 to +382
def _extract_directories_from_pattern(self, pattern: str) -> List[Path]:
"""Extract potential directory paths from a file pattern.
Args:
pattern (str): File pattern like "src/**/*.py" or "docs/*.md"
Returns:
List[Path]: List of directory paths that could contain matching files.
"""
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called for every instruction during directory analysis. Consider caching results since patterns are likely to be repeated across instructions, especially for common patterns like **/*.py.

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good improvement but not in scope for this PR

@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 14:54
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 65 out of 66 changed files in this pull request and generated 6 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

… sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@Copilot Copilot AI review requested due to automatic review settings September 16, 2025 15:30
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 65 out of 66 changed files in this pull request and generated 5 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@danielmeppiel
Copy link
Collaborator Author

@localden ready for your review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge-candidate Reasonable change that is going to be merged after a review.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants