跳到主要内容

应用入口与 MCP Elicitation 桌面 E2E

本文定义 Wework“应用”入口和 MCP 业务表单的真实桌面端回归方案。测试复用现有桌面 runner 与 checkpoint,不新增本地专用脚本,也不使用浏览器 mock 替代 Electron、Executor 或 Codex。

覆盖范围​

本方案覆盖两组独立风险:

  1. “应用-站点”和“应用-小程序”是否把用户带入新的空白任务,并生成正确的结构化 Composer 草稿。
  2. 完整访问模式下,MCP server 发起的 elicitation/create 是否仍能显示为 Wework 表单,并把用户答案原样送回 MCP runtime。

应用插件的稳定技术标识和用户可见名称如下:

应用类型插件技术标识用户可见名称
站点wegent-sites快速建站
小程序weibo-miniapp-h5-develop-agent微博小程序H5开发助手

测试不得用可见名称替代技术标识。技术标识用于安装 API、Composer 节点属性和插件 URI;可见名称用于界面和草稿文本断言。

Checkpoint 与真实边界​

应用入口场景放入现有 sites-plugin-auto-install 插件 checkpoint:

pnpm --filter wework e2e:desktop:plugins -- --segment sites-plugin-auto-install

MCP 表单场景放入现有 permission-modes core checkpoint:

pnpm --filter wework e2e:desktop -- --segment permission-modes

两个 checkpoint 都必须由 GitHub CI 调用。新增的 MCP fixture 应在桌面 E2E 分类脚本中显式映射到 core:permission-modes,避免只修改 fixture 时触发无关桌面套件。

应用入口用例​

公共前置条件​

  • 使用 Sites upstream 的固定站点 E2E Product Site,项目 ID 为 prj_e2e_product。
  • 使用固定小程序 E2E Mini Program,项目 ID 为 prj_e2e_mini。
  • 每次点击入口前记录 Composer 的 standaloneChatKey、scopeKey、当前项目 ID 和当前 runtime task。
  • 点击后必须同时满足:standaloneChatKey 增加 1、scopeKey 改变、currentRuntimeTask 为 null、当前项目不变。
  • 草稿必须做规范化后的完整相等断言,并额外验证结构化 chip 属性;仅断言包含某段文字不够。

管理站点环境变量​

  1. 打开 E2E Product Site 行末的更多菜单和“环境变量”。
  2. 新增 Plain 变量 E2E_API_BASE=https://api.example.tes`t` 并保存。
  3. 等待对话框显示保存成功,并断言请求经过真实 Backend 后写入 Sites upstream fixture。
  4. 截图保存成功状态并关闭对话框。

管理内网站点访问权限​

  1. 打开 E2E Product Site 行末的更多菜单和“访问权限”。
  2. 选择“项目成员及指定成员”,输入两个顺序相反的用户名并保存。
  3. 等待对话框显示保存成功,并断言请求经过真实 Backend 后按确定顺序写入 Sites upstream fixture。
  4. 截图保存成功状态并关闭对话框。

管理站点协作者​

  1. 打开 E2E Product Site 行末的更多菜单和“管理协作者”。
  2. 添加 e2e-collaborator,等待其出现在列表并断言 upstream fixture 已保存。
  3. 移除同一协作者,等待其从列表消失并断言 upstream fixture 已清空。
  4. 截图最终状态并关闭对话框。

站点列表“继续开发”​

  1. 打开“应用-站点”。
  2. 点击 E2E Product Site 行的“继续开发”。
  3. 等待新的空白任务 Composer 出现。
  4. 断言可见草稿为:
快速建站 E2E Product Site 请说出你要做的改动
  1. 断言内部草稿为:
