chore: rebuild release package
This commit is contained in:
@@ -1 +1 @@
|
||||
codex-app-worker-timeout
|
||||
subagent-card-metadata
|
||||
|
||||
42
.planning/composer-slash-trigger/findings.md
Normal file
42
.planning/composer-slash-trigger/findings.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 调研记录
|
||||
|
||||
## 用户现象
|
||||
|
||||
- 输入形如 `/report/mcps?search` 的文件或路径文本时,界面显示“未知指令”,并阻止消息发送。
|
||||
- `/` 快捷选择目前只在输入框第一个字符生效,而 `@`、`$` 可在输入中间生效。
|
||||
|
||||
## 预期
|
||||
|
||||
- 未知 `/` 文本可以继续提示,但发送动作应继续完成。
|
||||
- `/` 在与 `@`、`$` 相同的合理 token 边界上可触发快捷选择。
|
||||
|
||||
## 仓库工作流
|
||||
|
||||
- Trellis 要求先建立并启动独立任务,再进入实现和质量检查阶段。
|
||||
- 当前前端组件与质量规范仍是占位文档,没有额外项目级实现约束;本次以现有代码风格和回归测试为准。
|
||||
- 前端交互应保持克制:沿用现有提示样式,只修正触发与发送语义,不增加新的界面层级。
|
||||
- Trellis 已为本次修复创建独立任务 `07-16-composer-slash-trigger`,不会混入原有 bootstrap 或子代理卡片任务。
|
||||
- `codebase-memory-mcp` 项目 `home-cc-web` 索引状态为 `ready`,包含 3191 个节点、7729 条边,可直接用于实现定位。
|
||||
|
||||
## 初步代码定位
|
||||
|
||||
- 服务端 `handleSlashCommand` 当前对所有以 `/` 开头的输入进入 `switch`;默认分支只发送“未知指令”系统消息并要求前端恢复草稿,因此原文本不会进入正常消息处理链路。
|
||||
- 前端 `sendMessage` 存在显式 `text.startsWith('/')` 分支,并为失败响应保存/恢复 slash 草稿;现有回归测试把未知 slash 视为“失败且恢复草稿”,正是用户所述的发送拦截行为。
|
||||
- 需要把“是否为内置 slash 命令”的判断与普通 `/路径` 文本分开:内置命令仍走命令处理,未知 slash 可提示后继续正常消息链路。
|
||||
- 快捷触发的具体解析函数尚待继续定位,需重点查看 `composer_suggestions` 请求生成以及光标前 token 匹配逻辑。
|
||||
|
||||
## 快捷触发根因
|
||||
|
||||
- `findActiveComposerToken` 对 `/` 使用独立特判:要求整段输入 `value.startsWith('/')` 且没有换行,因此只允许首字符触发。
|
||||
- 同一函数对 `@`、`$` 使用 `/(^|\s)([@$])([^\s]*)$/`,允许行首或空白后触发;这解释了三种触发符行为不一致。
|
||||
- 最小一致性修复应统一 token 边界解析:`/`、`@`、`$` 都允许行首或空白后触发,token 到光标前不能含空白。这样普通路径中的内部 `/`(如 `src/foo`)不会误开菜单,而“请看 /report”能触发。
|
||||
- `sendMessage` 仍用 `text.startsWith('/')` 判定命令,需新增明确的内置命令识别;未知 `/路径` 应走普通 `submitUserMessage`,服务端再提供提示或明确的非阻断反馈。
|
||||
|
||||
## 最终实现与验证
|
||||
|
||||
- 前端 `isKnownSlashCommandText` 按第一 token、忽略大小写精确匹配 8 个内置命令;未知 `/路径` 进入普通消息/附件流程。
|
||||
- `findActiveComposerToken` 统一使用行首或空白后的 `[/@$]` token 规则,并通过光标、LF、CRLF、路径内部斜杠用例。
|
||||
- 服务端 `handleSlashCommand` 返回是否已处理;未知命令发送无 `preserveComposerDraft` 的提示后,以 `unknownSlash` 标志进入普通 `handleMessage`,旧客户端与 Codex App 运行中 steer 也能正确放行。
|
||||
- 独立质量审查自动比较前后端完整命令集合,并确保每个服务端命令都有显式 `case`。
|
||||
- 主线程复验:定向回归、完整回归、三份 JS 语法检查及 `git diff --check` 全部通过;完整回归约 30 秒。
|
||||
- 并发中的“统一子代理卡片样式”任务也修改了 `public/app.js`、`scripts/regression.js`,最终总 diff 含其内容;本任务未回退或改写该部分,只按精确函数/断言范围核验 slash 改动。
|
||||
20
.planning/composer-slash-trigger/progress.md
Normal file
20
.planning/composer-slash-trigger/progress.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# 进度日志
|
||||
|
||||
- 2026-07-16:读取仓库指令及 planning-with-files、todo-list-csv、frontend-skill。
|
||||
- 2026-07-16:确认工作区已有 `.planning/subagent-card-metadata/` 的无关改动,将保持不触碰。
|
||||
- 2026-07-16:建立本任务独立计划与调研记录。
|
||||
- 2026-07-16:独立计划审查已通过。
|
||||
- 2026-07-16:读取 Trellis 工作流与前端规范,确认需要建立 Trellis 任务并按阶段推进。
|
||||
- 2026-07-16:创建并启动 Trellis 任务 `07-16-composer-slash-trigger`。
|
||||
- 2026-07-16:确认 `home-cc-web` 代码索引就绪,无需重新全量索引。
|
||||
- 2026-07-16:定位到服务端 `handleSlashCommand`、前端 `sendMessage` 与 slash 草稿恢复回归契约,确认发送拦截来自“所有 `/` 前缀都按命令处理”。
|
||||
- 2026-07-16:定位 `findActiveComposerToken`,确认 `/` 被首字符特判,而 `@`、`$` 支持行首/空白 token 边界。
|
||||
- 2026-07-16:补齐 Trellis PRD、调研文档以及 implement/check 上下文,明确未知 slash“提示并继续普通发送”的验收标准。
|
||||
- 2026-07-16:Trellis 任务上下文校验通过;定位阶段完成,进入失败回归测试阶段。
|
||||
- 2026-07-16:未知 slash 放行失败回归已先红后绿,覆盖系统提示、普通消息持久化和附件保留。
|
||||
- 2026-07-16:快捷触发回归覆盖 `/` 的行首、空白后、换行后触发,以及 `src/foo` 不误触发,并保持 `@`、`$` 行为。
|
||||
- 2026-07-16:完成三处最小实现:前端已知命令判定、统一 token 解析、服务端未知 slash 提示后回落正常消息链路。
|
||||
- 2026-07-16:Trellis 独立质量审查通过,并补强命令集合一致性、CRLF/光标、Codex App 运行中 steer 回归。
|
||||
- 2026-07-16:主线程复验定向回归、完整回归、语法检查和 diff 检查均通过。
|
||||
- 2026-07-16:完成最终差异核对;未调用服务重启,未触碰并发会话的子代理卡片改动。
|
||||
- 2026-07-16:Trellis 当前任务指针被并发会话切回其他任务,为避免误结束其任务,未运行无参数的 `task.py finish`。
|
||||
31
.planning/composer-slash-trigger/task_plan.md
Normal file
31
.planning/composer-slash-trigger/task_plan.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 输入框快捷指令修复计划
|
||||
|
||||
## 目标
|
||||
|
||||
修复输入框中未知 `/` 文本阻止发送的问题,并让 `/` 与 `@`、`$` 一样能在输入中的合理位置触发快捷选择,同时补齐回归测试。
|
||||
|
||||
## 阶段
|
||||
|
||||
1. [complete] 初始化 Trellis 与代码索引并定位输入解析、快捷选择和发送拦截实现
|
||||
2. [complete] 补充未知斜杠文本仍可发送的失败回归测试
|
||||
3. [complete] 补充斜杠可在非首字符位置触发的失败回归测试
|
||||
4. [complete] 修复发送拦截和斜杠触发边界实现
|
||||
5. [complete] 运行相关测试、类型检查和静态检查
|
||||
6. [complete] 审查差异、记录结果并清理临时清单
|
||||
|
||||
## 约束
|
||||
|
||||
- 保留“未知指令”提示,但提示不能阻止普通文本发送。
|
||||
- `/` 的触发位置语义与现有 `@`、`$` 保持一致,并避免路径内容误触发。
|
||||
- 不扩大到 composer 快捷指令体系之外的 UI 改版。
|
||||
- 保护工作区内与本任务无关的既有改动。
|
||||
|
||||
## 错误记录
|
||||
|
||||
| 错误 | 尝试 | 处理 |
|
||||
|---|---:|---|
|
||||
| Trellis 新任务未自动生成 `prd.md` | 1 | 按工作流手动创建 PRD,并补齐 research/context 文件 |
|
||||
| `rg` 传入不存在的 `test`、`tests` 路径导致非零退出 | 1 | 已确认本项目回归入口是 `scripts/regression.js`,后续收敛到存在路径 |
|
||||
| 独立审查首次完整回归命中并发中的 `subAgentActivity` 断言失败 | 1 | 未越界修改;等待对应会话收敛后复跑通过,主线程也再次完整复验通过 |
|
||||
| 更新调研文档时使用了不存在的 `## 风险` 锚点 | 1 | 读取文件尾部后改用实际存在的末段锚点追加 |
|
||||
| 收尾时 Trellis 当前任务已被并发会话切回 `07-11-subagent-card-metadata` | 1 | 为避免误结束其他任务,未执行只作用于当前指针的 `task.py finish`;本任务计划与验证已独立闭环 |
|
||||
@@ -21,3 +21,24 @@
|
||||
- 独立复核确认实时缓存修复后,`renderMessages()` 会清空缓存;若历史只有空 close/wait,刷新仍退化为工具 ID。
|
||||
- 服务端 `updatePersistedCcwebMcpChildTool` 只按 `child.spawnToolId` 查找工具;真实会话缺少该 spawn 工具时返回 null,未把 child 状态写入历史。
|
||||
- 后端兜底应只选择最近的 `collab_agent_tool_call`,不得把 child 合并进普通工具。
|
||||
- 2026-07-15 本机 PM2 `ccweb` 已实际重启并在线;其他机器仍显示旧样式属于发布物/部署路径问题,不是本机进程未重启。
|
||||
- CentOS 7 单文件发布必须重新运行 `scripts/build-single-exe.js`;该流程会在打包前复制 `public/` 运行时资源,源码更新不会自动进入旧 tar.gz。
|
||||
- 本机 `dist-exe/cc-web-bun-linux-x64-baseline.tar.gz` 已包含最新静态资源:tar 内 `app.js` / `style.css` 与源码 SHA-256 完全一致,并含 `collab-agent-item-description`、两行 clamp 和关闭状态缓存代码。
|
||||
- 单文件运行时从二进制同目录的 `public/` 加载资源;只替换 `cc-web` 二进制、保留旧 `public/`,或设置 `CC_WEB_APP_DIR/CC_WEB_PUBLIC_DIR` 指向旧目录,都会继续显示旧样式。
|
||||
- 旧历史会话本身若只保存 thread ID、没有 title/taskDescription,即使加载新前端也只能显示 `ID ...` 且没有简介;需要用新部署后新建的子代理验证,不能只看旧历史卡片。
|
||||
- 2026-07-16 确认同一版本存在两套事件链路:完整 `spawnAgent` 会以 `collab_agent_tool_call` 进入 `mergeCollabAgentTools()`;原生 `subAgentActivity` 仅在服务端用于线程恢复,前端不会把它合并成富卡片。
|
||||
- `mergeCollabAgentTools()` 明确过滤 `toolKind(tool) === 'collab_agent_tool_call'`;因此 `subAgentActivity + 空 wait` 会分别退化为原始折叠工具条和 `ID call_...` 卡片。
|
||||
- 修复应在进入渲染前将 `agentThreadId`、`agentPath`、活动 `kind` 归一为结构化子代理状态,并避免原始活动事件重复渲染。
|
||||
- 真实会话中的 `subAgentActivity` 输入与结果都只包含 `kind/agentThreadId/agentPath`,未携带 spawn prompt;因此历史数据能恢复线程 ID、状态与角色标题,但不能凭空恢复完整任务简介。
|
||||
- 同一消息里随后出现的 `wait` 已被转换为 `collab_agent_tool_call`,但 `receiverThreadIds` 和 `agentsStates` 均为空,说明应将前置活动事件作为该 wait 的恢复来源。
|
||||
- 扫描现有会话得到 41 条 `subAgentActivity`:活动类型只有 `started` 与 `interacted`,输入字段稳定为 `type/id/kind/agentThreadId/agentPath`,均无 prompt;`interacted` 应保持运行态。
|
||||
- Phase 8 复审已通过;计划已明确字段映射、原始工具条与 `ID call_...` 去重、baseline 二进制 smoke test 和 tarball 核验。
|
||||
- 前端所有历史、恢复流和实时流都通过 `toolKind()` 分流;让它把 raw `subAgentActivity` 识别为协作显示工具,可同时复用现有合并、富卡片渲染和普通工具过滤逻辑,避免在三个调用点分别硬编码。
|
||||
- `normalizeCollabAgentData()` 是补齐活动字段的最小归一入口:从 `agentThreadId` 构建 receiver/state,从 `agentPath` basename 构建标题/角色,从活动 kind 映射状态,并按真实字段保留 prompt。
|
||||
- 新事件还应在 `lib/codex-app-runtime.js` 的 `itemKind/itemInput/itemResult` 层输出 `collab_agent_tool_call` 结构;这样旧前端也能把新会话视为富卡片,同时保留 `input.type=subAgentActivity` 供服务端恢复线程路由。
|
||||
- 首轮生产实现已让定向行为回归通过;人工审查仍需确认三项最小范围边界:空 wait 对整体头部状态的覆盖、agentPath 同时填充 role 导致标题/页脚重复、通用 tool_end 全量增加 name/input 的必要性。
|
||||
- 独立质量检查确认首轮实现仍有高风险缺口:完成态空 wait 会覆盖整体头部为已返回但 child 仍运行;runtime completed 不带 prompt 时会直接替换 started input,刷新后简介丢失。
|
||||
- 另有两个中风险边界:agentPath basename 回填 role 会导致标题/footer 重复;仅凭 name 匹配 `subAgentActivity` 会把无 agentThreadId 的同名普通工具误归类。
|
||||
- 第二轮已改为子状态优先聚合整体状态、runtime 活动输入结构化合并、agentPath 仅提供标题、activity 匹配必须存在 threadId;新增边界回归均通过,等待原检查代理复核。
|
||||
- 原检查代理复核时把 `item/completed` 误等同于 child completed;真实会话反证是 `input.kind=started` 的活动工具本身 `done=true`,因此 transport item 生命周期不能覆盖 activity kind 的 child 生命周期语义。
|
||||
- 正确契约:completed 通知缺少新 kind 时继承 previous activity kind/status;只有活动 kind 明确为 completed/returned/failed/closed 时才改变 child 终态,同时仍保留 started prompt。
|
||||
|
||||
@@ -22,3 +22,16 @@
|
||||
- 2026-07-15:空 close/wait 卡片重建实现与完整回归通过,进入独立复核。
|
||||
- 2026-07-15:独立复核发现刷新后历史仍丢失;追加服务端持久化兜底修复。
|
||||
- 2026-07-15:服务端在 spawnToolId 缺失时回退最近协作工具,刷新闭环回归及最终独立复核通过。
|
||||
- 2026-07-15:本机 ccweb 已重启在线;开始诊断其他机器发布后仍使用旧样式的问题,优先核对 dist-exe 产物与源码资源时间。
|
||||
- 2026-07-15:确认本机 tar 包静态资源哈希与源码一致;远端老样式应检查是否整体替换 public、运行目录/环境变量,以及是否仅查看旧历史数据。
|
||||
- 2026-07-15:本机 HTTP 返回 app.js/style.css 哈希与源码及 tar 完全一致,Cache-Control 为 no-store;Phase 7 完成。
|
||||
- 2026-07-16:用户确认同一实例不同对话仍有两种样式;恢复 Phase 8,定位 `subAgentActivity` 未进入富卡片合并链路。
|
||||
- 2026-07-16:Phase 8 首次计划审查要求补齐字段映射、重复渲染断言和最终发布包 smoke test,已收紧计划并进入复审。
|
||||
- 2026-07-16:Phase 8 复审通过;完成 41 条真实活动事件字段/状态盘点,进入失败回归编写。
|
||||
- 2026-07-16:新增 raw `subAgentActivity + 空 wait` 行为回归;当前实现按预期失败于 `call_wait_empty` 被误作子代理 ID,进入字段归一实现。
|
||||
- 2026-07-16:完成前端旧历史归一和 runtime 新事件结构化,定向回归通过;进入 Trellis 独立质量检查。
|
||||
- 2026-07-16:Trellis 独立检查未放行;追加空 wait 整体状态、completed prompt 保留、角色去重和同名普通工具隔离修正循环。
|
||||
- 2026-07-16:第二轮测试先行修正完成并通过定向回归;提交原 Trellis 检查代理复核。
|
||||
- 2026-07-16:对复核提出的“item/completed 强制 child completed”意见基于真实 done=true started 活动提出异议;补充协议语义回归后再复核。
|
||||
- 2026-07-16:原 Trellis 检查代理撤回错误意见并最终通过;字段归一与统一渲染完成,进入全量回归。
|
||||
- 2026-07-16:完整 `npm run regression`、服务端/mock 语法和全工作树 diff 检查通过;在 /tmp 安装 baseline Bun,进入发布构建。
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## 当前阶段
|
||||
|
||||
Phase 7
|
||||
Phase 8
|
||||
|
||||
## 阶段
|
||||
|
||||
@@ -42,15 +42,25 @@ Phase 7
|
||||
|
||||
### Phase 7: 修复关闭后子代理卡片消失
|
||||
|
||||
- [ ] 覆盖关闭更新缺失结构化状态的回归场景
|
||||
- [ ] 缓存子代理最后一次结构化状态
|
||||
- [ ] 用已关闭 ID 和状态缓存重建关闭卡片
|
||||
- [ ] 保留已关闭子代理的标题、简介与线程 ID
|
||||
- [ ] 验证关闭状态、数量和卡片持续可见
|
||||
- [ ] 验证普通工具调用不进入子代理合并路径
|
||||
- [ ] 找不到原 spawn 工具时,将 child 状态合并到最近的协作工具历史记录
|
||||
- [ ] 刷新/历史重渲染后仍保留标题、简介、线程 ID 和关闭状态
|
||||
- [ ] 实施前后核对工作树,只改子代理相关代码与测试
|
||||
- [x] 覆盖关闭更新缺失结构化状态的回归场景
|
||||
- [x] 缓存子代理最后一次结构化状态
|
||||
- [x] 用已关闭 ID 和状态缓存重建关闭卡片
|
||||
- [x] 保留已关闭子代理的标题、简介与线程 ID
|
||||
- [x] 验证关闭状态、数量和卡片持续可见
|
||||
- [x] 验证普通工具调用不进入子代理合并路径
|
||||
- [x] 找不到原 spawn 工具时,将 child 状态合并到最近的协作工具历史记录
|
||||
- [x] 刷新/历史重渲染后仍保留标题、简介、线程 ID 和关闭状态
|
||||
- [x] 实施前后核对工作树,只改子代理相关代码与测试
|
||||
- **Status:** complete
|
||||
|
||||
### Phase 8: 统一 subAgentActivity 与原生协作工具卡片
|
||||
|
||||
- [x] 复现并定位两套子代理事件链路
|
||||
- [x] 为活动归一空 wait 复用及去重写失败回归
|
||||
- [x] 实现 agentThreadId agentPath 状态及 prompt 字段归一
|
||||
- [x] 合并活动与协作工具并隐藏原始工具条及 call ID
|
||||
- [x] 运行语法检查和完整自动化回归
|
||||
- [ ] 重建 CentOS 7 发布包并完成二进制与 tar 核验
|
||||
- **Status:** in_progress
|
||||
|
||||
## 完成标准
|
||||
@@ -71,6 +81,12 @@ Phase 7
|
||||
3. 多代理不同 prompt 的标题和简介不串联。
|
||||
4. 无 prompt 时回退短线程 ID。
|
||||
5. 关闭更新即使不携带 `receiverThreadIds/agentsStates`,也保留原子代理卡片并显示“已关闭”。
|
||||
6. 仅有 `subAgentActivity` 与空 `wait` 的历史会话也显示统一富卡片,不再显示原始活动工具条或 `ID call_...`。
|
||||
7. `agentThreadId` 写入 `receiverThreadIds` 并作为 `agentsStates` 键;`agentPath` 的 basename 写入可读标题/角色。
|
||||
8. `started/interacted` 映射为运行态,`completed/returned` 映射为完成态,失败/关闭类活动映射到对应终态。
|
||||
9. 活动或同线程事件能提供 prompt 时写入 `taskDescription`;完全没有 prompt 时不伪造简介。
|
||||
10. 回归分别覆盖完整 `spawnAgent`、仅 `subAgentActivity + 空 wait`、刷新历史、原始工具条去重、无 `ID call_...` 与 prompt 保留。
|
||||
11. 发布包保持 `bun-linux-x64-baseline` 目标,完成 MCP JSON-RPC 初始化 smoke test,并核对 tarball 内运行文件与静态资源。
|
||||
|
||||
## 范围约束
|
||||
|
||||
@@ -95,3 +111,8 @@ Phase 7
|
||||
| 空 wait/close 工具缺少可渲染的子代理状态 | 1 | 缓存 `msg.child` 状态,并用已关闭 ID 重建关闭卡片 |
|
||||
| 测试先行缺少 `rememberCollabAgentState` | 1 | 实现按 threadId 缓存 helper 后回归通过 |
|
||||
| 实时缓存无法覆盖刷新后的历史重渲染 | 1 | 原 spawn 工具缺失时把 child 合并进最近协作工具并持久化 |
|
||||
| 收尾时临时 TODO CSV 已被外部流程移除 | 1 | 确认根目录无 TODO CSV 后不重建,直接闭合持久化计划 |
|
||||
| `task.py list-context` 误传 action 参数 | 1 | 查看 `--help`,确认该命令只接收任务目录,后续按正确形状调用 |
|
||||
| Phase 8 首次计划审查发现字段、去重和发布核验契约不够具体 | 1 | 补充字段级映射、逐项行为断言与 CentOS 7 二进制/tar 验证标准后复审 |
|
||||
| 首轮实现通过定向回归但独立检查发现空 wait 状态冲突与 completed 丢 prompt | 1 | 补充四类边界行为断言,改为子状态聚合整体状态并结构化合并 runtime 活动输入 |
|
||||
| `timeout` 后直接放环境变量导致命令被当成可执行文件 | 1 | 改用 npm `--registry` 单次参数,代理查询与临时 Bun 安装成功 |
|
||||
|
||||
Reference in New Issue
Block a user