Files
Cyrene-For-Android/devdocs/01-功能拆解与分步路线.md
T
AskaEth 84de51c7b7 feat: 初始化 Android 客户端(M0 骨架 + M1 登录 + M2 基础模块)
M0:Gradle 9.7.1 / AGP 9.2.1 / Kotlin 2.4 / Miuix 0.9.3,minSdk 33,compileSdk 37。
M1:登录页(服务器地址可配、服务端/本地错误分流、EncryptedSharedPreferences、自动登录与静默重登、401 登出)。
M2 基础模块:消息内容解析器(<p>/<action>/<narration> + 流式增量)、WebSocket 客户端、REST 数据层与分页去重。
45 个单元测试全绿,真机验证通过(登录页 + 启动图标)。
devdocs/ 收录设计文档、前后端协同事项与细化方案。
2026-09-08 20:40:58 +08:00

8.2 KiB
Raw Blame History

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 即登出、权限最小化、无悬浮球、不打日志敏感。