Back to home@hfyydd

dsh-goz

Everything-class whole-disk file lookup for DeepSeek Harness, backed by the goz engine (MFT filename index).

Stars
0
Language
JavaScript
Created
Aug 18, 2026
Updated
Aug 18, 2026
GitHub repo

Introduction

dsh-goz

Everything 级全盘文件定位插件:让 DeepSeek Harness 的 agent 毫秒级回答「某个文件在哪里」。

dsh-goz 是一个 Cordis 插件,注册 search_file / goz_status 两个面向模型(model-facing)的工具,底层由 goz 引擎支撑。goz 直接读取 NTFS 的 MFT(主文件表) 建立内存文件名索引,完全绕过目录树遍历——检索的是文件名 / 大小 / 时间索引,不含文件内容。

goz 是 Everything 的开源替代品。本机实测:315 万文件(C/D/E 三卷)全盘查询单字符 毫秒级 返回;daemon 空闲工作集约 220-290 MB(进程 private ~520-580 MB,索引结构约 300 MB),索引常驻内存。

设计动机:为什么需要 goz

官方 glob / greptool-fs-search)基于 ripgrep 遍历目录树,是沙箱内、项目内检索的正确答案。但「这个文件在哪」的跨工作区问题——例如「我昨晚下载的 PDF 在哪」「D 盘所有 .env 文件」——需要全盘遍历,代价随磁盘规模线性增长:

任务goz常规手段差距
全盘按文件名找 goz.exe619 msPowerShell Get-ChildItem -Recurse 331,437 ms~536x
全盘通配 *.docx756 ms(total 3451)find 限深 6 耗时 66,383 ms,只找到 355 个~88x,且漏检约 90%
子树(9,585 文件)*.md658 ms(total 3873)find 完整遍历 4,053 ms~6x

结论:差距最大的是全盘 / 跨盘符、模糊文件名的定位——没有 goz 时这类任务基本做不成(遍历磁盘需要数分钟且易超时);差距最小的是已知路径的小目录内搜索(此时 goz 只是锦上添花,官方 glob 更合适)。基准细节见性能

架构

┌─────────────┐   spawn (ctx.subprocess seam)   ┌─────────────┐   命名管道    ┌─────────────┐
│ dsh agent   │ ──▶  search_file / goz_status  ──▶ │  goz.exe    │ ──▶ \\.\pipe\goz-v1 ──▶ │  gozd.exe   │
│ (模型)      │ ◀──  结构化 JSON 值              ◀── │  (CLI 客户端)│ ◀──  查询结果   ◀── │  (系统服务)  │
└─────────────┘                                  └─────────────┘               └──────┬──────┘
                                                                                      │ 读 MFT
                                                                              ┌───────▼───────┐
                                                                              │ NTFS 卷 (C/D/E) │
                                                                              └───────────────┘
  • gozd.exe(daemon):管理员权限启动的系统服务,读取 NTFS MFT 建立内存索引,通过 \\.\pipe\goz-v1 命名管道服务查询。索引常驻,因此每次查询都是毫秒级。
  • goz.exe(CLI 客户端):每次工具调用由插件 spawn 一次,通过命名管道向 daemon 发查询,以 --json 输出结构化结果后立即退出。客户端本身是无权限用户态进程。
  • 插件(本包):负责工具 schema、参数校验、argv 构造、JSON 解析、结果规范化、超时声明和 tools/pre-execute 审批门。从不暴露后台任务——只有在 goz.exe 退出、被协作式超时终止、被中止或失败后,工具调用才返回。

为什么 daemon 需要管理员权限(唯一的人工步骤)

读 MFT 需要管理员权限,而 dsh 是用户态进程弹不了 UAC,所以 daemon 的安装是插件使用前唯一需要人工执行的一步(在管理员终端运行 gozd install)。安装后 daemon 作为 Windows 系统服务常驻,agent 的每一次 search_file 都是毫秒级响应。

安装

1. 安装插件

dsh plugin add dsh-goz
# 或本地目录
dsh plugin add ./dsh-goz

