# DSH Workspace Memory 架构 ## 1. 定位 `dsh-workspace-memory` 为 DeepSeek Harness 提供可持久化、按项目隔离的长期记忆。 它同时服务普通 Session、后台 Agent 和可选的 `dsh-voco` 语音 Agent;这些调用方 只依赖 `WorkspaceMemory` 接口,不共享存储实现细节。 目标是让 Agent 在后续任务中记住稳定的项目事实、决策、约定和用户偏好,同时保持 记忆可浏览、可审计、可删除。当前版本不引入向量数据库、Embedding 或 BM25。 ## 2. Scope 模型 记忆分为三类目录: - `global/`:跨项目的用户偏好和通用工作方式。所有项目 Session 都可以读取。 - `scopes/ws-/`:由规范化绝对 `cwd` 得到的项目 scope。项目 Session 会同时 读取全局记忆和本项目记忆。 - `archived/ws-/`:工作区注册记录删除后暂存的项目记忆。它不参与正常召回, 但可在设置的“回收区”查看,直到用户确认永久删除。 同一个规范化 `cwd` 始终映射到同一个 scope;缺少 `cwd` 时使用全局 scope。存储根目录 默认为 `$DSH_HOME/workspace-memory`,未设置时使用 `~/.dsh/workspace-memory`。 ## 3. 文件布局 ```text workspace-memory/ ├── global/ │ ├── memory_summary.md │ ├── memory_entries.json │ ├── state.json │ ├── checkpoints/ │ └── summary_history/ ├── scopes/ │ └── ws-/ │ ├── scope.json │ ├── memory_summary.md │ ├── memory_entries.json │ ├── state.json │ ├── checkpoints/ │ └── summary_history/ └── archived/ └── ws-/ ├── scope.json ├── memory_summary.md ├── memory_entries.json ├── state.json ├── checkpoints/ └── summary_history/ ``` `memory_entries.json` 是结构化事实的来源;`memory_summary.md` 是受大小限制的注入 摘要;`state.json` 保存 checkpoint 缓冲和计数;`checkpoints/` 与 `summary_history/` 用于故障排查和变更审计。所有写入经过 scope 级串行队列,并使用临时文件原子替换。 ## 4. 公共接口 ```ts interface WorkspaceMemory { recall(input: RecallInput): Promise checkpoint(input: CheckpointInput): Promise } ``` 此外,运行时提供 `remember`、`forget` 和 `search` 能力供显式记忆工具使用。调用方 不能直接操作 JSON 文件;这样可以统一处理去重、敏感信息过滤和并发写入。 ## 5. 数据流 ### Agent 1. `systemPrompt.context` 注入当前 scope 的稳定摘要。 2. Agent 第一个 step 根据用户消息调用 `recall`,追加相关条目。 3. Agent turn 结束时把完整消息交给 checkpoint 缓冲区,响应不会被蒸馏过程阻塞。checkpoint 只在短暂持锁时认领消息和提交结果,耗时的模型蒸馏在锁外执行;期间新到达的消息继续留在缓冲区。 4. 达到阶段条件后,蒸馏器提取长期有效事实并更新结构化条目。 ### 普通 Session 与后台 Agent 两者均从 Session 的 `cwd` 解析项目 scope。后台 Agent 继承来源 `cwd`,因此无需单独 的记忆目录,也不会把不同项目的事实混在一起。 ### dsh-voco 语音前台在路由前可调用同一个 `workspaceMemory.recall`,将结果作为带边界的参考材料 提供给路由器。前台默认最多等待 250 毫秒,超时后以空记忆继续路由;后台 Agent 仍会在首个 step 独立检索同一项目记忆。完成的语音 utterance 进入同一 checkpoint 策略,Session 关闭时强制评估 最后一阶段。 `dsh-voco` `0.3.6` 起,每个完成的 frontend-agent 委派任务还会使用子 Session ID 提交 `task-end` checkpoint。输入只包含 Voco 持有的用户原始请求(含已接受的补充要求)和最终可见结果, 不包含 reasoning、工具日志、runtime context、workspace memory 注入或轮换 handoff。子 Session 继承 主语音 Session 的 `cwd`,因此多个子 Session 与主会话自然进入同一个 workspace scope;任务 ID 派生的 稳定消息 ID 与记忆引擎的 seen-message 机制共同保证重复终止事件幂等。取消、失败、等待用户继续的 中间状态不作为稳定事实提交。服务不存在或调用失败时,Voco 保持原有行为。 ## 6. 阶段性 checkpoint “阶段性”按工作阶段和缓冲阈值判断,而不是按固定小时执行。以下任一条件满足即可 触发整理: - 后台 Agent 的任务完成; - 缓冲达到默认 10 个已完成用户轮次; - 缓冲文本达到默认 4000 字符; - 默认空闲 5 分钟; - Session 关闭,或调用方显式强制 checkpoint。 每轮只追加到缓冲区,不强制调用模型。任何记忆变更都会立即重建受影响 scope 的摘要,避免已纠正 事实继续注入;每成功整理 5 次仍执行一次兜底重建,并保留有限版本历史。 蒸馏器同时接收有数量和字节上限的相关现有记忆,并输出版本化操作:新增、修订、明确取代或 标记冲突。明确取代必须引用本次用户消息原文及目标记忆原文;证据不足时保留双方并建立冲突组。 修订前保存旧版本,取代后的条目继续保留用于审计。只有 active 条目进入稳定摘要,conflict 只在相关查询命中时返回,superseded 不参与普通召回。旧版裸 proposal 输出兼容为新增操作。 ## 7. 检索策略 检索使用结构化词法排序:精确短语和规范化子串优先,其次是标题、检索词、标签、ASCII token、中文字符 bigram,再综合内容匹配、重要性、新近度和短期已展示惩罚。结果同时受条目 数量和 UTF-8 字节数限制。 这种策略不依赖 BM25、Embedding 或向量数据库,便于离线运行、审计和控制安装体积; Agent 仍可通过 `memory_search` 进行第二次查询。 ## 8. 设置与生命周期 Web 设置的“记忆”页面从全局 scope 列表中选择任意项目,而不是绑定当前打开的会话。 活动记忆和回收区分为两个视图:活动视图显示全局及现存项目;回收区显示已归档项目的 摘要、结构化条目和整理计数。删除项目时只移动其 scope 目录,便于误删后的人工保留; “永久删除”需确认,并物理删除归档目录及其 checkpoint、摘要历史,操作不可恢复。 前端只能通过 Host 的只读读取路由访问脱敏数据,不能直接读写存储文件,也不会展示完整 checkpoint 原文。全局记忆不随项目删除而改变。 ## 9. 安全与降级 - 凭据形态内容默认拒绝持久化,召回前再次脱敏。 - 记忆以不可信参考资料注入,不能覆盖当前用户指令。 - 解析失败、存储失败、检索失败或蒸馏失败只记录日志,不阻断 Agent 或语音回复。 - checkpoint 输入有硬性字节上限,scope 写入串行化以避免并发覆盖;recall 使用写入后失效的 不可变内存快照,不进入写锁队列。 ## 10. 验证与发布 本项目使用 TypeScript。提交前运行 `pnpm check`、`pnpm build`、`pnpm pack --dry-run` 和 `git diff --check`;发布前确认打包内容包含 `README.md`、`DESIGN.md` 与本架构文档,并 在真实 Harness 中验证项目选择、回收区和永久删除流程。