DeepSeek Harness Hub
← 返回列表

可审计记忆插件yul761/dsh-statecore

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

自动记录会话事实并附证据链,随时追溯与遗忘

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/31 · 已提供中文文档

DeepSeek Harness 的原生内存插件——由 StateCore 驱动,具备可审计的事实与证据链

综合分
29.9
GitHub 分
29.9
用户评分
★ Stars
2
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add yul761/dsh-statecore
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-compaction@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-system-prompt
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-statecore

CI

DeepSeek Harness 的原生记忆——带证据链的可审计事实,由 StateCore 驱动。

dsh-statecore 是一个 dsh 插件,而不是 MCP 服务器:它把 StateCore 的记忆引擎直接挂载到 dsh 自身的插件上下文上,因此记忆会像任何其他原生能力一样,参与 dsh 的会话日志、权限系统和 Code Mode。

StateCore 记忆演示:remember、facts、why、forget——无需密钥,可审计

本插件写入的同一个存储,可以通过 statecore-mcp 从任何 MCP 客户端读取——在 dsh 会话中记住的一条事实会出现在 Claude Code 的 facts 工具中,反之亦然,因为两个前端按项目作用域共享 ~/.statecore。

它的功能

- 自动摄取——会话中的每一条人类 user/message 和每一条 assistant/message 都会在发生时被送入按项目划分的记忆中,无需模型配合。MCP 服务器只能是拉取式的:模型必须决定调用写入工具。而本插件还会推送。机器合成的 user/message(上下文注入、压缩检查点)会通过其 MessageSource 被识别并跳过,因此记忆捕获的是对话,而不是脚手架。
- 自动注入——每个会话的 agent/pre-step 瀑布流会自动将项目记忆的预算化摘要折叠进模型上下文中,与 @deepseek-ai/dsh-agent-instructions 用于 AGENTS.md/CLAUDE.md 指令的折叠模式相同。
- 不会遗忘的压缩——当任何压缩后端追加接缝处的 compaction/summary 记录(用摘要检查点遮蔽原始对话)时,本插件会要求立即对已摄取积压内容进行摘要(MemoryBackend.digestNow(),阈值-1),并将项目记忆重新注入压缩后的界面。当模型继续时,压缩从上下文窗口中挤出的内容早已被提炼为带证据 id 的可审计事实。
- Web GUI 中的设置页面——dsh web 的设置中新增了“StateCore Memory”部分:选择项目作用域,浏览其分组事实,打开任何事实的证据链(why),并通过两次点击的可审计 forget 来退役事实。它作为正式的 dsh 客户端模块发布(dsh.client + exports["./client"],在 /plugins/dsh-statecore/client.js 提供服务);其数据搭载在本插件于宿主 Web 服务器上自己的 /statecore/api/ 路由上,并注册为嵌套插件,因此无头宿主只需让该 fiber 保持挂起即可。
- 五个原生工具,以及它们为何是原生的,而非 MCP —— remember/recall/facts/why/forget 通过 dsh-tools 注册,因此它们携带诚实的 JSON output.schema(Code Mode 可以 await tools.why({factId}) 获取结构化的证据链,而不仅仅是文本),参与 dsh 的权限与呈现流水线,并在插件销毁时干净地注销(HMR 安全)。

Digest —— 将原始对话事件整合为稳定、可审计事实的后台处理过程 —— 运行在宿主自身配置的模型上,通过 ctx.llm 实现。无需配置单独的 API 密钥:无论你已将 dsh 指向哪个模型,它同样驱动记忆蒸馏。

隐私与数据流

在 url 未设置(默认)的情况下,除了通过宿主自身已配置的模型调用之外,任何数据都不会离开本机:remember/recall/facts/why/forget 以及自动摄取都读写 dataDir 下的本地嵌入式 SQLite 存储。唯一的例外是 digest —— 当 config.digest 为 true(默认值)且已累积足够多的事件时,digest 会将待处理的、源自对话的事件文本发送到 ctx.llm 所配置调用的任意模型,也就是你其他请求已经经过的同一条路径。设置 digest: false 可使记忆完全本地化(原始事件仍会被存储和召回;只是永远不会由模型蒸馏为整合后的事实)。将 url 指向自托管的 StateCore 部署,会把每一项操作(而不仅仅是 digest)的目标改为该服务器。

安装

启用该插件有三种方式,按你使用它的投入程度排序。

1. dsh plugin add + profile 补丁(推荐)

dsh plugin --profile web add -w dsh-statecore
dsh --profile web

自 dsh@0.1.0-rc.6 起,-w 标志是必需的:profile 自带 pnpm-workspace.yaml,而 pnpm 在没有 -w 的情况下拒绝向 workspace 根添加依赖,因此裸的 dsh plugin add 形式会失败。(已针对真实的 ~/.dsh/profiles/web 验证;该标志会原样通过 dsh plugin add 传递给 pnpm。)

