Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
752 changes: 752 additions & 0 deletions docs/superpowers/plans/2026-07-17-long-input-txt-upload.md

Large diffs are not rendered by default.

184 changes: 184 additions & 0 deletions docs/superpowers/specs/2026-07-17-long-input-txt-upload-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# 对话超长文本转 TXT 附件设计

## 背景

Issue #885 希望改善长需求、PRD 和日志的输入体验。任务对话输入框当前完整保留文本,并在内容超过 `MAX_TASK_CONTENT_LENGTH` 的 10000 字限制后禁用发送。用户需要手工创建文本文件后再上传。

本设计在任务详情对话输入框中提供超长文本转 TXT 附件能力,并复用现有任务附件上传链路。

## 已确认决策

- 首期仅覆盖任务详情对话输入框 `TaskChatInputBox`。
- 超长文本转换采用专用确认流程,一次确认完成文件创建和上传。
- 文件名采用 `long-input-YYYYMMDD-HHmmss.txt` 时间格式。
- 转换完成后清空原文并显示附件卡片。
- 用户需要补充说明文字后才能发送,前后端现有非空文本校验保持现状。
- 取消转换后保留完整原文,并提供手动“转为 TXT”入口。

## 目标

1. 输入或粘贴内容首次超过 10000 字时主动提示转换。
2. 用户确认后自动创建 UTF-8 TXT 文件并上传为当前消息附件。
3. 上传成功后允许用户继续输入补充说明。
4. 取消或上传失败时完整保留用户原文。
5. 沿用现有附件数量、文件大小、附件卡片、删除和发送逻辑。

## 首期范围

- `frontend/src/components/console/task/chat-inputbox.tsx` 的文本输入和附件状态。
- 超长文本确认弹窗及手动转换入口。
- TXT 文件创建、时间命名和上传编排。
- 中英文界面文案。
- 专项测试、静态检查、在线构建和 SaaS 人工验收。

## 后续范围

- 创建任务、默认任务和开始开发等其他 10000 字输入入口。
- 根据正文摘要自动生成文件名。
- 纯附件消息发送及后端非空文本校验调整。
- 提升模型上下文或消息文本上限。

## 交互流程

### 自动触发

1. 输入内容从 10000 字以内首次跨越到 10001 字时记录完整文本快照。长度计算沿用现有 JavaScript `string.length` 语义。
2. IME 组合输入结束后执行越界判断,保证中文输入过程连贯。
3. 当前任务处于空闲状态且附件仍有空位时打开确认弹窗。
4. 任务执行期间进入待提示状态并持续同步最新原文,任务恢复空闲后使用最新完整内容打开确认弹窗。

确认弹窗展示当前字符数、生成文件名、2MB 文件限制,以及确认和取消操作。

### 确认转换

1. 锁定输入区和弹窗操作,防止重复提交。
2. 使用确认时保存的完整文本创建 `text/plain;charset=utf-8` 文件。
3. 调用现有 `uploadTaskFile()` 执行 2MB 校验和 presigned upload。
4. 上传成功后将返回值追加到 `uploadedFiles`,清空输入内容和本地草稿。
5. 恢复输入框焦点并提示用户补充说明后发送。

转换后的附件使用现有附件卡片展示和删除。发送按钮继续由非空说明文字和字符上限共同控制。

### 取消与重新发起

取消后关闭弹窗并保留完整文本。同一次越界状态进入抑制模式,后续输入不会连续弹窗。内容回到 10000 字以内时重置抑制状态。

超限字符提示区域增加“转为 TXT”按钮,用户可随时手动重新打开确认弹窗。

## 组件与职责

### `chat-inputbox.tsx`

- 识别字符上限跨越和 IME 状态。
- 管理待转换文本快照、弹窗开关、转换中状态和自动提示抑制状态。
- 检查任务空闲状态和附件数量。
- 调用 TXT 创建函数与 `uploadTaskFile()`。
- 复用现有附件追加、焦点恢复和草稿清理逻辑。

### `task-long-content.ts`

新增纯函数模块,包含:

