dsh-at-file-everything 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 leaf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,214 @@
1
- # Temporary Holding Version
1
+ # dsh-at-file-everything
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Instant `@file` completion for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) on Windows, answered from the [Everything](https://www.voidtools.com/) search index through `es.exe`.
4
+
5
+ > 中文说明见 [README.zh.md](README.zh.md)。
6
+
7
+ ## Why
8
+
9
+ The shipped `@deepseek-ai/dsh-file-reference-local` provider answers `@` from a workspace walk it performs itself, bounded by `maxEntries`. In a large tree that walk is both slow and lossy. On the Unity project this plugin was written for:
10
+
11
+ | | upstream walk | this plugin |
12
+ |---|---|---|
13
+ | what it searches | every file under the workspace root | Everything's index, scoped with `-path` |
14
+ | entry budget | `maxEntries` (50 000 by default) | none |
15
+ | first `@` of a session | full traversal | ~80 ms |
16
+ | warm query | re-ranks a bounded index | ~70–80 ms |
17
+ | coverage | ~469 k of ~1.5 M files, after tuning | the whole scope |
18
+ | heap | ~99 MB for the index | none held by the provider |
19
+
20
+ A concrete failure the upstream budget caused: ~1.2 M files under `Library/` and ~270 k under `Output/` exhausted the index before any `Assets/` source was reached, so `@PlayablePrefab` answered `Library/*` noise while the real file was missing. Everything already maintains that index machine-wide as a Windows service, so this provider answers from it and walks nothing.
21
+
22
+ ## Install
23
+
24
+ ```powershell
25
+ # once per machine (see "Why es.exe is not bundled" below)
26
+ winget install voidtools.Everything
27
+ winget install voidtools.Everything.Cli
28
+
29
+ # once per profile
30
+ dsh plugin --profile <profile> add dsh-at-file-everything
31
+ ```
32
+
33
+ The bundled `cordis.patch.yml` then:
34
+
35
+ 1. inserts the `file-reference-everything` row (this plugin), and
36
+ 2. disables `file-reference-local`, so exactly one owner provides `ctx.fileReferences`.
37
+
38
+ Restart the Harness profile afterwards. Nothing else in the composition changes: the Session Controller's `fileReferences/list` Remote and the Web composer keep resolving the same service.
39
+
40
+ The published tarball ships the built `lib/`, so there is nothing to compile first.
41
+
42
+ ### From a local checkout
43
+
44
+ While developing, install this repository directly instead:
45
+
46
+ ```powershell
47
+ dsh plugin --profile <profile> add link:<path to this repository>
48
+ ```
49
+
50
+ > **Updating a `link:` install.** Under this profile's pnpm settings a `link:` dependency is materialised as a *copy*, not a symlink, so rebuilding `lib/` is not enough — the installed copy keeps serving the old bundle until you re-run `dsh plugin --profile <profile> add link:<path>` (or delete `<profile>/node_modules/dsh-at-file-everything` and re-add it). This bites during development: the plugin can look like it ignored a change.
51
+
52
+ ## Requirements
53
+
54
+ - **Windows.** The plugin declares `os: win32`; on other platforms Everything does not exist and the plugin has nothing to answer from.
55
+ - **Everything 1.4+ running and indexing.** The plugin queries it; it does not bundle or start it.
56
+ - **`es.exe` v1.1.0+ on `PATH`**, or `esCommand` pointing at it.
57
+
58
+ Check the environment before blaming the plugin:
59
+
60
+ ```powershell
61
+ es -get-everything-version # the Everything service answering
62
+ es -version # the command-line client
63
+ ```
64
+
65
+ ### Why `es.exe` is not bundled
66
+
67
+ Bundling it does not make the plugin install-and-go, because `es.exe` is only the *client* half of Everything. It talks to the Everything service over its IPC window, and without that service it answers:
68
+
69
+ ```
70
+ Error 8: Everything IPC window not found. Please make sure Everything is running.
71
+ ```
72
+
73
+ So even with a copy vendored into this package, the user still has to install Everything, keep it running, and let it index the drives they care about — the part that actually makes `@file` work. A bundled client also silently drifts from the user's service, because Everything's IPC and index format are upgraded together with the service while a pinned client is frozen at release time.
74
+
75
+ The honest install story is therefore two commands, in this order:
76
+
77
+ ```powershell
78
+ winget install voidtools.Everything # the service and its index
79
+ winget install voidtools.Everything.Cli # es.exe on PATH
80
+ ```
81
+
82
+ If a deployment wants to vendor `es.exe` anyway — an offline image, a locked-down machine — point `esCommand` at the copy you shipped. An explicit `esCommand` always wins over `PATH`, and nothing else needs to change:
83
+
84
+ ```yaml
85
+ esCommand: 'C:\Program Files\MyImage\tools\es.exe'
86
+ ```
87
+
88
+ `es.exe` itself is MIT-licensed (its `cli.c` carries the permission notice), so vendoring is permitted; it is simply not *sufficient*, which is why this package does not pretend otherwise.
89
+
90
+ ## Configuration
91
+
92
+ ```yaml
93
+ - id: file-reference-everything
94
+ name: dsh-at-file-everything
95
+ config:
96
+ esCommand: es.exe
97
+ maxResults: 20
98
+ maxCandidates: 300
99
+ timeoutMs: 3000
100
+ fuzzyFallback: true
101
+ excludedDirectories: [.git, node_modules, Library, Temp, Output]
102
+ extraPathDirectories: []
103
+ installPrompt: true
104
+ ```
105
+
106
+ | Field | Default | Meaning |
107
+ |---|---|---|
108
+ | `esCommand` | `es.exe` | Executable name or absolute path. A bare name resolves through `PATH`. |
109
+ | `maxResults` | `20` | Ranked candidates returned for one query. |
110
+ | `maxCandidates` | `300` | Rows requested from Everything before ranking. Raising this costs roughly linearly (measured ≈ +0.3 ms/row on a 470 k-entry tree). |
111
+ | `timeoutMs` | `3000` | Per-`es.exe` deadline. A timeout degrades to an empty completion list, never to an error in the composer. |
112
+ | `fuzzyFallback` | `true` | When a contiguous search matches nothing, retry as a subsequence (`pbin` → `PlayButton`). |
113
+ | `excludedDirectories` | build/VCS defaults | Directory **basenames** filtered out of results. Case-insensitive. A *file* named `build` is not excluded. |
114
+ | `extraPathDirectories` | `[]` | Prepended to the child `PATH`, for a portable Everything install. |
115
+ | `installPrompt` | `true` | Contribute the seam's `@path` guidance while the agent can call `read`. |
116
+
117
+ For a Unity project, add the generated trees:
118
+
119
+ ```yaml
120
+ excludedDirectories:
121
+ - .git
122
+ - node_modules
123
+ - Library
124
+ - Temp
125
+ - obj
126
+ - Logs
127
+ - UserSettings
128
+ - Output
129
+ - Publish
130
+ - .vs
131
+ ```
132
+
133
+ Keep `Export/` searchable if its build trees matter to you.
134
+
135
+ ## Behaviour
136
+
137
+ `@` opens completion; typing filters; picking inserts an ordinary `@path` mention. A directory candidate keeps the quote open with a trailing slash so completion can descend another level. Selecting a file never reads its contents — the model still has to call `read`.
138
+
139
+ - **Bare query** (`@Archive`) searches the whole working directory.
140
+ - **Directory query** (`@Assets/Scripts/`) lists that one directory, one cheap lookup per level.
141
+ - **Exclusion** is a filter over returned rows, so excluded trees cost nothing at query time.
142
+ - **Hidden entries** stay out of results until the query itself starts with `.`.
143
+ - **Scoped to the working directory.** A bare query carries `-path <cwd>` and every result is re-checked against the root before it is rendered, so nothing outside the workspace can appear. Directory descent is guarded too: `@../sibling/` or `@D:\elsewhere\` resolves outside the root and answers nothing rather than listing another tree. This matters on machines that hold several copies of the same project — one workspace can never surface or select a file from another.
144
+
145
+ Ranking reproduces the upstream tiers exactly, so switching providers does not change which file a keystroke sequence selects: exact basename > prefix > substring > directory-segment > subsequence, directories before files at equal scores, then shorter paths, then code-unit order.
146
+
147
+ ## How it works
148
+
149
+ Three properties of `es.exe`, each established by probing the real client, shape the implementation:
150
+
151
+ 1. **Every argv element is an independent AND-ed term.** A single argument containing spaces (`"package json"`) matches nothing, while `package` and `json` match `package.json`. Terms are never space-joined, and a literal space inside a pattern becomes `?`.
152
+ 2. **Everything indexes file names by default; `-p` widens a term to the full path.** Filename matching is also the fast path: the wildcard form answers in ~70–150 ms on a 470 k-entry workspace, whereas a `regex:` term over the full path costs 0.6–44 s because it scans the whole index. Queries therefore stay filename-scoped, and `-path` supplies the scoping.
153
+ 3. **Standard output is not UTF-8.** `es.exe` writes results in the process ANSI/OEM code page, so CJK and kana names arrive as mojibake on a zh-CN host. The only code-page-independent channel is `-export-csv <file>` with `-utf8-bom`, which writes real UTF-8 to a file the plugin owns. It costs about as much as stdout (~110 ms vs ~100 ms), so every query takes it.
154
+
155
+ Directory-versus-file comes from the exported `Attributes` column (`D` = directory), avoiding a second filesystem round trip.
156
+
157
+ ## Verify
158
+
159
+ ```powershell
160
+ npm run typecheck # strict TS over src/
161
+ npm run test # unit + live es.exe integration
162
+ ```
163
+
164
+ The unit suite runs anywhere. The live suite creates a fixture under `%TEMP%`, waits for Everything to index it, and checks directory classification, root scoping, UTF-8 decoding of CJK names, spaced names, the subsequence tier, empty results, and cancellation. It skips itself when `es.exe` is absent.
165
+
166
+ `test/` is deliberately independent of the Harness installation; the pure helpers live in `src/pure.ts` and build to `lib/pure.js` for that reason.
167
+
168
+ ## Package layout
169
+
170
+ ```
171
+ src/index.ts plugin, service class, config schema
172
+ src/es-client.ts es.exe adapter: spawn, export, decode, timeouts
173
+ src/candidates.ts pure ranking and path normalisation
174
+ src/pure.ts Harness-free entry for tests and reuse
175
+ cordis.patch.yml bundle layer: insert this row, disable file-reference-local
176
+ assets/ storefront icon and its licence record
177
+ scripts/make-icon.py renders assets/icon-{180,256,512}.png from icon-256.png
178
+ ```
179
+
180
+ `@deepseek-ai/*` imports stay external in the bundle: the host resolves those from the installation, and inlining them would give this plugin a second Cordis `Service` class identity.
181
+
182
+ ## Icon
183
+
184
+ `assets/icon-{180,256,512}.png` is voidtools' Everything magnifying-glass icon.
185
+ Everything — icon included — is MIT-licensed (Copyright (c) 2022 voidtools), so
186
+ reuse is permitted as long as the notice travels with the asset; it does, in
187
+ [assets/ICON-LICENSE.txt](assets/ICON-LICENSE.txt). Re-render the sizes with:
188
+
189
+ ```powershell
190
+ python scripts/make-icon.py
191
+ ```
192
+
193
+ Storefronts (the awesome-dsh-plugin list, dsh-market) pick it up from the
194
+ catalog entry:
195
+
196
+ ```yaml
197
+ icon: https://raw.githubusercontent.com/backkom/dsh-at-file-everything/master/assets/icon-180.png
198
+ ```
199
+
200
+ That list only accepts icons hosted on GitHub as `png`/`jpg`/`jpeg`/`webp`, and
201
+ draws the tile at ~96px, so a square raster is the shape that works. The default
202
+ branch here is `master`; if it is ever renamed, that URL has to change with it.
203
+
204
+ ## Limitations
205
+
206
+ - **Windows only**, and only as good as the Everything index. Files excluded from indexing are invisible here too.
207
+ - **Everything must be running.** If the service is down the plugin logs a warning and completion answers nothing; `@` does not fall back to a filesystem walk.
208
+ - **Filename-scoped search.** Typing a directory path with `/` lists that directory, but a bare query will not match deep path fragments that no file name contains — the upstream substring path match was traded for the ~30× latency of the index path.
209
+ - **One `es.exe` process per keystroke.** Each query is a fresh process (~70–80 ms warm). Cancellation kills it.
210
+ - **First query after Everything's index is cold** can take ~1 s as the service pages the index in.
211
+
212
+ ## Licence
213
+
214
+ MIT. See [LICENSE](LICENSE).
package/README.zh.md ADDED
@@ -0,0 +1,205 @@
1
+ # dsh-at-file-everything
2
+
3
+ 为 Windows 上的 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供秒级的 `@文件` 补全,数据来自 [Everything](https://www.voidtools.com/) 的索引,经 `es.exe` 查询。
4
+
5
+ > English documentation: [README.md](README.md)。
6
+
7
+ ## 为什么需要它
8
+
9
+ Harness 自带的 `@deepseek-ai/dsh-file-reference-local` 会自己遍历工作区,并按 `maxEntries` 截断。在大仓库里这种遍历既慢又有损。以本插件所针对的 Unity 工程为例:
10
+
11
+ | | 上游遍历方案 | 本插件 |
12
+ |---|---|---|
13
+ | 检索对象 | 工作区根目录下的每个文件 | Everything 索引,用 `-path` 限定范围 |
14
+ | 条目上限 | `maxEntries`(默认 50 000) | 无 |
15
+ | 会话里第一次 `@` | 完整遍历 | ~80 ms |
16
+ | 后续查询 | 在有限索引里重排 | ~70–80 ms |
17
+ | 覆盖范围 | 调优后约 46.9 万 / 约 150 万 | 整个限定范围 |
18
+ | 占用堆内存 | 索引约 99 MB | 插件不持有 |
19
+
20
+ 上游上限造成的真实故障:`Library/` 下约 120 万文件、`Output/` 下约 27 万文件,在校验触达 `Assets/` 源码之前就把索引额度耗尽,于是 `@PlayablePrefab` 只返回 `Library/*` 的噪声,真正的文件反而搜不到。Everything 本身就以 Windows 服务的形式维护着全机索引,因此本插件直接查它,不做任何遍历。
21
+
22
+ ## 安装
23
+
24
+ ```powershell
25
+ # 每台机器装一次(原因见下方「为什么不内置 es.exe」)
26
+ winget install voidtools.Everything
27
+ winget install voidtools.Everything.Cli
28
+
29
+ # 每个 profile 装一次
30
+ dsh plugin --profile <profile> add dsh-at-file-everything
31
+ ```
32
+
33
+ 随包提供的 `cordis.patch.yml` 会:
34
+
35
+ 1. 插入 `file-reference-everything` 行(即本插件);
36
+ 2. 禁用 `file-reference-local`,保证 `ctx.fileReferences` 只有一个提供者。
37
+
38
+ 之后重启该 Harness profile。组合中的其他部分无需改动:Session Controller 的 `fileReferences/list` Remote 与 Web 输入框仍然解析同一个服务。
39
+
40
+ 发布包自带已构建的 `lib/`,不需要你本地先编译。
41
+
42
+ ### 从本地代码库安装
43
+
44
+ 开发阶段可以直接指向本仓库:
45
+
46
+ ```powershell
47
+ dsh plugin --profile <profile> add link:<本仓库路径>
48
+ ```
49
+
50
+ > **更新 `link:` 安装时注意。** 在本 profile 的 pnpm 设置下,`link:` 依赖是被**复制**进去的,不是符号链接。因此只重新构建 `lib/` 不够——已安装的那份会继续跑旧代码,必须重新执行 `dsh plugin --profile <profile> add link:<本仓库路径>`(或先删掉 `<profile>/node_modules/dsh-at-file-everything` 再装)。开发时很容易被这一点误导,以为改动没生效。
51
+
52
+ ## 前置条件
53
+
54
+ - **Windows。** 插件声明 `os: win32`;其他平台上没有 Everything,也就没有答案来源。
55
+ - **Everything 1.4+ 正在运行并已建立索引。** 插件只查询它,不捆绑、不启动它。
56
+ - **`es.exe` v1.1.0+ 在 `PATH` 上**,或用 `esCommand` 指定路径。
57
+
58
+ 排查前先确认环境:
59
+
60
+ ```powershell
61
+ es -get-everything-version # Everything 服务是否在应答
62
+ es -version # 命令行客户端是否可用
63
+ ```
64
+
65
+ ### 为什么不内置 es.exe
66
+
67
+ 内置它并不能做到「装完即用」,因为 `es.exe` 只是 Everything 的**客户端**。​它要通过 IPC 窗口和服务通信,服务不在时它会直接报:
68
+
69
+ ```
70
+ Error 8: Everything IPC window not found. Please make sure Everything is running.
71
+ ```
72
+
73
+ 也就是说,即使把一份 `es.exe` 打进包里,用户仍然必须安装 Everything、让它常驻、并让它索引目标磁盘——而这几件事才是让 `@file` 真正可用的部分。​另外,随包固定的客户端会和服务**悄悄脱节**:Everything 的 IPC 与索引格式随服务一起升级,而插件里那份是冻结在发布时的。​
74
+
75
+ 所以诚实的安装步骤就是上面两条命令,顺序不能反。​如果确实需要自行分发(离线镜像、受限机器),把 `esCommand` 指向你随包放的那份即可——显式 `esCommand` 永远优先于 `PATH`,其他都不用改:
76
+
77
+ ```yaml
78
+ esCommand: 'C:\Program Files\MyImage\tools\es.exe'
79
+ ```
80
+
81
+ `es.exe` 本身是 MIT 许可(安装目录里的 `cli.c` 带有许可声明),所以自行分发是被允许的;它只是**不够**——这也是本包不假装相反的原因。​
82
+
83
+ ## 配置
84
+
85
+ ```yaml
86
+ - id: file-reference-everything
87
+ name: dsh-at-file-everything
88
+ config:
89
+ esCommand: es.exe
90
+ maxResults: 20
91
+ maxCandidates: 300
92
+ timeoutMs: 3000
93
+ fuzzyFallback: true
94
+ excludedDirectories: [.git, node_modules, Library, Temp, Output]
95
+ extraPathDirectories: []
96
+ installPrompt: true
97
+ ```
98
+
99
+ | 字段 | 默认值 | 含义 |
100
+ |---|---|---|
101
+ | `esCommand` | `es.exe` | 可执行文件名或绝对路径;写文件名时按 `PATH` 查找。 |
102
+ | `maxResults` | `20` | 单次查询返回的候选数量。 |
103
+ | `maxCandidates` | `300` | 排序前向 Everything 请求的行数。调高基本线性增加耗时(在 47 万条目上实测约 +0.3 ms/行)。 |
104
+ | `timeoutMs` | `3000` | 单次 `es.exe` 超时。超时只会让补全结果为空,不会在输入框里报错。 |
105
+ | `fuzzyFallback` | `true` | 连续子串匹配不到时,改用子序列重试(`pbin` → `PlayButton`)。 |
106
+ | `excludedDirectories` | 构建/版本控制目录 | 按目录**名**过滤结果,大小写不敏感。名为 `build` 的**文件**不受影响。 |
107
+ | `extraPathDirectories` | `[]` | 追加到子进程 `PATH` 前面,用于便携版 Everything。 |
108
+ | `installPrompt` | `true` | Agent 能调用 `read` 时,注入 seam 约定的 `@path` 说明。 |
109
+
110
+ Unity 工程建议补上生成目录:
111
+
112
+ ```yaml
113
+ excludedDirectories:
114
+ - .git
115
+ - node_modules
116
+ - Library
117
+ - Temp
118
+ - obj
119
+ - Logs
120
+ - UserSettings
121
+ - Output
122
+ - Publish
123
+ - .vs
124
+ ```
125
+
126
+ 如果 `Export/` 下的构建产物需要可搜,就不要排除它。
127
+
128
+ ## 行为
129
+
130
+ `@` 打开补全,继续输入即过滤,选中后插入普通的 `@path` 文本。目录候选会保留尾斜杠的引号形式,以便继续向下钻取。选中文件**不会**读取内容——模型仍需自行调用 `read`。
131
+
132
+ - **裸查询**(`@Archive`):搜索整个工作目录。
133
+ - **目录查询**(`@Assets/Scripts/`):只列该目录,每层一次很便宜的查询。
134
+ - **排除**是对返回行的过滤,因此被排除的目录在查询时零成本。
135
+ - **隐藏项**:查询本身以 `.` 开头之前,不会出现在结果里。
136
+ - **严格限定在工作目录内。** 裸查询带 `-path <cwd>`,每条结果在渲染前还会按根目录再校验一次,工作区之外的内容不会出现。目录下钻同样有守卫:`@../sibling/`、`@D:\elsewhere\` 会解析到根目录之外,此时返回空而不是列出另一棵树。这对同一工程存在多份副本的机器很关键——一个工作区永远看不到、也选不中另一个工作区的文件。
137
+
138
+ 排序完整复刻上游的分档,因此换用本插件不会改变某个按键序列最终选中的文件:全名精确 > 前缀 > 子串 > 目录段 > 子序列;同分时目录优先于文件,其次路径更短者优先,最后按码位排序。
139
+
140
+ ## 实现要点
141
+
142
+ `es.exe` 的三条行为决定了实现,每条都由实测真实客户端得出:
143
+
144
+ 1. **每个 argv 元素都是独立的、以 AND 相连的检索词。** 单个参数里带空格(`"package json"`)什么也匹配不到,而 `package`、`json` 两个参数能匹配到 `package.json`。因此检索词绝不拼接空格,模式里的字面空格改用 `?` 表示。
145
+ 2. **Everything 默认只索引文件名;`-p` 才把检索词扩展到完整路径。** 文件名匹配同时是快路径:通配符形式在 47 万条目的工作区上约 70–150 ms,而全路径的 `regex:` 会扫描整个索引,需要 0.6–44 s。因此查询保持在文件名范围,范围限定交给 `-path`。
146
+ 3. **标准输出不是 UTF-8。** `es.exe` 按进程 ANSI/OEM 代码页输出,在中文系统上 CJK 与假名会变成乱码。唯一与代码页无关的通道是 `-export-csv <文件>` 配 `-utf8-bom`,它把真正的 UTF-8 写进插件自己掌握的文件。它和 stdout 开销相近(约 110 ms 对 100 ms),所以每次查询都走这条路。
147
+
148
+ 目录与文件的区分来自导出的 `Attributes` 列(含 `D` 即目录),省去一次文件系统往返。
149
+
150
+ ## 验证
151
+
152
+ ```powershell
153
+ npm run typecheck # 对 src/ 做严格 TS 检查
154
+ npm run test # 单元测试 + 真实 es.exe 集成测试
155
+ ```
156
+
157
+ 单元测试在任何机器上都能跑。集成测试在 `%TEMP%` 下建一棵夹具树,等 Everything 索引后验证:目录识别、根范围限定、CJK 文件名解码、含空格文件名、子序列匹配、空结果与取消。缺少 `es.exe` 时自动跳过。
158
+
159
+ `test/` 刻意不依赖 Harness 安装:纯逻辑放在 `src/pure.ts`,单独打包成 `lib/pure.js` 就是为了这一点。
160
+
161
+ ## 目录结构
162
+
163
+ ```
164
+ src/index.ts 插件、服务类、配置 schema
165
+ src/es-client.ts es.exe 适配层:spawn、导出、解码、超时
166
+ src/candidates.ts 纯排序与路径归一
167
+ src/pure.ts 不含 Harness 依赖的入口,供测试与复用
168
+ cordis.patch.yml 打包层:插入本行,禁用 file-reference-local
169
+ assets/ 市场图标及其许可记录
170
+ scripts/make-icon.py 由 icon-256.png 渲染 assets/icon-{180,256,512}.png
171
+ ```
172
+
173
+ `@deepseek-ai/*` 在打包时保持 external:由宿主从安装目录解析;若内联,本插件会得到第二份 Cordis `Service` 类身份。
174
+
175
+ ## 图标
176
+
177
+ `assets/icon-{180,256,512}.png` 用的是 voidtools「Everything」的放大镜图标。
178
+ Everything(含图标)以 MIT 授权发布(Copyright (c) 2022 voidtools),因此复用
179
+ 是允许的,唯一条件是许可声明随资产一起分发——声明在
180
+ [assets/ICON-LICENSE.txt](assets/ICON-LICENSE.txt)。重新渲染各尺寸:
181
+
182
+ ```powershell
183
+ python scripts/make-icon.py
184
+ ```
185
+
186
+ 市场(awesome-dsh-plugin 列表、dsh-market)从目录条目里取图:
187
+
188
+ ```yaml
189
+ icon: https://raw.githubusercontent.com/backkom/dsh-at-file-everything/master/assets/icon-180.png
190
+ ```
191
+
192
+ 该列表只接受托管在 GitHub 的 `png`/`jpg`/`jpeg`/`webp`,卡片按约 96px 显示,
193
+ 所以方形位图最合适。本仓库默认分支是 `master`;若日后改名,这个 URL 要同步改。
194
+
195
+ ## 已知限制
196
+
197
+ - **仅 Windows**,且效果取决于 Everything 的索引范围。未纳入索引的文件同样搜不到。
198
+ - **必须让 Everything 保持运行。** 服务停掉时插件只记录一条警告、补全返回空,不会退回到文件系统遍历。
199
+ - **检索限定在文件名。** 带 `/` 的查询会列出该目录,但裸查询匹配不到「文件名里不含、只在深层路径里出现」的片段——这是用上游的路径子串匹配换来了索引路径约 30 倍的提速。
200
+ - **每次按键一个 `es.exe` 进程。** 每次查询都是新进程(预热后约 70–80 ms),取消会杀掉它。
201
+ - **Everything 索引处于冷态时**,首次查询可能需要约 1 s 让服务把索引换入。
202
+
203
+ ## 许可
204
+
205
+ MIT,见 [LICENSE](LICENSE)。
@@ -0,0 +1,55 @@
1
+ Icon: Everything application icon
2
+ Source repository: https://github.com/backkom/dsh-at-file-everything
3
+ Asset files: assets/icon-180.png, assets/icon-256.png, assets/icon-512.png
4
+
5
+ --------------------------------------------------------------------------
6
+ Upstream
7
+ --------------------------------------------------------------------------
8
+
9
+ The icon is voidtools' "Everything" application icon (a magnifying glass).
10
+ The 256x256 copy used as the source was extracted from the Everything
11
+ application binaries (version 1.4.1.1026) and is distributed at
12
+
13
+ https://commons.wikimedia.org/wiki/File:Everything_(software)_icon.png
14
+
15
+ Author / copyright holder: David Carpenter (voidtools), developer of
16
+ "Everything".
17
+
18
+ --------------------------------------------------------------------------
19
+ Licence
20
+ --------------------------------------------------------------------------
21
+
22
+ Everything, including this icon, is licensed under the MIT licence. The
23
+ permission notice shipped with the application (License.txt in the
24
+ Everything install directory, and https://www.voidtools.com/License.txt)
25
+ reads:
26
+
27
+ Everything
28
+
29
+ Copyright (c) 2022 voidtools
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining a
32
+ copy of this software and associated documentation files (the
33
+ "Software"), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included
40
+ in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
43
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
+
50
+ That notice is reproduced here to satisfy its one condition. The resized
51
+ derivatives were produced by scripts/make-icon.py.
52
+
53
+ "Everything" is voidtools' product name. This icon is used descriptively, to
54
+ identify that this plugin answers file completion from the Everything index;
55
+ this plugin is not affiliated with or endorsed by voidtools.
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ # Bundle patch layer for dsh-at-file-everything.
2
+ #
3
+ # The row loads this package's main entry as the host half (a Cordis plugin that
4
+ # provides `ctx.fileReferences` from the Everything index).
5
+ #
6
+ # `file-reference-local` is disabled rather than left mounted: Cordis refuses two
7
+ # providers of one service name in a scope, and the shipped provider would
8
+ # otherwise win or lose the registration by load order. Disabling it here keeps
9
+ # exactly one owner of the seam. Re-enable that row (or remove this patch layer)
10
+ # to go back to the upstream walk-based provider.
11
+ #
12
+ # ORDERING MATTERS: this patch can only disable a row that an earlier bundle
13
+ # layer already declared. `dsh-at-file-everything` must therefore appear *after*
14
+ # the bundle that mounts `file-reference-local` (in the shipped composition,
15
+ # `@deepseek-ai/dsh-web-app`) in `package.json`'s `dsh.profile.bundles` list.
16
+ # `dsh plugin add` appends at the end, which satisfies this by default. If the
17
+ # row cannot be found, the Loader reports
18
+ # `patch: entry "file-reference-local" not found` — move this bundle later in
19
+ # the list.
20
+ - insert:
21
+ - id: file-reference-everything
22
+ name: dsh-at-file-everything
23
+
24
+ - id: file-reference-local
25
+ disabled: true
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "dsh-at-file-everything",
3
+ "description": "Everything-backed @file completion for DeepSeek Harness on Windows",
4
+ "version": "0.1.0",
5
+ "entry": {
6
+ "name": "dsh-at-file-everything",
7
+ "inject": ["agents", "workingDirectory"]
8
+ }
9
+ }