APM – Agent Package Manager

一个开源的、社区驱动的 AI 智能体依赖管理器。

APM 为 AI 编程助手(如 GitHub Copilot、Claude、Codex 等)带来了声明式的依赖管理。通过 apm.yml 文件,你可以声明项目所需的技能、提示词、指令和工具,确保每一位开发者都能获得一致的智能体配置环境。APM 会像 NPM 或 Cargo 处理代码依赖一样,自动为你解析和安装所有嵌套的智能体依赖。

功能特性

  • 声明式依赖管理:通过 apm.yml 文件声明项目所需的智能体组件,实现配置即代码。
  • 递归依赖解析:支持包之间相互依赖,APM 能自动处理整个依赖树,解决版本冲突和循环依赖。
  • 多运行时支持:无缝集成多种 AI 运行时,包括 GitHub Copilot CLI、OpenAI Codex 以及通用的 llm 库。
  • 核心原语集成:统一管理智能体的核心组件:
    • 提示词 (Prompts).prompt.md 文件,可被编译或直接执行。
    • 技能 (Skills):SKILL.md 文件,为智能体提供特定领域的知识或工作流。
    • 指令 (Instructions).instructions.md 文件,用于定义代码风格或特定目录下的工作指引。
    • 钩子 (Hooks):Hook 脚本和配置,用于在智能体运行时执行自定义操作。
  • 确定性安装:通过锁文件 (apm.lock) 锁定依赖的确切版本,确保安装的可重复性。
  • 冲突检测与保护:自动检测目标文件中是否已存在用户自定义内容,避免覆盖。

安装指南

APM 提供了多种安装方式,以适应不同的开发环境。

通过安装脚本 (推荐)

使用以下命令一键安装 APM 二进制文件:

curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh

该脚本会自动检测你的操作系统(Linux/macOS)和架构,并将 apm 命令安装到 /usr/local/bin 目录。

使用包管理器

如果你更喜欢使用包管理器,也可以从以下方式安装:

# 使用 Homebrew (macOS/Linux)
brew install microsoft/apm/apm

# 使用 uv (Python)
uv pip install apm-cli

# 使用 pip (Python)
pip install apm-cli

环境要求

  • Python 3.8+:用于运行 APM 核心代码。
  • 可选:Node.js (v22+)、npm (v10+) 用于 copilot 运行时。
  • 可选:Git 用于克隆依赖仓库。

使用说明

1. 初始化项目

在你的项目根目录下,运行以下命令生成一个示例 apm.yml 文件:

apm init my-ai-native-project

2. 声明依赖

编辑生成的 apm.yml 文件,添加你需要的智能体组件。

# apm.yml
name: my-project
version: 1.0.0

dependencies:
  apm:
    # 从 GitHub 仓库安装技能
    - anthropics/skills/skills/frontend-design
    # 安装完整的 APM 包
    - microsoft/apm-sample-package
    # 安装特定目录下的提示词
    - github/awesome-copilot/prompts/code-review

scripts:
  # 定义一个名为 'start' 的脚本,执行时替换 {{name}} 参数
  start: "echo 'Hello, {{name}}!'"

3. 安装依赖

运行以下命令,APM 将读取 apm.yml,下载所有依赖并将其集成到你的项目中(例如,将提示词复制到 .github/prompts/ 目录)。

apm install

4. 运行脚本

APM 支持执行 apm.yml 中定义的脚本,并能进行参数替换。

# 运行 start 脚本,并传递 name 参数
apm run start --param name="YourGitHubHandle"

5. 编译上下文文件

APM 可以收集所有依赖和本地的提示词、指令,生成一个统一的 AGENTS.md 文件(或其他目标文件如 CLAUDE.md)。

# 生成 AGENTS.md 文件
apm compile

# 为 Claude 生成上下文
apm compile --target claude

核心代码

1. APM 依赖解析器 (apm_resolver.py)

负责递归地解析 apm.yml 中声明的依赖,构建依赖图,并检测循环依赖。

