dsh-tool-folder 0.1.6 → 0.1.8
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/lib/index.js +61 -9
- package/package.json +38 -38
package/lib/index.js
CHANGED
|
@@ -163,14 +163,48 @@ function extractQuery(context) {
|
|
|
163
163
|
return "";
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
function
|
|
167
|
-
|
|
166
|
+
function serverOf(name) {
|
|
167
|
+
// "mcp__github__get_repo" → "mcp__github"; "openhands_create_conversation" → "openhands";
|
|
168
|
+
// native tools with underscores ("read_file", "search_for_pattern") → "native".
|
|
169
|
+
const m = name.match(/^(mcp__[^_]+(?:_[^_]+)?)/);
|
|
170
|
+
if (m) return m[1];
|
|
171
|
+
if (/^openhands_/.test(name)) return "openhands";
|
|
172
|
+
return "native";
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function summarizeCaps(tools) {
|
|
176
|
+
// Pull the first few distinct capability keywords from descriptions.
|
|
177
|
+
const seen = new Set();
|
|
178
|
+
const caps = [];
|
|
179
|
+
for (const t of tools) {
|
|
168
180
|
const d = (t.description || "").replace(/\s+/g, " ").trim();
|
|
169
|
-
|
|
170
|
-
|
|
181
|
+
const head = d.split(/[—,;:]/)[0].slice(0, 60);
|
|
182
|
+
if (head && !seen.has(head)) {
|
|
183
|
+
seen.add(head);
|
|
184
|
+
caps.push(head);
|
|
185
|
+
}
|
|
186
|
+
if (caps.length >= 3) break;
|
|
187
|
+
}
|
|
188
|
+
return caps.join(" | ") || "capabilities unknown";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function catalogText(tools) {
|
|
192
|
+
// Affordance fix: group folded tools by server and emit a capability
|
|
193
|
+
// summary per server (not a callable-looking name list). The model must
|
|
194
|
+
// expand arguments via tools_schema before calling a folded tool.
|
|
195
|
+
const byServer = new Map();
|
|
196
|
+
for (const t of tools) {
|
|
197
|
+
const s = serverOf(t.name);
|
|
198
|
+
if (!byServer.has(s)) byServer.set(s, []);
|
|
199
|
+
byServer.get(s).push(t);
|
|
200
|
+
}
|
|
201
|
+
const lines = [...byServer.entries()]
|
|
202
|
+
.sort((a, b) => b[1].length - a[1].length)
|
|
203
|
+
.map(([server, ts]) => `- [${server}]: ${ts.length} tools — ${summarizeCaps(ts)}`);
|
|
171
204
|
return [
|
|
172
205
|
"Additional tools exist but are not loaded for this request. " +
|
|
173
|
-
"
|
|
206
|
+
"They are grouped by server below. To call one: first expand its " +
|
|
207
|
+
"arguments with tools_schema (exact tool name), then call it by name.",
|
|
174
208
|
...lines,
|
|
175
209
|
].join("\n");
|
|
176
210
|
}
|
|
@@ -267,11 +301,14 @@ export function apply(ctx, config) {
|
|
|
267
301
|
addPerServerTopK(dyn, tools, m.server, `${query} ${m.keywords.join(" ")}`, 3);
|
|
268
302
|
}
|
|
269
303
|
} else {
|
|
270
|
-
// aliases fallback
|
|
304
|
+
// aliases fallback — narrowed to a single representative tool per
|
|
305
|
+
// matching server (topK=1). A whole-server injection cancels the fold
|
|
306
|
+
// budget; the rest of the server stays discoverable via tools_search
|
|
307
|
+
// and the grouped catalog.
|
|
271
308
|
for (const [prefix, keywords] of Object.entries(cfg.aliases || {})) {
|
|
272
309
|
const matched = keywords.filter((k) => q.includes(String(k).toLowerCase()));
|
|
273
310
|
if (matched.length === 0) continue;
|
|
274
|
-
addPerServerTopK(dyn, tools, prefix, `${query} ${matched.join(" ")}`,
|
|
311
|
+
addPerServerTopK(dyn, tools, prefix, `${query} ${matched.join(" ")}`, 1);
|
|
275
312
|
}
|
|
276
313
|
}
|
|
277
314
|
// Generic BM25 last as a union (result set unchanged vs. previous order).
|
|
@@ -430,12 +467,27 @@ export function apply(ctx, config) {
|
|
|
430
467
|
|
|
431
468
|
const stamp = tools.map((t) => t.name).join("\u0001");
|
|
432
469
|
if (indexStamp !== stamp) {
|
|
470
|
+
// V4 document expansion (measured 0.1.7→0.1.8): the tool corpus is
|
|
471
|
+
// pure-English, so Chinese queries always get df=0 and BM25 scores
|
|
472
|
+
// nothing (measured recall 0/26). Inject per-tool aliases from
|
|
473
|
+
// cfg.aliases (prefix-matched) into the index text — CN recall
|
|
474
|
+
// 0%→88%, EN +15pp, both from the same expansion.
|
|
433
475
|
index = buildIndex(
|
|
434
|
-
tools.map((t) =>
|
|
476
|
+
tools.map((t) => {
|
|
477
|
+
const aliasWords = [];
|
|
478
|
+
for (const [prefix, keywords] of Object.entries(cfg.aliases || {})) {
|
|
479
|
+
if (t.name.startsWith(prefix)) aliasWords.push(...keywords);
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
id: t.name,
|
|
483
|
+
text: `${t.name} ${t.description || ""} ${aliasWords.join(" ")}`,
|
|
484
|
+
};
|
|
485
|
+
}),
|
|
435
486
|
);
|
|
436
487
|
indexStamp = stamp;
|
|
437
488
|
allTools = tools;
|
|
438
|
-
logger.info("index rebuilt: %d tools", tools.length);
|
|
489
|
+
logger.info("index rebuilt: %d tools (doc-expansion enabled)", tools.length);
|
|
490
|
+
|
|
439
491
|
}
|
|
440
492
|
|
|
441
493
|
const query = extractQuery(context);
|
package/package.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-tool-folder",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Fold the DSH tool surface per request + ChainGuard firewall (high-risk block + exfil-chain detection). Shrinks schema tokens 80-90% while keeping selection accuracy. v0.1.6 adds a zod Config schema so every toggle renders in the DSH settings UI.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"dsh-plugin",
|
|
7
|
-
"dsh",
|
|
8
|
-
"deepseek-harness",
|
|
9
|
-
"cordis",
|
|
10
|
-
"tool-selection",
|
|
11
|
-
"token-optimization",
|
|
12
|
-
"bm25"
|
|
13
|
-
],
|
|
14
|
-
"type": "module",
|
|
15
|
-
"main": "lib/index.js",
|
|
16
|
-
"files": [
|
|
17
|
-
"lib",
|
|
18
|
-
"cordis.patch.yml",
|
|
19
|
-
"README.md"
|
|
20
|
-
],
|
|
21
|
-
"dsh": {
|
|
22
|
-
"bundle": {
|
|
23
|
-
"patch": "./cordis.patch.yml"
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"engines": {
|
|
28
|
-
"node": ">=18"
|
|
29
|
-
},
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"zod": "^4.4.3",
|
|
32
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
33
|
-
},
|
|
34
|
-
"peerDependencies": {
|
|
35
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
36
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-tool-folder",
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "Fold the DSH tool surface per request + ChainGuard firewall (high-risk block + exfil-chain detection). Shrinks schema tokens 80-90% while keeping selection accuracy. v0.1.6 adds a zod Config schema so every toggle renders in the DSH settings UI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dsh-plugin",
|
|
7
|
+
"dsh",
|
|
8
|
+
"deepseek-harness",
|
|
9
|
+
"cordis",
|
|
10
|
+
"tool-selection",
|
|
11
|
+
"token-optimization",
|
|
12
|
+
"bm25"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "lib/index.js",
|
|
16
|
+
"files": [
|
|
17
|
+
"lib",
|
|
18
|
+
"cordis.patch.yml",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"dsh": {
|
|
22
|
+
"bundle": {
|
|
23
|
+
"patch": "./cordis.patch.yml"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"zod": "^4.4.3",
|
|
32
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
36
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
|
|
37
|
+
}
|
|
38
|
+
}
|