137 lines
9.2 KiB
Markdown
137 lines
9.2 KiB
Markdown
# 连续记忆第一阶段:实现与验证
|
||
|
||
状态:2026-10-09,源码分支 `feat/supervisor-memory-v1`。涉及 `deskpaw_agent` 和
|
||
`deskpaw-memory`;尚未替换或重启正式服务。本文描述已实现边界,不把架构目标当作已有能力。
|
||
|
||
## 执行路径
|
||
|
||
```text
|
||
Runtime 持久事件
|
||
├─ 上层收件箱:终态、阻塞、需要输入 → 下次决策上下文(只读)
|
||
└─ MemoryBridge 后台同步 → Memory 事件表 → 观察批次租约
|
||
→ 模型提案 → 校验并原子发布
|
||
用户消息 → 限时索引召回/缓存 → 上层自然语言+控制工具 → Runtime 校验与执行
|
||
└─ 迟到结果持久化 → 上层收件箱/按请求 ID 查询
|
||
```
|
||
|
||
上层是主要消费者。Pi 在派发后的执行准备阶段也能读取有限工作包,并通过
|
||
`memory_evidence_get` 按 `source_refs` 展开证据;证据读取没有电脑操作权限。
|
||
|
||
上层不等待观察模型、记忆写入或 Pi 停止完成。本地只读检索有 **75 毫秒等待预算**;
|
||
超时继续后台处理,上层得到 `pending`,不能据此回答“没有记忆”。这是共享 Node 进程中的
|
||
等待上限设计,不是 CPU 饱和时的硬实时保证。执行器已发出的原子操作仍需合作式停止。
|
||
|
||
## 谁在什么时候处理什么
|
||
|
||
| 部分 | 输入与触发 | 模型与限制 |
|
||
| --- | --- | --- |
|
||
| 事件筛选和任务投影 | 每秒检查持久事件;任务结束主动唤醒 | 程序,不调用模型 |
|
||
| 新观察 Worker | 最多 20 条事件;最早事件等约 30 秒;结束、失败、阻塞、需输入提前触发 | 独立记忆角色,`reasoning=low`、输出上限 3000、90 秒超时、并发 1 |
|
||
| 旧话题/事实整理 | 新观察队列没有可处理批次时;每分钟检查;闲置或夜间复核 | 同一记忆角色;保留旧协议,90 秒超时;不占 Pi FIFO |
|
||
| 上层决策 | 用户消息 | 当前上层角色;自然语言正文和一次原生控制调用分开 |
|
||
| 召回与来源展开 | 用户问题、Pi 任务准备、显式证据读取 | 中文/英文索引、ID 与 RRF,不另开模型 |
|
||
|
||
本机检查到的执行和上层模型配置均为 `deepseek / deepseek-v4-flash`;本次不修改运行配置。
|
||
新观察角色默认回退到执行角色,允许独立指定进程环境:
|
||
|
||
```text
|
||
DESKPAW_MEMORY_MODEL_PROVIDER=deepseek
|
||
DESKPAW_MEMORY_MODEL=deepseek-v4-flash
|
||
DESKPAW_SUPERVISOR_CONTEXT_BYTES=32000
|
||
```
|
||
|
||
这些是 **Agent 进程**使用的变量,不是要求 Memory SQLite 服务直接连接模型。
|
||
新变量暂未加入设备配置工具的可编辑白名单。现有上层模型/reasoning/timeout 变量继续有效。
|
||
是否换更小的观察模型,应以带来源提取、遗漏率、错误归属率的离线样本评估决定;本轮没有调用付费模型做质量测评。
|
||
|
||
## 事件与持久性
|
||
|
||
来源包括已完成的用户交互及上层回应、任务启动与终态、Pi 的失败/改策略/里程碑/阻塞/需输入报告。
|
||
没有把 `agent_message_end`、隐藏推理、普通点击、图片和原始工具大对象交给观察模型。
|
||
无变化的日程终态和日程启动被过滤。重复内容在同一批次内合并计数,仍保留每个原始事件 ID。
|
||
敏感文本做关键词防线式脱敏;这不是能识别任意未标注凭据的完整 DLP 系统。
|
||
|
||
Runtime 的 `events.seq` 是发送位置;`memory_event_cursor_v1` 只在 Memory 确认所有 ID 后推进。
|
||
Memory 接入以 `event_id` 幂等,重复 ID 不同内容会被拒绝。旧任务卡投影也会跳过完全相同的重复写入。
|
||
|
||
事件每条正文上限 2400 UTF-8 字节,观察工作包选取预算 12000 字节。队列状态为:
|
||
|
||
```text
|
||
待处理事件 → 带 token 的 120 秒租约 → 成功事务:经历+索引+来源已消费+回执
|
||
└→ 失败:保留来源,退避重试
|
||
```
|
||
|
||
租约过期可重领同一批;新 token 会拒绝旧 Worker 的迟到提交。提交成功而响应丢失时,
|
||
同一租约重试返回原回执,不重复发布。模型必须引用或明确丢弃所有本批事件,程序核对完整覆盖。
|
||
来源不在批次、对象无相应来源、候选偏好缺少用户逐字证据的提案均不能消费批次。
|
||
|
||
首版经历为只追加记录,带设备发布序号;未实现可覆盖事实的对象级 CAS 和自动冲突消解。
|
||
反复失败的批次会持续退避,不会默默丢弃;死信队列和人工重放界面是后续管理工作。
|
||
|
||
## 召回、回调和安全边界
|
||
|
||
新经历使用倒排表查找,不限于最近 100 次任务。融合正文、召回线索和显式对象 ID;正文证据的
|
||
排序权重高于模型生成的线索。召回结果携带 `reported`/`candidate` 状态,不能被当作已验证事实或已批准规则。
|
||
新经历与旧资料库并存;旧话题仍有全表排序成本,后续需要迁移,不宣称所有旧数据已完成索引化。
|
||
|
||
上层总文本预算默认 32000 UTF-8 字节,先扣除固定提示词和工具模式,再保留完整当前请求与实时状态。
|
||
日志、历史和记忆有单独裁剪及省略标记。过长的当前请求拒绝派发,不静默截断后执行。
|
||
这不是供应商精确 token 计数;中文不能用“4 字符等于 1 token”来保证预算。
|
||
|
||
暂停返回“已暂停队列、正在停止”,恢复返回“已接收,待检查”。改向/取消当前任务在模型调用前
|
||
捕获任务 ID 和控制修订号,持久化决定后再核对;A 完成、B 接替或 A 已被另一路修改时,旧指令不执行。
|
||
|
||
关键执行事件和召回结果进入 `supervisor_inbox`,重复阻塞按任务控制版本合并,用户交互优先消费。
|
||
`interaction_seq` 区分迟到召回;迟到结果保留,但不自动操作新的任务。
|
||
|
||
新增只读 Agent 接口:
|
||
|
||
- `GET /v2/attention`:未消费的上层注意事项。
|
||
- `GET /v2/memory/requests/<request_id>`:召回状态及有界结果。
|
||
|
||
**这一步没有新增主动聊天通知,也没有让回调自行调用模型继续执行。**
|
||
现有任务结果仍走原来的 Gateway 输出渠道;新记忆的迟到查询结果进入缓存和收件箱,
|
||
在后续上层交互中使用,也可按 ID 查询。下一步才加入可中断的只读回调评估、通知去重和渠道投递确认。
|
||
首次查询超过等待预算时,当前回复可能只说明查询中,不承诺已自动补发最终回答。
|
||
|
||
当前 `owner=device:<session_id>` 约束新索引与证据接口。旧全局资料仍按单设备共享会话使用。
|
||
这不是多租户身份认证;本地 socket 的受信边界没有改变。
|
||
|
||
## 开源复用落点
|
||
|
||
- T-Mem:实际移植 RRF 算法到 `src/rank-fusion.js`,保留 MIT 声明及版本;增加通道内去重和正文加权。
|
||
- Mastra:借鉴观察批次、显式来源引用、准备/发布分离与异步结果归属;没有把整个框架或其可能等待后台工作的激活路径嵌进上层。
|
||
- Letta Code:借鉴小型常驻区、按需证据展开、提案成功落地后才消费输入,以及偏好/经历/操作技能分开;没有复制 Git 工作树管理来替代 SQLite。
|
||
|
||
Mastra 与 Letta 本阶段属于协议和流程适配,不是宣称原样导入它们的模块。
|
||
|
||
## 后续顺序
|
||
|
||
1. 对象注册和关联:责任领域、跨月项目、软件资产与多个日程共用稳定 ID;目前适配器自动归属仅到会话/任务/日程,未自动识别所有项目。
|
||
2. 只读回调评估及主动通知:用户消息能抢占,过期回调归档,通知有去重和送达确认;操作仍须满足原授权。
|
||
3. 候选复核、纠正取代、遗忘/删除、保留期限与人工重放;然后迁移旧话题索引和补充向量通道。
|
||
4. 将观察 Worker/Pi 隔离到独立进程,做持续负载和模型限流测试,保证 H618 上的调度公平性。
|
||
|
||
财务示例中,发票日常整理与月度提交应归同一报销领域,月度提交使用每月实例;维护软件则绑定
|
||
资产和独立修复实例,休眠时只保留索引,相关报错再次出现才展开经历。这些对象关系是下一步,而不是在
|
||
首版按时间摘要上贴一个“项目记忆”名称。
|
||
|
||
## 验证
|
||
|
||
2026-10-09 本机结果:Memory 25 项通过;Agent 上述四个测试文件共 54 项通过;
|
||
Agent 完整 `npm run check` 通过;两个仓库的 `git diff --check` 通过。
|
||
|
||
Memory:`npm test`,隔离数据库与临时 Unix socket,覆盖幂等、租约恢复、来源校验、中文跨窗口检索、
|
||
重复观察、敏感文本、跨日复核,以及真实服务进程重启后的回执与证据读取。
|
||
|
||
Agent:仓库根目录 `npm run check`(包括格式、锁文件、TS、浏览器冒烟检查);
|
||
在 `packages/coding-agent` 执行:
|
||
|
||
```bash
|
||
node ../../node_modules/vitest/dist/cli.js --run test/device-continuity.test.ts test/device-runtime.test.ts test/device-memory.test.ts test/device-session.test.ts
|
||
```
|
||
|
||
这些测试使用离线模型与假 Executor,不操作真实桌面,不访问真实模型 API。覆盖慢记忆服务、
|
||
后台观察与前台解耦、暂停回执、过期目标、天然语言与控制分离、会话恢复、日程以及证据筛选。
|
||
正式环境验证和部署仍需单独进行;部署前备份 Runtime/Memory SQLite(含 WAL 一致性),先更新 Memory 协议再更新 Agent。
|