跳转至

默认从状态提供环境服务

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

结果

rea environment-serve <manifest> --evidence <capture> 从捕获所观察到的初始状态提供环境服务,无需再提供任何其他内容:启动时,它在进程内使用清单的 template_rules 从该捕获推导出 environment-state 视图。视图由状态支持的读取工具会基于同一个实时状态应答;/agentenv 数据平面针对该状态实现 data/reset、data/add 和 data/get;卡片会公布这些操作以及一个 intake 声明。--replay-only 提供的服务与主程序提供的无状态重放完全一致:每个清单工具都重放其录制内容,/agentenv 对每个方法都返回 not found,卡片逐字节相同。无法推导出的状态,或其目录超出发现预算的状态,会以重放模式启动服务器、记录原因并报告。导出的 bundle 默认提供状态服务,其验证器和 README 与实际提供的内容一致。本次增量中服务是只读的:写工具不基于状态提供服务。

要求

  • 在应用层推导状态,由 serve 和 export 共享: deriveEnvironmentState(source, capture, operation) 对命令已读取的 capture 值进行认证(由源加载认证过的自有快照会被复用,不会再次解析),通过 inspectAnalysisViewValidated 使用清单的 template_rules 投影 environment-state 视图,并将捕获作为保留的 Evidence(Evidence id 与手工投影得到的 id 相等,且捕获的字符串不会再次作为内联输入计费,否则会拒绝几 MiB 大小的捕获),然后应用 loadEnvironmentState:inspect_analysis_view Evidence 的 kind 为 environment-state,其 parent_evidence_id 等于捕获的 id,其 template_rules 与清单中的规则按相同顺序相等,且每个视图都指向一个清单工具,否则以 invalid_request 拒绝,其 issue 路径以 state 开头。源使用自有借用解析来验证 HAR 捕获,因此视图可复用该验证。
  • prepareServedState(source, capture, {name, operation}) 先在所服务名称下构建状态目录,然后推导状态,并报告 {served: true, evidence_id} 或 {served: false, reason: "unavailable", code, message},其中包含被拒绝请求的投影 code 和 message:超过发现预算的状态目录以 resource_constraint 视为不可用,且不会为其推导状态。一个已推导状态若其目录适配,则始终从状态提供服务。对于 --replay-only,CLI 自行报告 {served: false, reason: "replay-only"},且不推导任何内容。
  • 每个服务器进程只保留一个状态存储,由每个 MCP 会话和数据平面共享:实体按类型、集合和 id 键控,每个集合内的顺序取自实体数组;文档按工具键控。reset 恢复 Evidence 状态,replace 整份安装一个已验证的文档,变更同步进行。
  • 通过将路径参数所指向的实体渲染到 envelope_ordinal 的记录信封中,来应答条目视图。参数匹配方式与重放一致:持有的集合段等于参数原样或经过百分号解码后的形式,优先逐字拼写;身份标识作为最后一个参数先百分号解码,再按原样,绝不在 / 上重新拆分。任何被持有的实体都能应答,查询参数只设置 replay.exact_match。对于状态未持有的实体,或缺少必填字段的实体,以工具错误拒绝,绝不虚构响应体。
  • 仅当参数精确命中视图的 checked_record_ordinals 之一时(每个路径和查询值都相等,且没有遗漏任何已记录的查询参数),才从状态应答列表视图,并像重放一样在这些命中项中选择:对于 membership: "all",按状态顺序取集合中的每个实体;否则取状态仍持有的已记录成员。成员若缺少视图的 required_fields 之一,则调用成为工具错误,说明状态没有持有完整成员,绝不返回部分响应体,与条目视图的处理一致。在写入之后记录的、或带有其他过滤条件的行从未被检查,因此从录制内容应答。
  • 当参数精确命中文档的已检查行时,用状态中的值应答文档视图。
  • 对于已记录的视图、没有视图的工具以及未记录的请求,从录制内容应答,并以 state: {source: "recording", reason} 标记;对于状态应答,标记为 state: {source: "state", view, …},附带基础记录的重放来源信息以及 truncated: false;超过 256 KiB 的状态应答以工具错误拒绝,而不是截断它。
  • 提供 data/reset({})、data/add(恰好一个 data 或 file part:bytes、一个 file:// 普通文件或一次 https:// 下载,超时 30 秒覆盖整个响应体,不跟随重定向,流式上限 32 MiB;若给出 mimeType,则为 application/json)和 data/get({parts: [{kind: "data", data: rea_state}]})。若 file:// uri 的主机既不是空也不是 localhost,或其路径是 UNC 路径,则在打开任何东西之前即为 -32602。对于 data/get 一旦加上文档可能省略的成员后会超过 32 MiB 的文档,返回 -32602,因此已报告的状态总能再次加载。其他任何情况都是 -32602,包括空的 parts;下载失败为 -32000;错误绝不回显 uri 或内容,并在 error.data.reason 中给出粗略的失败类别。调用按到达顺序跨请求逐一运行;批次到达时,其每条消息都会排队,因此不会有其他请求的调用插入其中;通知运行时无回复。
  • 停止服务器(close 或 prepareShutdown)会中止数据平面的停止信号;当客户端离开时,请求自身的信号也会中止:进行中的下载以原因 cancelled 结束,排队的调用在不运行的情况下以 -32000 和原因 cancelled 应答,文件读取在取消之后才完成的 data/add 不会替换状态。
  • file:// 读取若描述符关闭失败,则应答 -32000,并将描述符保存在一个服务生命周期内的所有者中。下一次文件读取会先重试关闭;若仍然失败,则不打开文件直接应答 -32000。close 会再次重试,并在其仍打开时拒绝。
  • 将单个 /agentenv 响应限制为 64 MiB 的回复(intake 上限的两倍)。每个回复在生成时按消息顺序以有界 JSON 部分计量,并且只有在其适配时才组装,因此超出预算的回复会计数但绝不会被整体序列化。为每个后续回复的预算错误以及批次的括号和逗号保留空间,因此响应体绝不会超过预算;不适配的回复替换为 -32000,附上 data: {max_response_bytes, reply_bytes},除非该错误不小于原回复,因此响应体绝不会超出预算构建,小的写回复也会被保留。
  • 对照所服务的类型和视图验证 rea-state/v1 文档:已知类型、实例化其模板的集合、等于身份字段的 id、唯一键、view_fields 命名该类型的条目或列表视图且不将该类型的身份字段设置为标量文本与实体 id 不同的值(在该视图的 fields 处拒绝)、在初始路径恰好一次命名文档视图的文档,以及 data/get 报告的与所服务项相等的可选 state_evidence_id 和 types。拒绝没有精确原生值的数字以及 __proto__ 成员。用 JSON 指针指出第一个问题,最深不超过调用方数据成员(fields、value、types),并保持状态不变。
  • 保留记录引用的 Evidence 来源:拒绝使用该实体或文档的 Evidence 之外的 record_ordinals 或 record_ordinal;仅对与 Evidence 相同的已加载值保留 Evidence 的引用;编辑过或新增的值不引用任何内容。
  • 在状态模式下,声明 operations: ["data/reset", "data/add", "data/get"] 和 urn:agentenv:intake/v1 扩展;在状态支撑工具的地方,将工具描述为从状态应答;除查询 POST 外,省略 POST、PUT、PATCH 和 DELETE 工具。发现预算为实际提供的卡片和描述预留空间(servedCatalog 返回卡片声明的工具和数据平面)。状态目录可能超出重放目录能容纳的预算,因此这样的状态不可用,环境和其导出将提供重放服务:主程序曾提供和导出的所有内容仍会继续提供和导出。
  • CLI 没有 --state;--replay-only(默认 false)在不推导的情况下提供重放服务。否则,它在其服务所用的名称(ENVIRONMENT_NAME 或清单的名称)下准备状态。当状态不可用时,命令在绑定之前通过其监听器记录器记录带有代码和消息的警告,并提供重放服务。停止文档的 state 成员即为该报告。serveEnvironment 继续接受可选的已准备状态,在没有时提供重放服务;所提供的目录(servedCatalog)和应答函数(environmentToolAnswer)与导出共享。
  • environment-export 保留 bundle 命令 rea environment-serve /env/manifest.json --evidence /env/evidence.json;在完成名称检查后,它会像该服务器一样在 bundle 名称下准备状态,以预测服务器提供的内容,因此被拒绝的 --name 不会推导任何东西;其报告为 served 或 unavailable,绝不会是 replay-only。验证器的 TOOL_COUNT 和命令的 tool_count 是已提供服务的工具数量;其检查工具和期望状态来自:对第一个无路径参数且应答非错误的已提供 GET 工具,以 {} 调用服务器的应答函数。验证器和冒烟任务使用 id serve。README 的“What the environment serves”部分描述从状态提供服务、重放回退和 --replay-only,说明哪种方式适用于该 bundle(状态不可用时附上代码和消息),并保留非模拟和不可信内容注意事项。导出输出增加 state。托管通道验证器脚本期望的是已提供服务的数量。

验收范围与限制

服务测试涵盖派生(手工构建的 Evidence id 和状态、清单并非由其投影得到的捕获、内联准入拒绝的捕获)、已准备好的报告(可提供;对于具有头值但没有响应体的 capture_browser_scenario 捕获不可提供;对于重放目录可容纳的 350 工具只读清单,在带有 resource_constraint 时不可提供)、从状态和重放中提供的 bundle 计划(工具数量、检查工具及其状态、一个其状态答案在记录和状态上与重放不同的检查、一个跳过服务器无法回答的工具的检查、该 350 工具清单的重放回退、任何准备之前对名称的拒绝、两种模式都不接受的清单、验证器、冒烟任务和 README 措辞)、加载器的拒绝、存储重置、顺序、往返和原子替换、首个问题指针、加载后的引文出处,以及所有回答路径:item(包括百分号编码的集合段和 id)、list all、list recorded、写入后记录的或带有其他过滤器的行、重放的平局决胜不会选择的行、document、已记录视图、没有视图的工具、未记录的请求、缺失实体、缺失必填字段和正文限制、改变实体身份的视图值,以及缺少必填字段的列表成员。适配器测试涵盖数据平面形状、针对空部分和畸形部分及无效文档的 -32602、不精确数字、字节、file:// 及其失败类别、命名其他主机或 UNC 路径的 file:// URI、注入的 https 下载(状态、声明大小和流式传输大小,以及无论 fetcher 是否遵守其信号的超时)、默认 fetch 拒绝的重定向、跨请求的到达顺序应用、另一个请求的重置无法拆分的批次、由服务器停止和由已离开的调用方导致的取消、在下载停滞时关闭的服务器、保留状态文件的关闭、后续文件读取和 close 重试、响应预算、批量和通知、卡片声明、缺失写入工具、以 POST 提供的查询、按模式的发现预留,以及一个通过 MCP 改变下一个工具答案的 data/add。MCP 边界测试提供由构建的 CLI 仅根据一个清单和一个捕获派生出的状态,并覆盖在每个清单工具下使用 --replay-only、-32601 数据平面答案,以及一张 SHA-256 与主服务(main)为该 fixture 提供的卡片相同的卡片;进程边界测试检查已停止文档的 state(针对派生状态、--replay-only 和不可用状态),以及绑定前记录的警告;CLI 边界导出测试检查所提供服务的工具数量、验证器以及导出 bundle 的 README。没有测试会访问外部网络。写入效果、已记录行之外的列表过滤器以及摄取声明中的 tables 不在范围内。

延期问题标准

写入效果是 #4933 的后续增量。此 PR 必须引用该 issue,而不是将其关闭。

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