14 KiB
AgentMail 鸿蒙客户端(ArkUI)构筑计划
邮件驱动·多智能体协作平台 — HarmonyOS 客户端 构筑者:dsh | 版本:v0.1 | 日期:2026-09-07 上游接口契约:docs/API.md · 平台规划:docs/PLAN.md
0. 定位与分工
- jianf(发起人)→ 收件方 pi 负责 ele 客户端(Win/Linux),并作为长期维护者给我方提供 API 解读与支持;
- dsh(我)→ 负责 鸿蒙客户端(ArkUI),本计划即鸿蒙侧的构筑蓝图。
- 平台后端是 同一个 Gateway(Go + SQLite,HTTP REST + SSE),鸿蒙客户端调用其人类接口
(
/api/v1/me/*等),与 WebUI 完全等价,没有私有通道。 - 交付形态:一套 Stage 模型 ArkTS 工程,以 HAP 形式运行于 HarmonyOS 手机/平板/2in1, 覆盖 WebUI 的「邮件收发 + 会话 + 联系人 + 权限决策」核心功能面。
本机工具链(已勘察确认):
| 组件 | 版本/位置 |
|---|---|
| DevEco CLI | 26.0.0 Beta2,/opt/huawei/command-line-tools(devecocli 1.3.0 已包装在 /usr/local/bin) |
| HarmonyOS SDK | 6.1.0(API 23,Version 6.1.0.105 Release),/opt/huawei/harmonyos/ohos-sdk/linux |
| 包管理 | ohpm(command-line-tools/ohpm) |
| 模拟器 | HarmonyPhone(phone / HarmonyOS 6.1.1(24),KVM 加速,按需 harmony-emu start) |
| 真机 | 可选:hdc 无线调试(动态 IP,签名 hap 走 devecocli signature generate,材料在 ~/.ohos/config) |
鸿蒙生态约束(真机安装必须签名):模拟器可装 unsigned hap;真机一律要签名。
签名材料已就绪,devecocli signature generate --force 可随时重新生成。
1. 目标功能面(与 WebUI 对齐的裁剪集)
首版(M1-M3)做「个人邮件客户端」核心闭环,管理员面(用户管理/Agent 密钥/默认预算)不在鸿蒙侧首版 范围内 —— 那是 Web 管理台的职责,鸿蒙端聚焦日常使用。
| 模块 | 功能 | 对应 API |
|---|---|---|
| 登录/凭证 | 账号密码登录;用户密钥登录(跨设备场景,Bearer) | POST /auth/login、GET /auth/me、POST /auth/logout、POST /me/keys |
| 收件箱/发件箱 | 未读/全部列表、未读标记、发件箱 | GET /me/mail/inbox?s=unread|all、GET /me/mail/sent |
| 会话列表 | 我参与的会话(卡片/列表视图)、未读数、预算徽标 | GET /me/sessions、GET /contacts、GET /contacts/suggest |
| 邮件详情 | Markdown 正文渲染、附件清单、抄送显示、对话树 | GET /mail/{id}、GET /mail/{id}/thread |
| 写信 | 收件人三段式补全、抄送、正文、往返预算、附件上传、会话别名(.new 时) |
POST /me/mail/send、POST /me/attachments |
| 回复/转发 | 回复落回原会话、转发开新线索(附件随行) | POST /me/mail/{id}/forward |
| 权限决策 | 待决请求列表、同意/拒绝/备注 | GET /permission/pending、POST /permission/decide |
| 实时推送 | 新邮件、权限决策、会话更新(SSE) | GET /events/stream?access_token= |
| 会话管理 | 改名、预算调整、权限档位调整(plan / workspace / full)、改名提议展示/接受/驳回、归档 | PUT /sessions/{id}/alias、GET|PUT /sessions/{id}/budget、PUT /sessions/{id}/permission、rename-proposal 组、POST /contacts/archive |
| 权限档位 | 会话头部展示当前档位与强制力(permission_mode / permission_enforcement),可随时调整 |
见会话管理行;档位三值 plan / workspace / full |
| 附件 | 下载(保存到本地/分享) | GET /me/attachments/{id} |
明确不做(首版):管理员后台、Agent 侧接口、日历(/calendar/*,Web 端新功能,待 api 解读后二版评估)。
2. 技术方案
2.1 工程形态
- Stage 模型 +
@ohos/http(默认网络库,无需三方依赖),entry单模块起步; 若 UI 面膨胀再拆common/feature多模块,首版不预先拆。 - 语言:纯 ArkTS(严格模式,
arkts-*lint 全开),不用 JS/TS 混写。 - 状态管理:首版用组件内
@State/@Link/@Provide即可;跨页共享(登录态、token、未读数) 提炼为单例 Service 层(@ohos.data.preferences持久化凭证),不引第三方状态库。
2.2 API 层(核心设计)
对齐 WebUI 的 src/api/ 思路,鸿蒙侧实现一份同构的客户端:
entry/src/main/ets/
├── ability/ EntryAbility.ets
├── pages/ 登录 / 主界面 / 会话 / 邮件详情 / 写信 / 权限
├── api/
│ ├── ApiClient.ets # 统一 request():base + headers + 错误归一化(400/401/403/404/409/429)
│ ├── AuthApi.ets # login / logout / me / keys
│ ├── MailApi.ets # inbox / sent / detail / thread / send / forward / read
│ ├── SessionApi.ets # sessions / alias / budget / rename-proposal
│ ├── ContactApi.ets # contacts / suggest / archive
│ ├── PermissionApi.ets # pending / decide
│ ├── AttachmentApi.ets # upload / download
│ └── SseClient.ets # SSE 流式解析 + 指数退避重连
├── model/ # 领域模型(Mail/Session/Contact/…,与 API.md 字段一一对应)
├── store/ # 单例:SessionStore / MailStore / UnreadStore(跨页共享)
├── components/ # MailListItem / SessionCard / AddressInput / PermissionCard / MarkdownView …
└── common/ # 常量(BASE_URL、事件名)、工具(相对时间、rune 截断、Markdown 渲染)
要点:
- 基地址与凭证集中在
common/config:apiBase可运行时配置(设置页填写网关地址), 与 WebUI 的window.__AGENTMAIL_API_BASE__同思路 —— 一个构建产物可指向任意后端。 - 认证双通道:Cookie(账号密码登录,
@ohos.http手动管理 Cookie)与Authorization: Bearer <user_key>(密钥登录)。SSE 与附件下载这两个浏览器侧只能走 query 令牌的端点, 鸿蒙侧可以带请求头,优先 Bearer,避免令牌进 URL 日志。 - 错误归一化:统一把服务端
{"error": "中文可操作描述"}与 HTTP 状态码翻译成ApiError { code, message };401 统一触发「回登录页」;429/403 文案原样上屏。
2.3 SSE 实时(关键难点)
@ohos.http 的流式响应(on('dataReceive'))用于解析 SSE 帧:
- 手工按
\n\n分帧,解析event:/data:行;事件表与 API.md 一致:new_mail/permission_decision/session_update/session_archived/agent_online。 (pi 梳理补充:new_mail与session_update事件还带session_alias/permission_mode/permission_enforcement字段 —— 鸿蒙端模型层按此定义, 会话卡片同时显示档位徽标。) - 断线重连:指数退避 1s→15s 上限(对齐 Web 端
api/sse.ts),AbortController优雅停止。 new_mail到达 → 通知 MailStore 刷新收件箱与未读数;permission_decision→ 刷新权限卡片。- 生命周期:App 前台订阅、后台/退到
onBackground暂停,回到前台重连(省电 + 避免无谓重连风暴)。
2.4 Markdown 渲染
鸿蒙没有现成 react-markdown。选择(按优先级):
- 首版:轻量自研解析子集 —— 标题/粗体/斜体/行内代码/代码块/列表/引用/链接/分割线,
用
Span/RichText逐段渲染;raw HTML 一律不渲染、链接协议白名单(http/https), 守住 Web 端 Markdown XSS 回归测试立下的同一条纪律(见 PLAN.md 6.4)。 - 若正文复杂度超预期,评估
@ohos/webview加载本地渲染页(需白名单校验后再注入,引入 XSS 面,慎用)。
2.5 附件
- 上传:
@ohos.request/httpmultipart 到POST /me/attachments(字段名 file), 返回attachment_id后随send的attachment_ids使用 —— 两步流程与 Web 端一致。 - 下载:
GET /me/attachments/{id}→ 写入应用沙箱文件目录,用@ohos.file.picker/@ohos.share交出去(保存到相册/分享)。注意服务端强制 octet-stream + attachment, 按响应头Content-Disposition解析文件名(API.md 七、已暴露该响应头)。
2.6 UI 布局(ArkUI)
| 界面 | 结构 |
|---|---|
| 登录页 | 服务器地址 + 账号/密码 或 用户密钥;「保存地址」入 preferences |
| 主界面(手机) | 底部 Tab:收件 / 会话 / 联系人 / 权限 / 我的;顶栏未读徽标 |
| 主界面(平板/2in1) | 两栏/三栏自适应:左列表 + 右详情;@ohos.mediaquery 断点切换 |
| 会话列表 | 列表/卡片视图切换;卡片含主题、最新一封发件人+摘要、预算徽标(剩 1 橙 / 用尽红 / 不限不显示) |
| 邮件详情 | Markdown 正文 + 附件行 + 抄送行 + 权限卡片 + 底部「回复 / 转发」+ 对话树入口 |
| 对话树 | 缩进 + 连接线(不引图形库),分块加载:dir=around 首屏 + up/down 增量 |
| 写信页 | 收件人补全(三段式 suggest)+ 抄送 + 主题 + 正文 + 预算档位 + 附件 + 会话别名(仅 .new) |
| 设置 | 网关地址、退出登录、密钥管理(/me/keys 创建/吊销,展示 token_hint) |
窄屏三维地址补全:/contacts/suggest 无参 → name;带 name → path;带 name+path → 别名+new,
逐级展开,方向键选择(对齐 Web 端 AddressInput 交互)。
3. ArkTS 工程注意点(本机实操约束)
在写第一行 .ets 前先加载 arkts-grammar-standards 技能,按规范落地:
- 严格模式:禁
any、禁未声明类型、undefined处理显式化(??/ optional chain 白名单内)。 - 组件用
struct+@Component,状态用@State/@Prop/@Provide;列表用LazyForEach(邮件量可能上百,ForEach全量渲染会卡)。 - 网络模型用
interface描述(与 API.md 字段对齐),服务端多余字段不枚举。 - Sendable / Actor 需求确认:首版无跨线程共享大对象,先不进;若 SSE 解析放 worker 再评估。
@ohos.http需在module.json5声明ohos.permission.INTERNET(示例项目已带,照抄)。- 构建:
devecocli build/hvigorw assembleHap产出entry-default-signed.hap; 模拟器hdc install(unsigned 亦可),真机走签名 hap +hdc tconn。
4. 里程碑与验收
M0 脚手架(0.5 天)
devecocli create建 Stage 工程(包名com.agentmail.harmony,API 23);- 空壳 App 在 HarmonyPhone 模拟器跑通(
harmony-emu start→ build → install → 截图); - 签名配置写入
build-profile.json5(复用~/.ohos/config材料)。
验收:启动图标进桌面,devecocli ui screenshot 可见主页面。
M1 API 层 + 登录(1-2 天)
ApiClient(Base + 错误归一化 + 双认证通道)+AuthApi;- 登录页(账号密码 / 用户密钥)+ token/凭证持久化 + 401 全局回落登录。
验收:连本机 Gateway(http://localhost:8180)用真实账号登录成功,
GET /auth/me 返回当前用户;错密码显示服务端中文文案。
M2 邮件闭环(3-5 天)
- 收件箱/发件箱列表(未读态、分页)、邮件详情(Markdown 渲染 + 附件行 + 抄送)、
回复/转发、写信页(三段式补全 + 预算档位 + 附件上传两步流 +
.new会话别名)。
验收:人 → Agent → 人 端到端:给 pi/opencode 发一封带抄送与附件的任务邮件, Agent 回信后在本端看到详情并可继续回复;新信未读计数正确。
M3 实时 + 会话 + 权限(2-3 天)
SseClient(解析 + 退避重连 + 生命周期);未读徽标与列表随事件刷新;- 会话列表(列表/卡片)、改名提议条(接受/驳回)、预算调整、权限档位调整与档位徽标;
- 权限待决列表 + 决策卡片。
验收:另一浏览器标签给本账号发信,鸿蒙端 ≤3s 内未读 +1(SSE 路径); Agent 权限请求出现在待决列表,决策后 Agent 侧收到(对照 Web 端行为一致)。
M4 对话树 + 附件落盘 + 打磨(2-3 天)
- 对话树分块加载(
around/up/down+ 滚动位置补偿); - 附件下载到沙箱 → picker/share 导出;平板/2in1 自适应布局、深色模式(如有余力)。
验收:251 封长链线索在鸿蒙端分页取完、depth 连续;真机(若可用)安装签名 hap 全流程跑通。
M5 联调 + 文档(1-2 天)
- 与 ele 端(pi)在同一 Gateway 上双端并行联调:双端同账号互斥/一致性问题暴露;
- 对照
PLUGIN-CONTRACT.md的验收清单做客户端视角补测; - 更新本计划为「已落地」,同步 README 接入说明。
预计总工时:约 2-3 周(含联调与返工缓冲)。
5. 风险与依赖
| 风险 | 对策 |
|---|---|
@ohos.http 流式 SSE 稳定性(长连接、断流) |
退避重连 + 生命周期暂停;降级方案:轮询 /me/mail/inbox(SSE 仅作加速) |
| ArkTS 严格模式对三方库不友好 | 尽量零三方依赖;网络/存储/文件全走系统 API |
| Markdown 渲染面 | 首版渲染子集 + 协议白名单;复杂稿需时评估 webview 方案并单独过 XSS 评审 |
| 真机签名链路 | 材料已就绪;devecocli signature generate --force 兜底;无真机时模拟器验收为主 |
| 服务端接口变更 | 依赖方(pi)的 API 解读;所有模型层集中在 model/,变更只动一处 |
| 日历等 Web 新功能 | 首版明确排除,M5 后按 API 解读评估二版 |
需要 jianf / pi 提供的支持:
- 一个稳定的测试 Gateway 地址(开发联调用,含可登录账号);
- 接口变化时按
docs/API.md格式及时更新 —— 鸿蒙端模型层严格对齐该文档。
6. 与 ele 端(pi)的协同点
- 两端共用同一份 API.md 契约,建议把「API 解读」沉淀为
docs/API-INTERPRETATION.md(字段语义、边界行为、踩坑),供双端引用,避免各自重复踩; - 后端新增字段时(如日历),双端各自按需跟进;鸿蒙端涉及协议层的问题由 pi 提供解读支持(按分工)。