Back to home@helibeiqi

dsh-memory-projection

Hot-pluggable memory-projection scheduling framework for DeepSeek Harness (dsh): pure-function projection strategies + a runtime invariant guard, built on the cordis plugin kernel.

Stars
0
Language
TypeScript
Created
Aug 20, 2026
Updated
Aug 28, 2026

Introduction

dsh-memory-projection

DeepSeek Harness 可热插拔的「记忆投影」框架 —— 在运行时动态切换 Agent 的认知模式(模型可见上下文的切片方式),而非对历史做有损压缩。

CI License: MIT


项目介绍:关于「记忆投影」的定位

很多上下文管理方案做的是 context-compression(上下文压缩):把历史对话塞进一个摘要,用摘要替换原始记录,从而「缩小」喂给模型的 token 数。这种做法的代价是不可逆地丢弃了原始日志——一旦压缩,模型就再也看不到被压缩掉的真实事件。

本插件做的是 memory-projection(记忆投影),二者有本质区别:

维度Context CompressionMemory Projection(本插件)
对原始日志压缩 / 覆盖 / 丢弃只读、永不直接修改
历史的可恢复性不可恢复(摘要即真值)始终可从 append-only 日志精确重建
模型看到的内容一段「总结」原始事件的某个切片 / 重排(真实事件)
运行时行为通常静态热插拔、可切换、可回归默认
与 DSH 不变量关系容易破坏 Model-Visible ⇔ Logged由 invariant guard 强制守住该不变量

核心心智模型:

append-only 会话事件日志是唯一的真相源(single source of truth)。 投影(projection)只是这个日志的一个纯函数视图——同一个日志,配合不同策略,得到不同的「模型可见切片」。模型当下看到什么,永远可以追溯回某几条原始事件(sourceSeqs)。

因此本插件不是一个「压缩器」,而是一个调度框架 + 内置策略集:它让你在运行时按场景切换 Agent 关注历史的哪一部分,而历史本身一分不少地留在日志里。


核心特性

  • 🔌 可热插拔的调度框架ctx.memoryProjection 提供 registerStrategy / setActiveStrategy / getActiveStrategy / listStrategies,运行时动态切换 Agent 认知模式,下一次投影即生效。
  • 🧩 内置三种纯函数策略 + 默认 passthrough(等价于原生推导):
    • precision-window —— 保留最近 N 轮 + 关键事件(聚焦执行)。
    • associative-divergence —— 从全史召回与当前上下文语义相关的事件,前置拼接(创造联想)。
    • critical-focus —— 只保留错误 / 边界 / 未解决事件(调试 / 复盘)。
  • 🛡️ 运行时不变式守卫(invariant guard):对激活策略做「双跑可复现性 + 日志溯源(provenance)」校验。凡违反 Model-Visible ⇔ Logged 不变量的投影,自动回退到默认投影,绝不让 Agent 循环中断。可开关。
  • ♻️ 零残留热插拔:所有副作用(service、事件监听、第三方注册)均通过 Cordis 原生生命周期(fiber 作用域)注册,卸载时 LIFO 自动回滚。不手写事件总线、不手写服务管理器、不手写 cleanup。
  • 📐 Cordis 原生合规:仅使用 definePlugin / ctx.plugin(Service) / ctx.on(...) 等官方扩展点,不修改内核。
  • 🧪 严格工程:TypeScript strict + ESM、Vitest 测试、ESLint + Prettier、tsup 打包,npm publish 就绪,一键 GitHub CI。

快速开始

安装

npm install dsh-memory-projection

运行依赖为 @deepseek-ai/cordis@^4(即 DSH 运行时所用的 Cordis 内核,已发布于公共 npm,可直接 npm install)。 @deepseek/harness可选 peerDependency 声明——本插件只依赖 Cordis 契约,不强制依赖 Harness 内核。

在你的 DSH / Cordis 应用中加载

import { Context } from '@deepseek-ai/cordis';
import { dshMemoryProjection } from 'dsh-memory-projection';

const root = new Context();
root.plugin(dshMemoryProjection);

const svc = root.memoryProjection;

// 切换策略(下一次投影即生效)
svc.setActiveStrategy('precision-window', { windowSize: 6 });

