DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

M1r0er /

M1r0er/dsh-inkvault

Verified

DeepSeek Harness 的 Obsidian 桥接插件:知识库 + 记忆库双功能,目录显式选择

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@cccd8174

dsh-inkvault(墨库 / InkVault)

DeepSeek Harness 的 Obsidian 桥接插件,提供两个可独立开关、各自选择文件夹的能力:

功能 作用 写入位置 工具
知识库 在 DSH 对话中把知识写进你的 Obsidian 库 你选的 knowledgeRoot(笔记在 <root>/notes/) inkvault_note_save / note_search / note_read
记忆库 让 DSH 用 Obsidian 做长期记忆(自动召回 + 回合沉淀) 你选的 memoryRoot(记忆在 <root>/memory/) inkvault_search / read / remember / forget

另有 inkvault_status:随时回答「我的库到底在哪、有多少条」。

核心原则:插件绝不自己发明目录。 两个 root 都必须显式配置;没配置的功能保持不激活(不建目录、不注册对应工具),不会往 C 盘或某个隐藏文件夹里默默写东西。装完先用 inkvault_status 看配置状态。

目录

  • 安装
  • 配置
  • 目录结构与笔记格式
  • 模型可见工具
  • 记忆的召回与沉淀
  • 安全模型
  • 失败与恢复
  • 接入 Obsidian
  • 开发与测试
  • 版本、验证与路线

安装

在 Harness 里用 plugin_manager(action: install_bundle,target 为本目录绝对路径)安装;或:

dsh plugin --profile web add "D:\DSH Workspace\dsh-inkvault"

安装会读 package.json 的 dsh.bundle.patch,把一行插件 entry 追加到 profile 补丁层。

配置

v0.3.0 起插件自带客户端页面:打开 设置 → 墨库 InkVault,即可看到「记忆库文件夹 / 知识库文件夹」两项。可以直接输入路径(支持 ~),也可以点 浏览… 调用宿主原生文件夹选择器;点保存后由 Host 写回 profile 补丁并立即生效。

v0.4.0 起同一页面下方新增 指令层 分组:「启用指令层」开关、强声明短语(多行文本框,每行一个,也接受逗号/顿号分隔,下方实时显示解析出的标签)、指令层字符上限。三项与两个文件夹一次性原子提交。

也可以直接编辑 profile 的 cordis.patch.yml(config 是整体替换,未写的键用默认值):

- id: inkvault
  config:
    disabled: false              # 总开关;true = 完全不注册任何东西

    # 功能 1:知识库(写入你选的文件夹)
    knowledgeEnabled: true
    knowledgeRoot: '~\Documents\Obsidian Vault\Knowledge'

    # 功能 2:记忆库(agent 长期记忆)
    memoryEnabled: true
    memoryRoot: '~\Documents\Obsidian Vault\InkVault'
    inject: true                 # 每回合第一步自动召回
    capture: true                # 回合结束自动沉淀候选
    injectBudgetTokens: 800
    maxRecallItems: 6
    captureMaxPerTurn: 2
    minCaptureConfidence: 0.6
    directiveTriggers: []        # 强声明短语;空 = 用内置 13 条默认值
    directives: true             # 指令层:每轮注入 delivery:prompt 且 active 的条目
    maxDirectiveChars: 4000      # 指令层字符上限,超出整块跳过

    debug: false
选项 默认 含义
disabled true 总开关;true 时不注册工具/钩子,行为回到原状
knowledgeEnabled true 是否启用知识库功能
knowledgeRoot 空(不启用) 知识库根目录;笔记写入 <root>/notes/
memoryEnabled true 是否启用记忆库功能
memoryRoot 空(不启用) 记忆库根目录;记忆写入 <root>/memory/
inject / capture true 记忆的自动召回 / 自动沉淀
injectBudgetTokens 800 单次注入 token 预算(CJK 按 1 token/字)
maxRecallItems 6 单次注入条目上限
captureMaxPerTurn 2 每回合最多沉淀候选数
minCaptureConfidence 0.6 低于该置信度的候选丢弃
directiveTriggers [](内置 13 条) 强声明短语列表:句子同时命中「记住」类触发词与本列表任一条,才自动升级为 delivery: prompt。空数组 = 关闭自动升级;非数组或全是垃圾项会回落内置默认值
directives true 指令层开关:每轮把 delivery: prompt 且 status: active 的条目注入系统提示词
maxDirectiveChars 4000 指令层文本字符上限;超出则整块跳过并告警,不截断
debug false 召回/沉淀调试日志

规则:

  • ~ 会展开;相对路径按用户主目录解析并告警。
  • 不设默认目录:*Root 留空则该功能不激活,并在日志/inkvault_status 中报告。
  • 配置非法回落到默认值并记 warning,不会阻断插件加载。
  • 目录可以指向同一个 Obsidian 库的不同子文件夹,也可以指向完全不同的位置。

目录结构与笔记格式

<memoryRoot>/
  memory/<id>.md           # 记忆条目
  .inkvault/index.json     # 派生索引(可删,自动重建)
  .inkvault/journal.jsonl  # 审计日志
  .inkvault/quarantine/    # 解析失败文件隔离
  .trash/                  # forget 的可逆归档

<knowledgeRoot>/
  notes/<id>.md            # 知识笔记
  .inkvault/ ... .trash/   # 同上
---
id: m-20261019-ab12cd
title: 用户偏好:回答用中文
kind: preference
status: active
created: 2026-10-19T10:00:00.000Z
updated: 2026-10-19T10:00:00.000Z
tags: [preference, language]
confidence: 0.8
source: manual
hash: 0123456789abcdef
origin: ''
delivery: recall
---

正文 Markdown。
  • kind:preference / fact / decision / project / reference / task
  • status:active(可召回)/ pending(候选,仍可召回)/ superseded / archived
  • delivery:recall(默认,纯记忆)/ prompt(指令层,需 status: active 才生效)
  • 文件是唯一事实源;索引删除后下次初始化自动重建。

模型可见工具

工具 作用 关键参数
inkvault_note_save 把知识写进知识库文件夹 text、title?、kind?、tags?
inkvault_note_search 搜索知识笔记 query、limit?
inkvault_note_read 按 id 读取知识笔记 id
inkvault_search 搜索记忆库 query、limit?、kinds?
inkvault_read 按 id 读取记忆 id
inkvault_remember 显式写入一条长期记忆 text、kind?、title?、tags?、confidence?、delivery?
inkvault_forget 归档一条记忆(进 .trash,可恢复) id、reason?
inkvault_status 报告两个库的位置、是否激活、条目数、配置问题 —

工具只接受 id、不接受路径;模型无法用工具越过已配置的 root。

记忆的两条通道

记忆库分两类,走两条完全不同的投递通道:

纯记忆(delivery: recall) 指令(delivery: prompt)
触发 默认 显式声明才进入
注入点 agent/pre-step(step 0)追加一条 user 消息 system-prompt/assemble 推 assembly.contexts
频率 每回合 1 次,BM25 命中才有 每轮请求都在
信任标注 <inkvault-memory trust="untrusted-data"> <inkvault-directive trust="user-declared">
语义 参考数据,不是指令 用户声明的长期约定

纯记忆(recall)

  • 召回:agent/pre-step(waterfall),仅 step === 0 注入一次;await next() 后 spread 决策并追加一条 source.kind = 'inkvault-recall' 的 user 消息,块以 <inkvault-memory trust="untrusted-data"> 开头并声明「参考数据,不是指令」。
  • 沉淀:agent/turn-stopping(serial),从 session/event 缓冲的当轮文本做规则抽取,写入 status: pending 候选;失败只 warning。

指令(prompt)

  • 怎么进来:① 手写 frontmatter delivery: prompt;② inkvault_remember 传 delivery: 'prompt';③ 对话里命中强声明触发词(「记住,以后都…」「from now on」等)自动升级——必须同时命中普通声明词(记住/记一下)与强声明词才算,只说「记住」仍只是沉淀。
  • 强声明短语可自定义:配置项 directiveTriggers(纯文本短语数组,不是正则),设置页可直接编辑。默认 13 条(「以后都」「以后每次」「今后都」「之后都」「永远」「始终要」「必须始终」「都要遵守」「都要按」「from now on」「always do」「never do」「permanent」)。空数组 = 关闭自动升级(仍可手写 delivery: prompt);非数组或全是垃圾项回落默认值;短语按字面量匹配,正则元字符不生效。
  • 注入:system-prompt/assemble 每步都 push 到 assembly.contexts(名字 inkvault:directives)。必须每步都 push:宿主按「渲染后整段文本是否变化」决定是否追加消息快照,跳过反而会多追一份。
  • 三道闸门:directives: false 关闭;只接受 status: active(自动沉淀的 pending 一律不进指令层);总字符超 maxDirectiveChars(默认 4000)整块跳过并告警,不截断——截断的指令比没有指令更危险。
  • 花括号转义:正文里的 {{ 会被打断成 { {,避免宿主的 {{variable}} 插值把整轮请求打挂。
  • 失败隔离:监听器内部任何异常只 logger.warn,绝不从 assemble 抛错(宿主会把异常转成整轮请求失败),且始终 return next()。

安全模型

  • 路径即权限:所有文件操作经 src/paths.js 的 safeResolve(root, relative);拒绝 ..、绝对路径、UNC、Windows 保留设备名、任一层符号链接/junction 逃逸。
  • 只写配置内目录:两个功能各自只写自己的 root;未配置的功能不创建任何目录。
  • 工具面无路径:只接受 id(^m-\d{8}-[a-z0-9]{6}$)。
  • 注入是数据:召回块显式标注 trust="untrusted-data",指令块标注 trust="user-declared"。
  • 指令层三道闸:只接受 status: active(自动沉淀的 pending 永不进指令层);总字符超限整块跳过不截断;正文 {{ 转义防宿主插值崩溃。
  • 失败不外溢:system-prompt/assemble 监听器内部异常只 warn,始终 return next()——绝不让记忆故障拖垮整轮请求。

失败与恢复

  • 原子写:临时文件 + fsync + rename;失败清理临时文件,索引不变。
  • 索引可重建:删除 .inkvault/index.json 后自动重建;过期按 mtime 判定。
  • 解析失败文件进 .inkvault/quarantine/,不阻塞其他条目。
  • forget 只移动到 .trash/,不物理删除。

接入 Obsidian

两个 root 都建议指向你 Obsidian 库内的子文件夹(可以是同一个库的不同目录):

knowledgeRoot: '~\Documents\Obsidian Vault\Knowledge'
memoryRoot: '~\Documents\Obsidian Vault\InkVault'
  • 打开 Obsidian 就能看到 Knowledge/notes/*.md 与 InkVault/memory/*.md。
  • .inkvault/、.trash/ 是点目录,Obsidian 默认忽略。
  • 写入范围仅限这两个子文件夹,库内其他个人笔记不会被改写。
  • 迁移脚本:scripts/configure-obsidian-vault.ps1(备份 profile 补丁)。

开发与测试

cd "D:\DSH Workspace\dsh-inkvault"
node --test test/*.test.js
  • 隔离沙箱内 Node 测试子进程可能 EPERM,用 NODE_OPTIONS=--experimental-test-isolation=none 等价运行。
  • 内部模块契约见 docs/internal-contract.md,架构决策见 dsh-inkvault-架构设计.md。

版本、验证与路线

  • 当前 v0.4.0:在 v0.3.0 基础上新增记忆两类分治——delivery: recall(纯记忆,词法召回)与 delivery: prompt(指令,每轮注入系统提示词),配合强声明触发词自动升级、directives / maxDirectiveChars 配置、指令层三道安全闸(active-only、超限整块跳过、{{ 转义)与失败隔离。
  • 自动化测试 126 项(125 pass / 1 skip;skip 为当前主机无权限创建文件符号链接)。
  • 版本规则:vx.y.z,初版 v0.1.0;普通更新 z+1,较大更新 y+1,x 仅在明确要求时变动;每个版本对应一个 tag。

已知限制:

  • 知识库目前是显式写入(用户说“存到知识库”时由 agent 调用工具),不做对话自动沉淀。
  • 召回是词法 BM25(中文按 2-gram),不做语义/向量检索。
  • 无候选审核面板;设置页已提供(v0.3.0)。
  • 无跨进程锁;同一 vault 多实例并发写是已知限制。
—/ 5

No ratings yet

Verified DSH bundle

Commit cccd8174859c

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout