Skip to content

feat: SSE 流式记账对话(话术+接棒+卡片入场) - #62

Merged
hinson0 merged 4 commits into
mainfrom
worktree-feat-ai
Apr 22, 2026
Merged

hinson0 merged 4 commits into
mainfrom
worktree-feat-ai

Conversation

@hinson0

@hinson0 hinson0 commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

让文字/语音/OCR 三种记账入口在 LLM 解析期间先流式吐出一段 CoCo 口吻的话术,再把账单卡片从下方淡入滑上,消除用户"按下就等几秒"的等待感。

  • 后端:新增 /chat/stream 和 /record-ocr/stream 两个 SSE 端点,话术 LLM 与 extract_bill 并发执行;事件协议用 StreamChunkEvent/StreamBillEvent/StreamTextEvent/StreamAsrEvent/StreamErrorEvent 判别联合;上游限流/鉴权错误帧显式抛出并映射为 error 事件,避免静默失败
  • 前端:引入 react-native-sse,Promise 链串行化 onEvent 防乱序;新增 StreamingBubble 配合末尾光标闪烁;buildListItems 通过「内容匹配」让真实 text 气泡零闪烁接棒流式气泡;RecordCard 仅对会话内新增的卡片应用 FadeInDown 250ms(首屏历史不抖)
  • 共享类型:@coco/shared/types/stream.ts 统一前后端事件契约,消除漂移
  • 人格:LLM 话术从"精算师"调整为轻松俏皮的 CoCo,20-40 字,不评价消费/不说教/不重复数字
  • 单测:buildListItems 接棒判定 6 个 case,覆盖匹配/不匹配/typing 降级/非 assistant-text 不触发接棒

Test plan

  • 后端 just cicd-be: ruff + 49 pytest 通过
  • 前端 just cicd-fe: eslint + prettier + typecheck + 19 suites / 183 tests 通过
  • 实机真机验证:
    • 文字"买咖啡25元" → CoCo 口吻话术 20-40 字 → 卡片从下方淡入滑上 → user 消息稳定在视觉上方无位移
    • 语音长按说话 → ASR 气泡更新 → 话术流式 → 卡片
    • 拍小票 → "小票拍到了,正在识别..." → 话术 → 卡片
    • 杀进程重进,历史 RecordCard 无入场动画(首屏不抖)
    • 断网 → "连接异常,以上内容已保存,可以再试一次~" 追加
    • 闲聊"你好" → 话术流式 → 稳定成普通 text 消息,无卡片无闪烁

Co-Authored-By: Claude noreply@anthropic.com

hinson0 and others added 4 commits April 22, 2026 21:29
POST /chat/stream 和 POST /record-ocr/stream 两个 SSE 端点,让记账时
先流式吐出 CoCo 口吻的话术再发送账单卡片,消除等待感。

话术生成与 extract_bill 并发,上游错误帧(如限流)显式抛出并映射为
StreamErrorEvent,避免"账单出来但零话术"的静默失败。

Co-Authored-By: Claude <noreply@anthropic.com>
StreamEvent 判别联合(chunk/bill/text/asr/error)与后端 Pydantic schema
一一对应,供 mobile 的 SSE 消费层复用,避免前后端手写两份漂移。

Co-Authored-By: Claude <noreply@anthropic.com>
- 引入 react-native-sse 消费 /chat/stream 和 /record-ocr/stream,onEvent
  用 Promise 链串行化避免乱序
- StreamingBubble 复用现有气泡样式 + 末尾光标闪烁
- 三入口(文字/语音/OCR)统一通过 runStream 走流式,闭包局部累积缓冲
  消除共享态污染
- buildListItems 通过「内容匹配」让真实 text 气泡接棒 StreamingBubble,
  finally 块 await invalidateQueries 再 setStreamingText(null),消除
  "user 消息从卡片底部闪回中间"的位置跳动
- RecordCard 仅对会话内新增的卡片应用 FadeInDown 250ms,首屏历史无动画
- OCR 失败时软删"正在识别"提示,服务端有错误文案时不重复弹 onFail
- SSE 接棒逻辑抽到 chat-list-items.ts + 单测覆盖接棒/typing/非匹配分支

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@hinson0
hinson0 merged commit a56a704 into main Apr 22, 2026
2 checks passed
@hinson0
hinson0 deleted the worktree-feat-ai branch April 22, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant