Skip to content

feat: add support for Awesome Copilot Collections as APM packages#22

Merged
danielmeppiel merged 9 commits intomainfrom
collections-support
Oct 30, 2025
Merged

feat: add support for Awesome Copilot Collections as APM packages#22
danielmeppiel merged 9 commits intomainfrom
collections-support

Conversation

@danielmeppiel
Copy link
Collaborator

This pull request implements support for installing "collections" from Awesome Copilot repo as virtual packages in the APM CLI, allowing users to fetch and organize sets of related prompt/instruction/chatmode files from GitHub repositories via a manifest. It introduces a parser for .collection.yml files, adds logic to download and validate collections, and provides integration tests for these new capabilities. Additionally, it refines orphaned package detection and updates test markers.

Copilot AI review requested due to automatic review settings October 30, 2025 06:42
Copy link
Contributor

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 PR implements support for virtual collection packages in APM, extending the existing virtual file package feature. It enables users to install curated collections of files (prompts, instructions, chat modes) directly from repositories without installing the full package.

Key changes:

  • Added collection manifest parser and data models
  • Implemented collection package downloading in GitHub downloader
  • Fixed orphan detection to properly recognize virtual packages (both files and collections)
  • Added comprehensive integration tests for virtual package orphan detection and collection installation

Reviewed Changes

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

Show a summary per file
File Description
src/apm_cli/deps/collection_parser.py New module for parsing .collection.yml manifests with validation
src/apm_cli/deps/github_downloader.py Added download_collection_package() method to download and organize collection files
src/apm_cli/cli.py Updated orphan detection logic to handle virtual packages with correct naming
tests/integration/test_virtual_package_orphan_detection.py New integration tests verifying virtual packages aren't flagged as orphans
tests/integration/test_collection_install.py New integration tests for collection installation and manifest parsing
pyproject.toml Added slow test marker for long-running integration tests

'agent': 'agents',
'context': 'contexts',
}
return kind_to_subdir.get(self.kind.lower(), 'prompts') # Default to prompts
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The default fallback to 'prompts' for unknown kinds is implicit behavior that could lead to unexpected file placement. Consider raising a warning or error for unknown kinds instead of silently defaulting, or document this behavior in the docstring.

Copilot uses AI. Check for mistakes.
manifest_content = self.download_raw_file(dep_ref, collection_manifest_path, ref)
except RuntimeError as e:
# Try .yaml extension as fallback
if ".collection.yml" in str(e):
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The error message check is fragile and could match unrelated errors containing this substring. Consider catching specific exception types or checking error codes rather than string matching in the exception message.

Copilot uses AI. Check for mistakes.
Comment on lines +553 to +557
apm_yml_content = f"""name: {package_name}
version: 1.0.0
description: {manifest.description}
author: {dep_ref.repo_url.split('/')[0]}
"""
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The manifest.description is inserted directly into the YAML content without escaping. If the description contains special YAML characters (like colons, quotes, or newlines), this could produce invalid YAML or injection vulnerabilities. Use proper YAML serialization instead of string formatting.

Copilot uses AI. Check for mistakes.
Comment on lines +561 to +562
apm_yml_content += f"\ntags:\n"
for tag in manifest.tags:
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

Tags are inserted directly into YAML without escaping. Tags could contain special YAML characters that break the format or introduce injection issues. Use proper YAML serialization (e.g., yaml.dump()) instead of manual string concatenation.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +69
# Build expected installed packages set (same logic as _check_orphaned_packages)
expected_installed = set()
for dep in declared_deps:
repo_parts = dep.repo_url.split('/')
if len(repo_parts) >= 2:
org_name = repo_parts[0]
if dep.is_virtual:
package_name = dep.get_virtual_package_name()
expected_installed.add(f"{org_name}/{package_name}")
else:
repo_name = repo_parts[1]
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

This logic is duplicated across three test functions and also mirrors the implementation in cli.py. Consider extracting this into a shared test helper function to reduce code duplication and ensure consistency.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +7
import shutil

Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

Import of 'shutil' is not used.

Suggested change
import shutil

Copilot uses AI. Check for mistakes.
recognized and not flagged as orphaned when they are declared in apm.yml.
"""

import tempfile
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

Import of 'tempfile' is not used.

Suggested change
import tempfile

Copilot uses AI. Check for mistakes.
"""

import tempfile
from pathlib import Path
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

Import of 'Path' is not used.

Suggested change
from pathlib import Path

Copilot uses AI. Check for mistakes.
- Refactored package validation to use GitHubPackageDownloader for virtual packages.
- Enhanced dependency resolution to support namespaced package directories.
- Added logic to create minimal apm.yml for zero-config execution of virtual packages.
- Introduced auto-install feature that downloads virtual packages on first run.
- Implemented tests for auto-install functionality, including end-to-end scenarios.
- Added validation methods for checking the existence of virtual packages.
- Updated GitHubPackageDownloader to handle API requests for downloading files.
- Created integration tests for the auto-install feature and guardrailing scenarios.
@danielmeppiel danielmeppiel merged commit 5609107 into main Oct 30, 2025
22 checks passed
@danielmeppiel danielmeppiel deleted the collections-support branch February 27, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants