@fishdivinity/dsh-local-search 0.2.0 → 0.3.0
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/README-zh.md +36 -22
- package/README.md +35 -21
- package/cordis.patch.yml +2 -1
- package/lib/anytxt.js +49 -35
- package/lib/bootstrap.js +201 -0
- package/lib/client.js +1196 -290
- package/lib/config.js +193 -49
- package/lib/describe.js +157 -0
- package/lib/engines.js +6 -6
- package/lib/errors.js +2 -3
- package/lib/everything.js +70 -15
- package/lib/format.js +38 -33
- package/lib/index.js +75 -38
- package/lib/limits.js +13 -0
- package/lib/probe.js +34 -21
- package/lib/ref.js +5 -5
- package/lib/roots.js +34 -16
- package/lib/route.js +253 -70
- package/lib/schema.js +130 -0
- package/lib/tools.js +46 -36
- package/package.json +3 -2
package/lib/tools.js
CHANGED
|
@@ -7,10 +7,9 @@ import { parseRef, assertRefEngine } from './ref.js'
|
|
|
7
7
|
import { defaultAllRoots, parseAllRoots, rootsFor } from './roots.js'
|
|
8
8
|
import { readConfig } from './config.js'
|
|
9
9
|
import { probeEngines } from './probe.js'
|
|
10
|
+
import { MAX_LIMIT, MAX_READ } from './limits.js'
|
|
10
11
|
|
|
11
12
|
const STATUS_ENGINES = ['auto', ...new Set([...engineNames().files, ...engineNames().content])]
|
|
12
|
-
const MAX_LIMIT = 100
|
|
13
|
-
const MAX_READ = 20000
|
|
14
13
|
const MAX_FRAGMENTS = 20
|
|
15
14
|
|
|
16
15
|
function toHarnessError(error) {
|
|
@@ -30,13 +29,12 @@ async function guard(fn) {
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* @param
|
|
37
|
-
* @param
|
|
38
|
-
* @
|
|
39
|
-
* @returns the usable count
|
|
32
|
+
* 把可选的数字参数收进 `[1, cap]`。非数字参数回落到配置的默认值,而不是让窗口变成 NaN
|
|
33
|
+
* ——那样会静默返回空结果。
|
|
34
|
+
* @param value - 模型发来的参数原样
|
|
35
|
+
* @param fallback - 不是有限数字时用的默认值
|
|
36
|
+
* @param cap - 闭区间上界
|
|
37
|
+
* @returns 可用的条数
|
|
40
38
|
*/
|
|
41
39
|
function clampCount(value, fallback, cap) {
|
|
42
40
|
const number = Number.isFinite(value) ? Math.floor(value) : fallback
|
|
@@ -65,6 +63,19 @@ function validateEngine(engine, allowed) {
|
|
|
65
63
|
return value
|
|
66
64
|
}
|
|
67
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 这次调用该用哪个后端。
|
|
68
|
+
*
|
|
69
|
+
* `auto`(或没传)跟随配置里选的后端,而不是「注册表里的第一个」:配置里的 backend 就是
|
|
70
|
+
* 「默认用哪个」的声明,自动选第一个会让那个字段变成死配置。
|
|
71
|
+
* @param {string|undefined} requested - 调用参数里的 engine
|
|
72
|
+
* @param {string} configured - 配置里选的后端
|
|
73
|
+
* @returns {string} 要解析的后端名
|
|
74
|
+
*/
|
|
75
|
+
function engineFor(requested, configured) {
|
|
76
|
+
return requested === undefined || requested === '' || requested === 'auto' ? configured : requested
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
function presentSearchCall(label) {
|
|
69
80
|
return (args) => ({
|
|
70
81
|
card: 'generic',
|
|
@@ -189,20 +200,19 @@ const statusOutput = {
|
|
|
189
200
|
}
|
|
190
201
|
|
|
191
202
|
/**
|
|
192
|
-
*
|
|
203
|
+
* 构建并注册五个面向模型的工具。
|
|
193
204
|
* @param {import('@deepseek-ai/cordis').Context} ctx
|
|
194
205
|
* @param {object} config
|
|
195
|
-
* @returns {Array<() => void>}
|
|
206
|
+
* @returns {Array<() => void>} 工具的 disposer
|
|
196
207
|
*/
|
|
197
208
|
export function createTools(ctx, config) {
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// page applies to the next call instead of the next reload.
|
|
209
|
+
// 注册时就固定了工具的截止时间与描述默认值的文案;一次调用真正用到的一切都是每次操作现读
|
|
210
|
+
// 的,所以配置页上的保存对下一次调用生效,而不是对下一次重载生效。
|
|
201
211
|
const initial = readConfig(config)
|
|
202
212
|
const names = engineNames()
|
|
203
213
|
|
|
204
214
|
async function resolveWorkspace(exec, cfg) {
|
|
205
|
-
if (cfg.workspaceRoot) return cfg.workspaceRoot
|
|
215
|
+
if (cfg.scopes.workspaceRoot) return cfg.scopes.workspaceRoot
|
|
206
216
|
if (exec.agent && ctx.workingDirectory?.ensure) {
|
|
207
217
|
try {
|
|
208
218
|
return await ctx.workingDirectory.ensure(exec.agent, exec.signal)
|
|
@@ -239,11 +249,11 @@ export function createTools(ctx, config) {
|
|
|
239
249
|
},
|
|
240
250
|
engine: {
|
|
241
251
|
type: 'string',
|
|
242
|
-
description: `auto (default)
|
|
252
|
+
description: `auto (default) follows the configured files backend; ${names.files.join(', ')} otherwise. Name one only when the user asks for a specific engine.`,
|
|
243
253
|
},
|
|
244
254
|
limit: {
|
|
245
255
|
type: 'number',
|
|
246
|
-
description: `Max results (default ${initial.maxResults}; max ${MAX_LIMIT}).`,
|
|
256
|
+
description: `Max results (default ${initial.limits.maxResults}; max ${MAX_LIMIT}).`,
|
|
247
257
|
},
|
|
248
258
|
},
|
|
249
259
|
timeoutMs: initial.timeoutMs,
|
|
@@ -252,7 +262,7 @@ export function createTools(ctx, config) {
|
|
|
252
262
|
return guard(async () => {
|
|
253
263
|
const cfg = readConfig(config)
|
|
254
264
|
const query = requireQuery(args.query)
|
|
255
|
-
const engine = resolveFilesEngine(args.engine)
|
|
265
|
+
const engine = resolveFilesEngine(engineFor(args.engine, cfg.files.backend))
|
|
256
266
|
const scope = args.scope || 'workspace'
|
|
257
267
|
const workspace = await resolveWorkspace(exec, cfg)
|
|
258
268
|
let dir
|
|
@@ -264,11 +274,11 @@ export function createTools(ctx, config) {
|
|
|
264
274
|
return await engine.search({
|
|
265
275
|
query,
|
|
266
276
|
dir,
|
|
267
|
-
limit: clampLimit(args.limit, cfg.maxResults),
|
|
268
|
-
esPath: cfg.esPath,
|
|
277
|
+
limit: clampLimit(args.limit, cfg.limits.maxResults),
|
|
278
|
+
esPath: cfg.files.everything.esPath,
|
|
269
279
|
timeoutMs: initial.timeoutMs,
|
|
270
280
|
signal: exec.signal,
|
|
271
|
-
encoding: cfg.esEncoding,
|
|
281
|
+
encoding: cfg.files.everything.esEncoding,
|
|
272
282
|
})
|
|
273
283
|
})
|
|
274
284
|
},
|
|
@@ -303,11 +313,11 @@ export function createTools(ctx, config) {
|
|
|
303
313
|
},
|
|
304
314
|
engine: {
|
|
305
315
|
type: 'string',
|
|
306
|
-
description: `auto (default)
|
|
316
|
+
description: `auto (default) follows the configured content backend; ${names.content.join(', ')} otherwise. Name one only when the user asks for a specific engine.`,
|
|
307
317
|
},
|
|
308
318
|
limit: {
|
|
309
319
|
type: 'number',
|
|
310
|
-
description: `Max files (default ${initial.maxResults}; max ${MAX_LIMIT}).`,
|
|
320
|
+
description: `Max files (default ${initial.limits.maxResults}; max ${MAX_LIMIT}).`,
|
|
311
321
|
},
|
|
312
322
|
},
|
|
313
323
|
timeoutMs: initial.timeoutMs,
|
|
@@ -316,15 +326,15 @@ export function createTools(ctx, config) {
|
|
|
316
326
|
return guard(async () => {
|
|
317
327
|
const cfg = readConfig(config)
|
|
318
328
|
const query = requireQuery(args.query)
|
|
319
|
-
const engine = resolveContentEngine(args.engine)
|
|
329
|
+
const engine = resolveContentEngine(engineFor(args.engine, cfg.content.backend))
|
|
320
330
|
const workspace = await resolveWorkspace(exec, cfg)
|
|
321
331
|
const roots = rootsFor(args.scope || 'workspace', args.path, cfg, workspace)
|
|
322
332
|
const result = await engine.search({
|
|
323
333
|
query,
|
|
324
334
|
roots,
|
|
325
335
|
ext: args.ext,
|
|
326
|
-
limit: clampLimit(args.limit, cfg.maxResults),
|
|
327
|
-
url: cfg.
|
|
336
|
+
limit: clampLimit(args.limit, cfg.limits.maxResults),
|
|
337
|
+
url: cfg.content.anytxt.url,
|
|
328
338
|
timeoutMs: initial.timeoutMs,
|
|
329
339
|
signal: exec.signal,
|
|
330
340
|
})
|
|
@@ -382,7 +392,7 @@ export function createTools(ctx, config) {
|
|
|
382
392
|
const fragments = await engine.fragments({
|
|
383
393
|
ref: args.ref,
|
|
384
394
|
query,
|
|
385
|
-
url: cfg.
|
|
395
|
+
url: cfg.content.anytxt.url,
|
|
386
396
|
timeoutMs: initial.timeoutMs,
|
|
387
397
|
signal: exec.signal,
|
|
388
398
|
})
|
|
@@ -412,7 +422,7 @@ export function createTools(ctx, config) {
|
|
|
412
422
|
},
|
|
413
423
|
max: {
|
|
414
424
|
type: 'number',
|
|
415
|
-
description: `Max characters (default ${initial.readMaxChars}; max ${MAX_READ}).`,
|
|
425
|
+
description: `Max characters (default ${initial.limits.readMaxChars}; max ${MAX_READ}).`,
|
|
416
426
|
},
|
|
417
427
|
},
|
|
418
428
|
timeoutMs: initial.timeoutMs,
|
|
@@ -423,7 +433,7 @@ export function createTools(ctx, config) {
|
|
|
423
433
|
if (typeof args.ref !== 'string' || args.ref.trim().length === 0) {
|
|
424
434
|
throw new Error('ref must be a non-empty string')
|
|
425
435
|
}
|
|
426
|
-
const max = clampCount(args.max, cfg.readMaxChars, MAX_READ)
|
|
436
|
+
const max = clampCount(args.max, cfg.limits.readMaxChars, MAX_READ)
|
|
427
437
|
const offset = clampOffset(args.offset)
|
|
428
438
|
const parsed = parseRef(args.ref)
|
|
429
439
|
const requested = args.engine && args.engine !== 'auto' ? args.engine : parsed.engine
|
|
@@ -436,7 +446,7 @@ export function createTools(ctx, config) {
|
|
|
436
446
|
}
|
|
437
447
|
const text = await engine.read({
|
|
438
448
|
ref: args.ref,
|
|
439
|
-
url: cfg.
|
|
449
|
+
url: cfg.content.anytxt.url,
|
|
440
450
|
timeoutMs: initial.timeoutMs,
|
|
441
451
|
signal: exec.signal,
|
|
442
452
|
})
|
|
@@ -463,21 +473,21 @@ export function createTools(ctx, config) {
|
|
|
463
473
|
return guard(async () => {
|
|
464
474
|
const cfg = readConfig(config)
|
|
465
475
|
const engine = validateEngine(args.engine, STATUS_ENGINES)
|
|
466
|
-
let workspace = cfg.workspaceRoot || ctx.workingDirectory?.defaultDirectory || process.cwd()
|
|
476
|
+
let workspace = cfg.scopes.workspaceRoot || ctx.workingDirectory?.defaultDirectory || process.cwd()
|
|
467
477
|
try {
|
|
468
478
|
workspace = await resolveWorkspace(exec, cfg)
|
|
469
479
|
} catch {
|
|
470
|
-
//
|
|
480
|
+
// 工作区没了也得把引擎报出来。
|
|
471
481
|
}
|
|
472
482
|
|
|
473
|
-
//
|
|
483
|
+
// 与配置页测试按钮要的是同一个探测。
|
|
474
484
|
const { everything, anytxt } = await probeEngines(config, {
|
|
475
485
|
only: engine,
|
|
476
486
|
workspace,
|
|
477
487
|
signal: exec.signal,
|
|
478
488
|
})
|
|
479
489
|
|
|
480
|
-
const all = cfg.allRoots ? parseAllRoots(cfg.allRoots) : defaultAllRoots()
|
|
490
|
+
const all = cfg.scopes.allRoots ? parseAllRoots(cfg.scopes.allRoots) : defaultAllRoots()
|
|
481
491
|
return {
|
|
482
492
|
text: formatStatus({
|
|
483
493
|
everything,
|
|
@@ -485,8 +495,8 @@ export function createTools(ctx, config) {
|
|
|
485
495
|
engines: engineNames(),
|
|
486
496
|
roots: {
|
|
487
497
|
workspace,
|
|
488
|
-
work: cfg.workRoot,
|
|
489
|
-
personal: cfg.personalRoot,
|
|
498
|
+
work: cfg.scopes.workRoot,
|
|
499
|
+
personal: cfg.scopes.personalRoot,
|
|
490
500
|
all,
|
|
491
501
|
},
|
|
492
502
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fishdivinity/dsh-local-search",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Local file and document search for DeepSeek Harness: Everything filenames plus Anytxt document contents, read-only, with a configuration page on the Plugins page.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "node --test",
|
|
26
|
-
"check": "node --check lib/index.js && node --check lib/tools.js && node --check lib/engines.js && node --check lib/ref.js && node --check lib/everything.js && node --check lib/anytxt.js && node --check lib/roots.js && node --check lib/format.js && node --check lib/errors.js && node --check lib/config.js && node --check lib/probe.js && node --check lib/route.js && node --check lib/client.js",
|
|
26
|
+
"check": "node --check lib/index.js && node --check lib/tools.js && node --check lib/engines.js && node --check lib/ref.js && node --check lib/everything.js && node --check lib/anytxt.js && node --check lib/roots.js && node --check lib/format.js && node --check lib/errors.js && node --check lib/config.js && node --check lib/schema.js && node --check lib/describe.js && node --check lib/bootstrap.js && node --check lib/limits.js && node --check lib/probe.js && node --check lib/route.js && node --check lib/client.js && node --check scripts/expand-release-links.mjs && node --check scripts/privacy-scan.mjs",
|
|
27
|
+
"privacy": "node scripts/privacy-scan.mjs",
|
|
27
28
|
"pack:check": "npm pack --dry-run"
|
|
28
29
|
},
|
|
29
30
|
"keywords": [
|