- Home
- Plugins
- Tools & Capabilities
- dsh-sag-wiki
dsh-sag-wiki
clear0/dsh-sag-wiki
Adds four tools that query a local SAG Wiki index through the installed SAG CLI: semantic search, exact or regex match, and index status or update. Needs the SAG CLI on PATH, and semantic search also needs a JEV model configured in SAG; the model chooses which directory to index or drop (default: the session working directory).
Install
dsh plugin --profile web add github:clear0/dsh-sag-wikiREADME
dsh-sag-wiki
把 SAG Wiki 的本地代码 / 文档检索能力接进 DeepSeek Harness。
宿主侧 Cordis 插件(纯 host,无浏览器半侧),向 tools 服务注册 4 个 sag_* 工具;索引与检索全部交给本机已安装的 SAG CLI 完成——插件自己不建索引、不联网、不缓存正文。
模型 ──► sag_* 工具(本插件)──► sag 可执行文件 ──► 本地索引(SAG 后台服务)
▲
索引由 sag add / sag remove 管理
0. 一页速览
# 1) 准备 SAG CLI(两条通道择一;插件按 PATH 顺序取第一个可用的)
# a. 桌面版 SAG Wiki:安装后自带随包 CLI
# b. 独立 CLI:npm install -g @zleap-ai/sag
sag --version
# 2) 给要检索的目录建索引(在该目录内执行)
cd /path/to/project && sag add . --json
# 3) 装插件:把本仓库放到任意目录,然后在 Harness 插件管理器里
# install_bundle,target = 该目录的绝对路径
# (本机 PATH 里没有 dsh 命令,安装一律通过插件管理器)
# 4) 验证:调用 sag_index_status,应看到上面的目录 status=ready
sag_search(语义检索)需要额外配置 JEV 模型;没配时会返回可操作的提示并建议改用sag_grep(精确 / 正则检索),后者不依赖任何模型。
1. 依赖与平台
1.1 需要什么
| 依赖 | 是否必需 | 说明 |
|---|---|---|
| DeepSeek Harness(含 Cordis 插件系统) | 必需 | 本插件是宿主侧 bundle,需 tools / subprocess / workingDirectory 三个服务 |
| Node.js ≥ 20 | 必需 | 插件本身是 ESM;与宿主共用同一个 Node 运行时 |
SAG CLI(sag 可执行文件) | 必需 | 真正干活的部分;缺失时工具返回“未找到可执行文件”的提示 |
| SAG 后台服务 + 已建索引的目录 | 必需 | 首次 sag add 会拉起常驻服务;未索引的目录检索会报“目录未建立索引” |
| JEV 模型配置 | 可选 | 仅 sag_search(语义检索)需要;sag_grep、索引管理都不需要 |
1.2 平台支持
| 平台 | 支持情况 | 说明 |
|---|---|---|
| Windows x64 | ✅ | SAG 随包提供 sag.exe |
| macOS arm64(Apple Silicon) | ✅ | 提供 sag 原生二进制 |
| macOS x64 / Linux | ⚠️ 取决于 SAG 发布 | 插件按 process.platform + process.arch 推导原生二进制目录;上游提供了对应平台的构建即可用 |
| 其他 Node 运行时 | ⚠️ | 需要宿主支持的 Node ≥ 20 |
插件代码本身不含平台分支(除“sag.exe 与 sag 文件名差异”外),路径统一走 Node path 处理;从 CLI 输出里取回的 Windows \\?\ 前缀与 ./ 前缀在返回前会被剥掉。
2. 安装 SAG CLI
插件不下载、不打包 CLI,只在本机 PATH 里找它。两条通道等价,选一条:
2.1 通道 A:桌面版(推荐)
安装 SAG Wiki 桌面版 后,安装器会附带一份 CLI,通常落在:
| 平台 | 常见位置 |
|---|---|
| Windows | %USERPROFILE%\.local\bin\sag.exe |
| macOS | ~/.local/bin/sag |
并写入当前用户 PATH。装完开新终端验证:
sag --version
sag status # 服务与配置诊断
2.2 通道 B:独立 CLI(npm)
npm install -g @zleap-ai/sag
sag --version
需要全局安装:插件是在 PATH 里找 sag / sag.exe / sag.cmd,再据此推导同目录下的原生二进制;仅装成局部依赖不会出现在 PATH 里。
两种通道的差异:
| 桌面随包 CLI | npm 全局 CLI | |
|---|---|---|
| 形态 | 单个原生可执行文件 | shim(.cmd / 符号链接)→ Node 脚本 → 原生二进制 |
| 版本节奏 | 随桌面端更新 | 以 npm 上 @zleap-ai/sag 的 latest 为准 |
| 数据目录 | 与桌面端共享 | 与桌面端共享 |
两者使用同一个后台服务、同一份配置与索引数据,所以不要同时保留两份不同版本——PATH 里先命中的那个会决定实际运行的版本;后台服务只有一个,由先启动者决定其版本。
2.3 确认 CLI 能被找到
where sag # Windows
which sag # macOS / Linux
如果 sag 可用、但插件仍报找不到,通常是因为宿主进程的 PATH 与你终端里的不同(例如从 GUI 启动的 Harness 未继承最新 PATH)。重载插件或重启 Harness 即可让插件重新扫描。
3. 建立索引
在要检索的目录内执行:
cd /path/to/project
sag check . --json # 看是否已建索引
sag add . --json # 建索引(首次会拉起后台服务)
sag list --json # 列出所有已索引目录
sag remove . --json # 移除
add 可限制文件类型:
sag add . --types md,txt,js,ts,py,json,yaml --json
几点经验:
- 重型二进制文档(扫描版 PDF、超大 PPTX 等)转换耗时且有失败风险,建议在目录根放
.sagignore把它们排除:*.pdf *.docx *.pptx *.xlsx *.epub - 大树首次索引可能持续数分钟;
sag add在部分版本上会因后台服务继承输出管道而不返回,这是上游已知问题(已在较新版本修复)。用插件的sag_index_update时,超时但输出里已含index_status的会被视为“已生效”并附带说明。 - 索引完成后
sag check . --json的index_ready应为true,roots[].status为ready。
4. 安装插件
4.1 获取代码
git clone https://github.com/clear0/dsh-sag-wiki.git
cd dsh-sag-wiki
放在哪个目录都可以——安装时记录的是该目录的绝对路径。
4.2 在 Harness 里安装
通过 Harness 的插件管理器安装(plugin_manager install_bundle,target = 上面的绝对路径)。安装动作会:
- 在 profile 的
package.json写入依赖:"dsh-sag-wiki": "link:<你的路径>"(本地目录用 link,改源码无需重装); - 把
dsh-sag-wiki追加进dsh.profile.bundles; - 在 profile 的
node_modules/下建立指向源码目录的符号链接; - 通过包内
dsh.bundle.patch指向的 patch 把插件插入 boot graph 并启用:
# cordis.patch.yml
- insert:
- id: dsh-sag-wiki
name: dsh-sag-wiki
id必须与包名一致。
4.3 验证安装
- 工具列表里应出现
sag_search、sag_grep、sag_index_status、sag_index_update; - 调用
sag_index_status(不带参数),应返回当前工作目录的覆盖情况与索引状态。
4.4 改完源码如何重载
插件以 link: 方式安装,源码改动立即落到 profile 的 node_modules,但运行中的进程需要重载插件才生效。重载时要用 profile 里登记的 entry id(形如 include:dsh-sag-wiki,可用配置文件列举接口查到),只传包名通常会报 unknown-plugin:
set_plugin(entryId, enabled=false) → applied
set_plugin(entryId, enabled=true) → applied
4.5 卸载
从 profile 的 dsh.profile.bundles 移除并删除对应依赖项,或通过插件管理器的卸载动作完成;源码目录可以保留。
5. 工具参考
四个工具都返回结构化 JSON,同时渲染成紧凑的中文文本。
5.1 sag_search — 语义检索
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
query | string | 必填 | 自然语言问题,建议写完整问句 |
directory | string | 会话工作目录 | 必须是已索引目录 |
maxResults | number | 5 | 1–100 |
timeoutSeconds | number | 180 | 10–600 |
对应 CLI:sag "<query>" [dir] -m N --json -c。需要 JEV 模型;未配置时返回配置指引而非报错。
5.2 sag_grep — 精确 / 正则检索
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
pattern | string | 必填 | 已知标识符、错误串、配置键、URL |
mode | fixed | regex | fixed | 字面量或正则 |
directory | string | 会话工作目录 | 已索引目录 |
maxResults | number | 50 | 1–200 |
ignoreCase | boolean | false | 忽略大小写 |
wholeWord | boolean | false | 整词匹配 |
filesOnly | boolean | false | 只返回文件名,不返回行 |
对应 CLI:sag -F|-E [--json] [-l|-c] [-i] [-w] -m N -- <pattern> <dir>。命中项带 file:line 与正文;未命中不算错误(退出码非 0 但结果为空时按“0 条”处理)。
5.3 sag_index_status — 索引状态
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
action | check | list | check | 单目录检查 / 列出全部 |
directory | string | 会话工作目录 | action=check 时使用 |
返回:覆盖状态(included / partial / excluded / none)、是否就绪、已索引文件数、扩展名列表、每个 root 的状态,以及 JEV 是否已配置密钥。
5.4 sag_index_update — 增删索引
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
action | add | remove | 必填 | 加入或移除索引 |
directory | string | 会话工作目录 | 目标目录 |
types | string[] | 全部 | add 时限定扩展名,如 ["md","ts"] |
timeoutSeconds | number | 180 | 10–900,大树可调高 |
6. 推荐用法
- 查概念 / 不熟的实现:
sag_search,但要先确认目录已索引; - 查已知符号:直接
sag_grep(mode=fixed最快;需要“或”关系时用mode=regex); - 结果太散:把
directory收窄到子目录,或调小maxResults; - 搜不到东西:先
sag_index_status,区分“没建索引”“目录不在覆盖范围”“索引未就绪”三种情况; - 新目录:
sag_index_status→ 需要时sag_index_update(add)→ 再检索。
索引规模越大检索越慢(时间大致随切片数线性增长),把查询限制在相关子目录通常比扩大 maxResults 更有效。
7. 与 sag skill 的分工
- skill:写给模型的流程说明(先
check再检索、一次一个目录、结果先取 3–5 条),不执行任何操作; - 插件工具:真正的执行单元。
两者互相独立,可以同时存在;技能描述里提到的“先确认索引状态”对应工具 sag_index_status。
8. 故障排查
| 现象 | 原因 | 处理 |
|---|---|---|
未找到 sag 可执行文件 | PATH 里没有 sag,或宿主没继承最新 PATH | 安装 CLI / 重载插件 / 重启 Harness |
spawn ... ENOENT | CLI 被卸载或移动,插件缓存了旧路径 | 插件会自动重新扫描并重试一次;仍失败则检查 PATH |
目录未建立索引 | 目录没 sag add 过,或不在覆盖范围 | sag_index_status → sag_index_update(action=add) |
索引未就绪(status: pending / indexing) | 后台服务正在索引,或索引器异常退出 | 等待;长时间不动则检查服务状态,必要时移除后重建索引 |
JEV 未配置 | 语义检索模型无密钥 | 配置 JEV,或改用 sag_grep |
此文件夹正在索引,请完成后再修改索引设置 | 索引进行中 | 等当前任务结束再 add / remove |
| 检索很慢 | 语料规模大 | 收窄 directory,或为无关子目录加忽略规则 |
| 工具不出现 | 插件未启用 / 安装未完成 | 检查 profile 的 bundles 列表与工具列表 |
9. 自测(不依赖宿主)
两个脚本用 mock ctx 直接驱动插件代码,验证参数拼装与输出渲染:
node test/smoke.mjs [目录] [检索词] [--write]
node test/bench.mjs [目录]
- 目录默认是当前工作目录,检索词默认
MIT; smoke依次跑sag_index_status→sag_grep(含filesOnly)→sag_search→sag_index_status(list);- 只有带
--write才会执行sag_index_update(add)——它会真的改动索引,默认不跑; bench计时冷/热调用并打印总计,用于判断延迟瓶颈在 CLI 启动还是检索本身;- 未装 SAG、未建索引、JEV 未配置时,脚本给出对应提示而不是崩溃。
10. 目录结构
dsh-sag-wiki/
├── package.json # dsh.bundle.patch 指向 cordis.patch.yml
├── cordis.patch.yml # 把插件插入 boot graph
├── lib/
│ ├── index.js # 插件入口:注册 4 个工具,输出降噪(null/undefined 剔除)
│ └── sag-cli.js # CLI 定位(PATH → 原生二进制)、子进程执行、JSON 解析
├── assets/icon.svg
├── test/
│ ├── smoke.mjs
│ └── bench.mjs
└── README.md
设计取舍
- 不等管道关闭:
sag拉起后台服务后可能继承并长期持有 stdout/stderr,等待close会挂住;只 await 子进程退出事实,再从已收集缓冲里读取(按字节偏移读取,非消耗式)。 - CLI 定位缓存可自愈:定位结果缓存,但每次使用前校验文件存在;
ENOENT时重扫 PATH 并重试一次。 - 输出降噪:宿主对工具输出 schema 校验很严,
null不合法,统一在注册包装层递归剔除null/undefined。 - 路径归一:剥掉 Windows
\\?\前缀与./前缀,返回可读的绝对路径。
11. 参考
- SAG Wiki:https://github.com/Zleap-AI/SAG-Wiki
- 本仓库:https://github.com/clear0/dsh-sag-wiki
- CLI 内建帮助:
sag --help、sag <subcommand> --help
License
MIT
Related plugins
archify (deepseek-harness)
tt-a1i/archify
WeKnora (dsh-weknora)
tencent/weknora
next-ai-draw-io (dsh-plugin)
dayuanjiang/next-ai-draw-io
weknora
tencent/weknora