Files
boss/docs/superpowers/specs/2026-03-29-chat-attachments-storage-and-ai-processing-design.md

686 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Boss 聊天附件、双存储与 AI 处理设计
日期:`2026-03-29`
## 1. 背景
当前 `Boss` 原生 Android 客户端已经完成:
- 微信式 `会话 / 设备 / 我的` 一级交互
- 线程 = 聊天窗口
- 会话信息、独立群聊、微信式消息转发
但聊天主链仍缺少真实的附件协作能力:
- 聊天框还不能直接发送本机图片、视频、文件
- 接收端还不能收到可预览/可下载的附件消息
- 存储目前只有服务器本地文件路线,没有可切换的对象存储
- AI 还不能基于聊天里的附件自动或手动分析内容
这次工作要把这四条链路一起打通:
1. 原生聊天框发送本机图片、视频、文件
2. 默认服务器文件存储 + 可选阿里 OSS 私有桶
3. Web 端做最简化的用户级存储配置
4. 主 Agent 统一处理附件分析,并把结果回写到聊天中
## 2. 目标
本次设计完成后,系统应满足:
1. 原生 Android 聊天框左侧提供单个 `+` 附件入口。
2. 点击 `+` 后通过底部抽屉选择 `图片 / 视频 / 文件`
3. 图片、视频在发送前需要预览确认;文件直接发送。
4. 默认使用服务器文件存储。
5. 用户可在 Web 端 `我的 > 附件与存储` 中切换到 `OSS`
6. `OSS` 当前只支持 `阿里 OSS`,并使用私有桶 + 签名 URL。
7. 存储配置按当前登录用户保存,不做全局唯一配置。
8. 接收端收到的附件消息不感知底层存储差异,都能统一预览/下载。
9. 图片 / PDF / 文本默认自动交给主 Agent 处理。
10. 视频 / Office / 大文件默认手动触发分析。
11. “大文件”阈值固定为 `20 MB`
12. AI 处理结果以“简短回复 + 可继续查看的分析卡片”形式回到当前聊天。
## 3. 非目标
本次明确不做:
1. 非阿里云的 OSS / S3 / COS 接入。
2. 语音附件、录音、外部分享面板。
3. 跨应用分享、系统分享菜单接入。
4. 附件版本管理、回收站、批量迁移工具。
5. 视频高级转码、视频在线播放 CDN 优化。
6. Office / 视频的深度结构化解析引擎。
7. 多租户复杂权限模型。
## 4. 已确认的产品决策
### 4.1 原生聊天入口
- 聊天输入框左侧保留单个 `+`
- 点击后打开底部抽屉
- 抽屉内固定展示:
- `图片`
- `视频`
- `文件`
### 4.2 发送前确认
- 图片:选中后先进入发送确认态
- 视频:选中后先进入发送确认态
- 文件:直接进入发送,不额外确认
### 4.3 Web 配置入口
- 配置入口固定放在 `我的 > 附件与存储`
- 不放在会话页,不藏在多层设置后面
### 4.4 OSS 最小配置项
阿里 OSS 最小配置字段固定为:
- `AccessKey ID`
- `AccessKey Secret`
- `Bucket`
- `Endpoint`
- `Region`
- `目录前缀`(可选,默认 `boss/`
### 4.5 AI 处理策略
- 图片 / PDF / 文本:默认自动处理
- 视频 / Office / 大文件:默认手动触发
- 大文件阈值:`20 MB`
- 所有附件分析统一走主 Agent
### 4.6 AI 结果展示
分析结果返回当前聊天时,固定使用混合展示:
1. 一条简短的主 Agent 回复
2. 一张分析结果卡片
## 5. 总体架构
### 5.1 发送链
发送链拆成两步:
1. 原生 APP 选择附件并上传
2. 服务端创建附件消息
用户视角上,它们仍是一条连续动作。
上传成功后,服务端会在目标会话写入统一的“附件消息”,而不是单独写“上传请求消息”。
### 5.2 存储链
存储层统一抽象成 `AttachmentStorageProvider`,底层实现两种:
- `server_file`
- `aliyun_oss`
所有附件都通过同一套元数据模型进入消息系统,聊天页和 AI 处理链不直接感知底层存储类型。
### 5.3 AI 处理链
AI 处理与上传解耦:
- 上传完成后先落附件消息
- 再由服务端根据文件类型和大小决定是否自动排队给主 Agent
- 不自动处理的附件,显示为“可分析”,由用户手动触发
### 5.4 接收链
接收端收到的消息固定是统一附件消息:
- 可看到文件类型、名称、大小、状态
- 图片支持预览
- 视频支持预览/下载
- PDF / 文本 / Office / 其他文件支持下载
- 可看到 AI 分析状态与结果
## 6. 存储设计
### 6.1 用户级配置模型
每个登录用户拥有独立的存储偏好:
```ts
type AttachmentStorageMode = "server_file" | "oss";
type OssProvider = "aliyun_oss";
interface UserAttachmentStorageConfig {
account: string;
mode: AttachmentStorageMode;
ossProvider?: OssProvider;
aliyunOss?: {
enabled: boolean;
accessKeyId: string;
accessKeySecretEncrypted: string;
bucket: string;
endpoint: string;
region: string;
prefix?: string;
};
updatedAt: string;
validatedAt?: string;
}
```
其中:
- `mode=server_file` 时,不要求任何 OSS 字段
- `mode=oss` 时,必须要求 `ossProvider=aliyun_oss`
- `prefix` 默认值为 `boss/`
### 6.2 密钥存储策略
由于当前系统仍使用文件持久化,阿里 OSS 的 `AccessKey Secret` 不能明文直接写入 `boss-state.json`
本次设计采用:
- `boss-state.json` 中只保存加密后的 `accessKeySecretEncrypted`
- 服务器本地使用单独密钥对该字段做对称加密
- 该本地密钥不进入仓库,不通过客户端下发
推荐实现方式:
- 优先读取环境变量,如 `BOSS_STORAGE_SECRET_KEY`
- 如果不存在,则在服务器本地生成仅运行时可见的密钥文件并持久化到数据目录
### 6.3 默认服务器文件存储
默认存储后端为服务器本地文件。
建议目录结构:
```text
data/uploads/<account>/<yyyy>/<mm>/<messageId>-<safeFileName>
```
优势:
- 符合当前“极轻云 + 本地设备端”路线
- 不引入额外云资源即可先跑通
- 与现有 `boss-state.json` 路线一致
### 6.4 阿里 OSS 存储
阿里 OSS 固定采用:
- 私有桶
- 临时签名 URL
服务端负责:
- 上传对象
- 生成对象 key
- 在下载或预览时生成短期签名 URL
对象 key 建议结构:
```text
<prefix>/<account>/<yyyy>/<mm>/<messageId>-<safeFileName>
```
其中:
- `prefix` 默认为 `boss/`
- 用户可在配置中改为其他目录前缀
### 6.5 统一下载入口
前台不直接拼 OSS URL也不直接暴露本地文件路径。
统一下载/预览入口建议为:
```text
GET /api/v1/attachments/[attachmentId]/download
```
该接口统一负责:
- 鉴权当前用户是否可访问对应会话
- 如果是 `server_file`
- 流式返回文件
- 如果是 `aliyun_oss`
- 生成短期签名 URL
- 302 跳转,或由服务端转发流式响应
这样可以保证:
- 客户端体验统一
- 存储切换不影响聊天 UI
- 不暴露底层凭证
## 7. 附件消息模型
### 7.1 新消息类型
现有消息类型只有文本和若干 intent 占位,不足以表达真实附件。
本次应扩展消息模型:
```ts
type MessageKind =
| "text"
| "voice_intent"
| "image_intent"
| "video_intent"
| "forward_notice"
| "forward_single"
| "forward_bundle"
| "attachment";
```
### 7.2 附件元数据
```ts
type AttachmentKind =
| "image"
| "video"
| "pdf"
| "text"
| "office"
| "binary";
type AttachmentStorageBackend = "server_file" | "aliyun_oss";
type AttachmentAnalysisState =
| "not_applicable"
| "queued_auto"
| "ready_manual"
| "processing"
| "completed"
| "failed";
interface MessageAttachment {
attachmentId: string;
fileName: string;
mimeType: string;
fileSizeBytes: number;
attachmentKind: AttachmentKind;
storageBackend: AttachmentStorageBackend;
storagePath: string;
previewAvailable: boolean;
uploadedAt: string;
uploadedBy: string;
analysisState: AttachmentAnalysisState;
analysisSummary?: string;
analysisCardId?: string;
}
```
每条附件消息可以先只支持单附件,避免第一轮就把消息结构做成多附件复合体。后续若要支持一条消息多个附件,再扩展成数组。
### 7.3 附件消息结构
```ts
interface Message {
id: string;
sender: MessageSender;
senderLabel: string;
body: string;
sentAt: string;
kind?: MessageKind;
attachment?: MessageAttachment;
forwardSource?: ForwardSource;
forwardBundle?: ForwardBundlePayload;
}
```
附件消息的 `body` 用作聊天摘要和兼容展示,例如:
- 图片:`已发送图片:车间异常截图.png`
- 视频:`已发送视频:工位巡检录像.mp4`
- 文件:`已发送文件:北区回归报告.pdf`
## 8. AI 分析模型
### 8.1 分析任务
附件分析统一走主 Agent不让单个普通线程自行处理。
建议新增任务模型:
```ts
type MasterAgentTaskType =
| "chat_reply"
| "attachment_analysis";
interface AttachmentAnalysisTaskPayload {
projectId: string;
messageId: string;
attachmentId: string;
fileName: string;
mimeType: string;
attachmentKind: AttachmentKind;
fileSizeBytes: number;
downloadUrl: string;
triggerMode: "auto" | "manual";
}
```
### 8.2 自动 / 手动分析规则
自动进入主 Agent 的条件:
- `attachmentKind=image`
- `attachmentKind=pdf`
- `attachmentKind=text`
- 文件大小 `<= 20 MB`
手动触发的条件:
- `attachmentKind=video`
- `attachmentKind=office`
- 文件大小 `> 20 MB`
### 8.3 AI 处理执行者
统一执行者为主 Agent
- 优先走 `Master Codex Node`
- 只有在容灾路径明确支持时,才考虑 `openai_api`
在能力未覆盖的情况下,应返回明确状态,不要假装已完成分析。
### 8.4 分析结果回写
分析结果固定回写到当前聊天会话中,形式为:
1. 一条简短主 Agent 回复
2. 一张分析结果卡片
简短回复示例:
```text
主 Agent已分析《北区回归报告.pdf》。核心问题是登录态恢复链和 OTA 覆盖安装文档不一致。
```
分析卡片中至少应包含:
- 分析对象文件名
- 分析模式(自动 / 手动)
- 核心结论摘要
- 关键提取点列表
- 分析完成时间
## 9. API 设计
### 9.1 Web 配置接口
新增用户级附件存储配置接口:
```text
GET /api/v1/storage/config
PATCH /api/v1/storage/config
POST /api/v1/storage/config/validate
```
语义:
- `GET`:获取当前用户的附件与存储配置
- `PATCH`:更新当前用户配置
- `validate`:校验阿里 OSS 是否配置可用
`validate` 至少检查:
- AK/SK 是否能通过认证
- Bucket 是否存在
- Endpoint / Region 是否匹配
- 是否具备读写权限
### 9.2 附件上传接口
新增统一附件上传接口:
```text
POST /api/v1/projects/[projectId]/attachments
```
建议使用 `multipart/form-data`,字段至少包括:
- `file`
- `sourceType`: `image | video | file`
该接口负责:
1. 鉴权
2. 解析文件类型
3. 读取当前用户存储配置
4. 上传到对应后端
5. 生成附件消息
6. 决定是否自动创建主 Agent 分析任务
返回值应直接带回新创建的消息和分析状态。
### 9.3 手动分析接口
新增:
```text
POST /api/v1/projects/[projectId]/attachments/[attachmentId]/analyze
```
用途:
-`ready_manual` 的附件手动触发 AI 分析
### 9.4 统一下载接口
新增:
```text
GET /api/v1/attachments/[attachmentId]/download
```
用途:
- 图片预览
- 视频预览或下载
- 文件下载
### 9.5 SSE 刷新
现有 `/api/v1/events` 继续承担刷新出口,需要增加这些事件:
- `attachment.uploaded`
- `attachment.analysis.queued`
- `attachment.analysis.updated`
- `attachment.analysis.completed`
- `attachment.analysis.failed`
## 10. 原生 Android 设计
### 10.1 聊天输入区
聊天输入区固定为:
- 左侧 `+`
- 中间输入框
- 右侧发送按钮
点击 `+` 后弹出底部抽屉,包含:
- 图片
- 视频
- 文件
### 10.2 系统文件选择
原生 Android 需要新增:
- 图片选择器
- 视频选择器
- 文件选择器
建议基于 `ActivityResultContracts.OpenDocument` / `GetContent` 实现。
### 10.3 发送前确认
- 图片:展示预览 + `取消 / 发送`
- 视频:展示预览或文件摘要 + `取消 / 发送`
- 文件:直接进入上传
### 10.4 聊天中的附件渲染
图片消息:
- 缩略图
- 文件名
- 大小
- 分析状态
视频消息:
- 缩略图或占位封面
- 文件名
- 大小
- 分析状态
文件消息:
- 文件图标
- 文件名
- 类型
- 大小
- 下载/查看动作
- 分析状态
### 10.5 分析状态呈现
附件卡片需能表示:
- `queued_auto`:自动分析排队中
- `ready_manual`:可分析
- `processing`:分析中
- `completed`:分析完成
- `failed`:分析失败,可重试
## 11. Web 配置页设计
### 11.1 入口
入口固定为:
```text
我的 > 附件与存储
```
### 11.2 页面结构
第一页只做两层:
1. 存储方式选择
- 服务器文件存储(默认)
- OSS
2. 如果选 `OSS`
- 供应商选择:当前只显示 `阿里 OSS`
- 展开最小配置表单
### 11.3 表单交互
表单交互应尽可能简化:
- `AccessKey ID`
- `AccessKey Secret`
- `Bucket`
- `Endpoint`
- `Region`
- `目录前缀(可选)`
按钮建议只有两个:
- `测试并保存`
- `切回服务器文件存储`
不做额外的高级设置入口作为第一屏主内容。
## 12. 与主 Agent 的关系
主 Agent 不再只处理文本请求,也需要能理解附件分析任务。
这次要求主 Agent
1. 收到附件任务时,知道当前附件来自哪个会话、哪条消息
2. 能通过统一下载 URL 获取附件
3. 对图片 / PDF / 文本自动分析
4. 对手动模式附件在用户触发后再分析
5. 把结果回写为:
- 一条简短消息
- 一张分析卡片
如果主 Agent 当前无法处理某类附件,应明确返回失败原因,而不是静默成功。
## 13. 错误处理
至少覆盖以下错误:
1. 用户未配置 OSS但切换到了 OSS
2. OSS 配置无效
3. Bucket 无权限
4. 上传中断
5. 本地文件 URI 无法读取
6. 附件消息已创建但自动分析排队失败
7. 分析任务执行失败
8. 下载 URL 失效
9. 原文件已被删除或不可用
错误处理原则:
- 上传失败:不创建成功消息,前台保留失败提示
- 上传成功、分析失败:保留附件消息,但把分析状态标为 `failed`
- 下载失败:允许用户重试,不直接删除消息
## 14. 测试与验收
### 14.1 Web / 服务端
至少验证:
1. 默认服务器文件存储上传成功
2. 阿里 OSS 上传成功
3. 用户级配置切换生效
4. 未配置 OSS 时不能误走 OSS
5. 图片 / PDF / 文本能自动排队分析
6. 视频 / Office / 大文件默认进入手动分析
7. 下载接口能正确返回本地文件或 OSS 签名 URL
### 14.2 原生 Android
至少验证:
1. `+` 按钮打开底部抽屉
2. 图片发送前确认
3. 视频发送前确认
4. 文件直接发送
5. 图片消息渲染
6. 视频消息渲染
7. 文件消息渲染
8. 分析状态切换
9. 下载 / 预览动作
### 14.3 验收标准
本次工作完成时,应满足:
1. 用户能从原生聊天框发送图片、视频、文件
2. 接收端能看到附件消息并统一预览/下载
3. 默认服务器文件存储可直接使用
4. 用户可在 Web 端开启 OSS并完成阿里 OSS 最小配置
5. 图片 / PDF / 文本会自动交给主 Agent 分析
6. 视频 / Office / 大文件可手动触发分析
7. 主 Agent 的分析结果会回到当前聊天中
8. UI 和交互仍保持当前微信式方向,不回退成控制台面板
## 15. 推荐实现顺序
1. 先补数据模型与用户级存储配置
2. 再补服务器文件存储上传 / 下载链
3. 再补阿里 OSS 适配器与校验
4. 再补原生 Android 选择文件、上传和附件卡片
5. 再把主 Agent 附件分析任务接通
6. 最后补 Web 配置页、联调、部署与发包