- 判断本次内容变化是否应触发自动转换提示。
- 生成 `long-input-YYYYMMDD-HHmmss.txt` 文件名。
- 通过完整文本创建 UTF-8 `File`。

纯函数保持浏览器状态之外的逻辑可独立测试。

### `task-long-content-dialog.tsx`

新增轻量确认弹窗,接收字符数、文件名、转换状态和确认/取消回调。上传期间按钮显示处理中状态,并锁定关闭操作。

### 现有上传链路

继续使用 `task-file-upload.tsx` 导出的:

- `uploadTaskFile()`
- `TaskUploadFileTooLargeError`
- `MAX_TASK_UPLOAD_FILE_SIZE_LABEL`

后端接口、附件 payload 和任务消息结构保持现状。

## 状态规则

- `content.length <= 10000`:正常输入,自动提示抑制状态重置。
- `content.length > 10000` 且首次越界:在可上传时打开确认弹窗。
- `content.length > 10000` 且任务执行中:记录待提示状态并随输入更新快照,恢复空闲后打开弹窗。
- 用户取消:保留内容并抑制本轮自动弹窗。
- 用户手动点击“转为 TXT”:忽略自动提示抑制并打开弹窗。
- 转换中:锁定输入、确认、取消和重复上传。
- 转换成功:追加附件、清空内容、关闭弹窗、恢复焦点。
- 转换失败:保留内容和已有附件,关闭转换中状态并展示错误。

## 错误处理

### 附件已满

当前消息已有 3 个附件时展示现有附件数量限制提示。原文继续保留,用户移除附件后可手动重新转换。

### 文件超过 2MB

沿用 `TaskUploadFileTooLargeError` 和现有本地化提示。原文继续保留。

### 网络或上传失败

展示上传错误,保留原文和已有附件。确认弹窗恢复可操作状态,用户可以重试或取消。

### 组件卸载或任务切换

使用现有 mounted 状态保护异步回调。上传结果仅应用到发起转换的当前任务输入框。

## 可访问性

- 弹窗使用项目现有 Dialog 组件,标题和说明与内容建立语义关联。
- 初始焦点放在取消操作,降低误转换风险。
- 上传期间通过按钮状态和可见文字表达进度。
- “转为 TXT”入口使用可聚焦按钮,并提供完整中英文标签。
- 上传完成后焦点回到对话输入框。

## 本地化

在中文和英文资源中增加:

- 超长内容转换标题与说明。
- 生成文件名和字符数展示。
- “转为 TXT”、确认、取消和转换中文案。
- 转换失败、附件已满和补充说明提示。

## 测试策略

### 纯函数测试

- 10000 和 10001 字边界。
- 取消抑制与内容回到上限后的重置。
- 中文、Emoji 和换行内容生成的 UTF-8 文件保持一致。
- 时间文件名格式稳定。

### 组件契约与回归测试

- 普通输入和普通发送行为保持现状。
- 纯文本粘贴和持续输入都可触发转换。
- IME 组合输入期间保持稳定。
- 用户取消后原文完整保留,手动入口可重新发起。
- 上传成功后清空原文并显示附件。
- 上传失败、文件超过 2MB、附件满 3 个时保留原文。
- 任务执行期间延迟提示,恢复空闲后触发。
- 文件粘贴、拖拽上传和手工上传流程保持现状。
- 生成附件后发送按钮等待用户补充说明。

### 完整验证

```bash
cd frontend
pnpm lint
pnpm run build:online
```

连接 SaaS 后端人工验收输入、粘贴、取消、重试、附件删除、补充说明和发送流程。

## 风险与控制

- `chat-inputbox.tsx` 状态较多:文件创建逻辑和弹窗 UI 分离到独立模块,主组件仅保留编排状态。
- 用户可能一次粘贴数 MB 文本:上传前沿用 2MB 文件限制,失败后保留完整文本。
- 弹窗可能反复打断输入:首次越界自动提示,取消后抑制,超限区域提供手动入口。
- 异步上传期间内容竞争:转换期间锁定输入,并基于任务和文本快照应用成功结果。
Loading