// 投影:输入 append-only 事件日志,输出模型可见消息
const messages = svc.project(sessionEvents);

接入原生推导(拦截 session/derive-messages

插件在加载时注册了一个 waterfall 事件监听 session/derive-messages

  • 监听存在时 → 用当前激活策略替换原生推导(veto next)。
  • 监听移除时(插件卸载)→ 原生 next() 原样执行,默认投影完全恢复

在 DSH 侧,只需把原生 Session.deriveMessages() 作为 next 续体传入该 waterfall 即可;本插件不要求修改内核。


内置策略详解

所有策略都是纯函数:相同输入(日志 + 选项)→ 相同输出,只读日志、无 I/O、无时钟读取、不修改入参。

passthrough(默认)

恒等投影,等价于 DSH 原生推导。即「不投影」,把完整日志逐事件映射为模型可见消息。作为守卫回退的安全兜底。

precision-window

选项(均可选):
  windowSize      number  保留最近 N 个会话轮次(以 user 消息为轮次边界),默认 6
  keepSystemEvents boolean 轮次外仍保留 system/boundary 事件,默认 true
  keepErrors      boolean 轮次外仍保留 error 事件,默认 true

适用:高频工具调用 Agent、聚焦执行场景。模型只需「最近上下文 + 持久系统约束」,丢弃窗口外的冗余工具步骤。

associative-divergence

选项(均可选):
  threshold       number  历史事件的语义相似度下限,默认 0.08
  topK            number   最多召回的历史事件数(0 = 不限),默认 0
  keepRecentRound boolean 始终保留最近一轮(当前线程),默认 true

全史中,按「当前上下文(最新 user prompt / recentContent)」的局部词重叠余弦相似度,召回语义相关事件并前置拼接。不强制截断——最近上下文始终保留,相关历史是「追加」而非「替换」。

相似度用确定性、零依赖的局部词重叠余弦作为「语义相关」的代理,保证策略仍是纯函数。 生产环境可通过 registerStrategy 注册基于 embedding 的策略实现真正的语义召回。

适用:创造联想、跨会话回溯——模型拿到相关先验上下文,同时不丢失当前线程。

critical-focus

选项(均可选):
  keepErrors      boolean 保留 error/failure 事件,默认 true
  keepBoundary    boolean 保留 boundary(约束)事件,默认 true
  keepUnresolved  boolean 保留 unresolved 事件,默认 true
  keepLastUser    boolean 保留最后一条 user 消息作为上下文锚点,默认 true

只保留 error / boundary / unresolved 事件,丢弃所有「顺利执行」的步骤。适用:调试、质量审查、风险复盘——模型只看「什么出错了 + 约束是什么」。


自定义策略开发指南

一个策略 = 一个满足 ProjectionStrategy 契约的纯函数对象:

import type { ProjectionStrategy, ProjectedMessage, SessionEvent } from 'dsh-memory-projection';

const myStrategy: ProjectionStrategy = {
  name: 'my-strategy',
  project(events: readonly SessionEvent[], options?: Record<string, unknown>): ProjectedMessage[] {
    // 1) 只读 events + options,不读外部状态 / 不读时钟 / 不修改入参
    // 2) 每条产出的消息必须带 sourceSeqs(溯源到日志中的真实事件)
    const out: ProjectedMessage[] = [];
    for (const e of events) {
      if (/* 你关心的条件 */ e.data.role === 'user') {
        out.push({
          role: 'user',
          content: e.data.content ?? '',
          sourceSeqs: [e.seq], // 溯源:必须落在 events 的 seq 集合内
        });
      }
    }
    return out;
  },
};

注册并启用:

const svc = root.memoryProjection;
svc.registerStrategy('my-strategy', myStrategy);
svc.setActiveStrategy('my-strategy', {/* 运行时选项 */});

不变式要求(由 guard 强制)

  1. 可复现性:同一日志跑两次必须 deepEqual 一致。读外部状态 / 随机 / 时钟 → 守卫判定为「非纯函数」并回退。
  2. 日志溯源:每条输出消息的 sourceSeqs 必须是日志中真实存在的 seq。凭空捏造内容 → 守卫回退。

若你想关闭守卫(例如你信任自己的策略且需要跑非确定性逻辑),可:

svc.setGuardEnabled(false);

架构设计

1. 与 DSH 不变式的关系(Model-Visible ⇔ Logged

DSH 的核心不变量是:模型可见的内容,必须能从已落库(logged)的会话日志中重建。本插件把这条不变量变成可机检的工程约束:

  • 日志(SessionEvent[])是唯一的真相源,投影只读它。
  • 每条投影消息携带 sourceSeqs,显式声明「我来自哪几条原始事件」。
  • invariant-guard.ts 在每次投影后做两层校验:
    • 可复现性:纯函数双跑一致。
    • 溯源sourceSeqs ⊆ 日志.seq
  • 任一校验失败 → 回退到 passthrough(默认投影),并告警。Agent 循环永不因投影失败而中断。

这把「不变量」从一句哲学宣言,落地为每次投影都会跑的自动化测试。

2. 可逆副作用原则(零残留热插拔)

插件手写事件总线、不手写服务管理器、不手写 cleanup 函数。所有副作用都委托给 Cordis 原生生命周期:

副作用实现方式卸载时如何回滚
ctx.memoryProjection 服务继承 Service 基类,super(ctx, 'memoryProjection')Cordis 自动从所属 fiber 移除该服务
session/derive-messages 监听ctx.on('session/derive-messages', handler)返回的 fiber 作用域处置器自动注销
第三方策略注册ctx.plugin(...) / ctx.on(...)同样随 fiber 作用域 LIFO 回滚

加载流程(apply(ctx)ctx.plugin(MemoryProjectionService))→ 注册 4 个内置策略 + 1 个 waterfall 监听;卸载(ctx.dispose())→ 服务、监听、第三方注册全部自动撤销,原生推导恢复如初。不留下任何全局状态或孤儿监听。

3. 为什么把 session/derive-messages 建模为 waterfall

DSH 原生的「消息推导」是一个方法(Session.deriveMessages()),并不存在字面意义上的 session/derive-messages 事件。本插件把它建模为 Cordis 的 waterfall 接缝

  • 插件监听在该接缝上,包裹原生 next(即原生推导)。监听存在时,返回策略结果(veto 原生 next)。
  • 监听消失(卸载)时,next() 原样执行 → 默认投影完全恢复。

这是对「官方扩展点」的正确使用方式:既实现了「拦截推导」的诉求,又保证卸载可逆、零残留。

目录结构

dsh-memory-projection/
├── src/
│   ├── index.ts                      # definePlugin 包装 + 公共导出
│   ├── types.ts                      # 类型 + 纯辅助(classifyEvent/isKeyEvent/eventToMessage/deepEqual)+ 模块增强
│   ├── core/
│   │   ├── projection-service.ts     # MemoryProjectionService(ctx.memoryProjection)
│   │   └── invariant-guard.ts       # checkInvariant(可复现 + 溯源)
│   └── strategies/
│       ├── precision-window.ts
│       ├── associative-divergence.ts
│       └── critical-focus.ts
├── tests/                            # Vitest 单测(策略正确性 + 纯函数性 + 生命周期零残留)
├── examples/
│   └── basic-usage.ts                # 可运行最小示例
├── .github/workflows/ci.yml          # 推送自动 类型检查→单测→构建
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── vitest.config.ts
├── .eslintrc.json
├── .prettierrc.json
├── .gitignore
├── README.md
└── LICENSE

验证清单(自测通过项)

本仓库已覆盖以下 7 项自检:

  1. Cordis 原生合规:仅使用 definePlugin / Service / ctx.on / 模块增强,未修改内核。
  2. 不变式守卫checkInvariant 对非确定性 / 无溯源的策略自动回退。
  3. 零残留热插拔load → setActiveStrategy → dispose 后,session/derive-messages 恢复原生推导。
  4. 纯函数性:内置策略满足确定性、不可变性、同源同输出(测试覆盖)。
  5. 策略可扩展registerStrategy 注册自定义策略并即时生效;未知策略名安全忽略。
  6. 工程就绪tsc --noEmit / vitest run / tsup 全绿;ESLint + Prettier 配齐。
  7. 发布就绪files 字段、exports 映射、MIT LICENSE、CI 工作流齐备,npm publish 可直接发。

许可证

本项目基于 MIT 许可证 开源。