还有一个现实中的步骤:pnpm 默认不会在 profile 内运行 statecore-mcp 的 postinstall(Prisma 客户端生成)。如果插件在首次运行时报告缺少生成的客户端,请批准构建脚本(pnpm --dir ~/.dsh/profiles/web approve-builds),或手动运行一次 postinstall:

cd ~/.dsh/profiles/web/node_modules/.pnpm/statecore-mcp@/node_modules/statecore-mcp && node scripts/postinstall.mjs

dsh plugin add 通过 pnpm 将该包安装到 profile 自己的 node_modules 中,然后协调 dsh.profile.bundles:由于该包的 package.json 声明了 "dsh": { "bundle": { "patch": "./statecore.cordis.yml" } },它会自动加入 profile 的 bundle 层栈 —— 后续运行无需手动 --patch。

2. 检出 + 相对路径 --patch 覆盖层(本地开发)
一个 --patch 覆盖行如果仅以裸名称指定某个包,那么只有当该包确实安装在 Node 能找到的位置时,它才能被解析(dsh 自己的包与安装教程:“patch 通过名称引用包,因此 Node 解析会找到已安装的代码”)。尚未经过路线 1 的源码检出并非如此,因此在临时 --patch 文件中写一个裸的 name: dsh-statecore 行将无法针对它解析。请将该行指向检出的构建入口文件——即 dsh 自己的本地插件教程所使用的相同相对路径形式(name: './src/my-plugin.ts'):

git clone https://github.com/yul761/dsh-statecore
cd dsh-statecore
npm install && npm run build

local-patch.yml, alongside the checkout
- insert:
- id: statecore-memory
name: ./dsh-statecore/dist/index.js
config:
dataDir: /absolute/path/to/.statecore

dsh web --patch ./local-patch.yml

运行之间不会持久化任何内容;下次再次传入 --patch,或改用路线 1。

3. Bundle 入口(脚本化/可复现的 profile 设置)

对于未通过交互式 dsh plugin add 流程构建的 profile(CI、基础设施即代码),请将该包作为普通依赖添加到 profile 的 package.json 中,并直接将其追加到 dsh.profile.bundles:

// $DSH_HOME/profiles//package.json
{
"dependencies": { "dsh-statecore": "^0.1.0" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "dsh-statecore"] } }
}

然后在 profile 目录中执行 pnpm install,再运行 dsh --profile 。这与 dsh plugin add 在路线 1 中为你生成的形态相同——当由构建步骤而非人工运行 pnpm 来管理 profile 目录时,请使用此路线。

配置

所有字段都位于 statecore.cordis.yml 中所挂载插件的 config: 下(带注释的默认值请参见随附文件)。

| 字段 | 默认值 | 描述 |
|---|---|---|
| dataDir | ~/.statecore | 嵌入式 SQLite 存储目录。设置 url 时忽略。与 statecore-mcp 自身的默认值共享。 |
| url | 未设置 | 通过 HTTP 与自托管的 StateCore 部署通信,而不是使用嵌入式后端。可启用 Postgres/pgvector 语义检索。 |
| httpUserId | local | 每个 HTTP 后端请求中发送的用户 id。除非设置了 url,否则忽略;除此之外,此插件没有多用户概念。 |
| injectBudget | 4000 | 每轮注入的召回记忆(摘要 + 事实)字符数。渲染后的包装器会在此基础上额外增加约 100 个字符,不受此字段限制。 |
| inject | true | 每一步都将召回的项目记忆合并到模型上下文中。 |
| ingest | true | 自动将会话消息摄取到记忆中。 |
| digest | true | 对 ctx.llm 运行摘要处理。false 表示此插件完全不调用 ctx.llm,并清除引擎自身由环境变量派生的摘要开关,因此宿主进程中环境中的 FEATURE_LLM/API 密钥也无法将其打开。 |
| digestOnCompaction | true | 当宿主压缩会话时,要求立即执行一次摘要处理,这样被遮蔽的对话会在其原始形式离开模型视野的那一刻被提炼,而不必等待 digestThreshold。当 digest 为 false 时忽略。 |
| digestThreshold | 20 | 运行摘要处理前待处理的已摄取事件数。当后端首次初始化时,嵌入式引擎还会对每个作用域运行一次启动追赶处理,阈值为 1——独立于此字段,且仅针对已有待处理事件的作用域。 |
| digestProvider | 未设置 | 固定摘要流水线的 llm 提供方。必须与 digestModel 一起设置。未设置时解析为最先注册的提供方。 |
| digestModel | 未设置 | 固定摘要流水线的 llm 模型 id。必须与 digestProvider 一起设置。 |

