Tree:
48e31cf605
along
along-test
main
memory-center-impl-v1
memory-design-v0.2
${ noResults }
2 Commits (48e31cf605af88fb7f3f9bfa51891abe4b049a48)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
fc3f747dfb |
拾忆:周期报告弹窗 + 存量 DBTask 迁移
周期报告弹窗(MemoryReportSheet) - 一次只弹最近一份未确认的。用户一个月不开 App 会攒 4 份周报 + 1 份月报, 连弹 5 次没人受得了——服务端不带参数时就只返回最近一份。 - 不可关闭(需求 4 要求用户确认),但**确认失败也放人走**:把人扣在一个不可 关闭的弹窗里比漏记一次确认糟得多,下次进来会再弹。 - summary 为空时不播报、只显示统计。文案生成失败时服务端是刻意只回写统计的 (宁可少一句话也不让报告整个没有),这里对齐那个降级。 - 统计数字全部来自 stat_json,客户端不做任何加减——同一份数据在两处各算一遍, 早晚会出现两个不同的结果。花销按币种分行,不做汇率换算。 - 排在每日安排弹窗之后:两个都要播报,同时弹会互相盖住,而「今天要做什么」 比回顾更即时。 存量 DBTask → memory_item 迁移 模块 Start 时起 goroutine 跑一次,幂等(client_key="task:<id>" + 唯一索引)。 - **不删也不改 allhelp_task**。不可逆迁移的通例:出问题时旧表是唯一回退依据。 - **失败不阻断启动**。它是补数据不是启动前置;返回 error 会让 home 退出, 而五个服务同镜像、entrypoint 会连坐全杀。 - trigger_time 用 time.Parse 保留原时区再取日期,**不先转 UTC**—— 那会让 00:30+08:00 这类凌晨任务整体退到前一天(有用例守着)。 - RemindAhead 置 0:旧体系「服务端仅记录不触发」,用户从没被这些任务提醒过, 迁过来默认开提醒等于给所有人补发一堆历史提醒。 - UserEdited 置 true:迁移来的是用户资产,不该被会议重新生成之类的清理逻辑碰到。 - TaskType_Cron 按一次性迁,不猜重复规则——猜错会让用户每天被一个他没设过的 闹钟吵醒。 - 标题与描述都空、没有 uid、既无触发时间也无创建时间的一律跳过,不往新表塞垃圾。 7 个映射用例覆盖:基本字段、凌晨不退日期、五种 TaskType、三种状态、 无触发时间退回创建日期、四类该跳过的、标题回退描述。 验证:go build / go vet 全通过,comm + memory + mcp 三个包测试通过; dart analyze 零错误,flutter build apk --debug 通过。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
1 month ago |
|
|
0b0ac16b3c |
记忆中心后端:memory 模块 + 会议待办抽取 + 周报月报
按设计文档一~三期的后端部分落地。全量 go build / go vet 通过,新增 22 个测试。 memory 模块(modules/memory,由 home 装载,路径 /api/home/memory_*) 11 个接口:list / today / add / update / del / complete / upcoming / stats / getreport / confirmreport / listreports。 表由 proto + gorm tag 生成(不是手写 DDL——本仓所有业务表都走 mysql.CreateTable + AutoMigrate)。protobuf 没有 DECIMAL/DATE/DATETIME/null, 逐个落成:金额 int64 存分(与 pay/结算同口径,绝不用 double)、happen_date string + gorm type:date、next_remind_at int64 unix 秒(0=无)。 几处刻意的选择 - 建表失败只 Errorln 不外传。lego.Run 里 Init 返回非 nil 就 Panicf,而五个服务 同镜像、entrypoint 见任一 pid 退出就全杀,一次建表失败等于全站 502。 allhelp/model.go 那段用命名返回值 err,第二张表失败时会漏出去,是反例。 - client_key 服务端保证非空。它参与 (uid, client_key) 唯一索引,而 MySQL 的唯一 索引不像放行 NULL 那样放行空串,留空会让同一用户的第二条记录直接插不进去。 用 crypto/rand 生成:这个值是去重依据,可预测就可被抢占。 - 重复项的提醒改成「就地展开」。设计文档 v0.1 写的「remind_at 服务端算好客户端 直接用」对重复项不成立——一个字段表达不了「每天」,且没人在它过去后往前推。 现在 memory_upcoming 按项自己的 tz 展开成绝对时刻列表返回,不落库。 单条项按自己的 tz 算而不跟着请求方走:「今天有哪些事」是视图问题可以跟着人走, 「明早 8 点响」是承诺问题不能。 - 花销按币种分行统计,不做汇率换算。把 CNY 和 JPY 加成一个数是错的。 - 统计全部走 SQL,LLM 只把 stat_json 组织成一段适合朗读的话。明细截断到 20 条 (重度用户一周两百条未完成,全塞进 prompt 会顶爆上下文,播报也没人听得完)。 - 查询/删除/更新一律带 uid 作条件,报告确认校验 uid 归属。 - 更新字段走白名单而不是黑名单,漏挡一个 uid/id 就是越权改别人的数据。 选路走编排,不再写死服务商 新增 comm.IEchomeet.ChatLLM,由 echomeet 用它的 PickLLM/GetSummarizer 实现。 memory 的报告生成与会议抽取都经它选模型。allhelp/summary.go 直接 import sys/doubao 是历史债:绕过后台编排,海外应用照样调国内豆包、后台换模型也换不掉。 新模块不复制这个写法。 会议纪要 → 待办抽取(第三路) 挂在 AIProcess 写完 summary、状态置 Completed、出队之后,另起 goroutine。 prompt 内置代码不放 echomeet_template(1189 条模板改不齐,且输出要被程序 parse)。 输入用已生成的 summary 而非转写全文。注入 <meeting_date>,服务端二次校验 due_date:解析不出或早于会议当天的一律只留 due_raw、落会议当天并置 date_certain=false。抽取失败只记日志,绝不回头改 rec.State。 - gen_round 由 memory 按 source_id 现有最大值 +1 推出,不由调用方传。 echomeet 没有地方存轮次计数器,硬编码成 1 会让第二次「重新生成」的清理条件 gen_round < 1 一条都匹配不上,旧待办从此永远留在库里。 - 会议归属日期只能用 creationtime(上传时间)——DBEchoMeetRecord 上没有「会议实际 发生日期」字段,也没有客户端时区。补录历史录音会算错,是已知偏差,注释已记。 周报月报 cron 建单 → Redis 队列 → N worker。锁与队列 key 都过 redissys.RKey 加应用前缀: 测试机多应用共用一个 Redis,锁 key 不带前缀会让 A 应用挡住 B 应用整周不生成报告, 而且安安静静什么都不报。 补偿比防重更要紧:当前 compose 是单副本,多副本重复是前瞻性风险;真会发生的是 00:30 跑到一半容器重启、cron 不补跑、报告永远停在 pending。所以 memory_getreport 里做超时重新入队(同 echomeet 用 PollTranscribe 兜「转写回调丢了」的思路)。 文案生成失败不算整体失败——统计是完整的,宁可少一句话不可让报告整个没有。 顺带修的既有缺陷 - user 模块 cancel()(账号注销)补上 memory_item / memory_report 两张表, 以及既有遗漏的 useridverify(身份证掩码 + 加盐指纹)。这个清单是硬编码的, 漏了不报错,只是个人数据静静留在库里。 - errorcode.proto 新开 5201-5206 段。复用 ReqParameterError 会让客户端无法分流, 「报告还没生成好」该转圈重试而不是弹错。 测试 comm/memory_test.go 8 个:周日在 Go 里是 0、Dart 里是 7 的换算(错了不报错, 只会让每周日的闹钟在周一响)、ISO 跨年周、闰年二月、非法时区必须回退 time.Local 而不是 UTC(否则静默偏移 8 小时)、client_key 非空且不重复。 modules/memory 14 个:一次性/每天/每周展开、锚点在一年前仍能算出未来时刻、 过期项不排、灵感花销不提醒、全天项按 9:00 不落 0:00、展开结果必须升序 (客户端要按 iOS 64 条上限截断,顺序错了会把明天的排掉留下一周后的)、 项按自己时区算、LLM 输出容错(代码块/前后解释文字)与真失败必须报错。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
1 month ago |