将环境清单作为回放环境提供服务¶
问题:https://github.com/morluto/rea/issues/4933
结果¶
rea environment-serve <manifest.json> --evidence <capture.json> [--host H] [--port N] 将通过 inspect-analysis-view 从保留的 HAR 捕获 Evidence 投影出的环境清单作为代理环境提供服务:一个位于 /mcp 的 MCP 服务器,每个清单工具对应一个工具,用于回放该工具引用的保留记录;环境卡片位于 /.well-known/agent-env.json,其形状与 agentenv 框架的 echo 示例发布的一致;以及一个 /agentenv 数据平面,对所有 JSON-RPC 方法都回答“未找到”。不会从被记录的应用程序获取任何内容;每个答案都是保留的 Evidence,并标记为目标内容。此增量仅添加 serve 命令;导出 bundle 是后续增量。
要求¶
- 将两个文件作为有界 JSON 输入读取,将它们各自认证为 REA Evidence,并要求 kind 为
environment-manifest的inspect_analysis_viewEvidence,以及完整的inspect_web_network_captureEvidence;对任何其他组合,以invalid_request拒绝,其 issue path 指明违规文件。 - 将调用方的取消信号转发到文件读取,并在认证/监听器工作之前检查启动边界;如果已经观察到中止,则不得绑定或公布监听器。
- 在绑定任何端口之前,拒绝
parent_evidence_id与证据文件的evidence_id不同的清单;Evidence 认证已覆盖捕获的记录,因此不再定义进一步的记录覆盖拒绝。 - 仅根据清单构建
McpServer:每个工具的输入 schema 将每个路径参数列为必填字符串,由其在路径片段中的索引、规则和观测值描述;每个观测到的查询名称列为可选字符串;对于POST、PUT和PATCH,还有一个可选的body对象(与路径参数冲突的查询名称会变成query_<name>;超过 64 个字符的查询名称变成query_<n>;当查询参数名为body时,body 变成request_body),并以additionalProperties: false结束,从而拒绝未知参数;描述为METHOD template; replays retained records [ordinals]; evidence ev_…。所服务的目录与 REA 自身的工具契约和摘要保持分离。 - 为工具描述添加共享的 captured-catalog 警告前缀,使独立的卡片读取器在 MCP 初始化之前就能收到信任提示。
- 在拼接前,将每个路径观测值、body 键和引用的序号描述样本限制为 1 KiB 的 UTF-8 完整值,并附上单独的省略计数和 manifest-Evidence 提示。保持完整数组和回放语义不变。
- 在相同预算下,将捕获的方法、路径和查询名称文本限制为 UTF-8 安全显示前缀,并附上明确的全值 Evidence 提示。保留完整的查找值;较长的路径和查询名称使用冲突安全的别名。
- 仅当提供的查询参数可能影响选择时,才解析记录的查询。
- 回放时,在工具引用的记录中选择:路径片段在参数索引处匹配最多提供值的记录;然后优先选择这些片段中按原样等于该值的数量最多的记录,而非仅在百分号解码之后;然后选择匹配最多提供的查询值的记录;平局时保持清单顺序。返回
status、content_type、body(对于 JSON 类内容类型,解析为 JSON 并进行安全数值转换,否则返回文本;超过 256 KiB 的 body 会在 UTF-8 边界截断并设置truncated: true)以及replay,其中包含record_ordinal、evidence_id、exact_match、recorded_path和recorded_query(每个都截断到 1 KiB,并设置recorded_line_truncated;显式空查询为?)、body_recorded(当捕获未保留响应体时为 false,这样nullbody 不会被误认为已记录的 body)、body_encoding(当保留的字节不是 UTF-8 时为base64,因此它们被原样返回而不是有损解码)和truncated(大的保留 base64 body 只解码到该限制),同时作为结构化内容和文本返回,并在_meta中带有 REA 现有的目标内容溯源标记。 - 按照 echo 示例完全相同的键和嵌套结构提供卡片:
name(来自环境快照的ENVIRONMENT_NAME,否则使用清单名称;已设置但为空白值时以configuration_invalid拒绝)、protocolVersion1.0、url/agentenv、preferredTransportJSONRPC、additionalInterfaces[{url: /mcp, transport: mcp}]、capabilities(包含extensions: null、工具列表和operations: []),以及children_environments: null。在 SDK 的 4 MiB 界限内读取/agentenv的 body,超过该界限则返回413和 JSON-RPC-32000。 - 按
rea mcp --http的方式解析主机和端口(标志、MCP_HOST/MCP_PORT,然后是127.0.0.1和端口0),将已绑定的 URL 以一行 pino JSON 输出到 stderr,通过共享的可流式 HTTP 监听器提供服务,并且仅在收到 SIGINT 或 SIGTERM 后停止运行;随后关闭,打印一个stopped文档,并通过共享的命令取消处理器以退出码130或143退出;加载期间收到信号会在绑定前返回cancelled;绑定后出现监听器失败会被记录,并以resource_constraint错误和退出码1结束命令。 - 在 CLI 清单中注册扁平的
environment-serve命令,附带所描述的参数,且不包含 MCP 工具契约;保持 CLI 接线薄,映射和回放在应用层,服务程序集在服务层;延迟加载监听器,以便命令目录在无需监听器的情况下完成注册。
验收与限制¶
Services 测试涵盖源加载和每种拒绝、工具映射和 schema 推导、卡片形状、精确和尽力选择、查询匹配、平局顺序、文本和非解析 body、UTF-8 边界截断以及 base64 内容。Adapters 测试将所服务的卡片与携带固定工具集的 echo 卡片形状进行字节比较,驱动 /agentenv(包括超过界限的 body),并通过 SDK 的可流式 HTTP 客户端调用工具,断言溯源信息和未知参数拒绝。mcp-boundary 测试使用由 slice-1 的 Grafana 形状固定数据生成的清单和捕获启动构建后的 CLI,并断言工具数量、body.login === "probe" 的精确 get_users_by_id 回放、一次非精确回放、ENVIRONMENT_NAME 下的卡片以及数据平面拒绝;cli-boundary 测试覆盖父 ID 不匹配的拒绝、缺少 --evidence 的用法错误和不可读路径;process-boundary 测试断言以 143 退出并释放端口。回放不验证所提供的值,不执行任何网络活动,也不建立授权、响应语义或状态转换。按照共享监听器的定义,一次只服务一个 MCP 客户端。非 loopback 绑定放宽 Host 检查且不进行测试;绑定后的监听器 error 已接线,但不由测试触发。
资源和取消边界¶
- 整体发现准入在保留每个 schema 属性之前,按每个 UTF-16 单元六个字节加上 schema 开销,最多预留 1 MiB。聚合工具、参数和选定环境标识都会参与;过大的目录会在绑定之前以不可重试的容量错误失败。校准使用了 1500 个查询字段和八个并发发现请求;紧凑的传输大小可以小于保守预留。
- 查询匹配逐字段扫描选定名称;路径评分只扫描一次,并仅保留所提供的参数坐标。原生表单解码语义、格式错误的转义处理以及完整捕获的事实都会得到保留。
- 内容类型显示限制为 1 KiB,并报告
content_type_truncated;完整的媒体类型语义仍可供正文解释使用。 - 取消也负责 DNS/监听启动;一旦观察到中止,就会在 URL 公布之前关闭监听器。
延迟问题判据¶
- 将清单及其证据作为带有验证器的代理-环境捆绑包导出,以及托管验证通道,都是 #4933 的后续独立增量。此 PR 必须引用而不是关闭整个问题。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea