心愿助手最吸引人的地方是它好像记得“我想做什么”。最容易令人失望的地方也在这里页面刷新后内容消失演示标签重新出现却仍写着“长期记忆”。我会先把普通存储做诚实再考虑模型怎样理解心愿。记忆不是一组隐藏默认值第一次打开没有数据就显示空列表用户写过内容才保存。自报精力可以是 0 到 100 的滑块但不能由几句文本自动推断更不能叫健康评估。清单保留已完成与未完成状态用户可以导出、删除删除后不应在下一次启动时被默认种子数据补回来。浏览器存储说明提醒我们本地数据仍可能被清理。界面的“已保存”应该注明保存在哪里。想要可恢复就提供备份文件想要跨设备就另做同步协议不能把二者含混称为 AI 记忆。模型只拿到用户选中的内容若接推荐模型我会让用户勾选本次允许发送的心愿而不是把历史记录全部拼进提示词。Anthropic 在 10 月 7 日介绍的 Haiku 5.5把分类和摘要列为小模型用途之一这不说明本地保存应交给模型也不能证明它适合某个人的私人日记。本例完全离线不比较模型质量。下面用版本化 JSON 保存心愿与精力值注入一个最小 storage 接口方便测试刷新式重载。删除使用同一存储键并返回空状态。代码没有实现多标签页冲突解决生产版本还要处理同时编辑和存储异常。node wishes.js的验证覆盖重载、清空、精力范围和重复 ID 拒绝没有测真实浏览器配额、加密或云同步。清单做得轻一点没关系但它记住了什么、忘掉了什么应该让人看得见。可独立运行的核心例子const EMPTY()({version:1,energy:50,wishes:[]}); function check(x) { if(x.version!1||!Number.isInteger(x.energy)||x.energy0||x.energy100|| !Array.isArray(x.wishes)||x.wishes.length500)throw Error(坏状态); const idsnew Set(); for(const w of x.wishes) { if(typeof w.id!string||!w.id||ids.has(w.id)|| typeof w.text!string||!w.text.trim()||w.text.length500||typeof w.done!boolean) throw Error(坏心愿); ids.add(w.id); } return x; } function store(storage) { return { save(x){check(x);storage.setItem(wishes-v1,JSON.stringify(x));}, load(){const rawstorage.getItem(wishes-v1);return raw?check(JSON.parse(raw)):EMPTY();}, clear(){storage.removeItem(wishes-v1);return EMPTY();} }; } const mnew Map(), storage{getItem:km.get(k)??null,setItem:(k,v)m.set(k,v),removeItem:km.delete(k)}; const repostore(storage); repo.save({version:1,energy:35,wishes:[{id:w1,text:做一张叶片卡,done:false}]}); if(store(storage).load().wishes.length!1)throw Error(重载丢失); repo.clear();if(repo.load().wishes.length!0)throw Error(清空后不应补回种子); let rejectedfalse;try{repo.save({...EMPTY(),energy:101});}catch{rejectedtrue;} if(!rejected)throw Error(应拒绝超范围精力); const w{id:a,text:散步,done:false};rejectedfalse; try{repo.save({...EMPTY(),wishes:[w,w]});}catch{rejectedtrue;} if(!rejected)throw Error(重复ID应拒绝); console.log(repo.load());