dsh-locator 0.13.0 → 0.14.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/CHANGELOG.md +7 -0
- package/README-es.md +5 -0
- package/README-hi.md +5 -0
- package/README-pt.md +5 -0
- package/README.en.md +5 -0
- package/README.md +5 -0
- package/bin/darwin-arm64/indexd +0 -0
- package/bin/darwin-x64/indexd +0 -0
- package/bin/linux-arm64/indexd +0 -0
- package/bin/linux-x64/indexd +0 -0
- package/bin/win32-arm64/indexd.exe +0 -0
- package/bin/win32-x64/indexd.exe +0 -0
- package/lib/capabilities.d.ts +109 -0
- package/lib/capabilities.d.ts.map +1 -0
- package/lib/capabilities.js +372 -0
- package/lib/capabilities.js.map +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -0
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities.ts +405 -0
- package/src/index.ts +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.0 — 2026-11-14
|
|
4
|
+
|
|
5
|
+
* **Capability adapter (Wave 3, part 1)**: new tools `capability_search(intent, kinds?, riskMax?, ...)` and `capability_preflight(capability, argsJson?)` index the **live** DSH registries — tool definitions (including `mcp__<server>__<tool>` entries) and the skill catalog — and add intent matching, inferred risk (read/write/exec plus approval/sandbox hints), argument-schema validation and side-effect reporting. It reads `ctx.tools.definitions()` / `ctx.skills.list()`; it does not duplicate discovery and has no embedding dependency.
|
|
6
|
+
* Snapshot cache (60 s) and graceful degradation: a missing skill service or registry produces warnings instead of breaking the tool.
|
|
7
|
+
* `171 tests`; six engine binaries rebuilt at 0.14.0.
|
|
8
|
+
* Deferred and explicitly documented: refs persistence plus URL/spill/attachment refs and the panel ref chip (Wave 2), the panel capability view (Wave 3 UI), and tenant/enterprise packaging (blocked on a real dsh-ee instance and credentials).
|
|
9
|
+
|
|
3
10
|
## 0.13.0 — 2026-11-14
|
|
4
11
|
|
|
5
12
|
* **Authorization fix**: `locator_find` no longer lets `sessionId`, `scope: "all"` or `pathPrefix` bypass the caller's identity. An explicit session id is allowed only for the caller session or sessions whose immutable `cwd` equals the caller cwd (the same rule as DSH's session-query tools); `pathPrefix` must resolve inside the configured roots; `scope: "all"` still searches every indexed file but keeps session documents inside the caller's authorized set unless the new `allowCrossWorkspaceSessions: true` is configured.
|
package/README-es.md
CHANGED
|
@@ -403,6 +403,11 @@ DeepSeek Harness
|
|
|
403
403
|
|
|
404
404
|
El motor es un único proceso Go y respeta las variables estándar `GOMEMLIMIT` y `GOGC` (o `memoryLimitMB` en la configuración). Un índice de 1,2–1,5 M de entradas alcanza varios cientos de MB de RSS con el GC por defecto; usa `GOMEMLIMIT=600MiB` (límite blando, el runtime cambia CPU por memoria) o `GOGC=50` cuando el host vaya justo de RAM. Ninguno cambia el formato de la instantánea. En la instalación en vivo usada para las cifras anteriores, el proceso anfitrión de DSH (incluida la caché de páginas de la base de contenido) rondaba los 700 MB de RSS con el índice construido, y la latencia del host en reposo se mantenía en p50 2 ms.
|
|
405
405
|
|
|
406
|
+
## Notas de actualización 0.14.0
|
|
407
|
+
|
|
408
|
+
- **Adaptador de capacidades**: `capability_search` (encontrar "quién puede hacer esto" desde una intención) y `capability_preflight` (visibilidad, validación del esquema de argumentos, aprobación/sandbox y efectos secundarios) leen el registro de herramientas en vivo (incluidas acciones MCP) y el catálogo de skills. Sin descubrimiento duplicado ni embeddings; refresco cada 60 s.
|
|
409
|
+
- Primera parte de Wave 3; la vista de capacidades en el panel, el empaquetado multi-tenant/empresa y los refs persistentes de Wave 2 quedan para versiones posteriores.
|
|
410
|
+
|
|
406
411
|
## Notas de actualización 0.13.0
|
|
407
412
|
|
|
408
413
|
- **Corrección de autorización**: `locator_find` ya no permite que `sessionId`, `scope:"all"` o `pathPrefix` eludan la identidad del llamador. Un id de sesión explícito solo se acepta para la sesión del llamador o sesiones cuyo `cwd` inmutable coincide (misma regla que las herramientas session-query de DSH); `pathPrefix` debe resolver dentro de los roots configurados; `scope:"all"` sigue buscando todos los archivos pero limita las sesiones al conjunto autorizado salvo `allowCrossWorkspaceSessions: true`.
|
package/README-hi.md
CHANGED
|
@@ -404,6 +404,11 @@ DeepSeek Harness
|
|
|
404
404
|
|
|
405
405
|
इंजन एक Go प्रोसेस है और मानक `GOMEMLIMIT` और `GOGC` (या कॉन्फ़िग में `memoryLimitMB`) मानता है। 1.2–1.5 M एंट्री का इंडेक्स डिफ़ॉल्ट GC के साथ कई सौ MB RSS तक जाता है; होस्ट पर RAM कम हो तो `GOMEMLIMIT=600MiB` (सॉफ़्ट सीमा, रनटाइम CPU देकर मेमोरी बचाता है) या `GOGC=50` रखें। इनसे स्नैपशॉट फ़ॉर्मेट नहीं बदलता। ऊपर के आँकड़ों वाले लाइव सेटअप में DSH होस्ट प्रोसेस (कंटेंट डेटाबेस पेज कैश सहित) इंडेक्स बने रहने पर लगभग 700 MB RSS पर था, और खाली बैठे होस्ट की देरी p50 2ms रही।
|
|
406
406
|
|
|
407
|
+
## 0.14.0 अपग्रेड नोट्स
|
|
408
|
+
|
|
409
|
+
- **क्षमता अनुकूलक (capability adapter)**: `capability_search` (स्वाभाविक भाषा में "यह कौन कर सकता है" खोजें) और `capability_preflight` (दृश्यता, argument schema जाँच, approval/sandbox आवश्यकताएँ, side effects) होस्ट के live tool registry (MCP actions सहित) और skill catalog से पढ़ते हैं। कोई दोहरा discovery या embedding नहीं; snapshot हर 60 s में ताज़ा।
|
|
410
|
+
- यह Wave 3 का पहला भाग है; panel capability view, tenant/enterprise packaging और Wave 2 के refs persistence/URL·spill·attachment refs आगे के संस्करणों में।
|
|
411
|
+
|
|
407
412
|
## 0.13.0 अपग्रेड नोट्स
|
|
408
413
|
|
|
409
414
|
- **अधिकार सुधार**: `locator_find` अब `sessionId`, `scope:"all"` या `pathPrefix` को कॉलर की पहचान बायपास करने नहीं देता। स्पष्ट session id केवल कॉलर सत्र या जिनका अपरिवर्तनीय `cwd` कॉलर के बराबर है (DSH session-query नियम) के लिए मान्य है; `pathPrefix` कॉन्फ़िगर किए roots के अंदर होना चाहिए; `scope:"all"` सभी फ़ाइलें खोजता है पर सत्र पंक्तियाँ कॉलर के अधिकृत सेट तक सीमित रहती हैं जब तक `allowCrossWorkspaceSessions: true` न हो।
|
package/README-pt.md
CHANGED
|
@@ -404,6 +404,11 @@ DeepSeek Harness
|
|
|
404
404
|
|
|
405
405
|
O motor é um único processo Go e respeita as variáveis padrão `GOMEMLIMIT` e `GOGC` (ou `memoryLimitMB` na configuração). Um índice de 1,2–1,5 M de entradas chega a várias centenas de MB de RSS com o GC padrão; use `GOMEMLIMIT=600MiB` (limite suave, o runtime troca CPU por memória) ou `GOGC=50` quando o host estiver apertado de RAM. Nenhum altera o formato do snapshot. Na instalação ao vivo usada para os números acima, o processo anfitrião do DSH (incluindo o cache de páginas do banco de conteúdo) ficava por volta de 700 MB de RSS com o índice construído, e a latência do host ocioso permanecia em p50 2 ms.
|
|
406
406
|
|
|
407
|
+
## Notas de atualização 0.14.0
|
|
408
|
+
|
|
409
|
+
- **Adaptador de capacidades**: `capability_search` (encontrar "quem pode fazer isso" a partir de uma intenção) e `capability_preflight` (visibilidade, validação de schema dos argumentos, aprovação/sandbox e efeitos colaterais) leem o registro de ferramentas ao vivo (incluindo ações MCP) e o catálogo de skills. Sem descoberta duplicada e sem embeddings; atualização a cada 60 s.
|
|
410
|
+
- Primeira parte da Wave 3; a visão de capacidades no painel, o empacotamento multi-tenant/empresa e os refs persistentes da Wave 2 ficam para versões futuras.
|
|
411
|
+
|
|
407
412
|
## Notas de atualização 0.13.0
|
|
408
413
|
|
|
409
414
|
- **Correção de autorização**: `locator_find` não deixa mais `sessionId`, `scope:"all"` ou `pathPrefix` contornarem a identidade do chamador. Um id de sessão explícito só é aceito para a sessão do chamador ou sessões cujo `cwd` imutável coincide (mesma regra das ferramentas session-query do DSH); `pathPrefix` deve resolver dentro dos roots configurados; `scope:"all"` continua buscando todos os arquivos mas limita as sessões ao conjunto autorizado, salvo `allowCrossWorkspaceSessions: true`.
|
package/README.en.md
CHANGED
|
@@ -404,6 +404,11 @@ DeepSeek Harness
|
|
|
404
404
|
|
|
405
405
|
The engine is a single Go process and honours the standard `GOMEMLIMIT` and `GOGC` environment variables (or `memoryLimitMB` in the config). A 1.2–1.5 M-entry index peaks around several hundred MB of RSS with the default GC; set `GOMEMLIMIT=600MiB` (soft limit, the runtime trades CPU for memory) or `GOGC=50` when the host is tight on RAM. Neither changes the snapshot format. In the live setup used for the numbers above, the DSH host process (including the content database page cache) sat around 700 MB RSS with the content index built, and idle host latency stayed at p50 2 ms.
|
|
406
406
|
|
|
407
|
+
## 0.14.0 upgrade notes
|
|
408
|
+
|
|
409
|
+
- **Capability adapter**: `capability_search` (find "who can do this" from a natural-language intent) and `capability_preflight` (visibility, argument-schema validation, approval/sandbox requirements and side effects) read the host's live tool registry (including MCP actions) and skill catalog. No duplicate discovery and no embedding model; snapshots refresh every 60 s.
|
|
410
|
+
- This is part 1 of Wave 3. The panel capability view, tenancy/enterprise packaging (needs a real dsh-ee instance and credentials) and the Wave 2 refs persistence/URL·spill·attachment refs remain future work.
|
|
411
|
+
|
|
407
412
|
## 0.13.0 upgrade notes
|
|
408
413
|
|
|
409
414
|
- **Authorization fix**: `locator_find` no longer lets `sessionId`, `scope: "all"` or `pathPrefix` bypass the caller identity. An explicit session id is allowed only for the caller session or sessions whose immutable `cwd` equals the caller cwd (same rule as DSH's session-query tools); `pathPrefix` must resolve inside the configured roots; `scope: "all"` still searches every indexed file but keeps session bodies inside the caller's authorized set unless `allowCrossWorkspaceSessions: true` is configured.
|
package/README.md
CHANGED
|
@@ -366,6 +366,11 @@ Go 引擎在 `engine/` 下,测试用 `cd engine && go test ./...`。macOS 的
|
|
|
366
366
|
- 当前会话范围只覆盖已落定索引的会话消息(活跃会话约 2 分钟延迟);实时查找用 `Ctrl+F`。会话内查找条只覆盖已加载窗口,更早历史需手动加载。
|
|
367
367
|
- 会话内高亮依赖 CSS Custom Highlight API;不支持它的旧浏览器会退化为整行描边。
|
|
368
368
|
|
|
369
|
+
## 0.14.0 更新
|
|
370
|
+
|
|
371
|
+
- **能力索引适配器**:新增 `capability_search`(自然语言找“谁能做这件事”)与 `capability_preflight`(能力是否可见、参数是否符合 schema、需要什么审批/沙箱、有哪些副作用);数据来自宿主已有的 tool registry(含 MCP 工具)与 skill catalog,不重复发现、不用 embedding,60s 自动刷新。
|
|
372
|
+
- 本版是 Wave 3 的第一部分;面板能力页、租户/企业包,以及 Wave 2 的 refs 持久化/URL·spill·attachment ref 留待后续版本(企业包需 dsh-ee 实例与凭据)。
|
|
373
|
+
|
|
369
374
|
## 0.13.0 更新
|
|
370
375
|
|
|
371
376
|
- **授权修复**:`locator_find` 的 `sessionId`/`scope:"all"`/`pathPrefix` 不再绕过调用方身份——显式会话 id 只允许「当前会话」或「header.cwd 与调用方相同的会话」(与 DSH session-query 工具一致);`pathPrefix` 必须落在已配置 root 内;`scope:"all"` 仍可搜全部文件,但会话正文默认限调用方授权集合(`allowCrossWorkspaceSessions: true` 可显式放开)。
|
package/bin/darwin-arm64/indexd
CHANGED
|
Binary file
|
package/bin/darwin-x64/indexd
CHANGED
|
Binary file
|
package/bin/linux-arm64/indexd
CHANGED
|
Binary file
|
package/bin/linux-x64/indexd
CHANGED
|
Binary file
|
|
Binary file
|
package/bin/win32-x64/indexd.exe
CHANGED
|
Binary file
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability index: which tool/skill/MCP action can do a job, what it costs and
|
|
3
|
+
* what it may touch. This is a thin adapter over the DSH registries the host
|
|
4
|
+
* already keeps (tool definitions, skill catalog): it does not re-implement
|
|
5
|
+
* discovery, it adds intent matching, risk labels and a preflight check.
|
|
6
|
+
* @module dsh-locator/capabilities
|
|
7
|
+
*/
|
|
8
|
+
import type { ToolRunContext } from '@deepseek-ai/dsh-tools';
|
|
9
|
+
/** One capability card. */
|
|
10
|
+
export interface CapabilityCard {
|
|
11
|
+
id: string;
|
|
12
|
+
kind: 'tool' | 'mcp' | 'skill';
|
|
13
|
+
name: string;
|
|
14
|
+
summary: string;
|
|
15
|
+
input?: Record<string, unknown>;
|
|
16
|
+
tags: string[];
|
|
17
|
+
risk: {
|
|
18
|
+
level: 'read' | 'write' | 'exec';
|
|
19
|
+
actions: string[];
|
|
20
|
+
basis: 'schema' | 'name';
|
|
21
|
+
};
|
|
22
|
+
permission: {
|
|
23
|
+
approval: 'none' | 'ask';
|
|
24
|
+
sandbox: 'none' | 'write' | 'any';
|
|
25
|
+
};
|
|
26
|
+
state: 'available' | 'unknown';
|
|
27
|
+
source: 'tools' | 'skills';
|
|
28
|
+
}
|
|
29
|
+
/** One snapshot of the live capability surface. */
|
|
30
|
+
export interface CapabilitySnapshot {
|
|
31
|
+
builtAt: number;
|
|
32
|
+
cards: CapabilityCard[];
|
|
33
|
+
warnings: string[];
|
|
34
|
+
}
|
|
35
|
+
/** Minimal shape of the host services this module reads. */
|
|
36
|
+
export interface CapabilitySources {
|
|
37
|
+
tools?: {
|
|
38
|
+
definitions?: (scope?: unknown, toolSet?: unknown) => readonly unknown[];
|
|
39
|
+
get?: (name: string, scope?: unknown) => unknown;
|
|
40
|
+
} | undefined;
|
|
41
|
+
skills?: {
|
|
42
|
+
list?: (options?: Record<string, unknown>) => Promise<readonly unknown[]>;
|
|
43
|
+
} | undefined;
|
|
44
|
+
}
|
|
45
|
+
/** Tokenize one intent/name for the lexical scorer (letters, digits, CJK). */
|
|
46
|
+
export declare function tokenize(text: string): string[];
|
|
47
|
+
/** Infer risk/permission from a tool name, description and parameter schema. */
|
|
48
|
+
export declare function inferRisk(name: string, description: string, parameters?: Record<string, unknown>): CapabilityCard['risk'] & {
|
|
49
|
+
permission: CapabilityCard['permission'];
|
|
50
|
+
};
|
|
51
|
+
/** Build one capability snapshot from the live host services. */
|
|
52
|
+
export declare function buildCapabilitySnapshot(sources: CapabilitySources, scope?: unknown): Promise<CapabilitySnapshot>;
|
|
53
|
+
/** Card projection returned by tools: drop the full input schema payload. */
|
|
54
|
+
export declare function publicCard(card: CapabilityCard): Omit<CapabilityCard, 'input'>;
|
|
55
|
+
/** One ranked capability hit. */
|
|
56
|
+
export interface CapabilityHit {
|
|
57
|
+
card: CapabilityCard;
|
|
58
|
+
score: number;
|
|
59
|
+
why: string[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Rank capability cards against an intent and optional filters.
|
|
63
|
+
* @param cards - snapshot cards.
|
|
64
|
+
* @param intent - what the caller wants to do.
|
|
65
|
+
* @param options - kind/risk filters and pagination.
|
|
66
|
+
* @returns ranked hits and the total before paging.
|
|
67
|
+
*/
|
|
68
|
+
export declare function searchCapabilities(cards: readonly CapabilityCard[], intent: string, options?: {
|
|
69
|
+
kinds?: readonly CapabilityCard['kind'][];
|
|
70
|
+
riskMax?: 'read' | 'write' | 'exec';
|
|
71
|
+
limit?: number;
|
|
72
|
+
offset?: number;
|
|
73
|
+
availableOnly?: boolean;
|
|
74
|
+
}): {
|
|
75
|
+
hits: CapabilityHit[];
|
|
76
|
+
total: number;
|
|
77
|
+
};
|
|
78
|
+
/** One preflight result. */
|
|
79
|
+
export interface PreflightResult {
|
|
80
|
+
ok: boolean;
|
|
81
|
+
card?: CapabilityCard;
|
|
82
|
+
admitted: boolean;
|
|
83
|
+
schema?: {
|
|
84
|
+
valid: boolean;
|
|
85
|
+
violations: string[];
|
|
86
|
+
};
|
|
87
|
+
requires: {
|
|
88
|
+
approval: 'none' | 'ask';
|
|
89
|
+
sandbox: 'none' | 'write' | 'any';
|
|
90
|
+
};
|
|
91
|
+
sideEffects: string[];
|
|
92
|
+
next: {
|
|
93
|
+
callable: boolean;
|
|
94
|
+
suggestion?: string;
|
|
95
|
+
};
|
|
96
|
+
error?: string;
|
|
97
|
+
warnings: string[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check whether one capability can be called with the given arguments right
|
|
101
|
+
* now: existence/visibility, argument schema, predicted approval/sandbox and
|
|
102
|
+
* side effects. It never executes the target.
|
|
103
|
+
*/
|
|
104
|
+
export declare function preflightCapability(snapshot: CapabilitySnapshot, target: string, args?: Record<string, unknown>, sources?: CapabilitySources, scope?: unknown): PreflightResult;
|
|
105
|
+
/** Build `capability_search` and `capability_preflight` bound to the host registries. */
|
|
106
|
+
export declare function makeCapabilityTools(sources: CapabilitySources): readonly [import("@deepseek-ai/dsh-tools").ToolDefinition, import("@deepseek-ai/dsh-tools").ToolDefinition];
|
|
107
|
+
/** ToolRunContext re-export keeps the module self-describing for tests. */
|
|
108
|
+
export type { ToolRunContext };
|
|
109
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability index: which tool/skill/MCP action can do a job, what it costs and
|
|
3
|
+
* what it may touch. This is a thin adapter over the DSH registries the host
|
|
4
|
+
* already keeps (tool definitions, skill catalog): it does not re-implement
|
|
5
|
+
* discovery, it adds intent matching, risk labels and a preflight check.
|
|
6
|
+
* @module dsh-locator/capabilities
|
|
7
|
+
*/
|
|
8
|
+
import { defineTool, validateJsonSchemaValue } from '@deepseek-ai/dsh-tools';
|
|
9
|
+
const WRITE_WORDS = ['write', 'edit', 'delete', 'remove', 'move', 'rename', 'mkdir', 'install', 'uninstall', 'publish', 'patch', 'apply'];
|
|
10
|
+
const EXEC_WORDS = ['bash', 'shell', 'execute', 'terminal', 'run_code', 'spawn', 'command'];
|
|
11
|
+
const ALIASES = {
|
|
12
|
+
文件: ['file', 'files', 'path'], 搜索: ['search', 'find', 'grep'], 写: ['write', 'edit'], 删除: ['delete', 'remove'],
|
|
13
|
+
运行: ['run', 'exec', 'bash'], 命令: ['command', 'shell'], 网页: ['web', 'http', 'url'], 截图: ['screenshot', 'screen'],
|
|
14
|
+
测试: ['test'], 安装: ['install'], 插件: ['plugin'], 技能: ['skill'], 工具: ['tool'],
|
|
15
|
+
};
|
|
16
|
+
/** Tokenize one intent/name for the lexical scorer (letters, digits, CJK). */
|
|
17
|
+
export function tokenize(text) {
|
|
18
|
+
const lowered = text.toLowerCase();
|
|
19
|
+
const ascii = lowered.match(/[a-z0-9_]{2,}/g) ?? [];
|
|
20
|
+
const cjk = lowered.match(/[\u4e00-\u9fff]{2}/g) ?? [];
|
|
21
|
+
const expanded = [...ascii, ...cjk];
|
|
22
|
+
for (const [key, values] of Object.entries(ALIASES)) {
|
|
23
|
+
if (lowered.includes(key))
|
|
24
|
+
expanded.push(...values);
|
|
25
|
+
}
|
|
26
|
+
return [...new Set(expanded)];
|
|
27
|
+
}
|
|
28
|
+
/** Infer risk/permission from a tool name, description and parameter schema. */
|
|
29
|
+
export function inferRisk(name, description, parameters) {
|
|
30
|
+
const haystack = `${name} ${description}`.toLowerCase();
|
|
31
|
+
const properties = parameters !== undefined && typeof parameters === 'object' && parameters !== null && typeof parameters.properties === 'object'
|
|
32
|
+
? Object.keys(parameters.properties)
|
|
33
|
+
: [];
|
|
34
|
+
const actions = [];
|
|
35
|
+
let level = 'read';
|
|
36
|
+
if (EXEC_WORDS.some(word => haystack.includes(word)) || properties.includes('command') || properties.includes('cmd')) {
|
|
37
|
+
level = 'exec';
|
|
38
|
+
actions.push('may execute a process');
|
|
39
|
+
}
|
|
40
|
+
if (WRITE_WORDS.some(word => haystack.includes(word)) || properties.includes('content') || properties.includes('sandbox_permissions')) {
|
|
41
|
+
if (level !== 'exec')
|
|
42
|
+
level = 'write';
|
|
43
|
+
actions.push('may modify state');
|
|
44
|
+
}
|
|
45
|
+
if (properties.includes('sandbox_permissions'))
|
|
46
|
+
actions.push('can request escalated sandbox permissions');
|
|
47
|
+
return {
|
|
48
|
+
level,
|
|
49
|
+
actions: [...new Set(actions)],
|
|
50
|
+
basis: properties.length > 0 ? 'schema' : 'name',
|
|
51
|
+
permission: { approval: level === 'read' ? 'none' : 'ask', sandbox: level === 'read' ? 'none' : level === 'exec' ? 'any' : 'write' },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Convert one DSH ToolDefinition into a capability card. */
|
|
55
|
+
function toolCard(definition) {
|
|
56
|
+
if (typeof definition !== 'object' || definition === null)
|
|
57
|
+
return undefined;
|
|
58
|
+
const record = definition;
|
|
59
|
+
if (typeof record.name !== 'string' || record.name === '')
|
|
60
|
+
return undefined;
|
|
61
|
+
const name = record.name;
|
|
62
|
+
const description = typeof record.description === 'string' ? record.description : '';
|
|
63
|
+
const parameters = typeof record.parameters === 'object' && record.parameters !== null ? record.parameters : undefined;
|
|
64
|
+
const risk = inferRisk(name, description, parameters);
|
|
65
|
+
const mcpParts = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(name);
|
|
66
|
+
const kind = mcpParts !== null ? 'mcp' : 'tool';
|
|
67
|
+
const display = mcpParts !== null ? `${mcpParts[1]}/${mcpParts[2]}` : name;
|
|
68
|
+
return {
|
|
69
|
+
id: kind === 'mcp' ? `mcp:${display}` : `tool:${name}`,
|
|
70
|
+
kind,
|
|
71
|
+
name: display,
|
|
72
|
+
summary: description.split('\n')[0]?.slice(0, 240) ?? '',
|
|
73
|
+
...(parameters === undefined ? {} : { input: parameters }),
|
|
74
|
+
tags: tokenize(`${name} ${description}`).slice(0, 12),
|
|
75
|
+
risk: { level: risk.level, actions: risk.actions, basis: risk.basis },
|
|
76
|
+
permission: risk.permission,
|
|
77
|
+
state: 'available',
|
|
78
|
+
source: 'tools',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Convert one SkillSummary into a capability card. */
|
|
82
|
+
function skillCard(skill) {
|
|
83
|
+
if (typeof skill !== 'object' || skill === null)
|
|
84
|
+
return undefined;
|
|
85
|
+
const record = skill;
|
|
86
|
+
if (typeof record.name !== 'string' || record.name === '')
|
|
87
|
+
return undefined;
|
|
88
|
+
const summary = `${typeof record.description === 'string' ? record.description : ''}${typeof record.whenToUse === 'string' ? ` · ${record.whenToUse}` : ''}`.trim();
|
|
89
|
+
const invocation = typeof record.invocation === 'object' && record.invocation !== null ? record.invocation : undefined;
|
|
90
|
+
return {
|
|
91
|
+
id: `skill:${record.name}`,
|
|
92
|
+
kind: 'skill',
|
|
93
|
+
name: record.name,
|
|
94
|
+
summary: summary.slice(0, 240),
|
|
95
|
+
tags: tokenize(`${record.name} ${summary}`).slice(0, 12),
|
|
96
|
+
risk: { level: 'read', actions: ['loads instructions, no direct side effects'], basis: 'name' },
|
|
97
|
+
permission: { approval: 'none', sandbox: 'none' },
|
|
98
|
+
state: invocation?.modelInvocable === false ? 'unknown' : 'available',
|
|
99
|
+
source: 'skills',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Build one capability snapshot from the live host services. */
|
|
103
|
+
export async function buildCapabilitySnapshot(sources, scope) {
|
|
104
|
+
const warnings = [];
|
|
105
|
+
const cards = [];
|
|
106
|
+
try {
|
|
107
|
+
const definitions = sources.tools?.definitions?.(scope) ?? [];
|
|
108
|
+
for (const definition of definitions) {
|
|
109
|
+
const card = toolCard(definition);
|
|
110
|
+
if (card !== undefined)
|
|
111
|
+
cards.push(card);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
warnings.push(`tool-catalog-unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
116
|
+
}
|
|
117
|
+
if (sources.skills?.list !== undefined) {
|
|
118
|
+
try {
|
|
119
|
+
const skills = await sources.skills.list(scope === undefined ? {} : { scope });
|
|
120
|
+
for (const skill of skills) {
|
|
121
|
+
const card = skillCard(skill);
|
|
122
|
+
if (card !== undefined)
|
|
123
|
+
cards.push(card);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
warnings.push(`skill-catalog-unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
warnings.push('skill-service-unavailable');
|
|
132
|
+
}
|
|
133
|
+
cards.sort((left, right) => left.id.localeCompare(right.id));
|
|
134
|
+
return { builtAt: Date.now(), cards, warnings };
|
|
135
|
+
}
|
|
136
|
+
/** Card projection returned by tools: drop the full input schema payload. */
|
|
137
|
+
export function publicCard(card) {
|
|
138
|
+
const { input: _input, ...rest } = card;
|
|
139
|
+
return rest;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Rank capability cards against an intent and optional filters.
|
|
143
|
+
* @param cards - snapshot cards.
|
|
144
|
+
* @param intent - what the caller wants to do.
|
|
145
|
+
* @param options - kind/risk filters and pagination.
|
|
146
|
+
* @returns ranked hits and the total before paging.
|
|
147
|
+
*/
|
|
148
|
+
export function searchCapabilities(cards, intent, options = {}) {
|
|
149
|
+
const terms = tokenize(intent);
|
|
150
|
+
const limit = Math.max(1, Math.min(50, options.limit ?? 10));
|
|
151
|
+
const offset = Math.max(0, options.offset ?? 0);
|
|
152
|
+
const matches = cards.filter(card => {
|
|
153
|
+
if (options.kinds !== undefined && options.kinds.length > 0 && !options.kinds.includes(card.kind))
|
|
154
|
+
return false;
|
|
155
|
+
if (options.availableOnly === true && card.state !== 'available')
|
|
156
|
+
return false;
|
|
157
|
+
if (options.riskMax !== undefined) {
|
|
158
|
+
const order = { read: 0, write: 1, exec: 2 };
|
|
159
|
+
if (order[card.risk.level] > order[options.riskMax])
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
});
|
|
164
|
+
const scored = [];
|
|
165
|
+
for (const card of matches) {
|
|
166
|
+
const haystack = tokenize(`${card.name} ${card.summary} ${card.tags.join(' ')}`);
|
|
167
|
+
const why = [];
|
|
168
|
+
let score = 0;
|
|
169
|
+
for (const term of terms) {
|
|
170
|
+
if (card.name.toLowerCase().includes(term)) {
|
|
171
|
+
score += 6;
|
|
172
|
+
why.push(`name:${term}`);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (haystack.includes(term)) {
|
|
176
|
+
score += 2;
|
|
177
|
+
why.push(`text:${term}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (terms.length === 0) {
|
|
181
|
+
score = 1;
|
|
182
|
+
why.push('intent-empty: lists capabilities');
|
|
183
|
+
}
|
|
184
|
+
if (score > 0)
|
|
185
|
+
scored.push({ card, score, why: why.slice(0, 6) });
|
|
186
|
+
}
|
|
187
|
+
scored.sort((left, right) => right.score - left.score || left.card.id.localeCompare(right.card.id));
|
|
188
|
+
return { hits: scored.slice(offset, offset + limit), total: scored.length };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Check whether one capability can be called with the given arguments right
|
|
192
|
+
* now: existence/visibility, argument schema, predicted approval/sandbox and
|
|
193
|
+
* side effects. It never executes the target.
|
|
194
|
+
*/
|
|
195
|
+
export function preflightCapability(snapshot, target, args, sources, scope) {
|
|
196
|
+
const normalized = target.trim();
|
|
197
|
+
const card = snapshot.cards.find(entry => entry.id === normalized || entry.name === normalized || entry.id === `tool:${normalized}` || entry.id === `mcp:${normalized}` || entry.id === `skill:${normalized}`);
|
|
198
|
+
if (card === undefined) {
|
|
199
|
+
return { ok: false, admitted: false, requires: { approval: 'none', sandbox: 'none' }, sideEffects: [], next: { callable: false }, error: 'capability-not-found', warnings: [] };
|
|
200
|
+
}
|
|
201
|
+
const warnings = [...snapshot.warnings];
|
|
202
|
+
let visible = true;
|
|
203
|
+
if (card.kind !== 'skill' && sources?.tools?.get !== undefined) {
|
|
204
|
+
try {
|
|
205
|
+
visible = sources.tools.get(card.kind === 'mcp' ? card.name.replace('/', '__') : card.name, scope) !== undefined;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
visible = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
let schema;
|
|
212
|
+
if (args !== undefined && card.input !== undefined) {
|
|
213
|
+
try {
|
|
214
|
+
const violations = validateJsonSchemaValue(card.input, args);
|
|
215
|
+
schema = { valid: violations.length === 0, violations };
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
schema = { valid: false, violations: [error instanceof Error ? error.message : String(error)] };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const callable = visible && (schema?.valid ?? true);
|
|
222
|
+
const suggestion = callable
|
|
223
|
+
? undefined
|
|
224
|
+
: !visible
|
|
225
|
+
? 'capability is registered but not visible in this agent scope'
|
|
226
|
+
: schema?.valid === false
|
|
227
|
+
? 'fix the arguments against the declared schema'
|
|
228
|
+
: 'capability is not callable from this scope';
|
|
229
|
+
return {
|
|
230
|
+
ok: true,
|
|
231
|
+
card: publicCard(card),
|
|
232
|
+
admitted: callable,
|
|
233
|
+
...(schema === undefined ? {} : { schema }),
|
|
234
|
+
requires: card.permission,
|
|
235
|
+
sideEffects: card.risk.actions,
|
|
236
|
+
next: { callable, ...(suggestion === undefined ? {} : { suggestion }) },
|
|
237
|
+
warnings,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const CARD_SCHEMA = {
|
|
241
|
+
type: 'object',
|
|
242
|
+
additionalProperties: false,
|
|
243
|
+
properties: {
|
|
244
|
+
id: { type: 'string' }, kind: { type: 'string', enum: ['tool', 'mcp', 'skill'] },
|
|
245
|
+
name: { type: 'string' }, summary: { type: 'string' },
|
|
246
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
247
|
+
risk: { type: 'object', additionalProperties: false, properties: { level: { type: 'string' }, actions: { type: 'array', items: { type: 'string' } }, basis: { type: 'string' } } },
|
|
248
|
+
permission: { type: 'object', additionalProperties: false, properties: { approval: { type: 'string' }, sandbox: { type: 'string' } } },
|
|
249
|
+
state: { type: 'string' }, source: { type: 'string' },
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
/** Build `capability_search` and `capability_preflight` bound to the host registries. */
|
|
253
|
+
export function makeCapabilityTools(sources) {
|
|
254
|
+
let cached;
|
|
255
|
+
const snapshotFor = async (scope) => {
|
|
256
|
+
if (cached === undefined || Date.now() - cached.builtAt > 60_000)
|
|
257
|
+
cached = await buildCapabilitySnapshot(sources, scope);
|
|
258
|
+
return cached;
|
|
259
|
+
};
|
|
260
|
+
const searchTool = defineTool({
|
|
261
|
+
name: 'capability_search',
|
|
262
|
+
description: [
|
|
263
|
+
'Find the tool, MCP action or skill that can do a job (dsh-locator capability adapter).',
|
|
264
|
+
'',
|
|
265
|
+
'Use it when the caller knows the goal but not which capability performs it: pass the intent in natural language and filter by kind/risk. Every hit carries risk and permission hints plus the card id usable with `capability_preflight`.',
|
|
266
|
+
'',
|
|
267
|
+
'This is not a file search: it indexes the live DSH capability registry (tool definitions and the skill catalog), not file names or bodies.',
|
|
268
|
+
].join('\n'),
|
|
269
|
+
parameters: {
|
|
270
|
+
intent: { type: 'string', required: true, description: 'What should be done, in natural language (English or Chinese).' },
|
|
271
|
+
kinds: { type: 'array', items: { type: 'string', enum: ['tool', 'mcp', 'skill'] }, description: 'Restrict to these capability kinds.' },
|
|
272
|
+
riskMax: { type: 'string', enum: ['read', 'write', 'exec'], description: 'Only return capabilities at or below this risk level.' },
|
|
273
|
+
availableOnly: { type: 'boolean', description: 'Only return cards that are currently visible/available.' },
|
|
274
|
+
limit: { type: 'integer', description: 'Maximum hits (default 10, at most 50).' },
|
|
275
|
+
offset: { type: 'integer', description: 'Skip this many ranked hits.' },
|
|
276
|
+
},
|
|
277
|
+
output: {
|
|
278
|
+
schema: {
|
|
279
|
+
type: 'object',
|
|
280
|
+
additionalProperties: false,
|
|
281
|
+
properties: {
|
|
282
|
+
ok: { type: 'boolean', required: true },
|
|
283
|
+
intent: { type: 'string' }, total: { type: 'integer' }, returned: { type: 'integer' },
|
|
284
|
+
hits: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { card: CARD_SCHEMA, score: { type: 'number' }, why: { type: 'array', items: { type: 'string' } } } } },
|
|
285
|
+
warnings: { type: 'array', items: { type: 'string' } }, error: { type: 'string' },
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
render: (_args, value) => {
|
|
289
|
+
const v = value;
|
|
290
|
+
if (!v.ok)
|
|
291
|
+
return [{ type: 'text', text: `capability_search failed: ${v.error ?? 'unknown error'}` }];
|
|
292
|
+
const lines = [`capability_search ${JSON.stringify(v.intent ?? '')}: ${String(v.total ?? 0)} match(es)`];
|
|
293
|
+
for (const hit of v.hits ?? []) {
|
|
294
|
+
lines.push(`- ${hit.card.id} [${hit.card.kind}] risk=${hit.card.risk.level} approval=${hit.card.permission.approval} — ${hit.card.summary}`);
|
|
295
|
+
}
|
|
296
|
+
if ((v.warnings ?? []).length > 0)
|
|
297
|
+
lines.push(`warnings: ${[...new Set(v.warnings ?? [])].join(', ')}`);
|
|
298
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
async execute(args, exec) {
|
|
302
|
+
const snapshot = await snapshotFor(exec?.agent);
|
|
303
|
+
const kinds = Array.isArray(args.kinds) ? args.kinds.filter((kind) => kind === 'tool' || kind === 'mcp' || kind === 'skill') : undefined;
|
|
304
|
+
const riskMax = args.riskMax === 'read' || args.riskMax === 'write' || args.riskMax === 'exec' ? args.riskMax : undefined;
|
|
305
|
+
const result = searchCapabilities(snapshot.cards, args.intent, { ...(kinds === undefined ? {} : { kinds }), ...(riskMax === undefined ? {} : { riskMax }), limit: Math.max(1, Math.min(50, args.limit ?? 10)), offset: Math.max(0, args.offset ?? 0), availableOnly: args.availableOnly === true });
|
|
306
|
+
const hits = result.hits.map(hit => ({ ...hit, card: publicCard(hit.card) }));
|
|
307
|
+
return { ok: true, intent: args.intent, total: result.total, returned: hits.length, hits, warnings: snapshot.warnings };
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
const preflightTool = defineTool({
|
|
311
|
+
name: 'capability_preflight',
|
|
312
|
+
description: [
|
|
313
|
+
'Check one capability before calling it (dsh-locator capability adapter): whether it exists and is visible, whether the arguments match its declared schema, and which approval/sandbox/side effects it implies.',
|
|
314
|
+
'',
|
|
315
|
+
'It never executes the target. Use it when a plan depends on a tool/MCP action/skill and the caller needs to know the cost or permission risk first.',
|
|
316
|
+
].join('\n'),
|
|
317
|
+
parameters: {
|
|
318
|
+
capability: { type: 'string', required: true, description: 'Card id (`tool:<name>`, `mcp:<server>/<action>`, `skill:<name>`) or plain name from capability_search.' },
|
|
319
|
+
argsJson: { type: 'string', description: 'Candidate arguments as a JSON object string to validate against the declared schema.' },
|
|
320
|
+
},
|
|
321
|
+
output: {
|
|
322
|
+
schema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
additionalProperties: false,
|
|
325
|
+
properties: {
|
|
326
|
+
ok: { type: 'boolean', required: true },
|
|
327
|
+
card: CARD_SCHEMA,
|
|
328
|
+
admitted: { type: 'boolean' },
|
|
329
|
+
schema: { type: 'object', additionalProperties: false, properties: { valid: { type: 'boolean' }, violations: { type: 'array', items: { type: 'string' } } } },
|
|
330
|
+
requires: { type: 'object', additionalProperties: false, properties: { approval: { type: 'string' }, sandbox: { type: 'string' } } },
|
|
331
|
+
sideEffects: { type: 'array', items: { type: 'string' } },
|
|
332
|
+
next: { type: 'object', additionalProperties: false, properties: { callable: { type: 'boolean' }, suggestion: { type: 'string' } } },
|
|
333
|
+
error: { type: 'string' }, warnings: { type: 'array', items: { type: 'string' } },
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
render: (_args, value) => {
|
|
337
|
+
const v = value;
|
|
338
|
+
if (!v.ok)
|
|
339
|
+
return [{ type: 'text', text: `capability_preflight failed: ${v.error ?? 'unknown error'}` }];
|
|
340
|
+
const lines = [
|
|
341
|
+
`capability_preflight ${v.card?.id ?? ''}: callable=${String(v.next?.callable ?? v.admitted ?? false)}`,
|
|
342
|
+
` risk: ${v.card?.risk.level ?? '?'} · approval=${v.requires?.approval ?? '?'} · sandbox=${v.requires?.sandbox ?? '?'}`,
|
|
343
|
+
` schema: ${v.schema === undefined ? 'not checked (no args/schema)' : v.schema.valid ? 'valid' : `invalid (${v.schema.violations.join('; ')})`}`,
|
|
344
|
+
];
|
|
345
|
+
if ((v.sideEffects ?? []).length > 0)
|
|
346
|
+
lines.push(` side effects: ${(v.sideEffects ?? []).join('; ')}`);
|
|
347
|
+
if (v.next?.suggestion !== undefined)
|
|
348
|
+
lines.push(` suggestion: ${v.next.suggestion}`);
|
|
349
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
async execute(args, exec) {
|
|
353
|
+
const snapshot = await snapshotFor(exec?.agent);
|
|
354
|
+
let candidate;
|
|
355
|
+
if (typeof args.argsJson === 'string' && args.argsJson.trim() !== '') {
|
|
356
|
+
try {
|
|
357
|
+
const parsed = JSON.parse(args.argsJson);
|
|
358
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
359
|
+
return { ok: false, admitted: false, requires: { approval: 'none', sandbox: 'none' }, sideEffects: [], next: { callable: false }, error: 'invalid-args-json', warnings: [] };
|
|
360
|
+
}
|
|
361
|
+
candidate = parsed;
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
return { ok: false, admitted: false, requires: { approval: 'none', sandbox: 'none' }, sideEffects: [], next: { callable: false }, error: 'invalid-args-json', warnings: [] };
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return preflightCapability(snapshot, args.capability, candidate, sources, exec?.agent);
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
return [searchTool, preflightTool];
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAYzC,OAAO,EAAE,YAAY,IAAI,MAAM,EAAE,CAAA;AAEjC,0BAA0B;AAC1B,eAAO,MAAM,IAAI,gBAAgB,CAAA;AAEjC,2DAA2D;AAC3D,eAAO,MAAM,MAAM,UAAY,CAAA;AAoC/B;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAoHxD"}
|
package/lib/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { makeReindexTool } from "./reindex.js";
|
|
|
11
11
|
import { registerHttp } from "./http.js";
|
|
12
12
|
import { resolveBinary, resolveRoots, resolveStateDir } from "./paths.js";
|
|
13
13
|
import { LocatorRuntime } from "./runtime.js";
|
|
14
|
+
import { makeCapabilityTools } from "./capabilities.js";
|
|
14
15
|
import { makeCiteTool, makeResolveTool } from "./ref-tools.js";
|
|
15
16
|
import { makeRebuildTool, makeSearchTool, makeStatusTool } from "./tools.js";
|
|
16
17
|
export { ConfigSchema as Config };
|
|
@@ -160,6 +161,15 @@ export function apply(ctx, config) {
|
|
|
160
161
|
ctx.tools.register(makeExportTool(rt));
|
|
161
162
|
ctx.tools.register(makeResolveTool(rt, content));
|
|
162
163
|
ctx.tools.register(makeCiteTool());
|
|
164
|
+
// Capability adapter: read the host's tool registry and skill catalog instead
|
|
165
|
+
// of duplicating discovery. Optional services stay optional.
|
|
166
|
+
const skillsService = ctx.get?.('skills');
|
|
167
|
+
const capabilitySources = {
|
|
168
|
+
tools: ctx.tools,
|
|
169
|
+
...(skillsService === undefined ? {} : { skills: skillsService }),
|
|
170
|
+
};
|
|
171
|
+
for (const tool of makeCapabilityTools(capabilitySources))
|
|
172
|
+
ctx.tools.register(tool);
|
|
163
173
|
if (content !== undefined) {
|
|
164
174
|
ctx.tools.register(makeFindTool(content, ensureContent, roots, config.allowCrossWorkspaceSessions));
|
|
165
175
|
ctx.tools.register(makeReindexTool(content, ensureContent));
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-locator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Whole-disk, millisecond file search for DeepSeek Harness without Everything: a self-built cross-platform index, an Everything-style query language, agent tools and a Web search panel (Ctrl+Shift+F). Windows, macOS and Linux.",
|
|
5
5
|
"author": "PerryLink contributors",
|
|
6
6
|
"repository": {
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability index: which tool/skill/MCP action can do a job, what it costs and
|
|
3
|
+
* what it may touch. This is a thin adapter over the DSH registries the host
|
|
4
|
+
* already keeps (tool definitions, skill catalog): it does not re-implement
|
|
5
|
+
* discovery, it adds intent matching, risk labels and a preflight check.
|
|
6
|
+
* @module dsh-locator/capabilities
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { defineTool, validateJsonSchemaValue } from '@deepseek-ai/dsh-tools'
|
|
10
|
+
import type { ToolRunContext } from '@deepseek-ai/dsh-tools'
|
|
11
|
+
|
|
12
|
+
/** One capability card. */
|
|
13
|
+
export interface CapabilityCard {
|
|
14
|
+
id: string
|
|
15
|
+
kind: 'tool' | 'mcp' | 'skill'
|
|
16
|
+
name: string
|
|
17
|
+
summary: string
|
|
18
|
+
input?: Record<string, unknown>
|
|
19
|
+
tags: string[]
|
|
20
|
+
risk: { level: 'read' | 'write' | 'exec'; actions: string[]; basis: 'schema' | 'name' }
|
|
21
|
+
permission: { approval: 'none' | 'ask'; sandbox: 'none' | 'write' | 'any' }
|
|
22
|
+
state: 'available' | 'unknown'
|
|
23
|
+
source: 'tools' | 'skills'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One snapshot of the live capability surface. */
|
|
27
|
+
export interface CapabilitySnapshot {
|
|
28
|
+
builtAt: number
|
|
29
|
+
cards: CapabilityCard[]
|
|
30
|
+
warnings: string[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Minimal shape of the host services this module reads. */
|
|
34
|
+
export interface CapabilitySources {
|
|
35
|
+
tools?: {
|
|
36
|
+
definitions?: (scope?: unknown, toolSet?: unknown) => readonly unknown[]
|
|
37
|
+
get?: (name: string, scope?: unknown) => unknown
|
|
38
|
+
} | undefined
|
|
39
|
+
skills?: { list?: (options?: Record<string, unknown>) => Promise<readonly unknown[]> } | undefined
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const WRITE_WORDS = ['write', 'edit', 'delete', 'remove', 'move', 'rename', 'mkdir', 'install', 'uninstall', 'publish', 'patch', 'apply']
|
|
43
|
+
const EXEC_WORDS = ['bash', 'shell', 'execute', 'terminal', 'run_code', 'spawn', 'command']
|
|
44
|
+
const ALIASES: Record<string, string[]> = {
|
|
45
|
+
文件: ['file', 'files', 'path'], 搜索: ['search', 'find', 'grep'], 写: ['write', 'edit'], 删除: ['delete', 'remove'],
|
|
46
|
+
运行: ['run', 'exec', 'bash'], 命令: ['command', 'shell'], 网页: ['web', 'http', 'url'], 截图: ['screenshot', 'screen'],
|
|
47
|
+
测试: ['test'], 安装: ['install'], 插件: ['plugin'], 技能: ['skill'], 工具: ['tool'],
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Tokenize one intent/name for the lexical scorer (letters, digits, CJK). */
|
|
51
|
+
export function tokenize(text: string): string[] {
|
|
52
|
+
const lowered = text.toLowerCase()
|
|
53
|
+
const ascii = lowered.match(/[a-z0-9_]{2,}/g) ?? []
|
|
54
|
+
const cjk = lowered.match(/[\u4e00-\u9fff]{2}/g) ?? []
|
|
55
|
+
const expanded = [...ascii, ...cjk]
|
|
56
|
+
for (const [key, values] of Object.entries(ALIASES)) {
|
|
57
|
+
if (lowered.includes(key)) expanded.push(...values)
|
|
58
|
+
}
|
|
59
|
+
return [...new Set(expanded)]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Infer risk/permission from a tool name, description and parameter schema. */
|
|
63
|
+
export function inferRisk(name: string, description: string, parameters?: Record<string, unknown>): CapabilityCard['risk'] & { permission: CapabilityCard['permission'] } {
|
|
64
|
+
const haystack = `${name} ${description}`.toLowerCase()
|
|
65
|
+
const properties = parameters !== undefined && typeof parameters === 'object' && parameters !== null && typeof (parameters as { properties?: unknown }).properties === 'object'
|
|
66
|
+
? Object.keys((parameters as { properties: Record<string, unknown> }).properties)
|
|
67
|
+
: []
|
|
68
|
+
const actions: string[] = []
|
|
69
|
+
let level: 'read' | 'write' | 'exec' = 'read'
|
|
70
|
+
if (EXEC_WORDS.some(word => haystack.includes(word)) || properties.includes('command') || properties.includes('cmd')) { level = 'exec'; actions.push('may execute a process') }
|
|
71
|
+
if (WRITE_WORDS.some(word => haystack.includes(word)) || properties.includes('content') || properties.includes('sandbox_permissions')) {
|
|
72
|
+
if (level !== 'exec') level = 'write'
|
|
73
|
+
actions.push('may modify state')
|
|
74
|
+
}
|
|
75
|
+
if (properties.includes('sandbox_permissions')) actions.push('can request escalated sandbox permissions')
|
|
76
|
+
return {
|
|
77
|
+
level,
|
|
78
|
+
actions: [...new Set(actions)],
|
|
79
|
+
basis: properties.length > 0 ? 'schema' : 'name',
|
|
80
|
+
permission: { approval: level === 'read' ? 'none' : 'ask', sandbox: level === 'read' ? 'none' : level === 'exec' ? 'any' : 'write' },
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Convert one DSH ToolDefinition into a capability card. */
|
|
85
|
+
function toolCard(definition: unknown): CapabilityCard | undefined {
|
|
86
|
+
if (typeof definition !== 'object' || definition === null) return undefined
|
|
87
|
+
const record = definition as { name?: unknown; description?: unknown; parameters?: unknown; output?: unknown }
|
|
88
|
+
if (typeof record.name !== 'string' || record.name === '') return undefined
|
|
89
|
+
const name = record.name
|
|
90
|
+
const description = typeof record.description === 'string' ? record.description : ''
|
|
91
|
+
const parameters = typeof record.parameters === 'object' && record.parameters !== null ? record.parameters as Record<string, unknown> : undefined
|
|
92
|
+
const risk = inferRisk(name, description, parameters)
|
|
93
|
+
const mcpParts = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(name)
|
|
94
|
+
const kind: CapabilityCard['kind'] = mcpParts !== null ? 'mcp' : 'tool'
|
|
95
|
+
const display = mcpParts !== null ? `${mcpParts[1]}/${mcpParts[2]}` : name
|
|
96
|
+
return {
|
|
97
|
+
id: kind === 'mcp' ? `mcp:${display}` : `tool:${name}`,
|
|
98
|
+
kind,
|
|
99
|
+
name: display,
|
|
100
|
+
summary: description.split('\n')[0]?.slice(0, 240) ?? '',
|
|
101
|
+
...(parameters === undefined ? {} : { input: parameters }),
|
|
102
|
+
tags: tokenize(`${name} ${description}`).slice(0, 12),
|
|
103
|
+
risk: { level: risk.level, actions: risk.actions, basis: risk.basis },
|
|
104
|
+
permission: risk.permission,
|
|
105
|
+
state: 'available',
|
|
106
|
+
source: 'tools',
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Convert one SkillSummary into a capability card. */
|
|
111
|
+
function skillCard(skill: unknown): CapabilityCard | undefined {
|
|
112
|
+
if (typeof skill !== 'object' || skill === null) return undefined
|
|
113
|
+
const record = skill as { name?: unknown; description?: unknown; whenToUse?: unknown; source?: unknown; invocation?: unknown }
|
|
114
|
+
if (typeof record.name !== 'string' || record.name === '') return undefined
|
|
115
|
+
const summary = `${typeof record.description === 'string' ? record.description : ''}${typeof record.whenToUse === 'string' ? ` · ${record.whenToUse}` : ''}`.trim()
|
|
116
|
+
const invocation = typeof record.invocation === 'object' && record.invocation !== null ? record.invocation as { modelInvocable?: unknown } : undefined
|
|
117
|
+
return {
|
|
118
|
+
id: `skill:${record.name}`,
|
|
119
|
+
kind: 'skill',
|
|
120
|
+
name: record.name,
|
|
121
|
+
summary: summary.slice(0, 240),
|
|
122
|
+
tags: tokenize(`${record.name} ${summary}`).slice(0, 12),
|
|
123
|
+
risk: { level: 'read', actions: ['loads instructions, no direct side effects'], basis: 'name' },
|
|
124
|
+
permission: { approval: 'none', sandbox: 'none' },
|
|
125
|
+
state: invocation?.modelInvocable === false ? 'unknown' : 'available',
|
|
126
|
+
source: 'skills',
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Build one capability snapshot from the live host services. */
|
|
131
|
+
export async function buildCapabilitySnapshot(sources: CapabilitySources, scope?: unknown): Promise<CapabilitySnapshot> {
|
|
132
|
+
const warnings: string[] = []
|
|
133
|
+
const cards: CapabilityCard[] = []
|
|
134
|
+
try {
|
|
135
|
+
const definitions = sources.tools?.definitions?.(scope) ?? []
|
|
136
|
+
for (const definition of definitions) {
|
|
137
|
+
const card = toolCard(definition)
|
|
138
|
+
if (card !== undefined) cards.push(card)
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
warnings.push(`tool-catalog-unavailable: ${error instanceof Error ? error.message : String(error)}`)
|
|
142
|
+
}
|
|
143
|
+
if (sources.skills?.list !== undefined) {
|
|
144
|
+
try {
|
|
145
|
+
const skills = await sources.skills.list(scope === undefined ? {} : { scope })
|
|
146
|
+
for (const skill of skills) {
|
|
147
|
+
const card = skillCard(skill)
|
|
148
|
+
if (card !== undefined) cards.push(card)
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
warnings.push(`skill-catalog-unavailable: ${error instanceof Error ? error.message : String(error)}`)
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
warnings.push('skill-service-unavailable')
|
|
155
|
+
}
|
|
156
|
+
cards.sort((left, right) => left.id.localeCompare(right.id))
|
|
157
|
+
return { builtAt: Date.now(), cards, warnings }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Card projection returned by tools: drop the full input schema payload. */
|
|
161
|
+
export function publicCard(card: CapabilityCard): Omit<CapabilityCard, 'input'> {
|
|
162
|
+
const { input: _input, ...rest } = card
|
|
163
|
+
return rest
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** One ranked capability hit. */
|
|
167
|
+
export interface CapabilityHit {
|
|
168
|
+
card: CapabilityCard
|
|
169
|
+
score: number
|
|
170
|
+
why: string[]
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Rank capability cards against an intent and optional filters.
|
|
175
|
+
* @param cards - snapshot cards.
|
|
176
|
+
* @param intent - what the caller wants to do.
|
|
177
|
+
* @param options - kind/risk filters and pagination.
|
|
178
|
+
* @returns ranked hits and the total before paging.
|
|
179
|
+
*/
|
|
180
|
+
export function searchCapabilities(
|
|
181
|
+
cards: readonly CapabilityCard[],
|
|
182
|
+
intent: string,
|
|
183
|
+
options: { kinds?: readonly CapabilityCard['kind'][]; riskMax?: 'read' | 'write' | 'exec'; limit?: number; offset?: number; availableOnly?: boolean } = {},
|
|
184
|
+
): { hits: CapabilityHit[]; total: number } {
|
|
185
|
+
const terms = tokenize(intent)
|
|
186
|
+
const limit = Math.max(1, Math.min(50, options.limit ?? 10))
|
|
187
|
+
const offset = Math.max(0, options.offset ?? 0)
|
|
188
|
+
const matches = cards.filter(card => {
|
|
189
|
+
if (options.kinds !== undefined && options.kinds.length > 0 && !options.kinds.includes(card.kind)) return false
|
|
190
|
+
if (options.availableOnly === true && card.state !== 'available') return false
|
|
191
|
+
if (options.riskMax !== undefined) {
|
|
192
|
+
const order = { read: 0, write: 1, exec: 2 } as const
|
|
193
|
+
if (order[card.risk.level] > order[options.riskMax]) return false
|
|
194
|
+
}
|
|
195
|
+
return true
|
|
196
|
+
})
|
|
197
|
+
const scored: CapabilityHit[] = []
|
|
198
|
+
for (const card of matches) {
|
|
199
|
+
const haystack = tokenize(`${card.name} ${card.summary} ${card.tags.join(' ')}`)
|
|
200
|
+
const why: string[] = []
|
|
201
|
+
let score = 0
|
|
202
|
+
for (const term of terms) {
|
|
203
|
+
if (card.name.toLowerCase().includes(term)) { score += 6; why.push(`name:${term}`); continue }
|
|
204
|
+
if (haystack.includes(term)) { score += 2; why.push(`text:${term}`) }
|
|
205
|
+
}
|
|
206
|
+
if (terms.length === 0) { score = 1; why.push('intent-empty: lists capabilities') }
|
|
207
|
+
if (score > 0) scored.push({ card, score, why: why.slice(0, 6) })
|
|
208
|
+
}
|
|
209
|
+
scored.sort((left, right) => right.score - left.score || left.card.id.localeCompare(right.card.id))
|
|
210
|
+
return { hits: scored.slice(offset, offset + limit), total: scored.length }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** One preflight result. */
|
|
214
|
+
export interface PreflightResult {
|
|
215
|
+
ok: boolean
|
|
216
|
+
card?: CapabilityCard
|
|
217
|
+
admitted: boolean
|
|
218
|
+
schema?: { valid: boolean; violations: string[] }
|
|
219
|
+
requires: { approval: 'none' | 'ask'; sandbox: 'none' | 'write' | 'any' }
|
|
220
|
+
sideEffects: string[]
|
|
221
|
+
next: { callable: boolean; suggestion?: string }
|
|
222
|
+
error?: string
|
|
223
|
+
warnings: string[]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Check whether one capability can be called with the given arguments right
|
|
228
|
+
* now: existence/visibility, argument schema, predicted approval/sandbox and
|
|
229
|
+
* side effects. It never executes the target.
|
|
230
|
+
*/
|
|
231
|
+
export function preflightCapability(
|
|
232
|
+
snapshot: CapabilitySnapshot,
|
|
233
|
+
target: string,
|
|
234
|
+
args?: Record<string, unknown>,
|
|
235
|
+
sources?: CapabilitySources,
|
|
236
|
+
scope?: unknown,
|
|
237
|
+
): PreflightResult {
|
|
238
|
+
const normalized = target.trim()
|
|
239
|
+
const card = snapshot.cards.find(entry => entry.id === normalized || entry.name === normalized || entry.id === `tool:${normalized}` || entry.id === `mcp:${normalized}` || entry.id === `skill:${normalized}`)
|
|
240
|
+
if (card === undefined) {
|
|
241
|
+
return { ok: false, admitted: false, requires: { approval: 'none', sandbox: 'none' }, sideEffects: [], next: { callable: false }, error: 'capability-not-found', warnings: [] }
|
|
242
|
+
}
|
|
243
|
+
const warnings = [...snapshot.warnings]
|
|
244
|
+
let visible = true
|
|
245
|
+
if (card.kind !== 'skill' && sources?.tools?.get !== undefined) {
|
|
246
|
+
try { visible = sources.tools.get(card.kind === 'mcp' ? card.name.replace('/', '__') : card.name, scope) !== undefined } catch { visible = true }
|
|
247
|
+
}
|
|
248
|
+
let schema: { valid: boolean; violations: string[] } | undefined
|
|
249
|
+
if (args !== undefined && card.input !== undefined) {
|
|
250
|
+
try {
|
|
251
|
+
const violations = validateJsonSchemaValue(card.input as unknown as Parameters<typeof validateJsonSchemaValue>[0], args)
|
|
252
|
+
schema = { valid: violations.length === 0, violations }
|
|
253
|
+
} catch (error) {
|
|
254
|
+
schema = { valid: false, violations: [error instanceof Error ? error.message : String(error)] }
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const callable = visible && (schema?.valid ?? true)
|
|
258
|
+
const suggestion = callable
|
|
259
|
+
? undefined
|
|
260
|
+
: !visible
|
|
261
|
+
? 'capability is registered but not visible in this agent scope'
|
|
262
|
+
: schema?.valid === false
|
|
263
|
+
? 'fix the arguments against the declared schema'
|
|
264
|
+
: 'capability is not callable from this scope'
|
|
265
|
+
return {
|
|
266
|
+
ok: true,
|
|
267
|
+
card: publicCard(card),
|
|
268
|
+
admitted: callable,
|
|
269
|
+
...(schema === undefined ? {} : { schema }),
|
|
270
|
+
requires: card.permission,
|
|
271
|
+
sideEffects: card.risk.actions,
|
|
272
|
+
next: { callable, ...(suggestion === undefined ? {} : { suggestion }) },
|
|
273
|
+
warnings,
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const CARD_SCHEMA = {
|
|
278
|
+
type: 'object',
|
|
279
|
+
additionalProperties: false,
|
|
280
|
+
properties: {
|
|
281
|
+
id: { type: 'string' }, kind: { type: 'string', enum: ['tool', 'mcp', 'skill'] },
|
|
282
|
+
name: { type: 'string' }, summary: { type: 'string' },
|
|
283
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
284
|
+
risk: { type: 'object', additionalProperties: false, properties: { level: { type: 'string' }, actions: { type: 'array', items: { type: 'string' } }, basis: { type: 'string' } } },
|
|
285
|
+
permission: { type: 'object', additionalProperties: false, properties: { approval: { type: 'string' }, sandbox: { type: 'string' } } },
|
|
286
|
+
state: { type: 'string' }, source: { type: 'string' },
|
|
287
|
+
},
|
|
288
|
+
} as const
|
|
289
|
+
|
|
290
|
+
/** Build `capability_search` and `capability_preflight` bound to the host registries. */
|
|
291
|
+
export function makeCapabilityTools(sources: CapabilitySources) {
|
|
292
|
+
let cached: CapabilitySnapshot | undefined
|
|
293
|
+
const snapshotFor = async (scope?: unknown): Promise<CapabilitySnapshot> => {
|
|
294
|
+
if (cached === undefined || Date.now() - cached.builtAt > 60_000) cached = await buildCapabilitySnapshot(sources, scope)
|
|
295
|
+
return cached
|
|
296
|
+
}
|
|
297
|
+
const searchTool = defineTool({
|
|
298
|
+
name: 'capability_search',
|
|
299
|
+
description: [
|
|
300
|
+
'Find the tool, MCP action or skill that can do a job (dsh-locator capability adapter).',
|
|
301
|
+
'',
|
|
302
|
+
'Use it when the caller knows the goal but not which capability performs it: pass the intent in natural language and filter by kind/risk. Every hit carries risk and permission hints plus the card id usable with `capability_preflight`.',
|
|
303
|
+
'',
|
|
304
|
+
'This is not a file search: it indexes the live DSH capability registry (tool definitions and the skill catalog), not file names or bodies.',
|
|
305
|
+
].join('\n'),
|
|
306
|
+
parameters: {
|
|
307
|
+
intent: { type: 'string', required: true, description: 'What should be done, in natural language (English or Chinese).' },
|
|
308
|
+
kinds: { type: 'array', items: { type: 'string', enum: ['tool', 'mcp', 'skill'] }, description: 'Restrict to these capability kinds.' },
|
|
309
|
+
riskMax: { type: 'string', enum: ['read', 'write', 'exec'], description: 'Only return capabilities at or below this risk level.' },
|
|
310
|
+
availableOnly: { type: 'boolean', description: 'Only return cards that are currently visible/available.' },
|
|
311
|
+
limit: { type: 'integer', description: 'Maximum hits (default 10, at most 50).' },
|
|
312
|
+
offset: { type: 'integer', description: 'Skip this many ranked hits.' },
|
|
313
|
+
},
|
|
314
|
+
output: {
|
|
315
|
+
schema: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
additionalProperties: false,
|
|
318
|
+
properties: {
|
|
319
|
+
ok: { type: 'boolean', required: true },
|
|
320
|
+
intent: { type: 'string' }, total: { type: 'integer' }, returned: { type: 'integer' },
|
|
321
|
+
hits: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { card: CARD_SCHEMA, score: { type: 'number' }, why: { type: 'array', items: { type: 'string' } } } } },
|
|
322
|
+
warnings: { type: 'array', items: { type: 'string' } }, error: { type: 'string' },
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
render: (_args, value) => {
|
|
326
|
+
const v = value as { ok: boolean; intent?: string; total?: number; hits?: Array<{ card: CapabilityCard; why: string[] }>; warnings?: string[]; error?: string }
|
|
327
|
+
if (!v.ok) return [{ type: 'text', text: `capability_search failed: ${v.error ?? 'unknown error'}` }]
|
|
328
|
+
const lines = [`capability_search ${JSON.stringify(v.intent ?? '')}: ${String(v.total ?? 0)} match(es)`]
|
|
329
|
+
for (const hit of v.hits ?? []) {
|
|
330
|
+
lines.push(`- ${hit.card.id} [${hit.card.kind}] risk=${hit.card.risk.level} approval=${hit.card.permission.approval} — ${hit.card.summary}`)
|
|
331
|
+
}
|
|
332
|
+
if ((v.warnings ?? []).length > 0) lines.push(`warnings: ${[...new Set(v.warnings ?? [])].join(', ')}`)
|
|
333
|
+
return [{ type: 'text', text: lines.join('\n') }]
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
async execute(args, exec) {
|
|
337
|
+
const snapshot = await snapshotFor(exec?.agent)
|
|
338
|
+
const kinds = Array.isArray(args.kinds) ? args.kinds.filter((kind): kind is CapabilityCard['kind'] => kind === 'tool' || kind === 'mcp' || kind === 'skill') : undefined
|
|
339
|
+
const riskMax = args.riskMax === 'read' || args.riskMax === 'write' || args.riskMax === 'exec' ? args.riskMax : undefined
|
|
340
|
+
const result = searchCapabilities(snapshot.cards, args.intent, { ...(kinds === undefined ? {} : { kinds }), ...(riskMax === undefined ? {} : { riskMax }), limit: Math.max(1, Math.min(50, args.limit ?? 10)), offset: Math.max(0, args.offset ?? 0), availableOnly: args.availableOnly === true })
|
|
341
|
+
const hits = result.hits.map(hit => ({ ...hit, card: publicCard(hit.card) }))
|
|
342
|
+
return { ok: true as const, intent: args.intent, total: result.total, returned: hits.length, hits, warnings: snapshot.warnings }
|
|
343
|
+
},
|
|
344
|
+
})
|
|
345
|
+
const preflightTool = defineTool({
|
|
346
|
+
name: 'capability_preflight',
|
|
347
|
+
description: [
|
|
348
|
+
'Check one capability before calling it (dsh-locator capability adapter): whether it exists and is visible, whether the arguments match its declared schema, and which approval/sandbox/side effects it implies.',
|
|
349
|
+
'',
|
|
350
|
+
'It never executes the target. Use it when a plan depends on a tool/MCP action/skill and the caller needs to know the cost or permission risk first.',
|
|
351
|
+
].join('\n'),
|
|
352
|
+
parameters: {
|
|
353
|
+
capability: { type: 'string', required: true, description: 'Card id (`tool:<name>`, `mcp:<server>/<action>`, `skill:<name>`) or plain name from capability_search.' },
|
|
354
|
+
argsJson: { type: 'string', description: 'Candidate arguments as a JSON object string to validate against the declared schema.' },
|
|
355
|
+
},
|
|
356
|
+
output: {
|
|
357
|
+
schema: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
additionalProperties: false,
|
|
360
|
+
properties: {
|
|
361
|
+
ok: { type: 'boolean', required: true },
|
|
362
|
+
card: CARD_SCHEMA,
|
|
363
|
+
admitted: { type: 'boolean' },
|
|
364
|
+
schema: { type: 'object', additionalProperties: false, properties: { valid: { type: 'boolean' }, violations: { type: 'array', items: { type: 'string' } } } },
|
|
365
|
+
requires: { type: 'object', additionalProperties: false, properties: { approval: { type: 'string' }, sandbox: { type: 'string' } } },
|
|
366
|
+
sideEffects: { type: 'array', items: { type: 'string' } },
|
|
367
|
+
next: { type: 'object', additionalProperties: false, properties: { callable: { type: 'boolean' }, suggestion: { type: 'string' } } },
|
|
368
|
+
error: { type: 'string' }, warnings: { type: 'array', items: { type: 'string' } },
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
render: (_args, value) => {
|
|
372
|
+
const v = value as { ok: boolean; card?: CapabilityCard; admitted?: boolean; schema?: { valid: boolean; violations: string[] }; requires?: { approval: string; sandbox: string }; sideEffects?: string[]; next?: { callable: boolean; suggestion?: string }; error?: string; warnings?: string[] }
|
|
373
|
+
if (!v.ok) return [{ type: 'text', text: `capability_preflight failed: ${v.error ?? 'unknown error'}` }]
|
|
374
|
+
const lines = [
|
|
375
|
+
`capability_preflight ${v.card?.id ?? ''}: callable=${String(v.next?.callable ?? v.admitted ?? false)}`,
|
|
376
|
+
` risk: ${v.card?.risk.level ?? '?'} · approval=${v.requires?.approval ?? '?'} · sandbox=${v.requires?.sandbox ?? '?'}`,
|
|
377
|
+
` schema: ${v.schema === undefined ? 'not checked (no args/schema)' : v.schema.valid ? 'valid' : `invalid (${v.schema.violations.join('; ')})`}`,
|
|
378
|
+
]
|
|
379
|
+
if ((v.sideEffects ?? []).length > 0) lines.push(` side effects: ${(v.sideEffects ?? []).join('; ')}`)
|
|
380
|
+
if (v.next?.suggestion !== undefined) lines.push(` suggestion: ${v.next.suggestion}`)
|
|
381
|
+
return [{ type: 'text', text: lines.join('\n') }]
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
async execute(args, exec) {
|
|
385
|
+
const snapshot = await snapshotFor(exec?.agent)
|
|
386
|
+
let candidate: Record<string, unknown> | undefined
|
|
387
|
+
if (typeof args.argsJson === 'string' && args.argsJson.trim() !== '') {
|
|
388
|
+
try {
|
|
389
|
+
const parsed: unknown = JSON.parse(args.argsJson)
|
|
390
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
391
|
+
return { ok: false as const, admitted: false, requires: { approval: 'none' as const, sandbox: 'none' as const }, sideEffects: [], next: { callable: false }, error: 'invalid-args-json', warnings: [] }
|
|
392
|
+
}
|
|
393
|
+
candidate = parsed as Record<string, unknown>
|
|
394
|
+
} catch {
|
|
395
|
+
return { ok: false as const, admitted: false, requires: { approval: 'none' as const, sandbox: 'none' as const }, sideEffects: [], next: { callable: false }, error: 'invalid-args-json', warnings: [] }
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return preflightCapability(snapshot, args.capability, candidate, sources, exec?.agent)
|
|
399
|
+
},
|
|
400
|
+
})
|
|
401
|
+
return [searchTool, preflightTool] as const
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** ToolRunContext re-export keeps the module self-describing for tests. */
|
|
405
|
+
export type { ToolRunContext }
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { makeReindexTool } from './reindex.ts'
|
|
|
14
14
|
import { registerHttp } from './http.ts'
|
|
15
15
|
import { resolveBinary, resolveRoots, resolveStateDir } from './paths.ts'
|
|
16
16
|
import { LocatorRuntime } from './runtime.ts'
|
|
17
|
+
import { makeCapabilityTools, type CapabilitySources } from './capabilities.ts'
|
|
17
18
|
import { makeCiteTool, makeResolveTool } from './ref-tools.ts'
|
|
18
19
|
import { makeRebuildTool, makeSearchTool, makeStatusTool } from './tools.ts'
|
|
19
20
|
|
|
@@ -168,6 +169,14 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
168
169
|
ctx.tools.register(makeExportTool(rt))
|
|
169
170
|
ctx.tools.register(makeResolveTool(rt, content))
|
|
170
171
|
ctx.tools.register(makeCiteTool())
|
|
172
|
+
// Capability adapter: read the host's tool registry and skill catalog instead
|
|
173
|
+
// of duplicating discovery. Optional services stay optional.
|
|
174
|
+
const skillsService = (ctx as unknown as { get?: (name: string) => unknown }).get?.('skills')
|
|
175
|
+
const capabilitySources: CapabilitySources = {
|
|
176
|
+
tools: ctx.tools as unknown as CapabilitySources['tools'],
|
|
177
|
+
...(skillsService === undefined ? {} : { skills: skillsService as CapabilitySources['skills'] }),
|
|
178
|
+
}
|
|
179
|
+
for (const tool of makeCapabilityTools(capabilitySources)) ctx.tools.register(tool)
|
|
171
180
|
if (content !== undefined) {
|
|
172
181
|
ctx.tools.register(makeFindTool(content, ensureContent, roots, config.allowCrossWorkspaceSessions))
|
|
173
182
|
ctx.tools.register(makeReindexTool(content, ensureContent))
|