插件包内自带 goz.exe + gozd.exe 二进制(Windows x86_64,位于 vendor/),无需单独下载或编译。daemon 版本可用 .\vendor\gozd.exe --version 验证(当前为 gozd 0.1.1);goz.exe 是无状态 CLI 客户端,刻意不提供 --version 开关(会报 unknown switch),其行为版本跟随同目录的 gozd.exe

2. 一次性安装 daemon(唯一的人工步骤)

# 开始菜单搜「PowerShell」或「终端」,右键 → 以管理员身份运行
# gozd.exe 不在系统 PATH 里,先进入插件的 vendor 目录(路径按实际安装位置调整)
cd C:\Users\Administrator\Desktop\dsh\dsh-goz\vendor
.\gozd.exe install

关于工作目录gozd install 内部用自身可执行文件的绝对路径注册服务(安装后服务 PathName 为 ...\vendor\gozd.exe run --service),与你在哪个目录执行无关,所以不需要特意 cd 到某个"工作目录"。上面的 cd 只是为了让系统能找到 gozd.exe 这个命令——它不在 PATH 里,直接敲 gozd install 会报「无法将 gozd 识别为 cmdlet」。你也可以不 cd,直接写完整路径:& "C:\...\dsh-goz\vendor\gozd.exe" install

也可以手动前台运行:.\gozd.exe run(调试用,关窗即停)。查看安装后的状态:.\goz.exe --status

3. 验证

先核对二进制版本(输出应为 gozd 0.1.1):

.\vendor\gozd.exe --version

然后在 dsh 对话里问 agent「找一下 goz.exe 在哪」,或直接跑测试:

node tests/e2e.mjs           # 主集成测试:真实启动 web profile,13 项断言(需 daemon 在线)
node tests/verify-syntax.mjs # README 查询语法表逐条核对(CLI 级)
node tests/verify-readme.mjs # README 插件层声明核对(web profile + overlay)
node tests/smoke.mjs         # CLI 冒烟测试:直接 spawn vendor/goz.exe 验证查询链路

工具

工具参数行为
search_filequery(必填)、scope?max?全盘/限定目录按文件名毫秒级定位,返回结构化匹配
goz_status检查 daemon 是否在线、索引健康状态;离线时返回安装指引

search_file(query, scope?, max?)

参数类型说明
querystring,必填goz 查询语法(见查询语法),非空
scopestring,可选限定搜索目录(映射 -path)。缺省为全盘。超出白名单的 scope 会触发用户审批
maxnumber,可选结果上限(映射 -n),默认取配置 defaultMax(50)

返回规范 JSON 值(SearchValue):

{
  "query": "goz",              // 回显原始查询
  "scope": null,               // 本次搜索根,null 表示全盘
  "total": 2,                  // 完整匹配数(诚实位)
  "returned": 2,               // 实际返回条数(≤ max)
  "more": false,               // 是否还有更多(诚实位;注意 goz 在 -n 截断时仍为 false,截断判断用 returned < total)
  "volumes_incomplete": false, // 结果可能不完整(诚实位)
  "results": [
    {
      "path": "C:\\dsh\\dsh-goz\\vendor\\goz.exe",
      "is_dir": false,
      "size": 4617216,
      "mtime_iso": "2026-08-17T03:12:44.000Z"
    }
  ]
}

模型看到的是渲染后的文本(output.render),例如:

搜索 "goz" 于 全盘:共 2 个匹配,返回 2 条。
[1.2 MB] C:\dsh\dsh-goz\vendor\goz.exe  修改于 2026-08-17T03:12:44.000Z
[目录] C:\dsh\dsh-goz\vendor  修改于 2026-08-17T03:14:02.000Z

诚实位设计total / more / volumes_incomplete 三个字段原样透传 goz 的 QueryResults 帧,模型永远知道自己看到的结果是否完整——volumes_incomplete 为真时渲染会加 前缀提示;结果被 max 截断(returned < total)时提示可缩小查询或增大 max。注意 goz 的 more 字段在 -n 截断时仍为 false,截断判断以 returned < total 为准。