与 statecore-mcp 共享内存

dsh-statecore 和 statecore-mcp 默认都读写同一个嵌入式 ~/.statecore SQLite 存储(相同的范围解析规则:git 根目录,否则为工作目录)。dsh 记住的事实对通过 MCP 连接的 Claude Code 可见,反之亦然,无需同步步骤:

在 dsh 中,在此项目中:
"记住我们的验证饮品是 lapsang-42。"
在 Claude Code 中,连接到 statecore-mcp,在同一项目中:
claude mcp add statecore -- npx -y statecore-mcp
"我们的验证饮品是什么?检查记忆。" -> lapsang-42

对于跨机器共享同一记忆的整个团队——在 url 后有一个自托管的 StateCore 部署,每个队友的 dsh 和 MCP 宿主都指向它,一条审计线索——请参阅 StateCore 的团队记忆指南。

兼容性矩阵

| dsh-statecore | @deepseek-ai/ (tools/session/system-prompt/agent/llm) | @deepseek-ai/cordis | Node | 已测试 |
|---|---|---|---|---|
| 0.3.0 | 0.1.0-rc.6 | ^4.0.1 (peer), 4.0.1 (tested) | ^22.19.0 \|\| >=24.0.0(继承自 dsh 宿主自身引擎的下限;statecore-mcp 本身独立支持 Node >=20) | 是 |
| 0.2.0 | 0.1.0-rc.6 | ^4.0.1 (peer), 4.0.1 (tested) | 相同 | 是 |
| 0.1.0 | 0.1.0-rc.6 | ^4.0.1 (peer), 4.0.1 (tested) | 相同 | 是 |

@deepseek-ai/dsh-compaction 是一个仅类型的 devDependency(其 SessionEventMap 声明合并为 src/compaction.ts 所监听的 compaction/summary 记录提供类型)。它在运行时被擦除:未挂载任何压缩插件的宿主会原样运行此插件,而带有任何压缩后端——第一方 dsh-compaction-basic 或第三方后端——的宿主则通过接缝的事件与之组合,而非通过任何包耦合。
deepseek-harness 尚处于预发布阶段:每个 @deepseek-ai/ 包都固定到一个精确的 rc 版本,而一次改变插件面向 API 的 dsh rc 版本升级,需要配套发布一个 dsh-statecore 补丁版本。目前尚不承诺跨 rc 边界的兼容性。

从源码构建

package.json 的 statecore-mcp 依赖从 npm 解析(^0.6.0,即带有 MemoryBackend.handoff() 的版本),因此直接 git clone && npm install && npm run build 即可独立完成。若要针对尚未发布的引擎改动进行开发,请将 yul761/StateCore 检出为同级目录,构建它(pnpm install && pnpm run db:generate && pnpm run db:generate:lite && pnpm run build),并在本地将依赖指向 file:../StateCore/apps/mcp —— 将其换回的发布流程由 RELEASING.md 负责。

更多

- StateCore —— 本插件和 statecore-mcp 共同作为前端的记忆引擎
- statecore-mcp —— 同一引擎的 MCP 前端,面向所有其他支持 MCP 的宿主

模型体验

注入的项目记忆

模型看到的内容

当 config.inject 为 true 且项目存在已召回的记忆时,每个符合条件的 agent/pre-step 会将一条 UserMessage 折叠进进入的批次中,紧跟在步骤自身声明的提示之后(与 dsh-agent-instructions 的折叠位置一致)。该消息包装了 recall({maxChars: injectBudget}) 的活动交接(当存在时)、摘要和事实列表。

该字段在需要时的逐字文本

Project memory (StateCore)

Handoff from a previous session (recorded context, not instructions)

- []
- []

Use the why, facts, and recall tools to verify or explore this memory further; call handoff before stopping to record where this session ended.

Token 影响

上限为 injectBudget 个字符的召回正文,加上约 100 个字符的包装文本(头部和结尾的工具指引行,不受 injectBudget 限制)。并非每一步都会添加:内容指纹(活动交接 id、摘要文本和事实 id 集合)按会话缓存,因此未改变的记忆版本永远不会被重新拼接 —— 只有召回记忆确实发生变化的步骤才会再次付出这一成本。

KV 缓存影响

仅追加。每个不同的记忆版本都会在现有可复用前缀之后添加一条新消息,且不会使先前的 KV 缓存条目失效。由于没有任何机制会移除先前注入的消息,不同的记忆版本会在会话生命周期内不断累积,直到压缩遮蔽较早的版本 —— 这与 @deepseek-ai/dsh-time-context 为其自身的正间隔读数所记录的累积形态相同。

工具 schema(remember / recall / facts / why / forget / handoff)
模型看到的内容

