feat(stash): Codex 草稿暂存 — 输入框旁 push/pop + Usage 下方暂存面板#550
Conversation
新增 CDP 注入器 codex_stash_injector,解决「预输入内容 vs 临时插话」冲突: 可把当前输入框草稿先暂存腾出输入框回复,随后选择性恢复到输入框或直接发送 (比原生 steer 的「按队列顺序自动发送」更灵活)。 - composer 工具栏:暂存(push)+ 快捷恢复(pop,1 条直接恢复 / 多条下拉选)按钮 - Usage 面板下方:Stash 列表,每行 恢复/发送/删除 - 全局 localStorage(catStash)存储,跨 reload 存活;恢复采用 swap 语义(输入框 非空时先暂存当前内容)不丢草稿 - 独立 daemon,settings.codexStashEnabled 开关(默认关) - quota injector 配合:Stash 面板在场时让位坐到其前,保证「Usage 在 Stash 上面」
bump VERSION 时漏改 ctx_breakdown_contract 测试里 pin 的版本字符串, CI 全量 test 捕获(本地只跑了 stash filtered 测试漏掉)。
- push/pop/面板恢复 携带图片:读 imageAttachments(dataURL),恢复经合成 paste 复用 Codex 原生摄入(fetch(dataURL) 被 CSP 挡→改 atob 解码) - 文件不在范围(注入侧无法干净恢复,见 followup CAT-260):push 不动文件 - save 返回成功标志:图片 dataURL 大,localStorage 配额溢出时降级为只存文字、不丢内容 - 面板行显示图片计数;push 按钮有文字或图片即可用;ensurePanel 改廉价 id 签名(不再每 tick stringify 大 dataURL) - VERSION 1→2
- 界面预览/Preview 下各功能展示(主界面/接入/主题/用量/Stash)统一收进 <details> 折叠分组,默认折叠缩短页面长度(GitHub Markdown 无标签页,用折叠实现整体展示区) - 新增 Codex 草稿暂存 Stash 展示:Stash 面板(带图片计数)+ 快捷恢复下拉两图
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e95e1a7b15
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- 暂存保留换行:textContent 改 innerText 捕获(多行不再被拼成一行);存储规范化为 每个换行一个 \n(captureText),恢复经 text/plain 合成 paste 重建段落 —— CDP 实证 本 composer Shift+Enter = 新建 <p> 段落,paste 按 \n 切段同构还原,往返幂等且精确; insertLineBreak 会插裸 \n 被 PM 规整成空格(丢换行)故弃用,回退仅 insertText/InputEvent - 图片发送前确认 paste 就位:waitImages 回调带 ok,超时不照发也不消费暂存 - 写失败不消费:restore/sendItem 仅在 setComposer 真落值后才移除目标项 - load 解析缓存:__rev 单调写计数,热路径(ensureBar/ensurePanel)不再每 tick 重解析数 MB 图片 dataURL;判空用 textContent 不触发 reflow 经 CDP 注入真机 Codex 跑完整 push→restore 往返验证:多行草稿换行保留、恢复结构精确、 目标项消费时机正确、用户原有暂存不受影响。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 688e31c07c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- 保留有意空行:captureText 改块级读取(顶层 <p> 各取 textContent 按单 \n join,空块=空行), 不再折叠连续换行;CDP 实证空行往返幂等(此前 collapse 会把 a\n\nb 压成 a\nb) - 图片就位判定先等旧图清空:settleImages 先轮询当前 data: 图清空到 0(clearImages 异步)再 paste + 计数,避免旧附件满足计数导致带错图/空图就提交 - restore 也等图就位才消费:之前只有 sendItem 等,restore 写完文本就消费 + addImages 不校验; 现在有图时同样等 paste 成功才移除暂存项,失败保留可重试 - clearImages 只清可序列化(data:)图:非 data:(如 blob 上传)readImages 存不了,就不删, 避免「没存上又删掉=丢图」 经 CDP 注入真机验证:空行往返幂等、图片(文本+图)push→restore 往返成功且消费时机正确、 用户原有暂存全程不受影响。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 26b371ce28
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- 清空判定改数「全部附件」非仅 data::settleImages 用 attCount()(composerAtt 全量)判断旧图 清空,避免一张非 data: 旧附件被当成已清空、跟着 paste+提交 - 纯文本 send/restore 也走 settleImages([]):先等旧图清空再消费/提交,否则 clearImages 异步 未清完时,纯文本暂存项会带着上一稿的图一起发出 - captureText 块内非 trailing <br> → \n(防御富文本粘贴/未来版本块内 hard break;CDP 实证本 composer 把 br/HTML 断行规整成独立段落,正常不触发;空块仍用 textContent 保留空行) 经 CDP 真机复验:空行往返仍幂等、图片往返仍正确;F2(块内 br)取防御实现而非忽略。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6151faa327
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- 清空判定改按附件行存在性(hasAttachments):附件行 [data-composer-attachments-row] 条件渲染 (有任意附件才在 DOM,CDP 实证),故其在场=有附件,**含文件**;文件清不掉时 send 超时安全中止, 不会把残留文件随暂存文本一起发出(此前 attCount 只数 imageAttachments,漏文件) - restore/sendItem 加全局串行锁 __busy:异步(settleImages)期间忽略重复点 + push,防同条重复点 / 并发 clobber composer / 重复 submit;每条早退路径与 callback 均复位 - stashCurrent 处理中也跳过(不在 restore/send 异步窗口里动 composer) 经 CDP 真机复验 V7:空行 + 图片往返仍正确;cargo test 262 passed。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b0a5176d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- setComposer 写校验改 sameText(块级 captureText 比对,保留空行;只去尾部空白/尾换行,不折叠 内部 \n):此前 nrm 折叠连续换行,把 a\n\nb 写成 a\nb 也判通过 → 消费/发送被破坏草稿;现在 空行不一致即判失败,保留暂存可重试 - sendItem 提交成功才消费:submitComposer() 返回 false(按钮/fiber 路径变化或暂不可提交)时 保留暂存、不静默吞掉(此前先消费再 submit,失败=静默丢失) - stashCurrent 暂存含图后等附件真正清空再解锁(__busy + 轮询 hasAttachments):clearImages 异步, 否则刚暂存的图还挂着、用户紧接着发送的插话会把它带出去 经 CDP 真机复验 V8:空行往返仍幂等(sameText 校验 happy-path 不误判)、图片往返仍正确;cargo test 262 passed。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 625448e703
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- sameText 不再裁剪前导/尾随换行:此前去掉前导 \n,丢了草稿的前导空行也判通过 → 消费被破坏 草稿;现在只归一 \r + 去各行尾水平空白,任何 \n(前导/内部/尾随)均保真比对(CDP 实证前导空行 paste 可保留、捕获/恢复一致) - push 遇文件附件中止:hasFileAttachment 检测附件 chip(.composer-attachment-surface)中无 <img> 的=文件;文件不可暂存/恢复(CAT-260),只存文字会把文件孤儿化、被下一条原生发送带走,故中止并 提示用户先移除文件(restore/send 侧已由 hasAttachments 门控自动规避) F1(暂存图片后亚帧窗口内用 Codex 原生发送的竞态)按维护者决定作为已知限制:关闭它需拦截 Codex 原生 Enter/发送(有误吞 Enter 风险),与近乎不可达的时序竞态不成比例。 经 CDP 真机复验 V9:内部空行 + 前导空行 + 图片往返均正确;cargo test 262 passed。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d67f0558e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- 不支持附件检测 unsupportedAtt 统一覆盖文件 + 非 data: 图(blob/上传中): imageAttachments 总数 > data: 图数(readImages)→ 有非 data: 图;总附件数(attTotal,附件行 flex 容器直接子节点数,1 附件 1 子)> 图片附件数 → 有文件。任一为真即中止 push/restore/send 保草稿。 (注:.composer-attachment-surface 类有嵌套,每附件命中 2 个,故用 flex 子节点数,CDP 实证) - restore/sendItem 在 swapInCurrent 前拦截不支持附件:避免把当前草稿拆成 text-only stash + 残留附件 - 配额溢出整体中止:不再降级为「只存文字、图片留输入框」(那会拆分草稿 + 残留图被原生发送带走), 改为不动 composer + 提示,保草稿完整 经 CDP 真机复验 V10:data: 图片往返正常(不误拦)、上传中/文件附件正确拦截、文本空行往返正常; cargo test 262 passed。
Refs CAT-259
做了什么
新增 CDP 注入器
codex_stash_injector,给 Codex 加「草稿暂存区」:把当前输入框内容先暂存腾出输入框去回复上一轮,随后选择性恢复到输入框或直接发送。比 Codex 原生 steer(预存后只能按队列顺序自动发送)更灵活。localStorage(catStash),跨 Codex reload 存活;恢复用 swap 语义(输入框非空先暂存当前内容)不丢草稿settings.codexStashEnabled开关(默认关)用户影响
默认关,开启后仅对「通过本应用启动的 Codex」生效。
验证
cargo check/fmt/test(3/3)/machete · 前端 vue-tsc + build · 活体 CDP 注入真机 Codex 渲染 + 死循环 guard 实测通过。完整点击链路真机 e2e 合并前打 .app 验。
实现细节 / 关键锚点 / review 修复见 CAT-259。