diff --git a/docs/architecture/ai_handoff_index_cn.md b/docs/architecture/ai_handoff_index_cn.md index 6075892..1266cc8 100644 --- a/docs/architecture/ai_handoff_index_cn.md +++ b/docs/architecture/ai_handoff_index_cn.md @@ -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:` 或 `unix://PATH` 同机长驻 App Server;长驻连接支持 `Authorization: Bearer `,配置上优先使用 `codexAppServerAuthTokenFile`。turn 启动前失败才回退 CLI,turn 启动后不重复执行;桌面远程控制默认先走 `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:` 或 `unix://PATH` 同机长驻 App Server;长驻连接支持 `Authorization: Bearer `,配置上优先使用 `codexAppServerAuthTokenFile`。turn 启动前失败才回退 CLI,turn 启动后不重复执行;桌面远程控制默认先走 `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。 diff --git a/docs/architecture/api_and_service_inventory_cn.md b/docs/architecture/api_and_service_inventory_cn.md index 90b73e5..bfdc866 100644 --- a/docs/architecture/api_and_service_inventory_cn.md +++ b/docs/architecture/api_and_service_inventory_cn.md @@ -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 中调用文件读写或命令控制操作。 diff --git a/docs/architecture/codex_server_progress_card_cn.md b/docs/architecture/codex_server_progress_card_cn.md index 6fa66f5..9c48142 100644 --- a/docs/architecture/codex_server_progress_card_cn.md +++ b/docs/architecture/codex_server_progress_card_cn.md @@ -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 治理 discovery:runner 会调用 `hooks/list` 并写入 `hookSummary`,设备详情页展示“Hook:N 个 · 启用 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、审批、租约和审计链路。 diff --git a/docs/architecture/current_runtime_and_deploy_status_cn.md b/docs/architecture/current_runtime_and_deploy_status_cn.md index ba0613b..70ddc8c 100644 --- a/docs/architecture/current_runtime_and_deploy_status_cn.md +++ b/docs/architecture/current_runtime_and_deploy_status_cn.md @@ -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。 diff --git a/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/json-schema/codex_app_server_protocol.v2.schemas.json b/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/json-schema/codex_app_server_protocol.v2.schemas.json index 04c8927..a765ff9 100644 --- a/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/json-schema/codex_app_server_protocol.v2.schemas.json +++ b/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/json-schema/codex_app_server_protocol.v2.schemas.json @@ -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", diff --git a/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/manifest.json b/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/manifest.json index eada9db..d2c0b8d 100644 --- a/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/manifest.json +++ b/docs/protocol-snapshots/codex-app-server/0.136.0-alpha.2/manifest.json @@ -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 } } diff --git a/local-agent/codex-app-server-runner.mjs b/local-agent/codex-app-server-runner.mjs index cf07d63..9719608 100644 --- a/local-agent/codex-app-server-runner.mjs +++ b/local-agent/codex-app-server-runner.mjs @@ -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(), diff --git a/scripts/codex-app-server-protocol-snapshot.mjs b/scripts/codex-app-server-protocol-snapshot.mjs index 1808665..d03ce16 100644 --- a/scripts/codex-app-server-protocol-snapshot.mjs +++ b/scripts/codex-app-server-protocol-snapshot.mjs @@ -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 })); diff --git a/src/components/app-ui.tsx b/src/components/app-ui.tsx index f9090ff..faedf51 100644 --- a/src/components/app-ui.tsx +++ b/src/components/app-ui.tsx @@ -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({
{detailCards.capabilities.items.codexThreadActions}
+
+ {detailCards.capabilities.items.codexThreadCollaboration} +
{detailCards.capabilities.items.codexPluginGovernance}
diff --git a/tests/codex-app-server-protocol-snapshot-script.test.mjs b/tests/codex-app-server-protocol-snapshot-script.test.mjs index d856ace..3f461a1 100644 --- a/tests/codex-app-server-protocol-snapshot-script.test.mjs +++ b/tests/codex-app-server-protocol-snapshot-script.test.mjs @@ -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 stdio:// unix:// ws://IP:PORT off"); + console.log("--listen 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 }); } diff --git a/tests/device-detail-capabilities-route.test.ts b/tests/device-detail-capabilities-route.test.ts index 41e5db7..e1669a0 100644 --- a/tests/device-detail-capabilities-route.test.ts +++ b/tests/device-detail-capabilities-route.test.ts @@ -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 项 · 读取可用"); diff --git a/tests/local-agent-codex-app-server-runner.test.mjs b/tests/local-agent-codex-app-server-runner.test.mjs index ce38ca9..52ce337 100644 --- a/tests/local-agent-codex-app-server-runner.test.mjs +++ b/tests/local-agent-codex-app-server-runner.test.mjs @@ -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,