deskpaw-memory/docs/implementation-v1.md

137 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 连续记忆第一阶段:实现与验证
状态: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。