DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

SherinG-official /

SherinG-official/dsh-siyuan-api

Verified

DeepSeek Harness plugin for SiYuan (思源笔记): search notes, create documents, read/append blocks, and run read-only SQL over the local kernel HTTP API.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@c9355336

dsh-siyuan-api

license node tests

让 DeepSeek Harness(dsh)直接读写 思源笔记(SiYuan)的插件。

走思源内核 HTTP API(默认 http://127.0.0.1:6806),不装思源插件、不碰工作区文件、不直接改 siyuan.db —— 所有写入都经内核事务层,思源能正常做索引与同步。

工具 干什么
siyuan_status 探活自检:内核版本、Token 是否有效、索引库能否查询、库里有多少块
siyuan_notebooks 列出笔记本(拿准确的名称与 ID)
siyuan_search 搜内容:mode=keyword 关键词模糊搜索,mode=sql 只读 SELECT
siyuan_create_doc 在指定笔记本新建 Markdown 文档(可指定父文档)
siyuan_block 按块 ID 读 Markdown 原文、追加内容(append)、前后插入(insert)

除了工具,插件还会往系统提示词里注入一小段使用规范(可用 prompt: false 关掉), 并在有 HTTP 宿主时挂一个只读诊断路由 GET /dsh-siyuan-api/status。

不需要装思源插件,也不需要 Python —— 运行时只用 Node 内置的 fetch。


1. 安装

1.1 从本地目录 / tarball 安装

# 打成 tarball(路径里不要有空格,pnpm 的 file: 依赖会被空格切断)
node <pnpm> pack --pack-destination C:/somewhere/no-spaces

# 装进目标 profile(web / headless / 你自己的 profile)
dsh plugin --profile web add "file:C:/somewhere/no-spaces/dsh-siyuan-api-0.1.2.tgz"

dsh plugin add 会自动同时做两件事:写入 profile 的 dependencies,并把包名加进 dsh.profile.bundles。装完重启该 profile 即可生效。

1.2 desktop profile(Electron 桌面端)

dsh plugin --profile desktop … 被 CLI 显式拒绝(桌面端 profile 由 Electron 独占), 需要手工改清单,或用本包附带的脚本:

node scripts/add-to-profile.mjs \
  "$DSH_HOME/profiles/desktop/package.json" \
  "C:/somewhere/no-spaces/dsh-siyuan-api-0.1.2.tgz"

# 然后在 profile 目录里装依赖(用 profile 自己的 pnpm 配置,不要加 --ignore-workspace)
cd "$DSH_HOME/profiles/desktop" && pnpm install

改完重启 DSH Desktop 生效。

1.3 依赖说明

运行时只需要 Node 内置 fetch。@deepseek-ai/dsh-tools、@deepseek-ai/cordis、 @deepseek-ai/schemastery 都由 dsh 宿主提供(通过 $DSH_HOME/profiles/node_modules 的符号链接解析),所以刻意没有写进 dependencies:

  • 写成 dependencies 会让 profile 的 pnpm install 去 npm 拉一份宿主私有版本,直接失败;
  • 写成 peerDependencies 同样会被 pnpm 解析并下载,还会锁死版本区间。

schemastery 保留为可选 peer(版本与宿主一致时用得上,缺了也不影响插件装载)。


2. 配置

2.1 思源侧准备

  1. 思源要处于运行状态。窗口最小化到托盘也算(内核是独立进程),但真正退出就没了。
  2. 记下内核地址。桌面端默认 127.0.0.1:6806;如果你在思源里改过端口或开了「网络伺服」, 就用实际地址(思源「设置 → 关于」能看到)。
  3. 拿 API Token:思源「设置 → 关于 → API token」(老版本在「设置 → 关于」)。
    • 没设锁屏密码时,本机访问(127.0.0.1)免鉴权,Token 可以留空;
    • 设了锁屏密码、或要让 dsh 走非 127.0.0.1 访问时,必须填 Token。

2.2 插件配置项

写进 profile 的 cordis.patch.yml(按行 id 覆盖),或用设置页:

- id: dsh-siyuan-api
  name: dsh-siyuan-api
  config:
    apiUrl: http://127.0.0.1:6806   # 内核地址;填 127.0.0.1:6806 这种简写也认
    token: ''                       # 思源 API Token;留空 = 只访问免鉴权的本机内核
    timeoutMs: 15000                # 单请求超时
    maxRows: 64                     # 搜索 / SQL 单次返回行数上限(1-1000)
    defaultNotebook: ''             # 默认笔记本(名称或 ID);留空则每次都要显式指定
    prompt: true                    # 是否注入系统提示词使用规范
    debug: false                    # 打开后在宿主日志里打印解析后的配置(不含 Token 明文)

也可以把 Token 放在环境变量 SIYUAN_TOKEN 里(配置文件里留空即可,配置文件优先)。

提示:!!js 表达式在 patch 里可用,所以 Token 不必落盘在配置里,例如 token: !!js process.env.SIYUAN_TOKEN || ''。

2.3 自检

装好后先问一句「思源连上了吗」,或直接调 siyuan_status。也可以打开诊断路由 (仅 web profile 有):

http://127.0.0.1:<dsh端口>/dsh-siyuan-api/status

它只报事实(地址、是否配 Token、工具清单、内核版本、笔记本数),不回显 Token。


3. 工具用法

siyuan_search —— 找内容

参数 说明
query 必填。keyword 模式给关键词(中文 / 英文、不分大小写、支持子串);sql 模式给完整 SELECT
mode keyword(默认)/ sql
notebook 可选,限定笔记本(名称或 ID)
limit 可选,返回条数(默认 20,上限 = maxRows)

关键词模式覆盖 blocks 表的 content(正文)、name(标题)、alias(别名)、memo(备注), 返回块 ID、所属文档、笔记本、路径、片段与更新时间 —— 这些 ID 就是后面 siyuan_block / siyuan_create_doc(parentID) 的输入。

sql 模式可查的表(blocks 为主):

blocks(id, parent_id, root_id, box, path, hpath, name, alias, memo, tag,
       content, fcontent, markdown, length, type, subtype, ial, sort, created, updated)
spans(id, block_id, root_id, box, path, content, markdown, type, ial)
attributes(id, name, value, type, block_id, root_id, box, path)
refs(id, def_block_id, def_block_root_id, def_block_path, block_id, root_id, box, path, content, markdown, type)
assets(id, block_id, root_id, box, docpath, path, name, title, hash)
file_annotation_refs(...)
  • box = 笔记本 ID;root_id = 所属文档 ID;hpath = 人类可读路径;markdown = Markdown 源文;
  • type:d 文档、h 标题、p 段落、l 列表、i 列表项、b 引述、t/tb 表格、c 代码块、m 公式块、s 超级块、av 数据库;
  • subtype:标题是 h1..h6,列表 / 列表项是 u(无序)o(有序),其余为空;
  • 行内标记(加粗、链接、标签)在 spans 里,不在 blocks;标签值在 blocks.tag 与 ial 里都有。

例子:

-- 最近改过的 10 篇文档
SELECT id, content, hpath, updated FROM blocks WHERE type = 'd' ORDER BY updated DESC LIMIT 10
-- 各笔记本的块数量
SELECT box, COUNT(*) AS n FROM blocks GROUP BY box ORDER BY n DESC
-- 带「TODO」的段落
SELECT id, hpath, content FROM blocks WHERE type = 'p' AND content LIKE '%TODO%' LIMIT 20

siyuan_create_doc —— 新建文档

参数 说明
title 必填,文档标题(也是文件名)。写「父文档/子文档」可建一层子文档
notebook 目标笔记本名称或 ID;不传则用 defaultNotebook
markdown 正文,标准 Markdown(省略则建空文档,之后用 siyuan_block 追加)
parentID 可选,父文档 ID(来自 siyuan_search),优先级高于标题里的 /

写入前请确认目标:笔记本用 siyuan_notebooks 查,父文档用 siyuan_search 定位。

siyuan_block —— 读写某个块

参数 说明
id 必填,块 ID(22 位,形如 20260919135122-lw63vfz)。传文档 ID 就是整篇文档
mode read(默认)/ append(追加为子块)/ insert(前后插入同级块)
data append / insert 要写的内容(Markdown;dataType=dom 时是思源块 DOM)
position insert 的位置:before(默认)/ after
confirm append / insert 必须显式传 true,否则拒绝执行

confirm 是刻意的摩擦:先 mode=read 看清目标,再带着 confirm=true 落笔, 比事后回滚便宜。


4. 设计要点

错误处理:失败也是正常返回。 思源没启动、Token 不对、笔记本不存在 / 已关闭、 块 ID 抄错 —— 这些都变成一句能照着排查的 message,而不是抛异常打断整轮对话。 错误按原因分了码(SIYUAN_UNREACHABLE / SIYUAN_TIMEOUT / SIYUAN_AUTH_FAILED / SIYUAN_BAD_RESPONSE / SIYUAN_API_ERROR / SIYUAN_INVALID_ARGUMENT), 文案里直接给出下一步动作,例如把 API 地址错配成思源 Web 界面地址时会明确说 「这个地址多半是 Web 界面,请改成内核地址」。

只读 SQL 是双保险。 插件侧先做「单条 + SELECT/WITH」预检(带注释 / 引号内分号处理), 再给没写 LIMIT 的语句补上上限;发请求时始终带 mode: "readonly" —— 思源 3.8.x 的内核只在 mode=readonly 时才真正做只读校验,默认 mode 并不拦写操作, 不能把「不写坏数据」寄托在自己的正则上。内核返回的 truncated / limit 也会转述给模型, 免得它把「被截断的结果」当成全部。

笔记本解析。 模型更可能说「运维笔记」而不是 22 位 ID,所以 notebook 参数 接受 ID、精确名称、唯一子串;匹配不到时报错里直接列出所有可用笔记本, 模型能立刻换个说法重试,不用回头问用户。

webServer 是延迟注入的。 dsh-host-webserver 属于 @deepseek-ai/dsh-web-app, 不在 dsh-base 里 —— headless / SDK / ACP 这些 profile 根本没有这个服务。 把 webServer 写进 inject 会让插件在那些宿主里永远停在 PENDING(工具也注册不上); 直接读 ctx.webServer 又会被 cordis 抛 cannot get property "webServer" without inject 并把装载搞挂。所以实现用 ctx.inject(['webServer'], …) 起一个子 fiber: 服务就绪才挂路由,没有就安静待命,工具在任何宿主都正常。


5. 开发

5.0 准备本地依赖

本仓库不提交 node_modules,但测试需要两个宿主包能被解析。一条命令搞定:

node scripts/dev-setup.mjs

它会:检查 @deepseek-ai/schemastery(缺了会提示你 npm install --no-save), 并把 @deepseek-ai/dsh-tools 就位 —— 优先链接本机 dsh 自带的真包, 找不到就退回复制 test/stubs/dsh-tools 里的替身(--stub 可强制走替身)。

为什么不是直接 npm i @deepseek-ai/dsh-tools:它运行时真的会 import '@deepseek-ai/cordis', 而每个 npm 版本都声明了一长串 @deepseek-ai/dsh-* peer 依赖,装它等于把整棵 dsh 依赖树拉下来。 替身只实现本插件依赖的部分,但编译规则与参数校验都照宿主实现 —— 作者侧的 required: true 会被编译成根节点的 required: [...] 数组, test/schema.test.mjs 断言的正是这份「模型实际收到的 JSON Schema」。 替身与真包两条路都跑过,61 条测试结果一致。

5.1 跑验证

# 61 条测试:客户端、SQL 防护、工具端到端(真 HTTP 假内核)、诊断路由、参数契约
node --test "test/*.test.mjs"

# 真启动一个 dsh 实例验证插件装载(独立假内核 + 独立端口,不动你正在用的 GUI)
node verify-boot.mjs --profile web --port 19401

verify-boot.mjs 会:起一个假思源内核 → 用 --patch verify-patch.yml 覆盖插件配置 → 启动 dsh --profile <p> --port <n> --no-open → 请求插件的诊断路由 → 核对「5 个工具都注册了 + 内核可达」。这是真机装载验证,能抓出单测抓不到的问题 (比如上面那条 without inject 的装载崩溃,就是它发现的)。

目标 profile 里得先装好本插件,而且不能是 desktop —— 那个 profile 由 Electron 独占, CLI 会直接拒绝启动(profile "desktop" is managed exclusively by the Electron application)。 用 web 或自建 profile 验证的是同一条代码路径。

CI(.github/workflows/test.yml)在 Linux + Windows、Node 22.13 / 24 上跑同一套测试。

CI 目前未启用。 工作流文件已就位,但 GitHub 拒绝用当前凭据推送它 —— 推送 workflow 需要 token 具备 workflow scope,而 gh 的 OAuth 凭据没有 (refusing to allow an OAuth App to create or update workflow … without 'workflow' scope)。 启用方式:执行一次 gh auth refresh -h github.com -s workflow(浏览器里点一下授权), 然后把这个文件加进版本控制:

git add -f .github/workflows/test.yml .gitignore   # .gitignore 里 .github/ 那一行顺手删掉
git commit -m "ci: enable the test workflow" && git push

工作流本身不依赖本机环境:装 schemastery + 复制 test/stubs/dsh-tools 替身后直接跑 npm test。

目录结构:

lib/
  index.js        插件入口:Config 声明、系统提示词注入、工具注册
  client.js       内核 HTTP 客户端:URL 归一化、Token 头、信封解析、错误分类
  api.js          端点语义化封装(一函数一接口)
  sql.js          只读 SQL 预检、LIMIT 处理
  format.js       把内核数据渲染成模型可读文本
  route.js        /dsh-siyuan-api/status 诊断路由(延迟注入 webServer)
  tools/          五个工具的 defineTool 声明
docs/             思源内核 HTTP API 实现参考(字段级,含版本矩阵)
test/             客户端 / SQL / 工具 / 诊断路由 / 参数契约的测试
test/stubs/       @deepseek-ai/dsh-tools 的测试替身(见 5.0)
scripts/          dev-setup.mjs 本地依赖引导;add-to-profile.mjs 写入 desktop profile 清单
verify-boot.mjs   真机装载验证(可选)
verify-patch.yml  验证时用的配置覆盖层
.github/          test.yml 工作流(待 workflow scope 后纳入版本控制,见 5.1)

verify-boot.mjs 用 DSH_HOME 定位 profile(未设置时按主目录推导),必要时可显式指定: node verify-boot.mjs --dsh /usr/local/lib/node_modules/@deepseek-ai/dsh/lib/bin.js。

改了代码后重新验证的完整流程:

node <pnpm> pack --pack-destination C:/somewhere/no-spaces
cd "$DSH_HOME/profiles/<p>" && pnpm install --force   # 同版本 tarball 需要强制重装

5.2 内核接口参考

docs/siyuan-kernel-api-reference.md 是思源内核 HTTP API 的字段级参考 (约 1120 行,对着 v3.8.6 源码逐条核对):鉴权矩阵、响应信封约定、端点清单、blocks 等表的完整列名、 type/subtype 取值、错误码、以及一堆容易踩的坑(例如 fullTextSearchBlock 的 orderBy 语义与社区文档 不同、/api/query/sql 默认不拦写操作、blocks.tag 与 IAL 的关系)。扩展这个插件、或写别的思源桥接时 先看它,可以省掉重新翻 Go 源码的时间。


6. 已知限制

  • 只读的边界靠内核:插件带 mode:"readonly",但思源 ≤3.1.x 没有这个字段,会忽略它; 那些版本上「不写坏数据」完全依赖插件侧的正则预检。建议思源 3.8.x 及以上。
  • 关键词搜索走 SQL LIKE,不是思源分词器。中文子串匹配没问题,但没有相关性排序; 需要思源自己的分词 / 排序质量时,用 mode=sql 自行组合(或直接用思源的全文搜索界面)。
  • 写入类工具刻意不做删除 / 移动 / 重命名。要删要在思源里做,或者自己调内核接口 —— 让模型手滑删笔记的代价太高。
  • 思源没启动时工具不可用。插件不会替你启动思源,也不会缓存上次结果; 调用会明确告诉你「连不上」以及怎么排查。
  • 单条 SQL 的结果受思源 search.limit(默认 64)约束,超出时内核会返回 truncated, 工具会把这件事转述给模型,但它仍可能只看到前 64 行。

7. 许可

MIT。思源笔记本体是 AGPL-3.0,本项目只通过它的公开 HTTP 接口交互,不包含其源码。

—/ 5

No ratings yet

Verified DSH bundle

Commit c9355336c0cc

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