跳转至

将环境清单导出为 agent 环境包

Issue: https://github.com/morluto/rea/issues/4933

成果

rea environment-export <manifest.json> --evidence <capture.json> <dir> [--package-tarball <path>] [--name <override>] 将 environment-serve 作为 bundle 文件夹提供的那一对清单与捕获写入其中,agentenv 框架通过 agent-env run <dir> 运行该文件夹:包含带来源信息的 README、一个 env 文件夹(其 Dockerfile 安装此精确版本的 rea-agents 并提供复制的配对)、一个 Python 重放验证器和一个 smoke 任务。托管的 real-agentenv 通道通过构建出的 CLI 从源码自有的 Grafana 形态捕获中导出这样的 bundle,将检出内容打包进镜像,并在 runner 的 Docker 上以固定的框架版本运行它。本次增量完成了该 issue 的 agent 环境工作;服务(serving)部分已在上一增量中完成。

需求

  • 通过常规文件读取器分别读取两个文件一次,从这些字节解析,并像 environment-serve 那样使用 loadEnvironmentSource 认证和交叉检查该配对,从而保证复制到 bundle 中的字节正是被认证过的字节;每次拒绝都报告操作 environment-export;如果清单是从不同的捕获投影而来,则在写入任何内容之前就会拒绝。
  • 如果 bundle 目录已存在且非空,或路径指向一个文件,则拒绝,返回 invalid_request,其 issue 路径为 directory;不存在或空目录则接受。每个文件都使用独占创建标志写入,因此绝不会覆盖任何内容。
  • 写入 README.md、envs/<name>/Dockerfile、envs/<name>/env.toml、envs/<name>/manifest.json 和 envs/<name>/evidence.json,作为输入的字节完全一致的副本(POSIX 上模式为 0600;Windows 保留继承的 ACL,不提供仅所有者权限保证),以及 artifacts/check_<name>/verify.py 和 tasks/smoke.json。其中 <name> 默认为清单的 kebab-case 名称;--name 必须是至多 64 个字符的 kebab-case 标签,且不能是 Windows 保留的设备名(con、prn、aux、nul、com1–com9、lpt1–lpt9),否则 env 文件夹无法在那里创建。
  • Dockerfile 使用 .nvmrc 中固定的 Node 版本及 bookworm-slim 变体,设置 MCP_HOST=0.0.0.0 和 MCP_PORT=18765,安装 Debian 的 python3 以用于框架的就绪探测,从 registry 安装 rea-agents@<PRODUCT_IDENTITY.packageVersion>;或者在指定 --package-tarball 时,将 tarball 复制为 rea-agents.tgz,从 /tmp/ 安装并在同一层中删除它;将这两个文件复制到 /env/,切换到镜像的 node 用户,然后运行 rea environment-serve /env/manifest.json --evidence /env/evidence.json。
  • verify.py 镜像框架的 echo 示例:通过 mcp.client.streamable_http 定义 async def verify(mcp_url),列出工具并检查数量是否等于清单的工具数量;调用第一个没有路径参数的 GET 工具,不传任何参数,并检查重放的 status 是否等于该工具第一条被引用记录中记录的 status;打印描述并返回 [{"id": "replay", "result": <bool>, "description": <both checks>}];如果没有这样的工具,则仅检查数量并说明这一点。
  • tasks/smoke.json 是在本地 sandbox 上对 <name> 执行 deploy_env,随后是 env_outcome_verifier,其 file_artifact_id 为 check_<name>,verifier_id 为 replay。README 记录捕获工件的 SHA-256、两个 Evidence ID、清单视图摘要、工具数量和包来源,说明重放证明的内容和未证明的内容,将运行命令指明为从 bundle 根目录(即它所在的文件夹,无论调用者如何命名)执行 agent-env run .,并包含权利说明。
  • 输出一个 JSON 文档,包含 status: "exported"、目录、名称、工具数量、两个 Evidence ID、固定的 package_source 以及写入的文件及其大小。在 CLI 清单中注册扁平化的 environment-export 命令;不添加 MCP 工具。
  • 添加 agentenv CI 范围、可复用的 real-agentenv.yml 工作流(workflow_dispatch 和 workflow_call,使用 build_cache_artifact、ubuntu-24.04、SHA 固定的 actions、setup-python 3.12、包含 agentenv-framework==0.9.1334 的虚拟环境、runner 的 Docker、30 分钟)、verify:agentenv:environment 脚本和 scripts/verify-agentenv-environment.mjs。该脚本像所有其他通道验证器一样要求绝对的 REA_AGENT_ENV_COMMAND 和 REA_DOCKER_COMMAND,运行 agent-env run <dir> --sandbox local,限制为 15 分钟,并且不从 PATH 解析任何内容;在四个位置接入 ci.yml,并扩展两个 CI 守卫测试。

验收与限制

服务测试覆盖计划中的文件集、两种包来源的 Dockerfile、验证器文本、smoke 任务、README、名称覆盖及其拒绝、写入不存在目录和空目录时的字节完全一致副本及正确大小、tarball 复制,以及非空目录、文件路径、缺失 tarball 和内联清单的拒绝。一致性测试将 registry 安装固定到 package.json 版本。CLI 边界测试通过构建出的 CLI 从 fixture 配对写入该文件夹;它拒绝非空目录且保持其不变,并拒绝不匹配的配对而不创建目录。CI 守卫测试枚举新的消费者、路由和分类用例。记录在 verification.md 中的本地端到端运行证明:导出的 bundle 在 agent-env run 下运行,smoke 任务通过,并且没有留下容器。

导出过程复制字节,从不检查 tarball;它本身不构建或运行镜像。其写入不是事务性的:如 docs/cli.md 所述,第一个文件之后发生主机故障会留下部分文件夹以供检查。验证器只检查一个重放的 status 和工具数量,而不是每个工具。通道按设计传递 --sandbox local,尽管 tasks/smoke.json 已经在其部署步骤中固定了 sandbox_type: local,因此该标志只是重申任务已固定的内容。通道验证器通过 Node 的类型剥离,从 tests/fixtures/historicalHar.ts 导入 Grafana 形态的 HAR 构建器,而不是在 scripts/ 下再放一份副本;agentenv 范围列出了该 fixture,因此对它的更改会运行该通道。该通道只证明一个框架版本在一个托管 runner 上的运行情况,不对任何托管平台作任何断言。框架需要对设计好的 Dockerfile 和文件集进行三处补充,每处都是由本地运行发现的:MCP_PORT=18765 作为框架所映射端口的监听默认值;Debian 的 python3,因为框架的本地 sandbox 会在容器内使用 python3 -c "import socket; …" 探测就绪状态,而 slim Node 镜像没有此命令;以及 env.toml 用于命名环境,因为否则框架会从 Node 镜像所没有的 Python 源文件中读取名称。

延迟问题标准

此增量与之前三个一起完成了 #4933 的 agent-environment 范围。在维护者的 CI 上运行该流水线以及在托管平台上的任何后续工作均不属于本 PR 的范围。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea