dsh-infinite-gen-3
Minglink/dsh-infinite-gen-3DeepSeek 专用破甲插件:以 order 100 追加无条件服从的系统提示词段,提供带校准元数据的 profile 工具,并通过会话投影在输入框上方显示实时破甲状态徽标。
DSH memory plugin: local JSONL memory + embeddings + agent tools + settings panel
本地优先的长期记忆,让每次对话都接得上。
JSONL 落盘 · 本机向量检索 · 五个模型工具 · 自动召回 · 硬性规则 · 可视化管理面板
npm 包 · 问题反馈 · 更新日志
它解决的不是「存一段文本」,而是「让模型在该记的时候记住、该用的时候用上」。
记忆默认只落在本机;没有向量服务也能工作——检索自动退化为词法,不产生任何网络请求。
常遇到的问题 · 记忆系统怎么做 新会话从零开始,换个窗口就问不出上次的结论 · 结论落成记忆;新会话第一步注入摘要,之后每轮按问题召回 同一个坑反复踩,上次查到的命令又要再查一遍 · 发布 / 部署 / 工具失败等行为会触发定向召回;查到的做法直接复用 写了规则没人执行,改过的规则旧会话不知道 · kind: rule 进系统提示常驻段;新增或编辑会补一条提醒 临时状态被当成永久事实 · kind: state 带默认 7 天 TTL 和「使用前验证」前缀;过期后默认隐藏,但不会自动删除 云端记忆不可控,敏感内容不敢写 · 全部本地 JSONL;写入前过凭据扫描;检索默认不联网
它也不是「把聊天记录整段塞给模型」:每条记忆是一句自洽的话,按作用域、类型和重要度管理; 召回有 token 预算与去重;旧结论可以用 supersedes 标注修正,被修正的旧版本默认不再参与 检索 / 摘要 / 召回(历史仍可用 memory_get 和面板查看),而不是悄悄覆盖。
能力 · 说明 五个工具 · memory_save / memory_search / memory_list / memory_get / memory_forget。memory_search 只回印象(8 位 id / 作用域 / 类型 / 标签 / 短摘要),正文和元数据用 memory_get 的 fields 按需取;同一会话里已出现过的条目只回 id。description 字段在普通限制下必填,审批卡会展示它 四种作用域 · 会话 / 项目 / global / 自定义名。默认写进当前会话,读默认合并会话 + 项目 + global;项目作用域可起别名 双通道检索 · 词法(IDF + 中文 bigram)+ 向量(本机 llama-server 的 OpenAI 兼容 /v1/embeddings)。向量缺席自动降级,不报错、不阻塞 自动召回 · 每轮按用户问题召回;新会话第一步注入项目 / global 摘要;发布、部署、工具失败等行为按标签触发定向召回 印象形态 · 每轮只给每条记忆的短摘要;模型判断相关但需要细节时再 memory_get 取全文,省 token 也不丢信息 硬性规则 · kind: rule 进系统提示常驻段;行首带 8 位 id,注入的是摘要,需要全文时用 memory_get;旧会话会收到新增 / 编辑提醒;超预算有明确警告,不静默丢弃 会话可见域 · 输入框旁的「记忆范围」按钮设置本会话可读的作用域 + 限制等级(绝对 / 普通 / 无限制);每个作用域还有绑定 / 可读 / 可写状态按钮——绑定到当前工作区后新会话默认可见,可读 / 可写独立影响工具读写;Agent 及其子 Agent 都按它检索、注入与 memory_get 修正版编辑 · 面板里编辑一条记忆 = 新建一条修正版并通过 supersedes 指向旧记录,旧记录不原地修改;记录页「是否被修正」筛选默认隐藏旧版本,可切到全部 / 只看已修正 范围外审批 · 普通限制下,工具命中可见域外的记忆时会在对应会话的输入框上方出现审批卡(样式与系统权限审批一致):展示工具、Agent 说明、查询关键词与范围外记忆摘要,支持逐条勾选 / 全选 / 取消全选(「允许选中的 N 条」或整单「允许一次」)或「拒绝」;点记忆 ID 直接跳到面板「记录」页并展开该条 上下文去重 · memory_search / memory_list 返回过的条目记进会话上下文状态;同一版本再次命中只回记忆 ID(memory_search 的裸 ID 与带摘要条目之间空一行),并提示用 memory_get 取全文(内容更新后重新给摘要) 状态记忆 · kind: state 默认 7 天 TTL;注入带「状态,使用前验证」;过期后默认不进检索 / 摘要 / 召回,但 memory_get 与面板仍可取 流程索引 · kind: procedure 的目录进系统提示:按当前工作区 + 触发词(工具名 / 关键词)列 id · 触发词 → 标题,需要时再用 memory_get 取全文 可视化管理 · 记录浏览 / 搜索 / 新建 / 编辑 / 删除(编辑生成修正版);记录页可主动做语义检索(与 memory_search 同一套排序),并有「是否被修正」筛选;记忆树展示作用域、类型与修正链;设置改完即存;导入导出 一键向量后端 · 面板里下载 llama.cpp 运行时与内置模型,按 CPU / 内存 / 显卡推荐;换模型自动重建向量 跨进程安全 · 每个作用域一把写锁,锁内重新读盘再合并;多个 DSH 实例或 MCP server 共用一个 store 不丢数据
记录页搜索框旁边有「语义检索」开关。开启后,搜索不再按关键词过滤,而是把这句话交给和 memory_search 同一套的召回排序(向量 + 词法,必要时再重排),结果按相关度返回并标出得分。
memory_search 后续的排序带偏。访问次数多时可能大于 1;结果顺序与这个分数一致。
没有响应时,不会把词法结果冒充成语义结果。嵌入完成后列表会自动刷新成语义结果。
按 作用域 → 类型 → 记录 三层展开,根节点显示总数。supersedes 是关系而不是层级, 所以不改树结构:金色虚线从修正版弯到旧版,悬停或选中任意一端,整条修正链一起点亮。
召回、摘要、印象、策略、状态、流程索引、规则、自动召回逐项开关;每个开关都有可见 label、说明和当前状态。 修改立即写入 settings.json,不需要点保存。
输入框工具行右侧有「记忆范围」按钮。打开会话时就会读取这个会话的设置,按钮上的数字是当前生效的作用域数量,边框样式表示限制等级(绝对限制 = 橙黄实线 / 普通限制 = 蓝色实线 / 无限制 = 灰色虚线;title 里写明「已设置 / 使用默认 / 继承父会话 + 数量 + 等级」)。点开的浮窗使用毛玻璃背景,按当前会话列出可选作用域(当前会话 / 当前项目 / global / 已有自定义作用域):
kinds 会被忽略,同一作用域下的事实 / 规则 / 流程等都可读。conversation.input.dock,只在发起审批的那个会话里显示,切到别的会话看不到;视觉与系统自带的权限审批弹窗一致(警告色 strip、卡片、右对齐动作行,同一批主题 token)。按动作分为「记忆读取 / 写入 / 删除审批」。读审批默认全部勾选:可逐条取消、用「全选 / 取消全选」批量操作,点条目任意位置即可切换选中,再点「允许选中的 N 条」,工具只放行勾选的 id、其余写入 withheld.reason='partial';全选时等价于原来的「允许一次」。strip 右侧可折叠 / 展开详情,折叠后仍保留「拒绝 / 允许」动作。写 / 删审批是单条,隐藏勾选框。0.22.0 起卡片展示工具调用的 description(普通限制下工具层强制模型提供),点记忆 ID 会打开记忆面板的「记录」标签页、选中并滚动到该条、自动展开;0.22.2 起查询与说明固定显示在条目列表上方,条目再多也不会被列表挤没(两行锁 flex:none,只有列表滚动);0.22.3 起审批卡高度只受 composer 文本区上限约束(与宿主审批卡同口径),矮窗口下列表也有空间。拒绝、超时或无法发起审批都会把原因告诉模型。Enter = 允许、Esc = 拒绝(焦点在卡片内时)。/visibility/.json,浏览器刷新 / 插件重载后仍在;0.18 的旧文件按「绝对限制」兼容读取。--dsw-alias-state-business-primary + --dsw-alias-label-primary-foreground,深色模式下不会出现白底白勾 / 白底白字;按钮三档边框用 state-warn-primary(橙黄)/ state-business-primary(蓝)/ 虚线灰;阴影已收敛为小范围投影,滚动列表高度收紧到 min(220px, 32vh)。memory_search / memory_list / memory_get 与 memory_save / memory_forget 共用同一份可见域;0.23.0 起每个作用域的「可读 / 可写」状态独立生效,失败原因会写进工具回复。面板管理页仍是用户本人的操作,不受会话语义限制。在本机托管 llama-server,下载运行时与模型;内置清单为每个模型配好 dims 与 pooling, 避免维度写错导致向量通道静默失效。按硬件推荐,也支持自定义 GGUF。
一条命令装进 Web profile:
dsh plugin --profile web add @restregular/dsh-memory也可以手动加进 profile 的依赖(桌面端 ~/.dsh/profiles/desktop,Web 端 ~/.dsh/profiles/web):
pnpm add @restregular/dsh-memory
# 或
npm i @restregular/dsh-memory装进任意 DSH profile(桌面端 ~/.dsh/profiles/desktop,Web 端 ~/.dsh/profiles/web)。 包自带 cordis.patch.yml,注册唯一一条 entry:
- insert:
- id: dsh-memory
name: '@restregular/dsh-memory'不写任何配置就能用:检索退化为词法,不产生任何网络请求。需要语义检索时, 在面板「服务 → 向量服务」里一键装本机后端即可。
宿主只允许一个包名、一个解析源,所以本插件是「一个包 + 一条 entry + 面板与服务端同包」。
拆成两个包会触发 resolves from multiple active Loader sources,客户端图组合失败,桌面端直接起不来。这段设计约束写在下面的折叠块里,不影响使用。
为什么是一个包(给想改结构的人)
宿主的 dsh-client-modules 只在「某条活的 Loader entry 能解析到包名」时才为该包提供 client bundle,并且 reconcilePackage 要求一个包名只有一个解析源。因此稳定形态只有一种: 一个包名、一条 entry、两侧都在。入口 lib/index.js 组合四个半边,每个半边各自 try/catch——任何一半失败都只记一行日志,绝不让 DSH 启动失败。
半边 · 作用 lib/provider · 提供 memory 服务:JSONL 存储、双通道检索、向量回填、向量后端生命周期与一键安装 lib/tools · 注册五个模型工具 lib/inject · agent/pre-step 召回、摘要、策略、规则与行为触发 lib/panel · /memory/api 管理接口(含同源 / 登录围栏) lib/client.js · 设置页「记忆系统」区块与左侧栏入口(注册 id == 包名)
设置页 →「记忆系统」;也可以在「设置 → 侧栏入口」打开左侧栏的「记忆系统」按钮。 面板分四个标签:服务 / 记录 / 记忆树 / 设置。记录页的搜索框旁有「语义检索」开关, 开启后可以直接用一句话主动搜索(需要先配置向量后端)。
模型自己会调,也可以直接对 Agent 说「记住:……」。工具入参如下:
memory_save({
"content": "本仓库用 pnpm 11 安装依赖;PATH 上的 pnpm 10 会报 ERR_PNPM_UNEXPECTED_STORE。",
"kind": "procedure", // fact / decision / preference / procedure / note / rule / state
"tags": ["pnpm", "toolchain"],
"triggers": ["pnpm", "install"], // 可选:流程索引按工具名/关键词匹配;缺省用 tags
"importance": 0.8, // 0~1
"expiresAt": 1793836800000, // 可选:过期时间(ms);kind=state 不传时按默认 TTL(7 天),也可传 ttlMs
"path": "D:/repositories/dsh-memory" // 可选:写入 project:<该路径>
})memory_search({ "query": "pnpm 装依赖", "topK": 5, "description": "查装依赖的约定" }) // 只回 id / 作用域 / 类型 / 标签 / 摘要
memory_search({ "query": "旧的发布流程", "includeSuperseded": true, "description": "核对旧发布流程" }) // 默认隐藏被修正/覆盖的旧版本
memory_get({ "ids": ["3f2a9c1d"], "description": "取装依赖那条的全文" }) // 默认:正文 + scope + kind + tags
memory_get({ "ids": ["3f2a9c1d"], "fields": ["summary", "updatedAt"] })
memory_get({ "ids": ["3f2a9c1d"], "fields": ["content"] }) // 只要正文
memory_list({ "limit": 20 })
memory_forget({ "id": "3f2a9c1d", "description": "删除过期的临时结论" }) // 按内容删:memory_forget({ query, scope })memory_search 不再返回正文:每条只有 8 位 id、作用域、类型、标签和摘要(默认 160 字, summaryChars 可调 20~2000)。判断相关后用 memory_get 取正文或元数据:
fields 省略 = content + scope + kind + tags(与旧版看到的一致);["summary"];只取正文:["content"];importance / createdAt / updatedAt / expiresAt / triggers / supersedes;id 始终返回;未知字段会明确报 FIELDS_INVALID,不会静默忽略。memory_search 省略 scope 时合并会话 + 项目 + global(按来源标注、按 id 去重); scope: "all" 查所有已发现的作用域,写入路径会明确拒绝 all。
上下文去重(0.21.0):同一会话里已经由 memory_search / memory_list(或摘要 / 召回 / memory_get) 放进上下文的条目,再次命中且 updatedAt 未变时,memory_search / memory_list 只回记忆 ID,并附一句 「本次请求部分记忆摘要因上下文去重机制被省略,若要获取完整内容请使用 memory_get」;内容更新(版本变化) 后会重新返回摘要。memory_search 里这些裸 ID 单独成块,与带摘要的条目之间空一行,不会看起来像 上一条的续行。状态与召回/摘要共用同一份会话去重记录(summary_injected / content_injected)。
`description`(0.22.0):五个工具都新增 description 参数 —— 一句话说明这次调用要做什么。 本会话「记忆范围」为普通限制(默认)时必填,漏了会被 DESCRIPTION_REQUIRED 拒绝; 绝对限制 / 无限制下可省略。它只用于范围外访问的审批卡(展示给用户判断是否放行),不写进记忆。
写法 · 含义 省略 / session · 当前会话(子代理共享父会话;拿不到会话信息时回退当前项目) project · 当前工作区(键是 project:) path + 可选 scope · 指定工作区目录;scope 成为这个项目作用域的显示名(别名) global · 所有项目共享 handbook、项目笔记 … · 自定义作用域,首次 memory_save 自动创建 session: / project: · 显式钉住某个会话 / 工作区 all / * · 只在读取时可用:跨所有已发现作用域
项目作用域的身份永远是 project:,别名只影响显示与引用,不迁移数据。 同一路径重复用同一个名字是幂等的;换名字会覆盖原别名;另一个路径抢同一个名字会被拒绝 (SCOPE_NAME_TAKEN)。
导出是纯文本 JSON:作用域、类型、内容、标签、重要度、时间戳,不含向量。 导入时逐条走保存路径,按当前模型重新嵌入,并按「作用域 + 内容」去重;一次最多 5000 条。
层 · 触发 · 作用 recall · 每轮 agent/pre-step · 按本轮用户问题检索,按 topK / token 预算注入;默认只给每条 120 字摘要 + memory_get 指引 digest · 会话第一步 · 注入项目 + global 概览:按重要度 × 新鲜度挑选;kind=rule 不进摘要(已常驻系统提示);正文超预算时附可检索的标签索引 policy · 系统提示常驻 · 什么时候查记忆、查到怎么复用、查不到时低风险推断 / 高风险先问用户 rules · 系统提示常驻 · kind: rule 的硬性规则摘要;每行 id · 正文,需要全文时 memory_get;限量与预算;mandatory / pinned 排在最前 procedures · 系统提示常驻 · kind: procedure 的目录:当前工作区 + 触发词命中的流程,每行 id · 触发词 → 标题;正文按需 memory_get turnEnd · 每轮结束(默认关) · 下一轮开头提醒「有可复用结论先落盘」 行为召回 · 可见文本 / 任务 / 命令 / 工具失败 · 命中标签后,在下一个 agent/pre-step 定向检索;工具失败优先用该工具自己的 description
行为召回只检索 global + 当前会话 + 当前工作区,不把自定义作用域或 fork 父会话带进来。 匹配源包括可见 assistant 文本、todo、command/run、goal/change、带 description 的 tool/call,以及工具失败描述;没有 `description` 的工具调用不触发,memory_* 工具一律不触发(memory_search 本身在取记忆,再召回一次只会重复注入)。不读取隐藏思维链。
系统提示段每步都会重渲染,但那只是提示词文本变化,不会产生对话消息;常驻段还有 token 预算, 新规则可能被更重要的旧规则挤掉。rules.delta(默认开)会在每轮第一步比较「该会话上一轮开始时 的规则快照」与当前规则:新增、以及编辑过(同一 id 的行变了)的规则都补一条提醒,没变化不重复; 宿主重启用历史里的规则行做种子,不会整批重提醒。关掉它只停提醒,常驻段与检索照旧。
规则段注入的是摘要:每行是 `- 。段头会明确说明这一点,模型需要完整规则或细节时用 memory_get` 按 ID 取;因此规则再长也不会把整段正文常驻在系统提示里。
流程通常很长,全部常驻会挤爆系统提示;而注入发生在 agent/pre-step,模型决定调用工具之前拿不到工具名。 所以系统提示里只放一个目录:当前工作区的 procedure 总是可见;其他作用域的流程必须命中 triggers(缺省用 tags),匹配源是本轮用户消息、本会话最近调用过的工具名和当前项目路径。 每行是 id · 触发词 → 标题,模型判断相关后用 memory_get 取全文。条数与 token 预算可在设置里调; 没有命中项时不注入。
memory_search 返回过的摘要记为 summary_injected,memory_list 返回过的正文记为 content_injected。同一会话再次命中同版本条目时只回记忆 ID 并提示用 memory_get 取全文;版本变化(updatedAt)后重新返回。标签索引(hint_injected)只给 id + tags,不算摘要已出现;memory_get 始终显式返回正文,不做去重。memory_get 取到正文后,这条记忆会记成「正文已注入」;同一会话后续的普通召回 / 摘要 / 自动召回都不会再把同一段正文塞一遍。只取 summary / tags / 元数据不算正文,仍可被召回。memory_save 保存成功同样算「正文已在上下文里」:写入语句(content)就是模型自己产出的 tool/call 参数,因此这条记录会立刻记成「正文已注入」,本会话后续的召回 / 摘要不会把刚保存的记忆原样再注入一次(去重命中既有记录时也一样)。保存失败不标记;记录之后被更新(updatedAt 变化)仍会重新评估。审计里会留一条 content_pinned / saved_in_context 的 lifecycle 事件,说明后面的「去重跳过」从哪来。/.dsh/dsh-memory/sessions/.jsonl,插件重载 / 宿主重启后自动恢复;只有首次接触该会话时读一次盘。
updatedAt)和时间戳,不存正文,也不存查询。inject.sessionState.{enabled,dir,debounceMs,maxAgeDays,maxFiles} 可覆盖默认值;默认开启。.dsh/ 已加入本仓库 .gitignore;其他项目按需自行忽略。supersedes 指向的旧记录不再进入 memory_search、memory_list、摘要、规则段和自动召回;memory_get(id) 与面板仍可查历史。需要历史检索时 memory_search({ includeSuperseded: true })。kind=rule;规则段实际进入系统提示的 id 会写进会话注入状态,recall 不再重复注入同一条规则。signal_dropped 审计。kind=state 过期后默认从检索 / 摘要 / 召回 / 列表隐藏,但数据不删除;memory_get 与面板仍可取。llama-server 的 OpenAI 兼容 /v1/embeddings;可用面板一键安装,也可接自己的端点。retrieval.llm.enabled,默认关。GET /memory/api/search,用同一套召回排序(只读、不写访问计数),并在结果说明里标明向量通道是否真的参与;旧 provider 会退回关键词过滤并在界面注明。
向量边车 .vec 的首行是身份头 #\t\t。任一对不上就整份丢弃并重新嵌入; 重建期间检索暂时只用词法。老边车只有 model + dims 两段,按兼容接受,下一次写向量时自动升级。 换模型 = 向量作废重建,面板会在切换前告诉你涉及多少条记忆。
minScore 默认 0.5 是按 BGE 的 CLS 噪声底定的;换模型后如果召回太少就调低、太杂就调高。
dims 与 pooling,选它就自动写入。维度写错会让向量通道静默失效,这是最容易踩的坑。cpu / vulkan / cuda / metal / auto。Vulkan 自包含;CUDA 会一并下载 cudart 伴随包;所选风味找不到时退回 CPU 并在面板说明。search_query: / search_document:)自动带上。retrieval:
vector:
preset: 'qwen3-embedding-0.6b' # 清单 id
variant: 'q8_0' # 量化档
flavor: 'auto' # auto / cpu / vulkan / cuda / metal
# customModel: { url: 'https://…/model.gguf', dims: 1024, pooling: 'auto' }