feat: surface codex thread collaboration capabilities

This commit is contained in:
AI Bot
2026-06-04 14:34:34 +08:00
parent de9f85bd21
commit 5bf2216cb0
12 changed files with 359 additions and 121 deletions

View File

@@ -153,10 +153,11 @@
- Web 和原生 Android 当前都已经接上“新设备导入草稿 -> 勾选 -> 决议预览 -> 应用导入”的前台页面;已绑定生产设备继续保留 heartbeat 自动导入链路
- 原生首页的刷新失败策略当前已改成按当前 tab 独立判错,不会再因为 `设备 / 设置 / OTA` 的旁路请求失败把会话页刷新一并判成失败
- 当前量产方向已经明确为“Boss 企业控制面 + 可插拔执行协议”:多租户、权限、审批、审计、备份、回退和 Skill 治理由 Boss 承担Codex App Server / Codex MCP / Codex CLI / Computer Use / 业务系统 API 都作为 provider 接入;详见 `docs/architecture/enterprise_ai_ops_architecture_cn.md`
- 当前 Codex App Server 已完成二十批接入boss-agent 默认开启 `local-agent/codex-app-server-runner.mjs` 作为 Codex 绑定入口,优先走 `codex app-server` stdio也可灰度连接 `ws://127.0.0.1:<port>``unix://PATH` 同机长驻 App Server长驻连接支持 `Authorization: Bearer <token>`,配置上优先使用 `codexAppServerAuthTokenFile`。turn 启动前失败才回退 CLIturn 启动后不重复执行;桌面远程控制默认先走 `codex-computer-use`,失败后回退 `cua-driver-computer-use`。2026-06-03 已按本机 `codex-cli 0.136.0-alpha.2` 生成协议快照 `docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/`
- 当前 Codex App Server 已完成二十批接入boss-agent 默认开启 `local-agent/codex-app-server-runner.mjs` 作为 Codex 绑定入口,优先走 `codex app-server` stdio也可灰度连接 `ws://127.0.0.1:<port>``unix://PATH` 同机长驻 App Server长驻连接支持 `Authorization: Bearer <token>`,配置上优先使用 `codexAppServerAuthTokenFile`。turn 启动前失败才回退 CLIturn 启动后不重复执行;桌面远程控制默认先走 `codex-computer-use`,失败后回退 `cua-driver-computer-use`。2026-06-04 已按本机 `codex-cli 0.136.0-alpha.2` 重新生成协议快照 `docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/`manifest 识别 151 个 method 和当前 schema 暴露的 ThreadItem 类型
- App Server runner 已把 plan、diff、item、approval、warning、file change、thread status、realtime、model route、token usage、MCP、remote control、thread goal、settings、compaction、account、model verification、collab、tool activity、reasoning summary、image generation、hook、Windows sandbox 和 stream delta 归一到 Boss `execution_progress` 卡片;字段白名单只保留安全摘要,不保存 SDP、音频原始数据、raw item、remote installationId、cwd、turnId、配置文件路径、collab 源/目标线程 ID、receiverThreadIds、collab prompt、agentsStates 私有消息、共享 Skill 根绝对路径、hook key/command/sourcePath/statusMessage/hash/error message、tool arguments/result/contentItems、web URL token、命令正文/输出、raw reasoning content、reasoning item id、imageGeneration revisedPrompt/result、Windows sandbox sourcePath/samplePaths、本地绝对路径或未清洗密钥。
- Heartbeat discovery 已能缓存 `model/list / skills/list / skills/extraRoots/set / hooks/list / plugin/list / app/list / modelProvider/capabilities/read / experimentalFeature/list / collaborationMode/list / permissionProfile/list / mcpServerStatus/list / account/read / account/rateLimits/read / config/read / configRequirements/read / externalAgentConfig/detect / thread/list / thread/loaded/list / thread/turns/list` 的能力摘要。`thread/turns/list` 固定使用 `itemsView=summary`,只额外提取最终 `agentMessage` 安全摘要,并合并进 `projectCandidates.recentAssistantMessages` 让 Codex Desktop 自己产生的新回复反向同步到 Boss APP不保存用户正文、reasoning 原文、命令输出、原始 items、内部 prompt 或系统提示词。同批已补 `turn/steer` 活跃 turn 干预和 `POST /api/v1/projects/[projectId]/thread-collaboration` 服务端线程协作排队入口。
- 第十九批另补 `threadActionSummary` 线程操作能力摘要:设备详情页会显示 archive / unarchive / fork / compact / rollback / rename / metadata / steer / interrupt / shell / unsubscribe 等能力分组;该字段只读,不在 heartbeat 中调用任何会改变线程状态的 App Server API。
- 第二十九批另补 `threadCollaborationSummary` 线程协作口径:设备详情页会显示 Boss Broker、协作事件 handler、协作模式数量和“非原生私聊”状态。本机 0.136.0-alpha.2 生成 schema 已确认 `app/list``app/list/updated``configRequirements/read``mcpServerStatus/list``ThreadItem.contextCompaction`,但未声明 `collaborationMode/list``thread/turns/list``ThreadItem.collabToolCall`;因此当前产品层把线程间协作定义为 Boss 受控 Broker + App Server 注入/执行链路,不把它表述成 Codex 原生任意线程 P2P 聊天。
- 第二十批另补 `pluginGovernanceSummary` 插件治理能力摘要:设备详情页会显示 install / uninstall / read / skill-read / share 等能力分组;该字段只读,不在 heartbeat 中调用任何插件安装、卸载或共享写 API。
- 第二十一批另补 `accountGovernanceSummary / configGovernanceSummary` 账号与配置治理能力摘要:设备详情页会显示 login / logout / token refresh / add credits nudge / config write / MCP reload / Skill config write 等能力分组;这些字段只读,不在 heartbeat 中调用任何账号或配置写 API。
- 第二十二批另补 `fileSystemGovernanceSummary / commandSessionSummary` 文件系统与命令会话治理能力摘要:设备详情页会显示 file read/write/remove/watch 与 command stdin / resize / terminate / stream 等能力分组;这些字段只读,不在 heartbeat 中调用任何文件读写或命令控制 API。

View File

@@ -124,6 +124,7 @@
- App Server heartbeat discovery 现在还会按 TTL 对非归档可见线程拉取 `thread/turns/list`,写入 `capabilities.codexAppServer.metadata.threadTurnSummary`。该字段用于 APP/后台展示 Codex 当前线程 turn 运行态;请求固定 `itemsView=summary`,只保留 turn 计数、运行中 / 完成计数、最近状态、更新时间和最终 `agentMessage` 安全摘要不保存用户正文、reasoning 原文、命令输出、原始 items、内部 prompt 或系统提示词。
- App Server heartbeat discovery 现在还会把最终 `agentMessage` 安全摘要合并进 `projectCandidates.recentAssistantMessages`。服务端根据 `codexThreadRef` 将 Codex Desktop 自己产生的新回复反向同步到 Boss APP 对应会话、preview、lastMessageAt 和未读数;已有本地扫描候选的 folder/thread 映射优先App Server 只补充最新回复摘要。
- App Server heartbeat discovery 现在还会写入 `capabilities.codexAppServer.metadata.threadActionSummary`。该字段用于 APP/后台展示当前协议下可接入的线程治理动作数量和分组,覆盖 archive / unarchive / fork / compact / rollback / rename / metadata / steer / interrupt / shell / unsubscribe它只来自 runner 安全 catalog 和协议快照,不会在 heartbeat 中调用这些写操作。
- App Server heartbeat discovery 现在还会写入 `capabilities.codexAppServer.metadata.threadCollaborationSummary`。该字段用于 APP/后台展示 Boss Broker、协作事件 handler、协作模式数量和“非原生私聊”边界当前本机 `codex-cli 0.136.0-alpha.2` schema 未声明 `ThreadItem.collabToolCall`,所以线程协作继续走 Boss 服务端 `thread-collaboration` 入口和受控 App Server 注入/执行链路。
- App Server heartbeat discovery 现在还会写入 `capabilities.codexAppServer.metadata.pluginGovernanceSummary`。该字段用于 APP/后台展示当前协议下可接入的插件治理动作数量和分组,覆盖 install / uninstall / read / skill-read / share它只来自 runner 安全 catalog 和协议快照,不会在 heartbeat 中调用插件安装、卸载或共享写操作。
- App Server heartbeat discovery 现在还会写入 `capabilities.codexAppServer.metadata.accountGovernanceSummary / configGovernanceSummary`。这些字段用于 APP/后台展示当前协议下可接入的账号与配置治理动作数量和分组,覆盖 login / logout / token refresh / add credits nudge / config write / MCP reload / Skill config write它们只来自 runner 安全 catalog 和协议快照,不会在 heartbeat 中调用账号或配置写操作。
- App Server heartbeat discovery 现在还会写入 `capabilities.codexAppServer.metadata.fileSystemGovernanceSummary / commandSessionSummary`。这些字段用于 APP/后台展示当前协议下可接入的文件系统与命令会话动作数量和分组,覆盖 file read/write/remove/watch 以及 command stdin / resize / terminate / stream它们只来自 runner 安全 catalog 和协议快照,不会在 heartbeat 中调用文件读写或命令控制操作。

View File

@@ -24,6 +24,8 @@ Boss 不能直接把 App Server 原始 Thread / Turn / Item 字段写进业务
2026-06-03 第二十八批已把 heartbeat `thread/turns/list``itemsView=notLoaded` 升级为 `itemsView=summary`,但只提取最终 `agentMessage` 安全摘要,并合并到 `projectCandidates.recentAssistantMessages`;服务端据此把 Codex Desktop 自己产生的新最终回复反向同步到 Boss APP 对应会话、preview、lastMessageAt 和未读数。
2026-06-04 第二十九批已按本机 `codex-cli 0.136.0-alpha.2` 重新生成协议快照manifest 扩展到 151 个 method并新增 schema 暴露的 `ThreadItem` 类型矩阵。当前 schema 确认 `app/list``app/list/updated``configRequirements/read``mcpServerStatus/list``ThreadItem.contextCompaction`,但未声明 `collaborationMode/list``thread/turns/list``ThreadItem.collabToolCall`Boss 因此新增 `threadCollaborationSummary`,在设备详情页明确展示 Boss Broker 可用、协作事件 handler 可用、协作模式数量和“非原生私聊”状态,避免把线程协作误做成无监管 P2P。
除用于 Boss APP 会话反向同步的最终 `agentMessage` 安全摘要外,`thread/realtime/sdp`、音频 base64、原始 realtime item、remote installationId、thread settings 的 `cwd`、compaction `turnId`、collaboration settings 内部 prompt、collabToolCall 源/目标线程 ID、`receiverThreadIds``agentsStates.message`、共享 Skill 根绝对路径、hook key/command/sourcePath/statusMessage/hash/error message、tool arguments/result/contentItems、web URL token、命令正文/输出、raw reasoning `content`、reasoning item id、imageGeneration 原始 result/revisedPrompt、hook id/sourcePath/statusMessage/entries、Windows sandbox sourcePath/samplePaths、本地绝对路径、permission profile 文件规则、MCP resource URI、账号邮箱、API key、完整 config、外部 Agent 迁移描述、turn id、turn items、turn 内容、用户正文、原始模型输出和未清洗的 MCP 错误不入账。
官方文档入口:`https://developers.openai.com/codex/app-server`
@@ -84,7 +86,7 @@ APP 展示结构对齐截图:
- `线程状态`:展示 `active / idle / systemError / notLoaded` 以及 `waitingOnApproval / waitingOnUserInput`
- `实时状态`:展示 realtime 启动、同步、关闭或错误状态,附带安全清洗后的 transcript 预览和计数
- `线程配置`:展示 thread goal、模型 / provider、审批 / 沙箱、协作模式和上下文压缩状态
- `线程协作`:展示 `collabToolCall` 的工具名、执行状态、目标类型、目标数量和智能体状态集合,不展示源/目标线程 ID、`receiverThreadIds`、prompt 或 agent 私有消息
- `线程协作`:展示运行时兼容 `collabToolCall` 事件或 Boss Broker 协作摘要的工具名、执行状态、目标类型、目标数量和智能体状态集合,不展示源/目标线程 ID、`receiverThreadIds`、prompt 或 agent 私有消息;本机 schema 未声明该 item 时APP 只显示 Boss 受控协作状态,不显示“原生线程互聊”
- `工具活动`:展示 MCP / dynamic tool / web search / image view / image generation / hook / Review / command 的类型、名称、状态和安全摘要不展示参数、结果、URL token、命令正文、命令输出、图像生成原始 result/revised prompt 或 hook 原始输出
- `思考摘要`:展示 Codex 官方 reasoning `summary` 和状态,不展示 raw reasoning `content`、item id 或密钥
- `流式增量`:展示 agent 回复片段、计划片段、思考片段、MCP 进度、命令输出片段、终端交互和文件输出片段计数,不展示原始 delta、命令输出、推理正文或文件输出
@@ -141,6 +143,7 @@ UI 参考:
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `thread/goal/updated|cleared``thread/settings/updated``thread/compacted` 归一成 `executionProgress.threadGoal / threadSettings / compaction`;服务端进度路由和 Android 原生进度卡已支持展示,测试覆盖 cwd、turnId、内部 prompt 不外泄
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `account/updated``account/rateLimits/updated``model/verification``warning``configWarning``deprecationNotice` 归一成 `executionProgress.accountStatus / modelVerification / warnings`;服务端进度路由和 Android 原生进度卡已支持展示测试覆盖配置路径、turnId 和密钥不外泄
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `ThreadItem.collabToolCall``ThreadItem.contextCompaction` 归一成 `executionProgress.threadCollaboration / compaction`;新版 `receiverThreadIds / agentsStates` 只归一为目标数量与 agent 状态集合;服务端进度路由和 Android 原生进度卡已支持展示,测试覆盖源/目标线程 ID、内部 prompt、agent 私有消息、turnId 和密钥不外泄
- `local-agent/codex-app-server-runner.mjs` 已新增 `threadCollaborationSummary` 能力摘要:当前 Boss Broker 和运行时 `collabToolCall` handler 可用,但本机 0.136.0-alpha.2 schema 没有声明 `ThreadItem.collabToolCall`所以产品口径固定为“Boss 受控线程协作”,不承诺 Codex 原生线程私聊。
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `mcpToolCall``dynamicToolCall``webSearch``imageView``enteredReviewMode``exitedReviewMode``commandExecution` 归一成 `executionProgress.toolActivities`;服务端进度路由和 Android 原生进度卡已支持展示,测试覆盖 tool arguments/result、URL token、命令正文/输出、本地路径和密钥不外泄
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `ThreadItem.plan``ThreadItem.reasoning.summary` 归一成 `executionProgress.steps / reasoningSummary`;服务端进度路由和 Android 原生进度卡已支持展示,测试覆盖 raw reasoning content、reasoning item id 和密钥不外泄
- `local-agent/codex-app-server-runner.mjs` 已把 App Server `ThreadItem.imageGeneration` 归一成 `executionProgress.toolActivities / artifacts`;服务端进度路由和 Android 原生进度卡已支持展示,测试覆盖 revisedPrompt、result、item id、本地绝对路径和密钥不外泄
@@ -164,6 +167,7 @@ UI 参考:
- 新增 App Server 共享 Skill 根下发:配置 `codexAppServerSkillExtraRoots``BOSS_CODEX_APP_SERVER_SKILL_EXTRA_ROOTS`runner 会在 discovery 阶段调用 `skills/extraRoots/set`,再刷新 `skills/list`;设备详情页展示“共享 Skill 根N 个 · 已下发/下发失败”metadata 只保存数量、basename 和状态,不保存绝对路径
- 新增 App Server Hook 治理 discoveryrunner 会调用 `hooks/list` 并写入 `hookSummary`设备详情页展示“HookN 个 · 启用 N 个 · 警告 N 个”metadata 只保存计数、事件名和 handler 类型,不保存 hook key、command、sourcePath、statusMessage、hash、error message 或本地路径
- 新增 App Server 线程操作能力摘要runner 写入 `threadActionSummary`设备详情页展示“线程操作N 项”;该字段只来自安全 catalog 和协议快照,不在 heartbeat 中调用任何会改变线程状态的 API后续真正执行这些动作必须走用户显式指令、RBAC、审批和审计链路。
- 新增 App Server 线程协作口径摘要runner 写入 `threadCollaborationSummary`设备详情页展示“线程协作Boss Broker 可用/不可用 · 协作事件可处理/不可处理 · N 种模式 · 原生私聊/非原生私聊”;该字段只来自当前 runner 能力、heartbeat discovery 和协议快照,不在 heartbeat 中向线程注入内容。
- 新增 App Server 插件治理能力摘要runner 写入 `pluginGovernanceSummary`设备详情页展示“插件治理N 项”;该字段只来自安全 catalog 和协议快照,不在 heartbeat 中调用插件安装、卸载或共享 API后续真正执行这些动作必须走用户显式指令、RBAC、审批和审计链路。
- 新增 App Server 账号与配置治理能力摘要runner 写入 `accountGovernanceSummary / configGovernanceSummary`,设备详情页展示“账号治理 / 配置治理”;这些字段只来自安全 catalog 和协议快照,不在 heartbeat 中调用账号登录、退出、令牌刷新、配置写入、MCP 重载或 Skill config 写入 API后续真正执行这些动作必须走用户显式指令、RBAC、审批和审计链路。
- 新增 App Server 文件系统与命令会话治理能力摘要runner 写入 `fileSystemGovernanceSummary / commandSessionSummary`,设备详情页展示“文件治理 / 命令会话”;这些字段只来自安全 catalog 和协议快照,不在 heartbeat 中调用文件读写、删除、监听、stdin 写入、PTY resize 或 terminate API后续真正执行这些动作必须走用户显式指令、RBAC、审批、租约和审计链路。