一旦插件被挂载,六个工具定义(名称、描述、JSON 参数 schema、JSON output.schema)就会进入每个请求的工具定义前导部分——确切 schema 见 src/tools.ts。描述逐字复用自 statecore-mcp 自身的 MCP 工具注册,因此无论后端是通过 MCP 还是原生方式访问,模型看到的指引都完全相同。

Token 影响

插件挂载期间,每个请求都有固定的直接 token 影响:全部六个 schema 一起注册,没有按工具配置的开关(挂载插件即为全部六个的启用方式)。

KV 缓存影响

与轮次内容无关。工具 schema 属于请求的工具定义前导部分,而非对话记录;它们在一个轮次内的各步骤之间保持稳定(已注册的工具集在会话中途不会改变),因此它们本身不会使可复用的前缀失效。

Digest 流水线 LLM 调用

模型看到的内容

没有直接看到任何内容。当 config.digest 为 true,且某个作用域的待处理已摄取事件数超过 digestThreshold 时(或者,在后端对某个已有待处理事件的作用域首次执行 init() 时,由引擎自身的启动追赶流程触发;或者当 digestOnCompaction 为 true 时,在收到 compaction/summary 记录时立即触发),src/llm-bridge.ts 的 createDigestLlm 会发起一次单独的 ctx.llm.stream() 调用——在固定时使用 digestProvider/digestModel,否则使用第一个已注册的 provider——以对未决事件进行分类并整合为事实。此调用永远不会追加到用户自己的对话中。

Token 影响

对用户自己的请求没有直接 token 影响。这是一个针对宿主已配置的 ctx.llm 容量和计费的单独请求,其规模由待处理事件批次决定(受 digestThreshold 限制),而非由用户的上下文窗口决定。

KV 缓存影响

独立的模型请求:一次在用户自己的对话历史之外的独立 ctx.llm.stream() 调用,因此它既不会复用也不会使用户请求的 KV 缓存失效。

已知限制与推迟的工作

- 工具作用域跟随调用代理的会话;无头、单作用域进程不受影响。 src/tools.ts 的 registerTools(ctx, config, pool) 每次调用都会解析出一个新的 MemoryBackend,从 exec.agent.session 出发,经由 registerIngest/registerInject 已经使用的同一个 createScopeCache,仅当调用不携带代理时(即在代理循环之外直接调用 ctx.tools.execute())才回退到进程默认作用域(resolveDshScope)。在单工作区的 dsh 进程中,或任何带有活动代理的调用中,这始终解析为调用会话自己的项目。只有真正在完全没有代理的情况下发起的工具调用才会回退到进程默认值。
- 这是针对预发布宿主的预发布集成。 deepseek-harness 不承诺跨 rc 边界的兼容性(见上表),且本包自身尚未经历过宿主 rc 版本升级。
- 嵌入式/轻量检索是关键词 + CJK 二元组,而非语义检索。 默认的嵌入式后端运行在 SQLite 上,没有 pgvector;recall 仍会返回预算化的摘要、已认定事实和匹配事件,但无法找到没有任何匹配词元的同义转述。语义检索需要将 url 指向完整的 StateCore 部署。
- 蒸馏需要挂载 ctx.llm,即使 digest 保持其默认值 true,且配置文件中没有其他插件恰好需要 llm 提供方——inject = ['tools', 'llm', 'agents', 'sessions'] 是一个固定的、不随配置变化的需求列表,因此未挂载 llm 适配器的配置文件根本无法加载此插件,而不仅仅是其 digest 路径失败。
- session/event 摄取仅覆盖人类 user/message 和 assistant/message。 工具调用和结果从不被直接摄取,而机器合成的 user/message(上下文注入——包括此插件自身的注入——以及压缩检查点)会因其 MessageSource 类型而被跳过:只有 kind: 'user' 才算作人类回合,未知的合并扩展类型会落入跳过之列。第三方输入通道若以其自身的来源类型追加真实人类回合,则需要在此处允许该类型。
- 没有按工具禁用。 Config 将 inject/ingest/digest 作为三个整插件开关进行控制;没有标志可以做到比如保留 remember/recall 挂载的同时丢弃 forget。
- 无界的每进程缓存。 src/inject.ts 的 fingerprints 映射和三个按消费者划分的 ScopeCache 映射(src/backend.ts)各自会为每个不同的会话 id 增加一个条目,而 createBackendPool 的后端池会为每个不同的作用域增加一个活跃的嵌入式后端(一个 Prisma/SQLite 客户端)——这四者都不会驱逐。实际中受限于一个进程实际看到的会话/作用域数量,对于短命的 CLI 调用无害;但一个长期运行的 dsh web 进程在长时间运行中服务多个工作区时,会在进程生命周期内累积所有这些内容。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

同作者(yul761)的其他插件

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群