meta(docs): devdocs/ 纳入版本库 —— 交接与协同文档不再只存在于本机
主人 2026-10-04 指示「项目仓库也可以写进去」。因此把 devdocs/ 从 .gitignore 移除并首次入库: - `05-开发进度与交接.md` —— 跨会话交接锚点:当前状态、易忘的实现约定、踩过的坑、实机验收方法 - `02-前后端协同事项.md` —— 与后端会话的**交换文档**(两边都会读写:我们登记缺口,对面写回执) - `01/03/04/06/07` + `DESIGN.md` —— 路线、客户端细化方案、构建环境、迁移说明、给后端会话的交接 **凭据扫描已过**:无账号口令、无 token/refreshToken 明文、无 API key 或私钥。 文档里只记「登录凭据不写进文档,问主人」这条口径本身。 (此前忽略它的理由已不成立:文档现在承担跨会话交接与前后端协同两件正事, 只留在本机磁盘会随机器丢失,而这批内容的价值恰恰在「后来人读得到」。)
This commit is contained in:
1 parent
29733914a4
commit
2369dd2115
9 files changed
+2170
-3
No files matched your search
@@ -0,0 +1,90 @@
|
||||
# 01 — 功能拆解与分步路线(Cyrene-For-Android 讨论稿 v1)
|
||||
|
||||
> 配套 `DESIGN.md`(总览)。本文按**分步**展开:每模块给出「做什么 / 交互 / 数据流 / 依赖 / 验收 / 边界 / Miuix 组件映射」。状态:**讨论稿**,与主人在本会话逐模块细化后定稿。
|
||||
> 前提(已定案):主界面=常规 AI APP;长按电源键=系统默认语音助手(VOICE_INTERACTION_SERVICE,全屏,无悬浮球);ASR/TTS 后端化;先纯文本版;UI 严格 Miuix(compose-miuix-ui)。
|
||||
|
||||
---
|
||||
|
||||
## 阶段 0 · 工程骨架
|
||||
**S0.1 工程搭建**
|
||||
- Gradle(版本目录)、Kotlin + Compose、`compose-miuix-ui` 依赖、`BuildConfig.BASE_URL`(debug `http://<host>:8080`,release 换 HTTPS)、单 Module `app`、包 `com.askaeth.cyrene.{app,core,data,domain,platform,ui}`。
|
||||
- 依赖:Retrofit+OkHttp、kotlinx-serialization、okhttp-WebSocket、EncryptedSharedPreferences、Hilt(可选)、Coil(图片)。
|
||||
- 验收:`./gradlew :app:assembleDebug` 通过,App 能起空壳 Miuix 首页。
|
||||
- 边界:暂不接后端。
|
||||
|
||||
## 阶段 1 · P0 纯文本聊天(零后端改动,契约现成)
|
||||
### S1.1 登录(已定稿 2026-09-08)
|
||||
- **服务器地址可配**(开源,各人部署地址不同):登录卡放「服务器地址」折叠项/入口,默认 `http://<host>:8080`,用户可改;存本地(EncryptedPrefs/DataStore)。
|
||||
- **仅 `.env` 单管理员**(`ADMIN_USERNAME/PASSWORD`)可登录,无注册/找回;成功 `role=owner`。
|
||||
- **自动登录**:默认记住 token(EncryptedPrefs),重启免登;仅 `401/auth_expired` 才清 token 回登录。
|
||||
- **报错**:**已建立连接**(服务端有响应)时用服务端 `{error.message}`;**本地错误**(连不上/证书/DNS/超时)**由客户端本地文案负责**——不把本机错误误当服务端文案。
|
||||
- **密码默认隐藏**(可切换明文)。
|
||||
- **数据流**:`AuthManager.login(baseUrl,username,password)` → `POST {base}/api/v1/auth/login` → `{token,expiresAt,role}` → `EncryptedPrefs` 存(baseUrl+token+role+expiresAt)→ `HomeScreen`。
|
||||
- **状态机**:`Idle→Loading→Success(Home)|Error(msg)`(`error.from==="server"` 用后端 `message`,`"local"` 用本地文案);登录中禁用按钮防连点;登录失败不清已存 token。
|
||||
|
||||
### S1.2 会话列表(已定稿 2026-09-08)
|
||||
- **主结构 = A**:启动**直接进主会话「与昔涟」(`web`) 聊天**;**顶栏汉堡 → 侧边栏**含【会话列表(切主/次级)+ IoT + App 设置 + 登出】。
|
||||
- **列表显示**:主会话="与昔涟",次级="会话 2/N"(按序号,title **自动**,零后端改动);无预览/时间(后端 `/sessions` 只有 id)。
|
||||
- **新建**:侧栏"+"新建次级(`POST /sessions` → `sessionId` → 切进去)。
|
||||
- **删除**:次级长按/滑出 → 确认 `Dialog` → `DELETE /sessions/{id}`;主会话禁删(提示"主会话不可删")。
|
||||
- **切换**:侧栏会话列表点选 → 切聊天页。
|
||||
- **数据流**:`GET /api/v1/sessions`(主会话 `web` 恒首位)。**依赖**:S1.1。**验收**:启动即主会话聊天;侧栏可切/建/删次级;主会话不可删;重启记住上次会话(可后续)。
|
||||
|
||||
### S1.3 聊天页:历史加载(已定稿 2026-09-08)
|
||||
- **数据流**:`GET /sessions/{id}/messages?limit=50&before=<ms>&platform=` **倒序**返回,客户端**逆序渲染**(最新在底)。**`platform` 不传 = 看全量主会话**(a,能同步 web/kook/微信所有主会话消息)。
|
||||
- **分页**:初始 50 条;**上拉**加载更多用 `before=<最早时间>` 再往前翻(**50 步进**),追加顶部。
|
||||
- **消息来源标识**:每条消息**默认显示来源**(`platform`/`deviceId` 小字角标,如"来自 web" / "来自 kook" / "来自微信" / "来自安卓(voiceassist)")——主人既定诉求。
|
||||
- **时间**:**完全隐藏**(不显示时间戳/分组,对话沉浸)。
|
||||
- **空态**:主会话无消息 → 昔涟欢迎语。
|
||||
- **依赖**:S1.2。**验收**:进会话拉 50 条倒序展示;上拉翻 50/页;每条标来源;无时间戳。
|
||||
|
||||
### S1.4 聊天页:发消息 + 流式(已定稿 2026-09-08)
|
||||
- **发消息**:WS `/ws/chat` 上行 `chat {sessionId,text,deviceId}`(**stream 流式**);本地乐观追加自己消息。
|
||||
- **流式渲染**:下行 `message.start` 开气泡 → `message.delta` **逐段追加**(气泡尾+光标)→ `message.end` 收口。
|
||||
- **流式期间新消息 = 两种模式(用户可切,默认「追加队列」)**:
|
||||
① **追加队列**(新消息进队列,流式结束后依次处理——豆包式);
|
||||
② **打断**(新消息触发 `interrupt`,保留残缺上下文 + 显示"打断"提示)。
|
||||
- **思维链 `thinking` / 工具卡 `tool_call`**:**默认展开**(方便观察思维;可折叠 + "总是收起"开关)。
|
||||
- **旁白 `<action>/<narration>`**:灰斜体小字,**按出现位置依附气泡上/下**。
|
||||
- **`mood`**:显示情绪标签(可关)。
|
||||
- **渲染**:`<p>` 拆气泡;图片;忙态 `session_busy/pending_*` 提示;`409/202` 兜底。
|
||||
|
||||
### S1.5 侧边栏(汉堡抽屉)
|
||||
- **做什么**:顶栏左上汉堡 → `Drawer` 侧边栏:当前会话/聊天、**[预留] IoT 入口**、**[预留] App 设置入口**、登出。
|
||||
- **数据流**:登出 → 清 token + 断开 WS → 回登录。
|
||||
- **验收**:汉堡展开侧栏;IoT/设置点开显示"规划中"(Miuix 空态);登出回登录页。
|
||||
- **边界**:侧栏入口预留(P0 占位不真做)。
|
||||
|
||||
### S1.6 401 / token 过期
|
||||
- **做什么**:REST 401 → `auth_expired` 清 token 停 WS → 回登录;WS 握手失败同理。
|
||||
- **验收**:JWT 过期或轮换后,下条请求自动登出重登,不无限 reconnect。
|
||||
|
||||
## 阶段 2 · P1 语音助手(后端 ASR/TTS,依赖本会话 TTS/ASR 进程接通后端)
|
||||
### S2.1 系统默认语音助手
|
||||
- **做什么**:Manifest 声明 `VOICE_INTERACTION_SERVICE`/`AssistantService`(`android:role="Assist"`),用户在系统「语音助手/电源键」设本 App 默认 → 长按电源键由系统拉起本 App `AssistantActivity`(全屏)。
|
||||
- **依赖**:系统设置入口(MIUI 自家更顺);Android 版本/厂商适配。
|
||||
- **验收**:长按电源键 → 本 App 全屏助手打开(无悬浮球)。
|
||||
|
||||
### S2.2 全屏助手 UI(AssistantActivity)
|
||||
- **做什么**:聆听动画 → 已识别文本(ASR 结果)→ 昔涟回复(流式)→ 重听/TTS;按钮:结束/放弃/再次说话。全程单页全屏,Miuix 玻璃质感。
|
||||
- **验收**:说话 → 文本上屏 → 昔涟回复 + 朗读。
|
||||
|
||||
### S2.3 语音闭环(后端 ASR/TTS)
|
||||
- **链路**:录音(`MediaRecorder`/`AudioRecord`)→ **REST 上传到后端**(音频→ASR)→ 文本 → `POST /api/v1/chat {text,deviceId}`(或 WS)→ 昔涟回复 → **后端 TTS** 返回音频 → 本端播放。`voice_output`(WS)也可拿音频。
|
||||
- **依赖**:**后端 ASR/TTS 真接通**(本会话 TTS/ASR 进程:真实 STT/TTS provider + REST 语音端点绕 4KB + `voice_input.deviceId`)。
|
||||
- **验收**:对话 3 轮语音一问一答;IM 渠道(微信/KOOK)语音也走同一后端 ASR/TTS。
|
||||
|
||||
## 阶段 3 · P2 智能
|
||||
- **IoT**:设备/场景列表(Miuix;预留接口 `GET /api/v1/iot/*`)。
|
||||
- **App 设置**:主题(Miuix 深/浅)、通知开关、语音偏好(ASR/TTS 后端已定)、关于。
|
||||
- **主动推送**:后端 proactive/backthink → 系统通知;前台服务保活(可选)。
|
||||
- **多角色**:`GET /personas` 只读展示;切换人格。
|
||||
- **记忆/子代理/自主思考**:只读面板(`memory`/`subagent`/`backthink` 过滤器)。
|
||||
|
||||
---
|
||||
|
||||
## 跨模块约定
|
||||
- **deviceId**:`voiceassist:myapp:v1`(design/16 §4.5),所有 `chat`/`voice_input` 携带 → 落库标来源、跨端可辨。
|
||||
- **主会话同步**:Android 加入 `web` 主会话,与 Web/IM 共享上下文;渲染按 `platform` 区分"本端/他端"(design/16 §4.4)。
|
||||
- **Miuix 映射**:`TopAppBar`(汉堡/标题)、`Scaffold`+`Drawer`(侧栏)、气泡(自定义 `BubbleView` 或 Miuix 卡片+毛玻璃)、`TextField`、`Button`(发送/语音)、`Snackbar`/`Dialog`(确认/错误)。**禁原生 Material**。
|
||||
- **安全红线**:token 加密存储、401 即登出、权限最小化、无悬浮球、不打日志敏感。
|
||||
Reference in new issue
Block a user