59 lines
2.8 KiB
Markdown
59 lines
2.8 KiB
Markdown
# 修复排队与运行中图片发送
|
||
|
||
## 背景
|
||
|
||
cc-web 已支持普通消息附带图片,也已通过 Codex app-server 的 `UserInput.localImage` 向新 turn 发送图片。但当前前端会拒绝排队消息与运行中插入消息携带图片,后端 steer 路径也会再次拒绝附件。
|
||
|
||
## 目标
|
||
|
||
在不改变现有纯文本、slash 指令和笔记模式语义的前提下,让现有图片附件可以:
|
||
|
||
1. 随排队消息保存,并在当前 turn 结束后发送。
|
||
2. 随 Codex App 运行中消息通过 `turn/steer` 插入。
|
||
3. 在 stale turn 自动转为新 turn 时继续保留。
|
||
4. 在会话历史与界面中保持与模型实际输入一致。
|
||
|
||
## 功能要求
|
||
|
||
### 排队发送
|
||
|
||
- 队列项保存创建时的附件元数据快照,不能依赖全局 composer 附件状态。
|
||
- 文本或附件至少存在一个即可入队;纯图片队列允许发送。
|
||
- 含 slash 的文本仍按现有规则禁止排队。
|
||
- 入队成功后清空 composer 文本和附件托盘。
|
||
- 队列卡片显示附件摘要,使用户能确认附件仍在队列中。
|
||
- 卡片内编辑只修改文本并保留附件。
|
||
- 删除未发送队列项时清理其上传附件。
|
||
- 出队时调用普通发送入口并传入附件数组。
|
||
|
||
### Codex App 运行中插入
|
||
|
||
- 前端运行中插入消息必须携带附件数组,用户气泡也显示相同附件。
|
||
- 插入成功提交后清空 composer 文本与附件托盘。
|
||
- 后端复用 `handleMessage` 已解析的安全附件,不信任前端路径。
|
||
- 持久化用户消息时保存规范化附件元数据。
|
||
- `turn/steer.input` 同时包含文本与 `localImage`;允许纯图片插入。
|
||
- 无文本时,系统提示使用图片文件名生成可读摘要。
|
||
- app-server 返回 `no active turn to steer` 时,replacement turn 必须继续使用同一批已解析附件。
|
||
|
||
## 非目标
|
||
|
||
- 不支持图片以外的任意文件附件。
|
||
- 不延长附件 TTL,也不保证超出既有 TTL 后仍可发送。
|
||
- 不改变 slash 指令、笔记模式、Claude/Codex CLI 进程模式的行为。
|
||
- 不重构现有附件存储体系。
|
||
|
||
## 验收标准
|
||
|
||
- 源码中不再存在排队图片和 Codex App 运行中图片的主动拒绝分支。
|
||
- 排队项保存附件,出队发送时附件不丢失,删除时清理附件。
|
||
- 成功 `turn/steer` 的 mock 输出能观察到 `localImage`。
|
||
- steer 用户历史包含原始附件文件名和可用状态。
|
||
- stale turn replacement 输出能观察到同一图片,历史中的用户消息只出现一次且保留附件。
|
||
- 新增 `node scripts/regression.js --target runtime-image-send` 在 60 秒内通过。
|
||
- `node --check public/app.js`、`node --check server.js`、`node --check scripts/regression.js` 通过。
|
||
|
||
## 改动保护
|
||
|
||
工作树中已有主题与回归相关未提交改动。实现必须使用局部补丁,禁止覆盖或格式化无关区域。
|