DeepSeek Harness 的跨会话长期记忆插件
36/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add DDDFXYqiming/dsh-layered-memory该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意未发布到 npm registry,仅可从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包@dsh-external/dsh-layered-memory(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.19 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 10:22:31
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 78 处,展示前 66 条)
- 读取本地文件src/apply.js:78
const version = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version; - 发起网络请求src/apply.js:181
requestMaintenance: (namespace, exec, report) => maintenance.request(nsRoot(cfg.memoryDir, namespace), namespace, exec.agent, { - 发起网络请求src/apply.js:213
review: (agent, activity) => maintenance.request(resolveRoot(agent.session.header.cwd), resolveNamespace(cfg, undefined, agent.session.header.cwd), ag - 读取本地文件src/store.js:56
try { return readFileSync(path, "utf8"); } - 读取本地文件src/store.js:66
try { return readdirSync(dir).filter(name => name.endsWith(".md")).sort(); } - 写入本地文件src/store.js:71
mkdirSync(root, { recursive: true }); - 写入本地文件src/store.js:73
for (const dir of ["sops", PENDING_DIR, ARCHIVE_DIR, HISTORY_DIR]) mkdirSync(join(root, dir), { recursive: true }); - 读取本地文件src/store.js:75
if (!existsSync(join(root, name))) atomicWriteFileSync(join(root, name), content); - 读取本地文件src/store.js:78
if (identity && !existsSync(join(root, ".namespace.json"))) atomicWriteFileSync(join(root, ".namespace.json"), JSON.stringify(identity, null, 2)); - 写入本地文件src/store.js:84
mkdirSync(root, { recursive: true }); - 写入本地文件src/store.js:98
for (const root of roots) mkdirSync(root, { recursive: true }); - 删除本地文件src/store.js:122
if (item.previous === null) rmSync(item.path, { force: true }); - 删除本地文件src/store.js:126
} finally { for (const item of staged) rmSync(item.tmp, { force: true }); } - 读取本地文件src/store.js:168
if (existsSync(path)) return null; - 读取本地文件src/store.js:369
try { files = readdirSync(join(root, HISTORY_DIR)); } - 写入本地文件src/store.js:551
mkdirSync(target, { recursive: true }); - 读取本地文件src/maintain.js:111
if (includeArchived && existsSync(archive)) { - 读取本地文件src/maintain.js:112
for (const file of readdirSync(archive).filter(file => file.endsWith(".md"))) { - 读取本地文件src/maintain.js:113
docs.push({ kind: "archive", name: file, title: file, archived: true, text: readFileSync(join(archive, file), "utf8") }); - 读取本地文件src/l1index.js:13
return existsSync(path) ? migrateIndexPolicy(readFileSync(path, "utf8")) : ""; - 读取本地文件src/l1index.js:13
return existsSync(path) ? migrateIndexPolicy(readFileSync(path, "utf8")) : ""; - 读取本地文件src/l1index.js:22
if (!existsSync(join(root, "rules.md"))) return sections(readIndex(root)).rules; - 读取本地文件src/tools.js:117
if (existsSync(path)) { - 读取本地文件src/tools.js:118
const content = readFileSync(path, "utf8"); - 读取本地文件src/tools.js:251
const readState = name => existsSync(join(root, name)) ? JSON.parse(readFileSync(join(root, name), "utf8")) : null; - 读取本地文件src/tools.js:251
const readState = name => existsSync(join(root, name)) ? JSON.parse(readFileSync(join(root, name), "utf8")) : null; - 读取本地文件src/tools.js:254
history_files: existsSync(history) ? readdirSync(history).filter(name => name.endsWith(".md") || name.endsWith(".json") && !name.endsWith(".meta.json" - 读取本地文件src/tools.js:254
history_files: existsSync(history) ? readdirSync(history).filter(name => name.endsWith(".md") || name.endsWith(".json") && !name.endsWith(".meta.json" - 写入本地文件src/tools.js:268
mkdirSync(join(root, ARCHIVE_DIR), { recursive: true }); - 写入本地文件src/tools.js:269
copyFileSync(join(root, PENDING_DIR, name), join(root, ARCHIVE_DIR, key)); - 删除本地文件src/tools.js:271
rmSync(join(root, PENDING_DIR, name)); - 发起网络请求src/events.js:83
return maintenance.request(root, namespace, agent, { purpose: "batch", trigger: { kind: "automatic", turn, endSeq }, report }); - 读取本地文件src/activity.js:104
try { runs = JSON.parse(readFileSync(join(nsRoot(cfg.memoryDir, current), "maintenance-runs.json"), "utf8")).runs; } - 读取本地文件src/store-service.js:35
const snapshot = JSON.parse(readFileSync(path, "utf8")); - 读取本地文件src/store-service.js:44
const file = readFileSync(path, "utf8"); - 读取本地文件src/store-service.js:50
const sidecar = JSON.parse(readFileSync(path.replace(/ md$/, ".meta.json"), "utf8")); - 写入本地文件src/atomic-write.js:8
writeFileSync(tmp, content, { encoding, flag: "wx" }); - 删除本地文件src/atomic-write.js:11
rmSync(tmp, { force: true }); - 写入本地文件src/atomic-write.js:17
try { renameSync(tmp, filePath); } - 删除本地文件src/atomic-write.js:18
finally { rmSync(tmp, { force: true }); } - 删除本地文件src/process-lock.js:19
try { rmdirSync(path); } - 读取本地文件src/process-lock.js:27
try { info = lstatSync(path); } - 读取本地文件src/process-lock.js:33
const [name] = readdirSync(path); - 读取本地文件src/process-lock.js:37
return { directory, ownerPath, owner: JSON.parse(readFileSync(ownerPath, "utf8")) }; - 删除本地文件src/process-lock.js:49
try { unlinkSync(lock.ownerPath); } - 读取本地文件src/process-lock.js:52
if (!lock.directory && error.code === "EPERM" && lstatSync(path).isDirectory()) return true; - 写入本地文件src/process-lock.js:62
mkdirSync(candidate); - 写入本地文件src/process-lock.js:63
writeFileSync(join(candidate, ownerFile), JSON.stringify({ id, pid: process.pid, host: hostname(), startedAt: new Date().toISOString() })); - 写入本地文件src/process-lock.js:73
try { renameSync(candidate, path); acquired = true; break; } - 读取本地文件src/process-lock.js:77
try { lstatSync(path); } - 删除本地文件src/process-lock.js:86
if (!acquired) { unlinkSync(join(candidate, ownerFile)); rmdirSync(candidate); } - 删除本地文件src/process-lock.js:86
if (!acquired) { unlinkSync(join(candidate, ownerFile)); rmdirSync(candidate); } - 删除本地文件src/process-lock.js:88
return () => { unlinkSync(join(path, ownerFile)); removeEmpty(path); }; - 读取本地文件src/reflection.js:10
try { return readFileSync(path, "utf8"); } - 读取本地文件src/reflection.js:14
try { return readdirSync(path).filter(name => name.endsWith(".md")).sort(); } - 读取本地文件src/review.js:24
try { return JSON.parse(readFileSync(join(root, REVIEW_STATE_FILE), "utf8")); } - 读取本地文件src/memory-ops.js:209
if (!existsSync(p)) return null; - 读取本地文件src/memory-ops.js:210
const text = readFileSync(p, "utf8"); - 读取本地文件src/search.js:18
if (!existsSync(memoryDir)) return []; - 读取本地文件src/search.js:19
const names = existsSync(join(memoryDir, "rules.md")) || existsSync(join(memoryDir, "facts.md")) || existsSync(join(memoryDir, "index.txt")) ? ["defau - 读取本地文件src/search.js:20
for (const dir of readdirSync(memoryDir, { withFileTypes: true })) { - 读取本地文件src/search.js:23
if (existsSync(join(root, "rules.md")) || existsSync(join(root, "facts.md")) || existsSync(join(root, "index.txt"))) names.push(dir.name); - 读取本地文件src/search.js:32
if (!existsSync(root)) continue; - 读取本地文件src/maintenance-agent.js:34
try { return JSON.parse(readFileSync(join(root, MAINTENANCE_HISTORY_FILE), "utf8")).runs; } - 读取本地文件src/maintenance-agent.js:56
try { return readFileSync(join(root, "index.txt"), "utf8").trimEnd().length; } - 读取本地文件src/maintenance-retry.js:13
try { state = JSON.parse(readFileSync(join(root, MAINTENANCE_RETRY_FILE), "utf8")); }
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-llm@deepseek-ai/dsh-sandbox@deepseek-ai/dsh-scope@deepseek-ai/dsh-session@deepseek-ai/dsh-session-query@deepseek-ai/dsh-storage-domain@deepseek-ai/dsh-subagent@deepseek-ai/dsh-tools@deepseek-ai/dsh-typert-protocol@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 跨会话长期记忆
README
由 DeepSeek 最新模型翻译生成description: "DeepSeek Harness 的跨会话记忆。项目与全局索引常驻上下文,条目带结构标识与证据,旧版本可以恢复。"
kind: "package-bundle"
@dsh-external/dsh-layered-memory
概述
分层记忆把规则、事实和操作经验从一次会话带到下一次。规则保存在 rules.md,事实放在 facts.md 的二级标题下,操作流程放在 sops/*.md;三类条目共用 {namespace, kind, key} 和现有记忆工具,来源与历史版本随条目保存。
目录
- 安装
- 使用
- 记忆管理页
- 配置
- 进一步探索
- 已知限制与暂缓工作
安装
dsh plugin --profile web add github:DDDFXYqiming/dsh-layered-memory "github:DDDFXYqiming/dsh-layered-memory#path:/lib/status"
两条 spec 都要装,因为 bundle 贡献两个组件(记忆插件本体与输入区的状态服务)。pnpm 默认阻止传递依赖里的 git 子包(blockExoticSubdeps),状态包必须作为直接依赖声明,否则新装只会有第一个组件。
桌面端用它随附的 dsh 命令,把 profile 换成 desktop。
展开完整文档(README 剩余 1 节)
description: "DeepSeek Harness 的跨会话记忆。项目与全局索引常驻上下文,条目带结构标识与证据,旧版本可以恢复。"
kind: "package-bundle"
@dsh-external/dsh-layered-memory
概述
分层记忆把规则、事实和操作经验从一次会话带到下一次。规则保存在 rules.md,事实放在 facts.md 的二级标题下,操作流程放在 sops/*.md;三类条目共用 {namespace, kind, key} 和现有记忆工具,来源与历史版本随条目保存。
目录
- 安装
- 使用
- 记忆管理页
- 配置
- 进一步探索
- 已知限制与暂缓工作
安装
dsh plugin --profile web add github:DDDFXYqiming/dsh-layered-memory "github:DDDFXYqiming/dsh-layered-memory#path:/lib/status"
两条 spec 都要装,因为 bundle 贡献两个组件(记忆插件本体与输入区的状态服务)。pnpm 默认阻止传递依赖里的 git 子包(blockExoticSubdeps),状态包必须作为直接依赖声明,否则新装只会有第一个组件。
桌面端用它随附的 dsh 命令,把 profile 换成 desktop。本地开发先执行 npm run build,再直接链接这个仓库与 lib/status,并让 profile 指向它们。
使用
基础工具 memory_search/list/read/write/update 随会话提供。加载 memory skill 或调用 memory_activate({mode:"common"}) 补充状态与冲突登记工具,管理操作用 mode:"manage"。读写权限由用户配置 memoryAccess 和 subagentMemoryAccess 决定,子 agent 默认只读。
条目用 search、list 或 create 返回的 entry 对象定位,不要拿标题重新拼一个身份出来。kind 可选 rule、fact、sop,分别记录后续要求、已知情况与可复用做法;规则依据可引用用户原始要求。已有条目通过 memory_update 修改。
memory_write({
namespace: "my-project",
kind: "fact",
topic: "预览命令", content: "跑 pnpm dev 就能起预览。", evidence: "命令正常启动,页面加载成功。"
})
// 后续调用复用返回的 entry。
memory_read({entry, full: true})
memory_update({entry, content: "修正后的事实", evidence: "新的验证过程"})
memory_activate({mode: "manage"})
memory_history({entry})
memory_rollback({entry, snapshot_id: "填一个返回的快照 id"})
| 要做的事 | 工具 |
| 查找与阅读 | memory_search、memory_list、memory_read |
| 新建与更新 | memory_write、memory_update |
| 查看证据 | memory_expand |
| 恢复历史 | memory_history、memory_rollback |
| 归档与恢复可见性 | memory_archive |
| 共享与迁移 | memory_promote、memory_namespace |
| 处理候选 | memory_pending、memory_accept、memory_discard |
| 状态与维护 | memory_stats、memory_index、memory_maintain、memory_review |
搜索默认只看当前空间和全局空间的活跃条目。要翻归档内容就传 include_archived:true,再用返回的 entry 去读。读取结果会给出行范围、总行数、revision、是否完整以及下一行位置。单条规则使用 kind:"rule";整段规则、完整索引与管理说明分别通过 rules、index、policy 三种只读视图读取。旧索引的规则会在空间首次初始化时逐条迁移,之后索引规则段从活跃规则生成。
记忆管理页
Web 界面左侧栏有一个“记忆”入口,点进去是独立页面:左边是条目列表,右边是详情。可以搜索、按类型过滤、查看已归档条目,也能直接改正文与证据、归档与恢复、看历史快照并回滚。界面文案跟随宿主语言设置,条目类型按语言显示为“规则/事实/经验”或 Rule/Fact/Skill。数据通道与页面规则见记忆管理页接口契约。
记忆管理页
工具行下面那行“索引占用”给出 L1 索引的已用比例和已用/预算字符数,展开后是说明、规则、事实目录、经验目录四段,悬停某一段会说明它的含义与占比。
索引占用的四段构成
主包另有一个可独立启停的“记忆状态”组件,Web 输入区底部那行显示当前会话的核对进度、真实变更条数或上次未完成的原因,点开可以看运行记录与只读历史。
记忆状态
配置
- id: dsh-layered-memory
config:
defaultNamespace: ''
autoNamespace: true
progressive: true
l1MaxChars: 12288
globalL1MaxChars: 2048
indexTargetRatio: 0.9
memoryAccess: write
subagentMemoryAccess: read
autoPending: false
turnReviewEnabled: true
turnReviewMinEvidence: 6
turnReviewReasoningEffort: ''
maintenanceMaxTokens: 16384
maintenanceMaxCalls: 64
maintenanceMaxWrites: 6
maintenanceTimeoutSeconds: 300
maintenanceCooldownMinutes: 30
reflectionMode: notify
自动命名空间来自工作区身份或规范化后的根路径,同一仓库的不同分支共用项目记忆,已有的命名空间要显式迁移。default 是全局空间,项目索引和默认搜索都把它算进来。字符预算同时管索引条目和手写规则,完整文件仍然可以通过工具读到。
主模型在任务中照常查阅和更新笔记,后台照看本轮相关笔记的遗漏、矛盾和重复。收尾核对默认开启,存量整理由 reflectionMode: auto 启用,索引压力作业以水位线为目标(目标字符 = l1MaxChars × indexTargetRatio)。调度、额度与检查点的细节见自动维护。
进一步探索
- 设计说明 讲存储、身份、上下文组装和索引占用的口径。
- 开发与端到端验收 讲怎么构建、载入真实宿主并验收改动。
- 自动维护 讲收尾核对、存量整理和索引压力作业的调度细节。
- 记忆管理页接口契约 讲记忆页与状态服务之间的数据通道、索引占用组件和页面要求。
- 热度排序契约 讲热度计分、排序快照与探索位的硬约束。
- 更新日志 记录已经发布的行为变化。
已知限制与暂缓工作
- 折叠会藏起细节,索引超出字符预算时条目被折叠、描述被截短。完整正文还能通过 memory_read 拿到。
- 索引是会话内的固定开销,项目索引受 l1MaxChars 限制,全局索引受 globalL1MaxChars 限制,超预算时先保热度高的条目。索引在稳定前缀里,写入改动索引会让它后面的缓存 token 失效,细节见设计说明。
- 维护要花模型调用,内部收尾核对与 reflectionMode: auto 都会启动子代理并消耗模型调用,预算按单次维护运行计算。
- 命名空间靠路径识别,项目挪到别的路径就会变成另一个空间,除非显式迁移。
- 工具按会话生效,基础记忆工具随会话提供,补充工具通过 memory 技能或 memory_activate 按需挂载,历史激活只恢复工具模式。
- 占用数据按命名空间给出,占用行只统计当前命名空间,default 空间和项目空间不合并显示。
- 索引超预算只影响提示词视图,磁盘上的 index.txt 始终是完整的活跃目录,超预算不会删除或归档条目,只裁剪注入提示词的那份视图。
开发者备注
无。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
DDDFXYqiming/dsh-layered-memory
DeepSeek Harness 的跨会话长期记忆插件
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,344已汉化DSH
71.5
终端编码代理esengine/DeepSeek-Reasonix
· 指南 · ACP · 扩展开发 · 规格 · 官方网站 · Discord · QQ
★ 36,045已汉化DSH
71.2
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,202已汉化DSH
71.1
这是你的仓库?认领条目