View File

@@ -35,13 +35,15 @@
- `launchd` 已安装:`~/Library/LaunchAgents/com.hyzq.boss.local-agent.plist`
- 当前执行底座抽象层已落地在 `src/lib/execution/`,并已补齐 `ExecutionBackend / PromptAssembler / PermissionPolicy / RemoteRuntimeAdapter / OrchestrationBackend` 默认实现
- 当前生产主链仍然沿用 `local-agent -> codex exec resume -> /api/v1/master-agent/tasks/[taskId]/complete`,执行底座重构以“先抽象、不改行为”为准
- 当前 Codex server 调研结论已记录在 `docs/architecture/codex_server_progress_card_cn.md`:长期优先方向更新为 `Codex App Server / Remote Control -> Inter-Thread Broker -> CodexMcpBackendAdapter -> codex exec resume` 的分层 provider 策略;当前 boss-agent 默认打开 `Codex App Server` runner 作为 Codex 绑定入口Boss 仍保留 `codex exec resume` 兜底,并继续用 `execution_progress` 结构化进度卡作为 APP 可见执行态。本机 `codex-cli 0.136.0-alpha.2` 协议快照已生成到 `docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/`,确认支持 WebSocket auth、`thread/inject_items``turn/steer``turn/interrupt``thread/archive``thread/unarchive``thread/fork``thread/compact/start``thread/rollback``thread/name/set``thread/metadata/update``thread/shellCommand``thread/unsubscribe``thread/realtime/*``thread/started|closed|archived|unarchived|name/updated``process/outputDelta|exited``rawResponseItem/completed``item/agentMessage/delta``item/plan/delta``item/reasoning/*Delta``item/mcpToolCall/progress``command/exec/outputDelta``item/commandExecution/terminalInteraction``item/fileChange/outputDelta``thread/goal/*``thread/settings/updated``thread/compacted``ThreadItem.contextCompaction``ThreadItem.collabToolCall``account/*``model/verification``configWarning``deprecationNotice``command/exec``command/exec/write``command/exec/resize``command/exec/terminate``model/list``skills/changed``skills/extraRoots/set``hooks/list``plugin/installed``plugin/install``plugin/uninstall``plugin/read``plugin/skill/read``plugin/share/*``config/value/write``config/batchWrite``config/mcpServer/reload``skills/config/write``fs/*``externalAgentConfig/import``marketplace/add|remove|upgrade``experimentalFeature/enablement/set``review/start``windowsSandbox/readiness|setupStart``fuzzyFileSearch/session*``mcpServer/oauth*``mcpServer/resource/read``mcpServer/tool/call``mcpServer/elicitation/request``item/tool/requestUserInput``thread/approveGuardianDeniedAction`
- 当前 Codex server 调研结论已记录在 `docs/architecture/codex_server_progress_card_cn.md`:长期优先方向更新为 `Codex App Server / Remote Control -> Inter-Thread Broker -> CodexMcpBackendAdapter -> codex exec resume` 的分层 provider 策略;当前 boss-agent 默认打开 `Codex App Server` runner 作为 Codex 绑定入口Boss 仍保留 `codex exec resume` 兜底,并继续用 `execution_progress` 结构化进度卡作为 APP 可见执行态。本机 `codex-cli 0.136.0-alpha.2` 协议快照已生成到 `docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/`,确认支持 WebSocket auth、`thread/inject_items``turn/steer``turn/interrupt``thread/archive``thread/unarchive``thread/fork``thread/compact/start``thread/rollback``thread/name/set``thread/metadata/update``thread/shellCommand``thread/unsubscribe``thread/realtime/*``thread/started|closed|archived|unarchived|name/updated``process/outputDelta|exited``rawResponseItem/completed``item/agentMessage/delta``item/plan/delta``item/reasoning/*Delta``item/mcpToolCall/progress``command/exec/outputDelta``item/commandExecution/terminalInteraction``item/fileChange/outputDelta``thread/goal/*``thread/settings/updated``thread/compacted``ThreadItem.contextCompaction``account/*``model/verification``configWarning``deprecationNotice``command/exec``command/exec/write``command/exec/resize``command/exec/terminate``model/list``skills/changed``skills/extraRoots/set``hooks/list``plugin/installed``plugin/install``plugin/uninstall``plugin/read``plugin/skill/read``plugin/share/*``config/value/write``config/batchWrite``config/mcpServer/reload``skills/config/write``fs/*``externalAgentConfig/import``marketplace/add|remove|upgrade``experimentalFeature/enablement/set``review/start``windowsSandbox/readiness|setupStart``fuzzyFileSearch/session*``mcpServer/oauth*``mcpServer/resource/read``mcpServer/tool/call``mcpServer/elicitation/request``item/tool/requestUserInput``thread/approveGuardianDeniedAction`
- 2026-06-04 重新生成 0.136.0-alpha.2 协议快照后manifest 识别 151 个 method并新增 `itemTypes` 支持矩阵。当前本机 schema 已确认 `app/list``app/list/updated``configRequirements/read``mcpServerStatus/list``ThreadItem.contextCompaction`;官方 App Server 文档列出的 `collaborationMode/list``thread/turns/list``ThreadItem.collabToolCall` 在本机生成 schema 中仍未声明,所以 Boss 只把它们作为运行时兼容/官方文档跟进项,不把“线程间对话”写成无监管 P2P。
- 当前 App Server 能力发现已新增治理摘要local-agent 会在 heartbeat discovery 中拉取 `experimentalFeature/list / collaborationMode/list / permissionProfile/list / mcpServerStatus/list`,并把实验特性、协作模式、权限 Profile 与 MCP 服务状态写入设备 `codexAppServer.metadata`;设备详情页会显示“治理”摘要。该链路只保留安全摘要,不保存 MCP resource URI、permission profile 文件规则、本地路径、token 或工具参数。
- 当前 App Server 能力发现已新增账号与配置摘要local-agent 会在 heartbeat discovery 中拉取 `account/read / account/rateLimits/read / config/read / configRequirements/read / externalAgentConfig/detect`并把账号登录方式、套餐、额度使用率、App 配置计数、托管要求数量和外部 Agent 迁移候选数量写入设备 `codexAppServer.metadata`;设备详情页会显示“账号 / 配置”摘要。该链路只读不写,不保存账号邮箱、完整 config、API key、本地路径或迁移描述。
- 当前 App Server 能力发现已新增线程可见性摘要local-agent 会在 heartbeat discovery 中拉取 `thread/list / thread/loaded/list`,并把线程总数、已加载线程数、活跃线程数、归档线程数、最新更新时间和非归档线程轻量目录写入设备 `codexAppServer.metadata.threadSummary`;设备详情页会显示“线程”摘要。该链路不保存 cwd、本地路径、turn 内容、用户正文或内部 prompt。
- 当前 App Server 能力发现已新增 turn 运行态摘要local-agent 会在 heartbeat discovery 中对非归档可见线程拉取 `thread/turns/list`,请求固定 `itemsView=summary`,并把总轮次、运行中轮次、完成轮次、最新 turn 更新时间、每个线程的最近 turn 状态和最终 `agentMessage` 安全摘要写入设备 `codexAppServer.metadata.threadTurnSummary`设备详情页会显示“轮次”摘要。该链路不保存用户正文、reasoning 原文、命令输出、原始 items、内部 prompt 或系统提示词。
- 当前 App Server discovery 还会把最终 `agentMessage` 合并进 heartbeat `projectCandidates.recentAssistantMessages`。服务端已有 `codexThreadRef` 匹配时会把 Codex Desktop 自己产生的新回复反向同步到 Boss APP 对应会话,并刷新 preview、lastMessageAt 和未读数;已有本地扫描候选的 folder/thread 映射优先保留App Server 只补充最新回复摘要。
- 当前 App Server 能力发现已新增线程操作能力摘要local-agent 会把已验证进入当前协议快照的 archive / unarchive / fork / compact / rollback / rename / metadata / steer / interrupt / shell / unsubscribe 写入设备 `codexAppServer.metadata.threadActionSummary`;设备详情页会显示“线程操作”。该字段只读,不在 heartbeat 中调用任何线程写 API。
- 当前 App Server 能力发现已新增线程协作口径摘要local-agent 会写入 `codexAppServer.metadata.threadCollaborationSummary`;设备详情页会显示 Boss Broker 可用性、协作事件 handler 可用性、协作模式数量和“非原生私聊”状态。该字段用于提醒产品和运维:当前可做的是 Boss 受控线程协作,不是 Codex 原生线程互聊。
- 当前 App Server 能力发现已新增插件治理能力摘要local-agent 会把已验证进入当前协议快照的 install / uninstall / read / skill-read / share 写入设备 `codexAppServer.metadata.pluginGovernanceSummary`;设备详情页会显示“插件治理”。该字段只读,不在 heartbeat 中调用任何插件写 API。
- 当前 App Server 能力发现已新增账号与配置治理能力摘要local-agent 会把已验证进入当前协议快照的 login / logout / token refresh / add credits nudge / config write / MCP reload / Skill config write 写入设备 `codexAppServer.metadata.accountGovernanceSummary / configGovernanceSummary`;设备详情页会显示“账号治理 / 配置治理”。这些字段只读,不在 heartbeat 中调用任何账号或配置写 API。
- 当前 App Server 能力发现已新增文件系统与命令会话治理能力摘要local-agent 会把已验证进入当前协议快照的文件读写、目录、元数据、复制、删除、监听、命令 stdin、PTY resize、terminate 和输出流能力写入设备 `codexAppServer.metadata.fileSystemGovernanceSummary / commandSessionSummary`;设备详情页会显示“文件治理 / 命令会话”。这些字段只读,不在 heartbeat 中调用任何文件或命令控制 API。

View File

@@ -13521,6 +13521,32 @@
}
}
},
"InitializeCapabilities": {
"description": "Client-declared capabilities negotiated during initialize.",
"type": "object",
"properties": {
"experimentalApi": {
"description": "Opt into receiving experimental API methods and fields.",
"default": false,
"type": "boolean"
},
"optOutNotificationMethods": {
"description": "Exact notification method names that should be suppressed for this connection (for example `thread/started`).",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requestAttestation": {
"description": "Opt into `attestation/generate` requests for upstream `x-oai-attestation`.",
"default": false,
"type": "boolean"
}
}
},
"FuzzyFileSearchSessionUpdatedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionUpdatedNotification",
@@ -13545,6 +13571,73 @@
}
}
},
"FuzzyFileSearchMatchType": {
"type": "string",
"enum": [
"file",
"directory"
]
},
"FuzzyFileSearchParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchParams",
"type": "object",
"required": [
"query",
"roots"
],
"properties": {
"cancellationToken": {
"type": [
"string",
"null"
]
},
"query": {
"type": "string"
},
"roots": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"FuzzyFileSearchSessionCompletedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionCompletedNotification",
"type": "object",
"required": [
"sessionId"
],
"properties": {
"sessionId": {
"type": "string"
}
}
},
"ClientInfo": {
"type": "object",
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"title": {
"type": [
"string",
"null"
]
},
"version": {
"type": "string"
}
}
},
"InitializeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InitializeParams",
@@ -13609,99 +13702,6 @@
}
}
},
"FuzzyFileSearchMatchType": {
"type": "string",
"enum": [
"file",
"directory"
]
},
"InitializeCapabilities": {
"description": "Client-declared capabilities negotiated during initialize.",
"type": "object",
"properties": {
"experimentalApi": {
"description": "Opt into receiving experimental API methods and fields.",
"default": false,
"type": "boolean"
},
"optOutNotificationMethods": {
"description": "Exact notification method names that should be suppressed for this connection (for example `thread/started`).",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requestAttestation": {
"description": "Opt into `attestation/generate` requests for upstream `x-oai-attestation`.",
"default": false,
"type": "boolean"
}
}
},
"ClientInfo": {
"type": "object",
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"title": {
"type": [
"string",
"null"
]
},
"version": {
"type": "string"
}
}
},
"FuzzyFileSearchSessionCompletedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionCompletedNotification",
"type": "object",
"required": [
"sessionId"
],
"properties": {
"sessionId": {
"type": "string"
}
}
},
"FuzzyFileSearchParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchParams",
"type": "object",
"required": [
"query",
"roots"
],
"properties": {
"cancellationToken": {
"type": [
"string",
"null"
]
},
"query": {
"type": "string"
},
"roots": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"ClientRequest": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ClientRequest",

View File

@@ -1,5 +1,5 @@
{
"generatedAt": "2026-06-03T04:31:48.629Z",
"generatedAt": "2026-06-04T06:31:54.080Z",
"codexVersion": "0.136.0-alpha.2",
"codexVersionRaw": "codex-cli 0.136.0-alpha.2",
"codexBin": "codex",
@@ -15,6 +15,8 @@
"account/read",
"account/sendAddCreditsNudgeEmail",
"account/updated",
"app/list",
"app/list/updated",
"command/exec",
"command/exec/outputDelta",
"command/exec/resize",
@@ -24,11 +26,13 @@
"config/mcpServer/reload",
"config/read",
"config/value/write",
"configRequirements/read",
"experimentalFeature/enablement/set",
"experimentalFeature/list",
"externalAgentConfig/detect",
"externalAgentConfig/import",
"externalAgentConfig/import/completed",
"feedback/upload",
"fs/changed",
"fs/copy",
"fs/createDirectory",
@@ -39,9 +43,15 @@
"fs/unwatch",
"fs/watch",
"fs/writeFile",
"fuzzyFileSearch",
"fuzzyFileSearch/sessionCompleted",
"fuzzyFileSearch/sessionUpdated",
"getAuthStatus",
"getConversationSummary",
"gitDiffToRemote",
"hooks/list",
"initialize",
"initialized",
"item/agentMessage/delta",
"item/autoApprovalReview/completed",
"item/autoApprovalReview/started",
@@ -70,6 +80,7 @@
"mcpServer/resource/read",
"mcpServer/startupStatus/updated",
"mcpServer/tool/call",
"mcpServerStatus/list",
"model/list",
"model/rerouted",
"model/verification",
@@ -91,6 +102,7 @@
"rawResponseItem/completed",
"remoteControl/status/changed",
"review/start",
"serverRequest/resolved",
"skills/changed",
"skills/config/write",
"skills/extraRoots/set",
@@ -140,15 +152,38 @@
"turn/start",
"turn/started",
"turn/steer",
"windows/worldWritableWarning",
"windowsSandbox/readiness",
"windowsSandbox/setupCompleted",
"windowsSandbox/setupStart"
],
"itemTypes": [
"agentMessage",
"commandExecution",
"contextCompaction",
"dynamicToolCall",
"enteredReviewMode",
"exitedReviewMode",
"fileChange",
"imageGeneration",
"imageView",
"mcpToolCall",
"plan",
"reasoning",
"userMessage",
"webSearch"
],
"supports": {
"stdioTransport": true,
"unixTransport": true,
"wsTransport": true,
"wsAuth": true,
"threadStart": true,
"threadResume": true,
"threadRead": true,
"threadList": true,
"threadLoadedList": true,
"threadTurnHistory": false,
"threadInjectItems": true,
"threadRollback": true,
"threadArchive": true,
@@ -165,6 +200,11 @@
"commandExec": true,
"realtimeThread": true,
"modelList": true,
"appList": true,
"appListUpdated": true,
"collaborationModeList": false,
"configRequirementsRead": true,
"mcpServerStatusList": true,
"skillsExtraRoots": true,
"hooksList": true,
"pluginInstall": true,
@@ -213,6 +253,8 @@
"mcpToolProgress": true,
"commandOutputDeltas": true,
"terminalInteraction": true,
"fileChangeOutputDelta": true
"fileChangeOutputDelta": true,
"threadCollaborationItems": false,
"contextCompactionItem": true
}
}

View File

@@ -1388,6 +1388,18 @@ function normalizeDiscoveryThreadActionSummary() {
};
}
function normalizeDiscoveryThreadCollaborationSummary(collaborationModes) {
const modeCount = asArray(collaborationModes).length;
return {
bossBrokerAvailable: true,
collabToolCallHandlerAvailable: true,
directThreadChatSupported: false,
collaborationModeCount: modeCount,
userInitiatedOnly: true,
labels: ["源线程读取", "上下文注入", "目标线程执行", "协作事件"],
};
}
function normalizeDiscoveryPluginGovernanceSummary() {
const actions = [
{ label: "安装", group: "lifecycle" },
@@ -2234,6 +2246,9 @@ export async function discoverCodexAppServerCapabilities(runnerConfig) {
threadSummary,
threadTurnSummary: normalizeDiscoveryThreadTurnSummary(threadTurnResults, limit),
threadActionSummary: normalizeDiscoveryThreadActionSummary(),
threadCollaborationSummary: normalizeDiscoveryThreadCollaborationSummary(
normalizeDiscoveryCollaborationModes(collaborationModesResult),
),
pluginGovernanceSummary: normalizeDiscoveryPluginGovernanceSummary(),
accountGovernanceSummary: normalizeDiscoveryAccountGovernanceSummary(),
configGovernanceSummary: normalizeDiscoveryConfigGovernanceSummary(),

View File

@@ -57,6 +57,10 @@ function parseCodexVersion(raw) {
return match?.[1] || "unknown";
}
function stripTrailingWhitespace(text) {
return String(text || "").replace(/[ \t]+$/gm, "");
}
async function listFiles(root) {
const entries = await readdir(root, { withFileTypes: true });
const files = [];
@@ -71,21 +75,106 @@ async function listFiles(root) {
return files;
}
function extractProtocolMethodsFromText(text) {
const methods = new Set();
const pattern = /"([A-Za-z][A-Za-z0-9]*(?:\/[A-Za-z0-9_-]+)+)"/g;
const PROTOCOL_METHOD_PREFIXES = [
"account",
"app",
"collaborationMode",
"command",
"config",
"configRequirements",
"experimentalFeature",
"externalAgentConfig",
"feedback",
"fs",
"fuzzyFileSearch",
"hooks",
"item",
"marketplace",
"mcpServer",
"mcpServerStatus",
"model",
"modelProvider",
"permissionProfile",
"plugin",
"process",
"rawResponseItem",
"remoteControl",
"review",
"serverRequest",
"skills",
"thread",
"turn",
"windows",
"windowsSandbox",
];
const PROTOCOL_EXACT_METHODS = new Set([
"fuzzyFileSearch",
"getAuthStatus",
"getConversationSummary",
"gitDiffToRemote",
"initialize",
"initialized",
]);
const THREAD_ITEM_TYPES = new Set([
"agentMessage",
"collabToolCall",
"commandExecution",
"contextCompaction",
"dynamicToolCall",
"enteredReviewMode",
"exitedReviewMode",
"fileChange",
"imageGeneration",
"imageView",
"mcpToolCall",
"plan",
"reasoning",
"userMessage",
"webSearch",
]);
function isProtocolMethod(value) {
return (
PROTOCOL_EXACT_METHODS.has(value) ||
PROTOCOL_METHOD_PREFIXES.some((prefix) => value.startsWith(`${prefix}/`))
);
}
function extractQuotedValues(text) {
const values = [];
const pattern = /"([A-Za-z][A-Za-z0-9_]*(?:\/[A-Za-z0-9_-]+)*)"/g;
let match;
while ((match = pattern.exec(text))) {
const value = match[1];
if (/^(thread|turn|item|rawResponseItem|model|modelProvider|experimentalFeature|permissionProfile|process|command|review|account|config|mcpServer|plugin|marketplace|skills|hooks|fs|remoteControl|externalAgentConfig|fuzzyFileSearch|windowsSandbox)\//.test(value)) {
values.push(match[1]);
}
return values;
}
function extractProtocolMethodsFromText(text) {
const methods = new Set();
for (const value of extractQuotedValues(text)) {
if (isProtocolMethod(value)) {
methods.add(value);
}
}
return methods;
}
async function extractProtocolMethods(root) {
function extractThreadItemTypesFromText(text) {
const itemTypes = new Set();
for (const value of extractQuotedValues(text)) {
if (THREAD_ITEM_TYPES.has(value)) {
itemTypes.add(value);
}
}
return itemTypes;
}
async function extractProtocolArtifacts(root) {
const methods = new Set();
const itemTypes = new Set();
for (const filePath of await listFiles(root)) {
if (!/\.(json|ts)$/.test(filePath)) {
continue;
@@ -94,17 +183,30 @@ async function extractProtocolMethods(root) {
for (const method of extractProtocolMethodsFromText(text)) {
methods.add(method);
}
for (const itemType of extractThreadItemTypesFromText(text)) {
itemTypes.add(itemType);
}
}
return Array.from(methods).sort();
return {
methods: Array.from(methods).sort(),
itemTypes: Array.from(itemTypes).sort(),
};
}
function buildSupportMatrix({ helpText, methods }) {
function buildSupportMatrix({ helpText, methods, itemTypes }) {
const methodSet = new Set(methods);
const itemTypeSet = new Set(itemTypes);
return {
stdioTransport: /stdio:\/\//.test(helpText) || /stdio/.test(helpText),
unixTransport: /unix:\/\//.test(helpText),
wsTransport: /ws:\/\/|websocket/i.test(helpText),
wsAuth: /--ws-auth/.test(helpText),
threadStart: methodSet.has("thread/start"),
threadResume: methodSet.has("thread/resume"),
threadRead: methodSet.has("thread/read"),
threadList: methodSet.has("thread/list"),
threadLoadedList: methodSet.has("thread/loaded/list"),
threadTurnHistory: methodSet.has("thread/turns/list"),
threadInjectItems: methodSet.has("thread/inject_items"),
threadRollback: methodSet.has("thread/rollback"),
threadArchive: methodSet.has("thread/archive"),
@@ -121,6 +223,11 @@ function buildSupportMatrix({ helpText, methods }) {
commandExec: methodSet.has("command/exec"),
realtimeThread: methods.some((method) => method.startsWith("thread/realtime/")),
modelList: methodSet.has("model/list"),
appList: methodSet.has("app/list"),
appListUpdated: methodSet.has("app/list/updated"),
collaborationModeList: methodSet.has("collaborationMode/list"),
configRequirementsRead: methodSet.has("configRequirements/read"),
mcpServerStatusList: methodSet.has("mcpServerStatus/list"),
skillsExtraRoots: methodSet.has("skills/extraRoots/set"),
hooksList: methodSet.has("hooks/list"),
pluginInstall: methodSet.has("plugin/install"),
@@ -197,6 +304,8 @@ function buildSupportMatrix({ helpText, methods }) {
methodSet.has("item/commandExecution/outputDelta"),
terminalInteraction: methodSet.has("item/commandExecution/terminalInteraction"),
fileChangeOutputDelta: methodSet.has("item/fileChange/outputDelta"),
threadCollaborationItems: itemTypeSet.has("collabToolCall"),
contextCompactionItem: itemTypeSet.has("contextCompaction"),
};
}
@@ -216,18 +325,16 @@ async function main() {
await mkdir(schemaDir, { recursive: true });
await mkdir(typescriptDir, { recursive: true });
const helpText = run(options.codexBin, ["app-server", "--help"]);
const helpText = stripTrailingWhitespace(run(options.codexBin, ["app-server", "--help"]));
await writeFile(path.join(snapshotDir, "app-server-help.txt"), helpText, "utf8");
run(options.codexBin, ["app-server", "generate-json-schema", "--out", schemaDir]);
run(options.codexBin, ["app-server", "generate-ts", "--out", typescriptDir]);
const methods = Array.from(
new Set([
...(await extractProtocolMethods(schemaDir)),
...(await extractProtocolMethods(typescriptDir)),
]),
).sort();
const schemaArtifacts = await extractProtocolArtifacts(schemaDir);
const typescriptArtifacts = await extractProtocolArtifacts(typescriptDir);
const methods = Array.from(new Set([...schemaArtifacts.methods, ...typescriptArtifacts.methods])).sort();
const itemTypes = Array.from(new Set([...schemaArtifacts.itemTypes, ...typescriptArtifacts.itemTypes])).sort();
const manifest = {
generatedAt: new Date().toISOString(),
@@ -236,7 +343,8 @@ async function main() {
codexBin: options.codexBin,
snapshotDir,
methods,
supports: buildSupportMatrix({ helpText, methods }),
itemTypes,
supports: buildSupportMatrix({ helpText, methods, itemTypes }),
};
await writeFile(path.join(snapshotDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
console.log(JSON.stringify({ ok: true, snapshotDir, codexVersion, methodCount: methods.length }));

View File

@@ -124,6 +124,9 @@ export function buildDeviceWorkspaceDetailCards(workspace: DeviceWorkspaceView)
const codexThreadSummary = objectFromMetadata(codexAppServerMetadata.threadSummary);
const codexThreadTurnSummary = objectFromMetadata(codexAppServerMetadata.threadTurnSummary);
const codexThreadActionSummary = objectFromMetadata(codexAppServerMetadata.threadActionSummary);
const codexThreadCollaborationSummary = objectFromMetadata(
codexAppServerMetadata.threadCollaborationSummary,
);
const codexPluginGovernanceSummary = objectFromMetadata(codexAppServerMetadata.pluginGovernanceSummary);
const codexAccountGovernanceSummary = objectFromMetadata(codexAppServerMetadata.accountGovernanceSummary);
const codexConfigGovernanceSummary = objectFromMetadata(codexAppServerMetadata.configGovernanceSummary);
@@ -211,6 +214,13 @@ export function buildDeviceWorkspaceDetailCards(workspace: DeviceWorkspaceView)
)} 项 · 生命周期 ${numberFromMetadata(codexThreadActionSummary.lifecycleActionCount)} 项 · 活跃干预 ${numberFromMetadata(
codexThreadActionSummary.liveTurnActionCount,
)} 项 · ${codexThreadActionSummary.shellActionAvailable === true ? "Shell 可用" : "Shell 不可用"}`,
codexThreadCollaboration: `线程协作:${
codexThreadCollaborationSummary.bossBrokerAvailable === true ? "Boss Broker 可用" : "Boss Broker 不可用"
} · ${
codexThreadCollaborationSummary.collabToolCallHandlerAvailable === true ? "协作事件可处理" : "协作事件不可处理"
} · ${numberFromMetadata(codexThreadCollaborationSummary.collaborationModeCount)} 种模式 · ${
codexThreadCollaborationSummary.directThreadChatSupported === true ? "原生私聊" : "非原生私聊"
}`,
codexPluginGovernance: `插件治理:${numberFromMetadata(
codexPluginGovernanceSummary.actionCount,
)} 项 · 安装/卸载 ${numberFromMetadata(codexPluginGovernanceSummary.lifecycleActionCount)} 项 · 共享 ${numberFromMetadata(
@@ -958,6 +968,9 @@ export function DeviceEditorCard({
<div className="rounded-2xl bg-[#F7F8FA] px-3 py-2">
{detailCards.capabilities.items.codexThreadActions}
</div>
<div className="rounded-2xl bg-[#F7F8FA] px-3 py-2">
{detailCards.capabilities.items.codexThreadCollaboration}
</div>
<div className="rounded-2xl bg-[#F7F8FA] px-3 py-2">
{detailCards.capabilities.items.codexPluginGovernance}
</div>

View File

@@ -28,7 +28,7 @@ if (args.includes("--version")) {
}
if (args[0] === "app-server" && args.includes("--help")) {
console.log("Usage: codex app-server [OPTIONS]");
console.log("--listen <URL> stdio:// unix:// ws://IP:PORT off");
console.log("--listen <URL> stdio:// unix:// ws://IP:PORT off ");
process.exit(0);
}
if (args[0] === "app-server" && args[1] === "generate-json-schema") {
@@ -36,6 +36,9 @@ if (args[0] === "app-server" && args[1] === "generate-json-schema") {
writeGenerated(out, "codex_app_server_protocol.schemas.json", JSON.stringify({
anyOf: [
{ properties: { method: { const: "thread/start" } } },
{ properties: { method: { const: "thread/resume" } } },
{ properties: { method: { const: "thread/read" } } },
{ properties: { method: { const: "thread/turns/list" } } },
{ properties: { method: { const: "thread/inject_items" } } },
{ properties: { method: { const: "thread/archive" } } },
{ properties: { method: { const: "thread/archived" } } },
@@ -93,6 +96,11 @@ if (args[0] === "app-server" && args[1] === "generate-json-schema") {
{ properties: { method: { const: "marketplace/upgrade" } } },
{ properties: { method: { const: "experimentalFeature/list" } } },
{ properties: { method: { const: "experimentalFeature/enablement/set" } } },
{ properties: { method: { const: "app/list" } } },
{ properties: { method: { const: "app/list/updated" } } },
{ properties: { method: { const: "collaborationMode/list" } } },
{ properties: { method: { const: "configRequirements/read" } } },
{ properties: { method: { const: "mcpServerStatus/list" } } },
{ properties: { method: { const: "review/start" } } },
{ properties: { method: { const: "windowsSandbox/readiness" } } },
{ properties: { method: { const: "windowsSandbox/setupStart" } } },
@@ -123,13 +131,22 @@ if (args[0] === "app-server" && args[1] === "generate-json-schema") {
{ properties: { method: { const: "hooks/list" } } },
{ properties: { method: { const: "turn/interrupt" } } },
{ properties: { method: { const: "turn/start" } } }
]
],
definitions: {
ThreadItem: {
anyOf: [
{ properties: { type: { const: "agentMessage" } } },
{ properties: { type: { const: "collabToolCall" } } },
{ properties: { type: { const: "contextCompaction" } } }
]
}
}
}, null, 2));
process.exit(0);
}
if (args[0] === "app-server" && args[1] === "generate-ts") {
const out = args[args.indexOf("--out") + 1];
writeGenerated(out, "ClientRequest.ts", 'export type ClientRequest = { "method": "thread/start" } | { "method": "skills/extraRoots/set" } | { "method": "hooks/list" } | { "method": "turn/start" };\\n');
writeGenerated(out, "ClientRequest.ts", 'export type ClientRequest = { "method": "thread/start" } | { "method": "app/list" } | { "method": "collaborationMode/list" } | { "method": "mcpServerStatus/list" } | { "method": "configRequirements/read" } | { "method": "skills/extraRoots/set" } | { "method": "hooks/list" } | { "method": "turn/start" }; export type ThreadItem = { type: "collabToolCall" } | { type: "contextCompaction" };\\n');
process.exit(0);
}
console.error("unexpected args " + args.join(" "));
@@ -160,6 +177,10 @@ process.exit(2);
assert.equal(manifest.codexVersion, "0.135.0-alpha.1");
assert.equal(manifest.supports.wsTransport, true);
assert.equal(manifest.supports.unixTransport, true);
assert.equal(manifest.supports.threadStart, true);
assert.equal(manifest.supports.threadResume, true);
assert.equal(manifest.supports.threadRead, true);
assert.equal(manifest.supports.threadTurnHistory, true);
assert.equal(manifest.supports.threadInjectItems, true);
assert.equal(manifest.supports.skillsExtraRoots, true);
assert.equal(manifest.supports.hooksList, true);
@@ -198,6 +219,13 @@ process.exit(2);
assert.equal(manifest.supports.marketplaceRemove, true);
assert.equal(manifest.supports.marketplaceUpgrade, true);
assert.equal(manifest.supports.experimentalFeatureEnablementSet, true);
assert.equal(manifest.supports.appList, true);
assert.equal(manifest.supports.appListUpdated, true);
assert.equal(manifest.supports.collaborationModeList, true);
assert.equal(manifest.supports.configRequirementsRead, true);
assert.equal(manifest.supports.mcpServerStatusList, true);
assert.equal(manifest.supports.threadCollaborationItems, true);
assert.equal(manifest.supports.contextCompactionItem, true);
assert.equal(manifest.supports.reviewStart, true);
assert.equal(manifest.supports.windowsSandboxReadiness, true);
assert.equal(manifest.supports.windowsSandboxSetupStart, true);
@@ -228,6 +256,9 @@ process.exit(2);
"account/login/start",
"account/logout",
"account/sendAddCreditsNudgeEmail",
"app/list",
"app/list/updated",
"collaborationMode/list",
"command/exec",
"command/exec/outputDelta",
"command/exec/resize",
@@ -236,6 +267,7 @@ process.exit(2);
"config/batchWrite",
"config/mcpServer/reload",
"config/value/write",
"configRequirements/read",
"experimentalFeature/enablement/set",
"experimentalFeature/list",
"externalAgentConfig/detect",
@@ -271,6 +303,7 @@ process.exit(2);
"mcpServer/oauthLogin/completed",
"mcpServer/resource/read",
"mcpServer/tool/call",
"mcpServerStatus/list",
"plugin/install",
"plugin/installed",
"plugin/read",
@@ -298,10 +331,13 @@ process.exit(2);
"thread/metadata/update",
"thread/name/set",
"thread/name/updated",
"thread/read",
"thread/resume",
"thread/rollback",
"thread/shellCommand",
"thread/start",
"thread/started",
"thread/turns/list",
"thread/unarchive",
"thread/unarchived",
"thread/unsubscribe",
@@ -311,10 +347,9 @@ process.exit(2);
"windowsSandbox/setupCompleted",
"windowsSandbox/setupStart",
]);
assert.match(
await readFile(path.join(outDir, "0.135.0-alpha.1", "app-server-help.txt"), "utf8"),
/ws:\/\/IP:PORT/,
);
const helpText = await readFile(path.join(outDir, "0.135.0-alpha.1", "app-server-help.txt"), "utf8");
assert.match(helpText, /ws:\/\/IP:PORT/);
assert.doesNotMatch(helpText, /[ \t]$/m);
} finally {
await rm(runtimeRoot, { recursive: true, force: true });
}

View File

@@ -163,6 +163,14 @@ test("device detail exposes Codex App Server discovered model and extension summ
userInitiatedOnly: true,
labels: ["归档", "恢复", "分叉", "压缩", "回滚", "改名", "元数据", "活跃干预", "中断", "Shell", "取消订阅"],
},
threadCollaborationSummary: {
bossBrokerAvailable: true,
collabToolCallHandlerAvailable: true,
directThreadChatSupported: false,
collaborationModeCount: 2,
userInitiatedOnly: true,
labels: ["源线程读取", "上下文注入", "目标线程执行", "协作事件"],
},
pluginGovernanceSummary: {
actionCount: 9,
lifecycleActionCount: 2,
@@ -321,6 +329,7 @@ test("device detail exposes Codex App Server discovered model and extension summ
assert.equal(cards.capabilities.items.codexThreads, "线程3 个 · 已加载 2 个 · 活跃 1 个 · 最新 2026-06-03 16:20");
assert.equal(cards.capabilities.items.codexTurns, "轮次3 个 · 运行中 1 个 · 完成 2 个 · 最新 2026-06-03 16:21");
assert.equal(cards.capabilities.items.codexThreadActions, "线程操作11 项 · 生命周期 5 项 · 活跃干预 2 项 · Shell 可用");
assert.equal(cards.capabilities.items.codexThreadCollaboration, "线程协作Boss Broker 可用 · 协作事件可处理 · 2 种模式 · 非原生私聊");
assert.equal(cards.capabilities.items.codexPluginGovernance, "插件治理9 项 · 安装/卸载 2 项 · 共享 4 项 · Skill 读取可用");
assert.equal(cards.capabilities.items.codexAccountGovernance, "账号治理6 项 · 登录 3 项 · 令牌刷新可用 · 额度提醒可用");
assert.equal(cards.capabilities.items.codexConfigGovernance, "配置治理5 项 · 写入 3 项 · 重载 1 项 · 读取可用");

View File

@@ -131,6 +131,14 @@ test("codex app-server discovery includes governance and MCP summaries without l
userInitiatedOnly: true,
labels: ["归档", "恢复", "分叉", "压缩", "回滚", "改名", "元数据", "活跃干预", "中断", "Shell", "取消订阅"],
});
assert.deepEqual(metadata.threadCollaborationSummary, {
bossBrokerAvailable: true,
collabToolCallHandlerAvailable: true,
directThreadChatSupported: false,
collaborationModeCount: 2,
userInitiatedOnly: true,
labels: ["源线程读取", "上下文注入", "目标线程执行", "协作事件"],
});
assert.deepEqual(metadata.pluginGovernanceSummary, {
actionCount: 9,
lifecycleActionCount: 2,