Tree:
d6892eb3d6
along
along-test
main
memory-center-impl-v1
memory-design-v0.2
${ noResults }
3 Commits (d6892eb3d656c5c65856765a8268da4256aba113)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
46ebf28d64 |
闹钟改成只在 App 内提示;通话翻译/通话录音挂前台服务;复刻档位日志提到 warn
1) 拾忆提醒不再发系统通知
改成进程内 Timer + App 内弹窗。代价必须说清楚:**App 不在前台就不会提示**,
它是「打开 App 时告诉你有什么要做」,不是系统闹钟。
- 一个 Timer 只指向队首那条,响完武装下一条;定时器最长压 30 分钟,
超过就到期重算(长定时器在移动端本来就不可靠)。
- 错过的不补弹,否则早上打开 App 会糊一串昨天的提醒。
- 仍保留 flutter_local_notifications,只用来撤老版本排进系统的那些排期
(装过老包的机器上还留着,不撤的话改口径之后仍会收到、且没法关)。
只撤自己的 id 区间,绝不 cancelAll(会干掉录音的前台通知)。
- 顺带删掉上一版加的「通知权限未开启」提示条,不再需要。
2) 通话翻译 / 通话录音 切后台继续工作
两条链路原先都没有前台服务:
- 通话翻译走 AliyunBailianE2EHelper,与 AzureAsrHelper 不是同一条路,
后者的前台服务管不到它;
- 通话录音的音频来自耳机 SPP 流,压根不经过识别插件。
没有前台服务时切后台会发生两件事且都不报错:国内 ROM(荣耀/华为尤其)
冻结或回收进程,WebSocket 断、PCM 流停摆;Android 9+ 后台拿不到麦克风。
→ AST 的 start/stopContinuousTranslation 里起停 AudioRecordingForegroundService;
另开两个 method channel 口子(startAudioForegroundService/stop…)给
通话录音用。三条链路互斥使用,暂不做引用计数,注释里写明并存时要改。
⚠️ 前台服务自带常驻通知,用户关掉通知权限后它不显示但服务照常跑——
所以第 1 条「不要系统通知」和这一条不冲突。
3) 声音复刻的档位日志提到 warn 级
[TRANS-INIT] 命中哪一档、[STS] initialize 的 voiceClone 开关,原先是 info,
release 包里看不到。而「有没有复刻」完全取决于命中的是 alibaba35 还是旧版档
(旧版模型静默忽略 enable_voice_clone),不看这两行只能靠猜。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
1 month ago |
|
|
733367002a |
闹钟真正排进系统通知:排期不再只认服务端,且当场重排
真机上「对助手说定个闹钟」完全不响,三个原因叠加,每一个都不报错:
1. MemoryReminderScheduler.reschedule 的数据源只有 MemoryService.loadUpcoming,
那是纯服务端接口。后端还没部署时它恒返回空,于是 SET_clock 把闹钟写进了
本地 reminders、拾忆页也显示出来了,却一条通知都没排。用户看到的是
「记下了但不会响」,而这跟「指令压根没落地」在表现上分不出来。
→ 加 _localSlots:未同步的本地闹钟也排进来,重复规则口径与
CalendarController._expandItem 逐条对齐。合流后必须自己再排一次序,
否则本地那批会按插入位置抢占前 N 个名额、把服务端更早的挤掉。
2. reschedule 只挂在 AppLifecycleManager 的「切回前台」上。新定的闹钟要等
下次切前台才进系统排期——「5 分钟后提醒我」当场就废了;冷启动那一轮
也根本不会排。
→ SET_clock 落地后(无论上传成败)当场重排;补传成功后也重排(来源从
本地兜底变成服务端,不重排会响两遍);CalendarController.refreshFromServer
末尾也排一次,覆盖冷启动。
3. 没有通知权限时 reschedule 直接 return,而 permissionDenied 这个标志
**没有任何 UI 在读**(注释里写了要显示提示,实际没接)。测试机上
POST_NOTIFICATIONS granted=false,所以无论如何都不会响、也没有任何解释。
→ 首页加一条常驻提示条指向权限管理页。刻意不是弹窗:申请必须由用户在
权限管理里主动发起,PermissionUtil 有 48 小时合规冷却。
文案 memNotifyDisabled 41 个语言文件里都已存在,无需补 key。
另外把指令链路的日志提到 warn 级(同上一轮恒玄那批的理由:release 的级别
门槛是 warning,写 info 等于真机上查不到)。协议层新增一行「指令帧」日志,
只在这一帧真带了 extra_info 或 command_calls 时打——它是区分
「百炼没下发」和「下发了但端侧没落地」的唯一证据。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
1 month ago |
|
|
66463e53f6 |
记忆中心客户端:拾忆页接服务端 + 写操作 UI + 本地提醒 + 每日播报
dart analyze 零错误,flutter build apk --debug 通过。 零期修缮 - tabTodo 补齐 41 个语言。此前只有 11 个文件有这个 key,其中 8 个的值是 'Remin'(不是任何语言里的词,像 Reminisce 打了一半),缺 key 的 30 个经 GetX 回退到 en_US 同样显示 'Remin' —— 41 个语言里 38 个是坏的,只是不报错。 - i18n_audit.py 补「缺失 key」检查。它此前**结构上无法发现缺失的 key**:循环遍历 的是该文件已有的 key,且对 baseline 里没有的直接 continue。这正是 tabTodo 在 30 个语言里悄悄丢掉而没人发现的原因。现以 zh_cn 为基准,实测报出 7243 处历史缺失 (40 个语言只有 1 个不缺)。加了 --fail-on-missing/--allow-missing 给 CI 卡「只增 不减」,默认不开——一上来就红会让人直接把检查关掉。 - pubspec 引入 timezone + flutter_timezone。zonedSchedule 只接受 tz.TZDateTime, 没有这两个依赖,提醒功能一行都写不了。 拾忆页从纯展示改成可写(此前最大的工作量遗漏) 页面原来没有 RefreshIndicator、没有 FloatingActionButton、卡片没有 onTap, 于是服务端的 add/update/del/complete 四个写接口在客户端一个调用点都没有, user_edited 那套「保护用户修改」的机制完全空转。本次补齐: - MemoryEditSheet:新增/编辑弹层,按分类分流表单(统一表存储 ≠ 统一表单) - 卡片 onTap 打开编辑、左侧勾选框标记完成(灵感不给勾选框,它没有完成一说) - 右下角 + 新增、RefreshIndicator 下拉刷新、带引导的空态页 - date_certain=false 的项单独归到「待定日期」小节。一次会抽出 8 条没写截止时间的 待办全堆在会议当天,不分开那一格就没法看了。 数据层 - MemoryItem / MemoryRemindSlot / MemoryReport 手写镜像服务端 pb。 **每个字段都经宽松解析器**(memInt/memBool/memStr),不直接 as int: 服务端删字段或老记录缺列时,non-nullable 会让整个 fromJson 抛 TypeError, 表现是整页空白而不是少一个字段(appconfig_model 已经为此踩过坑)。 单条解析失败只跳过那一条。 - 分类保留原始字符串而不是 enum 解析。服务端加分类只改常量不发包, 客户端 switch 不到就抛等于服务端一加分类就打崩所有存量 App。 CalendarEventCategory 加了 other 作为未知兜底,筛选与卡片分流都改成值比较 而不是穷举 switch。 - MemoryService 只缓存最近 90 天。GetStorage 是把整个 box 读进内存的 JSON, 一年三千多条全量缓存会让每次启动越来越慢。 - 拉取失败保留本地缓存并标 staleFromCache,页面显示行内「当前显示的是本地缓存」, 不清空、不弹红条。 - 勾选完成是乐观更新 + 失败回滚。不回滚会让用户以为已经勾上,下次进页面又变回来。 - memory_today / memory_upcoming 加进 AuthInterceptor 的红条抑制名单: 它们在启动与前台恢复时自动调,用户什么都没点就吃一条英文内部状态词很差。 删除 mock mockCalendarEvents() 与它引用的 44 个 demo* i18n key 一并删除(41 个文件共 484 行)。 真实数据上线后混着演示数据会让人以为系统出错。 本地提醒(MemoryReminderScheduler) - 通知 id 占 920000 起的固定区间,**逐条 cancel,绝不 cancelAll()** —— 仓库里已有 两个各自 new 的 FlutterLocalNotificationsPlugin 实例,cancelAll 会顺手干掉正在 录音的前台通知,表现是录音悄悄失去前台身份被系统回收。 - 单独的通知通道:录音提示是常驻低优先级通道,共用会让提醒被降级成静默。 - **只查权限不申请**。申请必须走 PermissionUtil(它收敛了过审要求的 48 小时冷却), 且只允许用户在权限管理页主动发起,这里主动申请等于绕过合规规则。 无权限时降级为「打开 App 才提醒」,不阻塞。 - 精确排期失败(Android 14 起 SCHEDULE_EXACT_ALARM 默认不授予)自动退化成 inexact 再试一次——不精确的提醒也比没有强,日志会记下来。 - 拿不到系统时区时按本机偏移找等价区兜底,不落回 UTC(那会让国内用户全部偏 8 小时)。 每日播报(MemoryDailySheet) - **不 await 在启动路径上**。冷启动已串四次网络往返,仓库刚做过相反方向的优化 (6a64c3d0 把会议模板拉取改成 unawaited)。这里是进主页后异步拉、拿到再弹。 - 排在隐私政策与强更弹窗之后,且必须在登录态确认之后。 - 通话翻译进行中一律不播报:两者共用同一个 AVAudioSession,在对方刚调好的会话上 再设一次会把通话音频路由弄乱(iOS 那条 phone_call 分支被改坏过三次)。 - 关窗必须真停:speakStream 是队列式播放,只 stop 不清队列会「关了还在念下一句」。 - 播报文案本地拼,不调 LLM。 生命周期与账号 - 切前台的刷新挂在 AppLifecycleManager(仓库已有 emai/translation/permissions 三个各自实现的 observer,本类就是收敛点),全部 unawaited。 - 登出清空记忆数据与已排提醒。不清的话换账号会看到上一个人的日程花销灵感, 提醒也会继续按上一个账号的安排响。 助手闹钟迁移 SET_clock 改为双写:本地 reminders 保留一个版本(上传失败时本机仍可用), 同时写服务端 memory_item(category=alarm)。**幂等键用指令 id** —— 本类的按 id 去重只在本进程内存里,换机/重装/重启后全失效,服务端靠 (uid, client_key) 唯一索引兜住。认不出的重复规则按单次处理,宁可只响一次也不按猜的规则天天响。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
1 month ago |