From a5d44b0cacbb8c8654e314b55bc5d9649d57c38c Mon Sep 17 00:00:00 2001 From: AI Bot Date: Thu, 4 Jun 2026 15:08:27 +0800 Subject: [PATCH] feat: show codex app server summaries on android --- .../com/hyzq/boss/DeviceDetailActivity.java | 58 +++++++++++ .../com/hyzq/boss/WechatSurfaceMapper.java | 98 ++++++++++++++++++- .../hyzq/boss/DeviceDetailActivityTest.java | 50 ++++++++++ docs/architecture/ai_handoff_index_cn.md | 1 + .../api_and_service_inventory_cn.md | 2 +- .../current_runtime_and_deploy_status_cn.md | 12 +-- 6 files changed, 212 insertions(+), 9 deletions(-) diff --git a/android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java b/android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java index 32de6b7..7f47abf 100644 --- a/android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java +++ b/android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java @@ -187,6 +187,64 @@ public class DeviceDetailActivity extends BossScreenActivity { null, null )); + if (WechatSurfaceMapper.hasCodexAppServerMetadata(device)) { + appendContent(BossUi.buildWechatMenuRow( + this, + "模型", + WechatSurfaceMapper.deviceCodexModelSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "扩展", + WechatSurfaceMapper.deviceCodexExtensionSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "治理", + WechatSurfaceMapper.deviceCodexGovernanceSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "账号", + WechatSurfaceMapper.deviceCodexAccountSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "线程", + WechatSurfaceMapper.deviceCodexThreadSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "轮次", + WechatSurfaceMapper.deviceCodexTurnSummary(device), + null, + null, + null + )); + appendContent(BossUi.buildWechatMenuRow( + this, + "线程操作", + WechatSurfaceMapper.deviceCodexThreadActionSummary(device), + null, + null, + null + )); + } appendContent(BossUi.buildWechatMenuRow( this, "线程协作", diff --git a/android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java b/android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java index 3a68a2e..5430709 100644 --- a/android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java +++ b/android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java @@ -252,6 +252,10 @@ public final class WechatSurfaceMapper { return resolveDeviceCapability(device, "codexAppServer") != null; } + public static boolean hasCodexAppServerMetadata(JSONObject device) { + return resolveCodexAppServerMetadata(device) != null; + } + public static String deviceCodexAppServerStatusLabel(JSONObject device) { JSONObject capability = resolveDeviceCapability(device, "codexAppServer"); boolean connected = capability != null && capability.optBoolean("connected", false); @@ -270,6 +274,64 @@ public final class WechatSurfaceMapper { return "最近上报 " + lastSeenAt; } + public static String deviceCodexModelSummary(JSONObject device) { + JSONObject metadata = resolveCodexAppServerMetadata(device); + int modelCount = metadataArrayLength(metadata, "models"); + if (modelCount <= 0) { + return "未发现"; + } + return modelCount + " 个" + + " · 默认 " + metadataText(metadata, "defaultModelId") + + " · 快速 " + metadataText(metadata, "fastModelId") + + " · 深度 " + metadataText(metadata, "deepModelId"); + } + + public static String deviceCodexExtensionSummary(JSONObject device) { + JSONObject metadata = resolveCodexAppServerMetadata(device); + return "Skill " + metadataArrayLength(metadata, "skills") + " 个" + + " · Plugin " + metadataArrayLength(metadata, "plugins") + " 个" + + " · App " + metadataArrayLength(metadata, "apps") + " 个"; + } + + public static String deviceCodexGovernanceSummary(JSONObject device) { + JSONObject metadata = resolveCodexAppServerMetadata(device); + return "实验特性 " + metadataArrayLength(metadata, "experimentalFeatures") + " 个" + + " · 协作模式 " + metadataArrayLength(metadata, "collaborationModes") + " 个" + + " · MCP " + metadataArrayLength(metadata, "mcpServers") + " 个" + + " · 权限 " + metadataArrayLength(metadata, "permissionProfiles") + " 个"; + } + + public static String deviceCodexAccountSummary(JSONObject device) { + JSONObject metadata = resolveCodexAppServerMetadata(device); + JSONObject accountSummary = metadata == null ? null : metadata.optJSONObject("accountSummary"); + JSONObject rateLimitSummary = metadata == null ? null : metadata.optJSONObject("rateLimitSummary"); + return objectText(accountSummary, "authMode") + + " · 套餐 " + objectText(accountSummary, "planType") + + " · 额度 " + objectInt(rateLimitSummary, "maxUsedPercent") + "%"; + } + + public static String deviceCodexThreadSummary(JSONObject device) { + JSONObject summary = resolveCodexAppServerMetadataObject(device, "threadSummary"); + return objectInt(summary, "threadCount") + " 个" + + " · 已加载 " + objectInt(summary, "loadedThreadCount") + " 个" + + " · 活跃 " + objectInt(summary, "activeThreadCount") + " 个"; + } + + public static String deviceCodexTurnSummary(JSONObject device) { + JSONObject summary = resolveCodexAppServerMetadataObject(device, "threadTurnSummary"); + return objectInt(summary, "totalTurnCount") + " 个" + + " · 运行中 " + objectInt(summary, "runningTurnCount") + " 个" + + " · 完成 " + objectInt(summary, "completedTurnCount") + " 个"; + } + + public static String deviceCodexThreadActionSummary(JSONObject device) { + JSONObject summary = resolveCodexAppServerMetadataObject(device, "threadActionSummary"); + return objectInt(summary, "actionCount") + " 项" + + " · 生命周期 " + objectInt(summary, "lifecycleActionCount") + " 项" + + " · 活跃干预 " + objectInt(summary, "liveTurnActionCount") + " 项" + + " · " + (summary != null && summary.optBoolean("shellActionAvailable", false) ? "Shell 可用" : "Shell 不可用"); + } + public static String deviceCodexThreadCollaborationSummary(JSONObject device) { JSONObject summary = resolveCodexAppServerMetadataObject(device, "threadCollaborationSummary"); if (summary == null) { @@ -528,11 +590,43 @@ public final class WechatSurfaceMapper { } private static JSONObject resolveCodexAppServerMetadataObject(JSONObject device, String key) { - JSONObject capability = resolveDeviceCapability(device, "codexAppServer"); - JSONObject metadata = capability == null ? null : capability.optJSONObject("metadata"); + JSONObject metadata = resolveCodexAppServerMetadata(device); return metadata == null ? null : metadata.optJSONObject(key); } + private static JSONObject resolveCodexAppServerMetadata(JSONObject device) { + JSONObject capability = resolveDeviceCapability(device, "codexAppServer"); + return capability == null ? null : capability.optJSONObject("metadata"); + } + + private static int metadataArrayLength(JSONObject metadata, String key) { + if (metadata == null) { + return 0; + } + JSONArray array = metadata.optJSONArray(key); + return array == null ? 0 : array.length(); + } + + private static String metadataText(JSONObject metadata, String key) { + if (metadata == null) { + return "未知"; + } + String value = metadata.optString(key, "").trim(); + return value.isEmpty() ? "未知" : value; + } + + private static String objectText(JSONObject object, String key) { + if (object == null) { + return "未知"; + } + String value = object.optString(key, "").trim(); + return value.isEmpty() ? "未知" : value; + } + + private static int objectInt(JSONObject object, String key) { + return object == null ? 0 : object.optInt(key, 0); + } + public static RootTopAction rootTopAction(String activeTab, boolean refreshing) { return rootTopAction(activeTab, refreshing, false); } diff --git a/android/app/src/test/java/com/hyzq/boss/DeviceDetailActivityTest.java b/android/app/src/test/java/com/hyzq/boss/DeviceDetailActivityTest.java index c2baeb3..099bdaf 100644 --- a/android/app/src/test/java/com/hyzq/boss/DeviceDetailActivityTest.java +++ b/android/app/src/test/java/com/hyzq/boss/DeviceDetailActivityTest.java @@ -97,6 +97,20 @@ public class DeviceDetailActivityTest { View content = activity.findViewById(R.id.screen_content); assertTrue(viewTreeContainsText(content, "Codex App Server")); assertTrue(viewTreeContainsText(content, "已连接")); + assertTrue(viewTreeContainsText(content, "模型")); + assertTrue(viewTreeContainsText(content, "2 个 · 默认 gpt-5.4 · 快速 gpt-5.4-mini · 深度 gpt-5.4")); + assertTrue(viewTreeContainsText(content, "扩展")); + assertTrue(viewTreeContainsText(content, "Skill 1 个 · Plugin 1 个 · App 1 个")); + assertTrue(viewTreeContainsText(content, "治理")); + assertTrue(viewTreeContainsText(content, "实验特性 2 个 · 协作模式 2 个 · MCP 2 个 · 权限 1 个")); + assertTrue(viewTreeContainsText(content, "账号")); + assertTrue(viewTreeContainsText(content, "chatgpt · 套餐 pro · 额度 42%")); + assertTrue(viewTreeContainsText(content, "线程")); + assertTrue(viewTreeContainsText(content, "3 个 · 已加载 2 个 · 活跃 1 个")); + assertTrue(viewTreeContainsText(content, "轮次")); + assertTrue(viewTreeContainsText(content, "3 个 · 运行中 1 个 · 完成 2 个")); + assertTrue(viewTreeContainsText(content, "线程操作")); + assertTrue(viewTreeContainsText(content, "11 项 · 生命周期 5 项 · 活跃干预 2 项 · Shell 可用")); assertTrue(viewTreeContainsText(content, "线程协作")); assertTrue(viewTreeContainsText(content, "Boss Broker 可用 · 协作事件可处理 · 2 种模式 · 非原生私聊")); assertTrue(viewTreeContainsText(content, "协议漂移")); @@ -372,6 +386,42 @@ public class DeviceDetailActivityTest { .put("connected", true) .put("lastSeenAt", "2026-06-04T10:00:00+08:00") .put("metadata", new JSONObject() + .put("models", new JSONArray() + .put(new JSONObject().put("id", "gpt-5.4")) + .put(new JSONObject().put("id", "gpt-5.4-mini"))) + .put("defaultModelId", "gpt-5.4") + .put("fastModelId", "gpt-5.4-mini") + .put("deepModelId", "gpt-5.4") + .put("skills", new JSONArray().put(new JSONObject().put("name", "image2-ui-prototype"))) + .put("plugins", new JSONArray().put(new JSONObject().put("id", "github"))) + .put("apps", new JSONArray().put(new JSONObject().put("id", "canva"))) + .put("experimentalFeatures", new JSONArray() + .put(new JSONObject().put("name", "multi_agent")) + .put(new JSONObject().put("name", "apps"))) + .put("collaborationModes", new JSONArray() + .put(new JSONObject().put("id", "solo")) + .put(new JSONObject().put("id", "plan"))) + .put("mcpServers", new JSONArray() + .put(new JSONObject().put("name", "github")) + .put(new JSONObject().put("name", "figma"))) + .put("permissionProfiles", new JSONArray().put(new JSONObject().put("id", ":workspace"))) + .put("accountSummary", new JSONObject() + .put("authMode", "chatgpt") + .put("planType", "pro")) + .put("rateLimitSummary", new JSONObject().put("maxUsedPercent", 42)) + .put("threadSummary", new JSONObject() + .put("threadCount", 3) + .put("loadedThreadCount", 2) + .put("activeThreadCount", 1)) + .put("threadTurnSummary", new JSONObject() + .put("totalTurnCount", 3) + .put("runningTurnCount", 1) + .put("completedTurnCount", 2)) + .put("threadActionSummary", new JSONObject() + .put("actionCount", 11) + .put("lifecycleActionCount", 5) + .put("liveTurnActionCount", 2) + .put("shellActionAvailable", true)) .put("threadCollaborationSummary", new JSONObject() .put("bossBrokerAvailable", true) .put("collabToolCallHandlerAvailable", true) diff --git a/docs/architecture/ai_handoff_index_cn.md b/docs/architecture/ai_handoff_index_cn.md index 06eb0eb..b24cb85 100644 --- a/docs/architecture/ai_handoff_index_cn.md +++ b/docs/architecture/ai_handoff_index_cn.md @@ -156,6 +156,7 @@ - 当前 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` 服务端线程协作排队入口。 +- 原生 Android `DeviceDetailActivity` 当前已展示 Codex App Server 连接态、模型、扩展、治理、账号、线程、轮次、线程操作、线程协作和协议漂移这些核心 metadata 摘要;更深的插件治理、文件治理、MCP 治理、流式增量等长尾治理摘要仍以 Web 设备详情和后台治理页为主,后续可继续分批补齐到原生端。 - 第十九批另补 `threadActionSummary` 线程操作能力摘要:设备详情页会显示 archive / unarchive / fork / compact / rollback / rename / metadata / steer / interrupt / shell / unsubscribe 等能力分组;该字段只读,不在 heartbeat 中调用任何会改变线程状态的 App Server API。 - 第二十九批另补 `threadCollaborationSummary` 线程协作口径:Web 与原生 Android 设备详情页会显示 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 聊天。 - 同批新增 `protocolDriftSummary` 协议漂移摘要:Web 与原生 Android 设备详情页会显示兼容/告警、失败探针数、官方文档跟进项和 Boss Broker 兜底策略。该字段来自 discovery errors 的 method 级安全归一,不保存错误原文、线程 ID、用户正文或内部 prompt;后续 Codex Server 更新时优先看这个摘要决定是否需要补 runner 或前台展示。 diff --git a/docs/architecture/api_and_service_inventory_cn.md b/docs/architecture/api_and_service_inventory_cn.md index c462f9f..2698025 100644 --- a/docs/architecture/api_and_service_inventory_cn.md +++ b/docs/architecture/api_and_service_inventory_cn.md @@ -80,7 +80,7 @@ - `MainActivity` 会记住最近一次停留的 `会话 / 设备 / 我的` tab - 根页返回逻辑已改成“先回会话 tab,再按一次返回进入后台” - 当前设备详情页: - - `DeviceDetailActivity` 已同步展示 Codex App Server 连接态、线程协作口径和协议漂移摘要;线程协作固定表达为 Boss Broker 受控协作,协议漂移只显示兼容/告警、失败探针数量、文档跟进数量和 Boss Broker 兜底,不渲染错误原文、线程 ID、用户正文或内部 prompt + - `DeviceDetailActivity` 已同步展示 Codex App Server 连接态、模型、扩展、治理、账号、线程、轮次、线程操作、线程协作口径和协议漂移摘要;线程协作固定表达为 Boss Broker 受控协作,协议漂移只显示兼容/告警、失败探针数量、文档跟进数量和 Boss Broker 兜底,不渲染错误原文、线程 ID、用户正文或内部 prompt - 当前会话列表: - 已切到“线程 = 会话窗口” - 主标题显示线程名 diff --git a/docs/architecture/current_runtime_and_deploy_status_cn.md b/docs/architecture/current_runtime_and_deploy_status_cn.md index 732f505..a26dc56 100644 --- a/docs/architecture/current_runtime_and_deploy_status_cn.md +++ b/docs/architecture/current_runtime_and_deploy_status_cn.md @@ -37,12 +37,12 @@ - 当前生产主链仍然沿用 `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`、`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 能力发现已新增治理摘要:local-agent 会在 heartbeat discovery 中拉取 `experimentalFeature/list / collaborationMode/list / permissionProfile/list / mcpServerStatus/list`,并把实验特性、协作模式、权限 Profile 与 MCP 服务状态写入设备 `codexAppServer.metadata`;Web 与原生 Android 设备详情页都会显示“治理”摘要。该链路只保留安全摘要,不保存 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`;Web 设备详情页会显示“账号 / 配置”摘要,原生 Android 设备详情页会显示“账号”摘要。该链路只读不写,不保存账号邮箱、完整 config、API key、本地路径或迁移描述。 +- 当前 App Server 能力发现已新增线程可见性摘要:local-agent 会在 heartbeat discovery 中拉取 `thread/list / thread/loaded/list`,并把线程总数、已加载线程数、活跃线程数、归档线程数、最新更新时间和非归档线程轻量目录写入设备 `codexAppServer.metadata.threadSummary`;Web 与原生 Android 设备详情页都会显示“线程”摘要。该链路不保存 cwd、本地路径、turn 内容、用户正文或内部 prompt。 +- 当前 App Server 能力发现已新增 turn 运行态摘要:local-agent 会在 heartbeat discovery 中对非归档可见线程拉取 `thread/turns/list`,请求固定 `itemsView=summary`,并把总轮次、运行中轮次、完成轮次、最新 turn 更新时间、每个线程的最近 turn 状态和最终 `agentMessage` 安全摘要写入设备 `codexAppServer.metadata.threadTurnSummary`;Web 与原生 Android 设备详情页都会显示“轮次”摘要。该链路不保存用户正文、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 会把已验证进入当前协议快照的 archive / unarchive / fork / compact / rollback / rename / metadata / steer / interrupt / shell / unsubscribe 写入设备 `codexAppServer.metadata.threadActionSummary`;Web 与原生 Android 设备详情页都会显示“线程操作”。该字段只读,不在 heartbeat 中调用任何线程写 API。 - 当前 App Server 能力发现已新增线程协作口径摘要:local-agent 会写入 `codexAppServer.metadata.threadCollaborationSummary`;Web 与原生 Android 设备详情页都会显示 Boss Broker 可用性、协作事件 handler 可用性、协作模式数量和“非原生私聊”状态。该字段用于提醒产品和运维:当前可做的是 Boss 受控线程协作,不是 Codex 原生线程互聊。 - 当前 App Server 能力发现已新增协议漂移摘要:local-agent 会写入 `codexAppServer.metadata.protocolDriftSummary`;Web 与原生 Android 设备详情页都会显示“协议漂移:兼容/告警 · 失败探针 N 个 · 文档跟进 N 项 · Boss Broker 兜底”。该字段把运行时 discovery 失败 method、官方文档跟进项和当前兜底策略拆开展示,避免 Codex Server 更新后只靠原始日志判断协议是否漂移。 - 当前 App Server 能力发现已新增插件治理能力摘要:local-agent 会把已验证进入当前协议快照的 install / uninstall / read / skill-read / share 写入设备 `codexAppServer.metadata.pluginGovernanceSummary`;设备详情页会显示“插件治理”。该字段只读,不在 heartbeat 中调用任何插件写 API。 @@ -277,7 +277,7 @@ cd /Users/kris/code/boss - 当前已新增 Codex App Server 受控线程分叉:服务端入口 `POST /api/v1/projects/[projectId]/thread-fork` 会创建 `intentCategory=thread_fork` 任务;App Server runner 直接执行 `thread/fork(target)`,不启动普通 turn,不保存 App Server 返回的 path、cwd、turns 或 instructionSources。当前不允许远程覆盖 model、sandbox、instructions 或 config;新 Codex 线程进入 Boss 会话列表仍通过现有 thread discovery / 导入链路完成。 - 当前 `local-agent` 对 `dispatch_execution` 任务会按 `orchestrationBackendId` 分流:默认走 `codex exec resume`;当任务显式选择 `omx-team` 且本机 `omxEnabled + omxCommand/omxArgs` 可用时,会改走 `OMX Team Runtime` JSON 协议执行并回写 `rawThreadReply / replyBody` - 当前 `local-agent` 会在 Codex 任务执行中和完成时回传 `executionProgress`:服务端把同一任务的进度卡从 queued / running 更新到 completed / failed,Android 原生聊天页会显示“进度 / 线程状态 / 实时状态 / 线程配置 / 线程协作 / 工具活动 / 思考摘要 / 账号状态 / 运行状态 / 安全提醒 / 审批状态 / 文件变更 / 分支详情 / 生成结果 / 后台智能体”。2026-05-31 起,Codex App Server 的 `turn/plan/updated`、`turn/diff/updated`、`item/started|completed`、`thread/started` 会直接映射为进度步骤、变更统计、生成产物和后台智能体;第二批已把 `item/*/requestApproval`、`item/autoApprovalReview/*`、`guardianWarning`、`serverRequest/resolved`、`item/fileChange/patchUpdated` 映射为审批、安全提醒和文件变更摘要;第三批已把 `thread/status/changed` 与 `thread/realtime/*` 安全映射为线程状态和实时状态摘要;第四批已把 `model/rerouted`、`thread/tokenUsage/updated`、`mcpServer/startupStatus/updated`、`remoteControl/status/changed` 安全映射为运行状态摘要;第五批已把 `thread/goal/*`、`thread/settings/updated` 和 `thread/compacted` 映射为线程配置摘要;第六批已把 `account/updated`、`account/rateLimits/updated`、`model/verification`、`warning`、`configWarning`、`deprecationNotice` 映射为账号状态、模型校验和安全提醒摘要;第七批已把 `ThreadItem.collabToolCall` 和 `ThreadItem.contextCompaction` 映射为线程协作和上下文压缩摘要;第八批已把 `mcpToolCall`、`dynamicToolCall`、`webSearch`、`imageView`、`enteredReviewMode`、`exitedReviewMode`、`commandExecution` 映射为工具活动摘要;第九批已把 `ThreadItem.plan` 和 `ThreadItem.reasoning.summary` 映射为计划步骤与思考摘要;第十批已把 `ThreadItem.imageGeneration` 映射为图像生成工具活动和图片产物;第十一批已把 `hook/started|completed` 映射为钩子生命周期工具活动;第十二批已把 `windowsSandbox/setupCompleted` 映射为 Windows 沙箱准备状态摘要;第十七批已把新版 `ThreadItem.collabToolCall.receiverThreadIds / agentsStates` 安全映射为线程协作目标数量和 agent 状态集合。所有进度均通过 `POST /api/v1/master-agent/tasks/[taskId]/progress` 实时刷新;字段白名单会剥离 cwd、turnId、配置文件路径、内部 prompt、collab 源/目标线程 ID、receiverThreadIds、agentsStates 私有消息、共享 Skill 根绝对路径、tool arguments/result、web URL token、命令正文/输出、raw reasoning content、reasoning item id、图像生成 revisedPrompt/result、hook sourcePath/statusMessage/entries、Windows sandbox sourcePath/samplePaths/本地绝对路径和未清洗密钥,complete 回写仍会携带最终进度兜底 -- 当前 `local-agent` heartbeat 已新增 Codex App Server capability discovery:按 TTL 拉取模型、provider 能力、Skill、Hook、Plugin、App 摘要,并附加只读线程操作、插件治理、账号治理、配置治理、文件治理、命令会话、外部 Agent 迁移、Marketplace、实验特性、审查、Windows 沙箱、文件搜索事件、MCP、用户交互、Guardian、运行事件、扩展事件、线程生命周期和流式增量能力 catalog,写入 `capabilities.codexAppServer.metadata`;Web 设备详情会展示 App Server 连接状态、模型数量、默认/快速/深度模型、扩展数量、Hook 治理摘要、线程操作摘要、插件治理摘要、账号治理摘要、配置治理摘要、文件治理摘要、命令会话摘要、迁移治理摘要、市场治理摘要、实验特性治理摘要、审查治理摘要、Windows 沙箱摘要、文件搜索事件摘要、MCP 治理摘要、用户交互摘要、Guardian 治理摘要、运行事件摘要、扩展事件摘要、线程生命周期摘要和流式增量摘要 +- 当前 `local-agent` heartbeat 已新增 Codex App Server capability discovery:按 TTL 拉取模型、provider 能力、Skill、Hook、Plugin、App 摘要,并附加只读线程操作、插件治理、账号治理、配置治理、文件治理、命令会话、外部 Agent 迁移、Marketplace、实验特性、审查、Windows 沙箱、文件搜索事件、MCP、用户交互、Guardian、运行事件、扩展事件、线程生命周期和流式增量能力 catalog,写入 `capabilities.codexAppServer.metadata`;Web 设备详情会展示 App Server 连接状态、模型数量、默认/快速/深度模型、扩展数量、Hook 治理摘要、线程操作摘要、插件治理摘要、账号治理摘要、配置治理摘要、文件治理摘要、命令会话摘要、迁移治理摘要、市场治理摘要、实验特性治理摘要、审查治理摘要、Windows 沙箱摘要、文件搜索事件摘要、MCP 治理摘要、用户交互摘要、Guardian 治理摘要、运行事件摘要、扩展事件摘要、线程生命周期摘要和流式增量摘要;原生 Android 设备详情当前已展示 App Server 连接态、模型、扩展、治理、账号、线程、轮次、线程操作、线程协作和协议漂移这些核心摘要 - 当前 `MasterAgentTask` 已具备服务端租约和取消基础状态机:claim 会写入 `attemptCount / maxAttempts / leaseExpiresAt`,运行中任务租约过期后可被重新认领,超过重试上限会转 `timed_out`;`POST /api/v1/master-agent/tasks/[taskId]/cancel` 会把任务转 `canceled`,迟到的成功 complete 不会覆盖终态 - 当前 App Server 执行中的任务取消已补真实中断链路:服务端新增 `GET /api/v1/master-agent/tasks/[taskId]/control-state` 给设备端按 token 轮询取消状态;`local-agent` 在 turn 启动后按 `masterAgentInterruptPollIntervalMs` 检查该接口,发现任务已取消会在同一个 App Server 连接上调用 `turn/interrupt`,并把 interrupted 作为干净取消结果处理,不再等长任务自然结束或把取消刷成失败日志 - 当前 `local-agent` 对 `browser_control / desktop_control` 已从占位骨架升级成外部 runtime 桥:当本机配置了 `browserControlEnabled + browserControlCommand` 或 `computerUseEnabled + computerUseCommand` 时,会把标准化 JSON 请求透传给外部进程,并解析单行 JSON 结果;未启用时会 fail closed,返回明确的 runtime disabled 错误,不再假装执行成功