goz_status()

返回 { running: boolean, detail: string }。在线时 detailgozd status 输出(卷数、每卷条目数、phase、drift、内存占用);离线时返回完整安装指引。建议模型在首次 search_file 前先确认引擎在线。

查询语法

goz 的查询语法与 Everything 兼容(es-compatible),作用于文件名(不含路径内容,但含路径的 token 按路径子串匹配):

语法含义示例
report文件名子串(大小写不敏感)report 匹配 QuarterlyReport.xlsx
*.pdf通配符(* / ?*.pdf
ext:pdf;docx扩展名过滤(多值用分号;逗号在当前二进制中无效)ext:docx
folder: / file:仅目录 / 仅文件folder: node_modules
size:>1mb大小过滤(< > <= >= =size:>1gb
path:projects\src路径子串匹配path:C:\dsh
"some dir"引号内整体匹配(含空格)"visual studio"
case:大小写敏感开关(当前 v0.1.1 二进制不生效case:goz.exe
多个词空格分隔 = ANDannual report

注意:排除运算符(!term)在当前 vendor 的 goz 二进制中尚未实现——使用会得到 exit 4 与「operator '!' is not supported yet」错误。需要排除语义时,用多个正向过滤组合(如 ext:pdf path:reports)或增大 max 后在结果中自行筛选。

注意(实测于 v0.1.1)ext: 多扩展名必须用分号分隔(ext:md;png 有效),逗号无效ext:md,png 返回 0——逗号被当作扩展名的一部分)。case: 大小写开关不生效:任何 case: 前缀查询都会被当作字面子串解析而返回 0;普通查询本身大小写不敏感,需要精确大小写匹配时目前只能靠增大 max 后在结果中筛选。

与 ripgrep 语法的区别:goz 查询是Everything 式搜索语言(子串 + 通配符 + 冒号过滤器),不是正则。项目内内容搜索仍用官方 grep

配置

插件通过 Cordis patch 文件配置,所有字段可选:

- id: goz
  name: dsh-goz
  config:
    defaultMax: 50            # 默认结果上限(模型未传 max 时)
    timeoutMs: 15000          # 工具调用协作式超时(毫秒)
    binDir: ""                # goz.exe 所在目录;留空用插件内 vendor/
    allowedRoots:             # 白名单目录;超出需用户审批(见安全模型)
      - "C:\\Users\\me\\Documents"
      - "D:\\projects"
配置键默认值含义
defaultMax50模型省略 max 时的结果上限;z.number().step(1).min(1)
timeoutMs15000附加到工具定义的协作式工具调用预算;min(1000)。subprocess seam 在预算之外另有 2s 终止升级宽限
binDir插件 vendor/自定义 goz.exe / gozd.exe 所在目录(绝对路径);留空用打包二进制
allowedRoots空(无审批)白名单目录数组;相对路径按会话工作目录解析

启停

插件列表页是只读投影,启停的唯一事实源是 profile 的 cordis.patch.yml,用同 id 条目覆盖:

- id: goz
  disabled: true   # 停用;去掉该行或改为 false 重新启用

loader 支持热重载,改完保存即生效,无需重启 dsh。

安全模型

goz 的信任模型与 Everything 一致:任何认证的本地用户可查询文件名/大小/时间索引(不含内容),已在 goz 上游 README 中文档化。索引本身永不触碰文件内容——内容搜索请用 grep

dsh-goz 在此之上提供两层防护:

  1. daemon 身份校验(强制)goz.exe 连接命名管道时验证服务器 owner 为 SYSTEM/Administrators,拒绝 pipe squatter(冒充 daemon 的进程,exit code 9)。客户端绝不向不受信任的管道发送查询。
  2. 白名单审批(可选):配置 allowedRoots 后,任何超出白名单的 scope 都会让插件在 tools/pre-execute 钩子里返回 ask 决策——dsh 向用户弹出审批面板,用户可拒绝。全盘可见性由此变成每次可审计、可拒绝的交互,而不是默认放开。

错误处理

goz.exe 的退出码被规范化为模型可见的错误消息:

退出码含义模型看到的消息
8daemon 未运行(\\.\pipe\goz-v1 无服务器)完整安装指引(管理员终端 gozd install
9管道上有服务器但不是受信任的提权 daemon(owner 非 SYSTEM/Administrators)拒绝说明:已拒绝发送查询
其他非零goz 启动失败 / 查询失败exit code N + stderr 尾部摘录(上限 16KB)

参数错误(空 query、非法 max 等)是普通工具参数错误:execute 入口的 parseSearchInputTypeError,不进入 goz 调用,也不映射任何退出码。

goz_status 对任何 goz 失败都不抛错,统一返回 { running: false, detail: 说明 } 让模型优雅降级:daemon 离线(exit 8)时 detail 为完整安装指引;管道不可信(exit 9)或其他非零退出时 detail 为拒绝说明/错误信息(与上表 search_file 抛出的消息文本一致)。

模型体验

系统提示词

插件在 ctx.systemPrompt 注册一个 tool:search_file 段(order 110),内容大致为:

search_file 是系统级全盘文件定位工具(Everything 级,毫秒响应),用于回答"某个文件在哪里"的跨工作区问题——例如"我昨晚下载的 pdf"、"D 盘所有 .env 文件"。它检索的是文件名/大小/时间索引,不含文件内容;内容搜索请用 grep 类工具。query 支持文件名子串、通配符(*.pdf)、ext:pdf、folder: 等语法;scope 限定目录(超出白名单会请求用户批准)。

工具 schema

  • search_file 描述强调:整台 Windows 机器按文件名毫秒级定位、索引不含内容、适合跨工作区模糊检索、项目内优先用 glob;返回含 total / more / volumes_incomplete 诚实位。
  • goz_status 描述建议模型在 search_file 前先确认引擎在线。

结果与错误

  • 结果:见search_file 返回的渲染示例。实际返回条数小于完整匹配数(returned < total,即结果被 max 截断)时,渲染附「还有更多结果」提示。
  • 错误:daemon 离线的 exit 8 错误会附带可执行的安装指引,模型可据此告知用户完成一次性安装。

Token / KV Cache 影响

提示词段和工具 schema 是注册期固定的:插件作用域、配置与文本不变时前缀稳定;激活/停用插件会使该段复用失效。结果与错误仅追加在可复用请求前缀之后,不使既有 KV Cache 条目失效。

性能

本机实测环境:Windows 11,NTFS 三卷(C: 1,914,045 + D: 1,202,415 + E: 38,137 ≈ 315 万条目),daemon 索引常驻内存。每次查询是「spawn goz.exe + 管道往返 + JSON 解析」,不含冷启动(索引已在内存)。

复查(2026-08-17):同一环境下全盘查询复测均值为 90-110 ms(此前另一次复测为 423-478 ms),均优于下表记录值——性能随系统负载与 daemon 状态波动,但量级一致(毫秒级),「与磁盘规模无关」的结论不变。

任务goz常规手段差距
全盘按文件名找 goz.exe619 msPowerShell Get-ChildItem -Recurse 331,437 ms(约 5.5 分钟)~536x
全盘通配 *.docx756 ms(total 3451,结果完整)find 限深 6:66,383 ms,只找到 355 个~88x,且漏检约 90%
子树(9,585 文件)*.md658 ms(total 3873)find 完整遍历 4,053 ms~6x
全盘 *.tsx682 ms(total 524)常规手段基本不可行

要点:

  • 全盘/跨盘符、模糊文件名定位是 goz 的质变场景(536x 且完整)。没有它,这类任务要么超时失败、要么深度受限漏检。
  • 已知路径的小目录内搜索差距缩小到个位数倍——这种场景官方 glob 足够,无需动用 goz。
  • goz 的时间开销几乎与磁盘规模无关(索引在内存);常规遍历的时间与文件数线性相关。

已知限制

  • 仅 Windowsos 字段限制为 win32;NTFS MFT 读取、命名管道服务、gozd 服务模型均为 Windows 专属。
  • 索引不含内容:只能按文件名/大小/时间检索。内容搜索用 grep,这是设计边界而非缺陷。
  • 结果可能不完整:卷仍处于索引(phase 未 live)或不可用时,volumes_incomplete 为真,goz 会诚实上报而不是假装完整。
  • 无 shell 层:查询词是普通 argv 元素,不存在 shell 引号问题,但也没有 shell 管道/组合能力;复杂过滤请多次调用或在应用侧组合。
  • 权限模型放行同名文件:goz 索引的是文件名而非 ACL;检索结果可能包含用户无权读取的路径(读取时才由文件系统拒绝)。
  • 没有 UI 卡片定制:工具沿用通用卡片渲染(presentCall/presentResult 未定制),模型可见文本由 output.render 提供。
  • 搜索与文件访问没有共享工作区证明:返回的绝对路径能否继续 read,取决于后续工具对该路径的权限,本插件不做运行时校验。

与官方搜索工具的分工

工具场景底层
glob / grep(官方 tool-fs-search沙箱内项目检索,高频ripgrep(遍历目录树)
search_file(本插件)全盘/跨工作区定位,低频,显式授权goz(MFT 内存索引,毫秒级)

开发

npm install          # 安装依赖(peer 由 dsh 宿主提供)
npm run build        # tsc 编译到 lib/
npm test             # 主集成测试 tests/e2e.mjs(需 daemon 在线)
node tests/smoke.mjs # CLI 冒烟测试(需 vendor/goz.exe 且 daemon 在线)

本地调试用 overlay(不修改 profile):

dsh --patch ./cordis.patch.yml

测试覆盖:

  • tests/smoke.mjs(CLI 冒烟):--json 输出可解析且字段与 GozQueryResults 一致、-path scope 子树查询、daemon 离线时 exit 8、-n 上限生效。
  • tests/e2e.mjs(主集成):真实启动 web profile,覆盖 loader 树、工具注册、goz_status / search_file 执行、scope 子树、渲染提示(含 returned < total 的「还有更多结果」)、参数校验、max 钳制。
  • tests/verify-syntax.mjs / tests/verify-readme.mjs(README 对照):前者逐条实测查询语法表,后者核对插件层声明(schema / timeoutMs / defaultMax / 白名单 / 参数校验矩阵),用于确认 README 与实际行为一致。

调试本机非提权 daemon 时可设 GOZ_INSECURE=1 附加 --insecure-no-server-check 验证数据链路(生产提权 daemon 不需要)。

故障排查

症状原因处理
search_file 报「goz 引擎未运行」daemon 未安装或未启动(exit 8)管理员终端执行 gozd install(或 gozd run 前台调试),再重试
search_file 报「管道服务器不受信任」(exit 9)有进程冒用 \\.\pipe\goz-v1,或 daemon 以非提权方式运行确认 gozd 以管理员身份运行;排查是否有其他进程占用同名管道
插件列表看不到 goz浏览器页面缓存 / 搜索框过滤刷新页面;清空搜索框或搜索「goz」
结果提示「结果可能不完整」某卷仍在索引或不可用等待索引完成;goz --status 查看各卷 phase
改动 patch 不生效loader 未热重载保存后确认无 YAML 语法错误;必要时重启 dsh

发布与发现

把本插件发布到 GitHub 时,建议给仓库添加 dsh-plugin 话题(Topics),便于被归类进 dsh 插件聚合页、被其他用户搜索发现。添加方式:仓库页 → Settings → Topics → 输入 dsh-plugin 保存。

注:dsh-plugin 仅是 GitHub 仓库的发现话题(topic),不是插件内部的标签字段,也不影响 harness 加载——harness 靠 cordis.patch.ymlid/name 识别插件。Gitee 等平台有各自独立的话题机制,与 GitHub 不互通。

License

MIT。goz 二进制来自 mustafaahci/goz(MIT)。