class APMDependencyResolver:
    """Handles recursive APM dependency resolution similar to NPM."""
    
    def resolve_dependencies(self, project_root: Path) -> DependencyGraph:
        """Resolve all APM dependencies recursively."""
        # ... 省略部分代码 ...
        root_package = APMPackage.from_apm_yml(project_root / "apm.yml")
        graph = DependencyGraph()
        self._resolve_node(root_package, graph, depth=0, parent=None)
        return graph

    def _resolve_node(self, package: APMPackage, graph: DependencyGraph, depth: int, parent: Optional[DependencyNode]):
        """Internal recursive resolver for a single package node."""
        # ... 检查深度限制和循环依赖 ...
        for dep_ref in package.dependencies:
            if dep_ref.is_apm():
                dep_package = self._download_or_load_package(dep_ref)
                # 递归解析子依赖
                self._resolve_node(dep_package, graph, depth + 1, current_node)

2. GitHub 包下载器 (github_downloader.py)

实现了从 GitHub 或 Azure DevOps 仓库下载指定包的核心逻辑,支持分支、标签和提交哈希。

class GitHubPackageDownloader:
    """Downloads APM packages from GitHub repositories."""
    
    def download_package(self, dep_ref: DependencyReference, dest_path: Path) -> Optional[Path]:
        """Download a package based on the dependency reference."""
        # ... 构建 Git 克隆 URL ...
        if is_github_hostname(host):
            clone_url = build_https_clone_url(host, repo_owner, repo_name, self.token)
        elif is_azure_devops_hostname(host):
            clone_url = build_ado_https_clone_url(host, org, project, repo_name, self.token)
        
        # 克隆仓库并切换到指定引用
        repo = Repo.clone_from(clone_url, dest_path, depth=1, branch=dep_ref.reference, ...)
        
        # 如果是虚拟子包,则只提取子目录
        if dep_ref.virtual_path:
            sub_package_path = dest_path / dep_ref.virtual_path
            # ... 验证子包的有效性 ...
            return sub_package_path
        return dest_path

3. 提示词集成器 (prompt_integrator.py)

负责将包中的 .prompt.md 文件集成到项目的 .github/prompts/ 目录,并处理链接解析。

class PromptIntegrator(BaseIntegrator):
    """Handles integration of APM package prompts into .github/prompts/."""
    
    def integrate_package_prompts(self, package_info, project_root: Path, ...) -> IntegrationResult:
        """Integrate all prompts from a package into .github/prompts/."""
        # ... 查找所有 .prompt.md 文件 ...
        prompt_files = self.find_prompt_files(package_info.install_path)
        # ... 为目标文件创建目录 ...
        prompts_dir = project_root / ".github" / "prompts"
        
        for source_file in prompt_files:
            target_path = prompts_dir / source_file.name
            # 检查是否与用户自定义文件冲突
            if self.check_collision(target_path, rel_path, managed_files, force):
                continue
            # 复制文件并解析 Markdown 链接
            links_resolved = self.copy_prompt(source_file, target_path)
            # ... 记录集成结果 ...

4. 脚本运行器 (script_runner.py)

执行 apm.yml 中定义的命令,支持参数替换和环境变量注入。

class ScriptRunner:
    """Executes APM scripts with auto-compilation of .prompt.md files."""
    
    def run_script(self, script_name: str, params: Dict[str, str]) -> bool:
        """Run a script from apm.yml with parameter substitution."""
        # ... 加载配置,进行参数替换 ...
        command = self._substitute_params(script_command, params)
        
        # 执行命令
        process = subprocess.Popen(command, shell=True, env=os.environ)
        process.communicate()
        return process.returncode == 0
    
    def _substitute_params(self, command: str, params: Dict[str, str]) -> str:
        """Replace {{param}} placeholders in the command with actual values."""
        for key, value in params.items():
            command = command.replace(f"{{{{{key}}}}}", value)
        return command

RzoU2hbzgaOmbsRx+SvxhA==
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