[$快速建站](plugin://wegent-sites@wegent) [E2E Product Site](wegent-sites-project://prj_e2e_product) 请说出你要做的改动
  1. 断言插件 chip 指向 wegent-sites@wegent,并断言链接 chip 的 provider、label 和 URL 分别为 wegent-sites-project、E2E Product Site 和 wegent-sites-project://prj_e2e_product。
  2. 断言首次使用按需安装 wegent-sites,页面没有 sites-create-error。

创建“站点”​

  1. 返回“应用-站点”,打开创建菜单并点击“站点”。
  2. 等待新的空白任务 Composer 出现。
  3. 断言可见草稿为:
快速建站 Build an internal website and validate it locally
  1. 断言内部草稿为:
[$快速建站](plugin://wegent-sites@wegent) Build an internal website and validate it locally
  1. 断言插件 chip 的技术名称和 marketplace 分别为 wegent-sites 和 wegent。
  2. 断言复用上一步已安装插件,不重复调用 ensure-installed。

创建“小程序”​

  1. 返回应用页,切换到“小程序”,打开创建菜单并点击“小程序”。
  2. 等待新的空白任务 Composer 出现。
  3. 断言可见草稿为:
微博小程序H5开发助手 创建并发布一个小程序
  1. 断言内部草稿为:
[$微博小程序H5开发助手](plugin://weibo-miniapp-h5-develop-agent@wegent) 创建并发布一个小程序
  1. 断言插件 chip 的技术名称和 marketplace 分别为 weibo-miniapp-h5-develop-agent 和 wegent。
  2. 断言首次使用按需安装小程序插件,页面没有安装错误。

MCP Elicitation 用例​

Fixture​

使用隔离的 stdio MCP server mcp-elicitation-server.mjs,暴露工具:

wegent_sites_interactions.confirm_inner_site_access

收到 tools/call 后,fixture 保持调用未完成,并向 Codex 发送:

{
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "请选择内网访问范围",
"requestedSchema": {
"type": "object",
"properties": {
"audience": {
"type": "string",
"title": "访问范围",
"enum": ["all", "owner"],
"enumNames": ["所有人", "仅自己"]
}
},
"required": ["audience"]
}
}
}

fixture 收到 Codex 响应后,先把原始结果写入当前 E2E result directory 的 JSONL 文件,再完成 tools/call。接受 owner 时工具返回唯一标记:

E2E_MCP_ELICITATION_ACCEPTED:owner

Codex 配置​

基础隔离配置继续保留:

approval_policy = "never"

仅增加测试 MCP server:

[mcp_servers.wegent_sites_interactions]
command = "<当前 Node 可执行文件>"
args = ["<fixture 绝对路径>", "<证据文件绝对路径>"]
default_tools_approval_mode = "approve"

不能把基础配置改成 granular 来让测试通过。用户在 UI 中启用完整访问后,Executor 必须在 thread/start、thread/resume、thread/fork 和 turn/start 覆盖为 granular policy:关闭执行安全审批,同时保留 mcp_elicitations: true。

模型与协议步骤​

固定模型场景必须按顺序处理三次请求:

  1. 对固定提示返回 tool_search,查询 confirm_inner_site_access。
  2. 从搜索结果中选择 namespace wegent_sites_interactions,调用 confirm_inner_site_access。
  3. 只有在模型输入中同时出现该 tool call 的输出和 E2E_MCP_ELICITATION_ACCEPTED:owner 后,才返回最终完成文本。

真实链路为:

真实模型请求
→ tool_search
→ MCP tools/call
→ elicitation/create
→ mcpServer/elicitation/request
→ Executor request_user_input
→ Wework 表单
→ 用户选择“仅自己”
→ MCP action=accept
→ 工具成功标记
→ 模型最终完成文本

UI 与证据断言​

场景在 permission-modes 已确认完整访问后、切换只读之前执行:

  1. 发送固定测试提示,等待 [data-testid="request-user-input-card"]。
  2. 断言卡片显示“访问范围”“所有人”“仅自己”,且不是普通 MCP tool approval 卡。
  3. 表单出现时证据文件必须仍不存在,证明 Codex 没有提前自动 decline。
  4. 点击 request-user-input-option-audience-1。单问题表单会自动提交,不再点击提交按钮。
  5. 等待模型最终完成文本和 runtime task 空闲。
  6. 展开 final-processing-toggle,等待 request-user-input-summary 显示“仅自己”。
  7. 精确断言 fixture 证据:
{
"action": "accept",
"content": {
"audience": "owner"
}
}

真实超时验证​

permission-modes 为隔离的应用及其 Executor 设置 WEGENT_CODEX_MCP_URL_TIMEOUT_MS=5000 和 WEGENT_CODEX_MCP_FORM_TIMEOUT_MS=30000。 URL 授权超时使用 5 秒真实计时器;并发和普通表单超时各使用 30 秒,三次固定等待 合计约 65 秒。表单需要在过期前完成普通问题回答、两次待回答卡片重载及状态断言。 CI Job 122373305638 的 fixture 证据显示,15 秒配置在 ordinary_first 场景中 于 15004ms 取消了本应被接受的 MCP 请求,因此表单不能与单纯等待过期的 URL 场景使用相同的短操作窗口。 其他 checkpoint 不自动设置该配置。未配置或配置无效时,生产默认值仍为 URL 10 分钟、表单 5 分钟;普通执行审批的超时不受该配置影响。

测试不修改时钟,不模拟取消结果。UI 倒计时和 Executor 等待使用同一截止时间, MCP fixture 记录实际经过时间,并断言不会提前收到取消。保留以下完整链路验证:

  • 真实 MCP 服务收到一次 action=cancel,会话解除等待。
  • 并发普通问题仍保持待回答,直到用户回答该问题。
  • 过期卡片不再提供操作,迟到回答被 Executor 拒绝。
  • 重载后过期状态保持,MCP 服务不收到重复回复。

Rust 单测独立断言 10/5 分钟默认值、短超时配置及无效配置处理。

证据与失败定位​

成功运行至少保留:

  • 三个应用入口各自的新任务草稿截图。
  • MCP 表单可见截图。
  • MCP 提交摘要和最终完成截图。
  • fixture 的原始 JSONL 回执。
  • runner 自动保存的 UI snapshot、模型请求和 executor 日志。

典型失败含义:

失败位置优先检查
新任务 identity 未变化openInNewChat、queued plugin trial 消费和 Workbench scope 切换
文本正确但 chip 属性错误插件技术标识、marketplace 或结构化 Composer parser
等不到 MCP 表单,fixture 记录 decline完整访问的 runtime approvalPolicy 是否保留 mcp_elicitations
表单可见但 fixture 无 acceptExecutor 的 enum label 到稳定 enum value 映射与回复路由
模型未完成MCP tool output 是否回到下一次模型输入,成功标记是否一致

测试结束时由现有 runner 终止 Electron、Executor、Codex 和 stdio MCP 子进程,并清理隔离 home。fixture 不得读取或写入用户的个人 Codex home。