基于 DSH 无损会话日志的引用式记忆:蒸馏出的事实带 `(sessionId, eventRange)` 引用,可随时展开回原始日志片段。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Jesse-njx/dsh-memory
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
该插件的 README 只有英文版本。
Cited memory over DSH's lossless session log. Distilled facts that can always escalate back to the exact original context.
dsh-memory is a DeepSeek Harness bundle. When a session ends, a background distillation pass extracts durable facts — user preferences, project decisions, environment quirks, corrections — into small markdown files under ~/.dsh/memory/. Every memory carries a citation (sessionId, [start..end]) pointing at the exact log events it came from. The next session gets a compact index of those memories, plus two tools: memory_read (the full memory) and memory_expand (the cited original log excerpt).
The key idea: summaries are an index into ground truth, never the truth. Retrieval surfaces the one-line distilled fact (cheap); when the agent needs more, memory_expand returns the exact original log events (exact, not reconstructed). DSH can do this cheaply because it already sits on a complete, append-only transcript store — no memory store is built, only a memory index.
Why this shape
Mainstream memory systems (Mem0, Letta/MemGPT, Zep) share one weakness: extraction is lossy and unaccountable. Once a summarizer mangles a fact, the original is gone or unfindable, and the agent confidently recalls the mangled version. DSH's differentiator is the append-only session log: everything the model ever saw is already durably stored. So dsh-memory distills into files (human-auditable, git-diffable, deletable with rm) and keeps a citation back to the log on every fact.
How it works
- Distill (post-session, async via
ctx.jobs) — when a session leaves the store, a background job feeds the session's live events (bounded transcript, token-capped) to one cheap-model pass and asks for durable facts as JSON. Facts become memory files; existing memories are updated in place (citation appended,revbumped) or contradicted (the named memory is rewritten, keeping its name). Every pass is recorded in<project>/_distill.log(JSONL). - Recall (every prompt assembly) — a system-prompt section renders a compact, token-capped index of
name — descriptionlines for the current project (plus shared user memories). Bodies stay onememory_readcall away; the cited source onememory_expandcall away. - Maintain — the distill pass updates and contradicts existing memories; the
dsh-memoryCLI lists, shows, edits (in$EDITOR), and deletes; the/memoryslash command lists them inside a session.
No vector database, no knowledge graph, no auto-injection of full memory bodies in v0.1.
Install
dsh plugin --profile web add @dsh-memory/bundle
The distillation pass routes through ctx.llm — it reuses the session's own provider/model by default, so a polyglot-style provider chain or your normal model serves it too. Override with distill.provider / distill.model.
Config
All fields optional (profile patch or cordis.patch.yml):
plugins:
dsh-memory:
enabled: true
home: ~/.dsh/memory # memory root override (default: $DSH_HOME/memory or ~/.dsh/memory)
maxIndexTokens: 800 # hard token cap for the injected recall index
maxExpandBytes: 8192 # output byte cap for one memory_expand excerpt
recall:
enabled: true
cacheMs: 5000 # index cache TTL
distill:
enabled: true
provider: deepseek-official # default: the session's own route
model: deepseek-v4-flash
maxTokens: 2048
temperature: 0.1
maxTranscriptTokens: 16000 # transcript cap; oldest events are dropped under it
Memory files
One small markdown file per memory, valid markdown with a JSON header comment:
<!-- dsh-memory: {"name":"prefers-ts","description":"Prefers TypeScript over JS","type":"user","citations":[{"sessionId":"session-12","start":4,"end":18}],"createdAt":1700000000000,"updatedAt":1700000000000,"rev":1} -->
The user prefers TypeScript for new projects and tests.
~/.dsh/memory/<project>/*.md— project + feedback memories, keyed by the session cwd's basename.~/.dsh/memory/_user/*.md—user-type (cross-project) memories.type:user(cross-project preference),project(facts about this project),feedback(corrections the user made).
A project memory with the same name shadows a user memory.
Tools
memory_read(name)— the full memory file: name, type, description, body, citations.memory_expand(name, [citation_index])— the exact original session-log excerpt the memory was distilled from (lossless escalation). Usesctx.sessionPersistence; the citation range is exact.
CLI
Standalone dsh-memory binary, pure Node (no harness packages):
dsh-memory list [--project P] [--json] # list memories (user + project)
dsh-memory show <name> [--project P] # show one memory with citations
dsh-memory edit <name> [--project P] # open the memory file in $EDITOR
dsh-memory delete <name> [--project P] # delete one memory file
dsh-memory distill-log [--project P] # recent distill audit entries
--home overrides the memory root. Inside a session, /memory (or /memory <name>) does the same.
Explicit non-goals (v0.1)
Vector databases, knowledge graphs, cross-project global memory beyond the user type, memory sharing/sync, auto-injection of full memory bodies. Each one multiplies the failure surface of the exact thing this plugin is skeptical about. If the index outgrows what a model can scan, then consider embedding search (v0.3, only with evidence).
Honest experiment framing
This is an experiment with a defined kill criterion, not a committed product. After the plugin is dogfooded on plugin-development sessions for two weeks: success = concrete instances where a recalled memory saved a re-explanation or prevented a repeated mistake, and zero instances of a stale memory misleading a session that wasn't caught via citation. If it fails that bar, the repo gets archived with a postmortem README — a documented negative result about agent memory is respectable open-source output; a zombie memory plugin is not.
Development
pnpm install
pnpm typecheck # tsc --noEmit
pnpm test # node --test (54 tests: store round-trips, index caps,
# transcript bounds, distill parsing/application, CLI)
pnpm build # tsc → lib/
pnpm pack # publishable tarball
The test suite covers the spec's testing goals: golden distillation fixtures (recorded session logs → expected memory files, via parseDistillOutput + applyFacts), a citation round-trip (distill consumes a session, memory_expand returns exactly those events), and index-cap truncation behavior.
License
MIT
链接
同类插件
volcengine/OpenViking#examples/dsh-memory-plugin★ 38815
面向 DeepSeek Harness 的 OpenViking 记忆与上下文插件:pre-step 自动召回与画像注入、会话捕获、`viking://` URI 防护,以及对接 OpenViking 服务端的 recall/write 记忆工具。
vectorize-io/hindsight#coding-agents★ 37670
Hindsight:会学习的 Agent 长期记忆系统,自动召回/保存、知识页、深度反思与按仓库隔离的记忆银行。
agentscope-ai/ReMe#dsh★ 3526
将 DeepSeek Harness 接入 ReMe 本地优先、自进化的个人知识库:自动把已完成的主 Agent 对话沉淀为用户掌控的 Markdown 记忆,通过 reme_search 结合 BM25、可选向量检索和 wikilink 展开搜索对话与资料,并按日整理长期记忆。
zilliztech/memsearch#MemSearch★ 2670
供 DSH 与其他编程 Agent 共享的 Markdown 记忆,支持自动捕获、步骤前上下文注入、搜索召回,以及通过审阅面板实现 memory-to-skill 自进化。
vshulcz/deja-vu#extensions/dsh★ 1074
读取本机上其他三十三个编程智能体已经写下的会话文件——Claude Code、Codex、Cursor、VS Code Copilot Chat、opencode、OpenClaw、Hermes、Kimi、Cline、Zed 等,包括安装之前的历史:提供 deja_recall、deja_session、deja_blame、deja_fix、deja_how、deja_remember 六个工具与 /deja 命令,并可选地把召回结果加入运行时上下文。本地 BM25 索引,不用大模型,不用向量嵌入,不联网(dsh plugin --profile web add dsh-deja)。
adoresever/graph-memory★ 630
DeepSeek Harness 的可追溯、可检索跨会话记忆:把对话知识沉淀为带类型的图节点(任务/技能/事件)与关系边。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。