@daweifu/capability-menu 0.1.0 → 0.1.2

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.en.md ADDED
@@ -0,0 +1,217 @@
1
+ <h1 align="center">dsh-capability-menu</h1>
2
+
3
+ <p align="center">
4
+ <strong>One unified capability management surface for DeepSeek Harness: control the exposure level (context footprint) and execution of Tools and Skills</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@daweifu/capability-menu"><img src="https://img.shields.io/npm/v/@daweifu/capability-menu.svg?style=flat-square&color=0969DA&labelColor=161b22&logo=npm&logoColor=white" alt="npm version"/></a>
9
+ <a href="https://www.npmjs.com/package/@daweifu/capability-menu"><img src="https://img.shields.io/npm/dt/@daweifu/capability-menu.svg?style=flat-square&color=0969DA&labelColor=161b22" alt="downloads"/></a>
10
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-2EA44F?style=flat-square&labelColor=161b22" alt="license"/></a>
11
+ <a href="https://github.com/PKUfudawei/dsh-capability-menu"><img src="https://img.shields.io/github/stars/PKUfudawei/dsh-capability-menu.svg?style=flat-square&color=dbab09&labelColor=161b22&logo=github&logoColor=white" alt="GitHub stars"/></a>
12
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-0.1.2--rc.1-4D6BFE.svg?style=flat-square&labelColor=161b22&logo=deepseek&logoColor=white" alt="DeepSeek Harness 0.1.2-rc.1"/></a>
13
+ <a href="https://github.com/PKUfudawei/dsh-capability-menu/actions"><img src="https://img.shields.io/github/actions/workflow/status/PKUfudawei/dsh-capability-menu/ci.yml?branch=master&label=CI&style=flat-square&labelColor=161b22&logo=github&logoColor=white" alt="CI"/></a>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="./README.md">简体中文</a> · <strong>English</strong>
18
+ </p>
19
+
20
+ <br/>
21
+
22
+ ## Table of Contents
23
+
24
+ - [Capability Overview](#capability-overview)
25
+ - [Quick Install](#quick-install)
26
+ - [Exposure Policy](#exposure-policy)
27
+ - [Configuration](#configuration)
28
+
29
+ ---
30
+
31
+ ## Capability Overview
32
+
33
+ dsh-capability-menu is a Cordis plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). It builds a unified capability catalog (`ctx.capability`) over a large number of tools / skills (MCP tools and harness-native built-in tools) and manages their **exposure level and execution** in three tiers — **Resident / On-demand / Disabled** — so you can adjust the agent's capability boundary at any time, keep a flood of tools/skills out of a single request, and save tokens and context. Changes apply immediately without restarting, and the plugin composes into the Harness runtime purely through the Cordis plugin mechanism — no upstream source is modified. **Without this plugin (policy) mounted, everything stays visible as before; mounted with no rules at all, every capability defaults to Resident.**
34
+
35
+ ### Capability Model
36
+
37
+ *Capability* is the umbrella concept introduced by this plugin: a Tool and a Skill are different *kinds* of capability.
38
+
39
+ | kind | provides to the agent | action | notes |
40
+ | --- | --- | --- | --- |
41
+ | `tool` | executes an action (an MCP tool or a harness-native built-in tool) | `execute` | indexed by `ctx.tools` |
42
+ | `skill` | the method / flow / knowledge for a class of tasks | `load` | indexed by `ctx.skills` |
43
+
44
+ The model gets two meta tools:
45
+
46
+ | tool | role | corresponding entry |
47
+ | --- | --- | --- |
48
+ | `meta_search` | search the capability catalog (Tool / Skill), list/detail dual mode | `@daweifu/capability-menu/search` |
49
+ | `meta_invoke` | unified execution surface: really executes Tools (full `ctx.tools` pipeline) + loads Skills | `@daweifu/capability-menu/invoke` |
50
+
51
+ ### Capability Management
52
+
53
+ <p align="center">
54
+ <img src="assets/screenshot-tools.png" alt="Tools tab" width="48%"/>
55
+ <img src="assets/screenshot-skills.png" alt="Skills tab" width="48%"/>
56
+ </p>
57
+ <p align="center">
58
+ <img src="assets/screenshot-policy.png" alt="View capability catalog · Policy (effective)" width="48%"/>
59
+ <img src="assets/screenshot-catalog.png" alt="View capability catalog · On-demand catalog" width="48%"/>
60
+ </p>
61
+
62
+ Once installed, a Capability Management tab appears under Settings → General Settings (between "Model" and "Plugins"). It lets you visualize and adjust the exposure policy; changes apply immediately, no restart needed:
63
+
64
+ - **Tools / Skills tabs**: the top tab bar shows `Tools` and `Skills`; its right side holds the per-class counts and the "View capability catalog" button. The Tools tab groups every tool by server (collapsible). MCP tools hang under their own server (`gongfeng`/`km`…); harness-native tools from the agent presets (`bash`/`read`/`write`/`glob`/`grep`…) hang under the reserved "System built-in" group (server key `built-in`). Click a row to view the model-facing tool definition — name / description / parameters.
65
+ - **Skills tab**: split into "Global skills" / "Project skills" sub-tabs (both always visible; the empty side shows an empty-state hint), and the per-class counts at the top follow the active sub-tab. Click a skill row to expand its directory tree; click a file to preview its content (e.g. the SKILL.md).
66
+ - **Three-state dot & click-to-cycle**: every capability carries a classification dot — solid = Resident, top-half-filled ring = On-demand, ring with a slash (no-entry sign) = Disabled — with per-class counts at the top of the pane; click a capability's dot or a class count to cycle its classification (built-in tools are manageable exactly like MCP tools), and if a higher-priority rule (e.g. a wildcard) overrides it, the UI reports that the classification did not apply.
67
+ - **View capability catalog**: the top-right button opens a read-only modal with the effective policy in a semantic view — every capability defaults to Resident, so `tools.resident` lists each server as `'*'`, exceptions appear only under `on-demand`/`disabled` grouped by server → tool name (skills have no server dimension, so `skills.resident` is just `'*'`) — plus the materialized On-demand catalog file (`catalogFile`) path and content. Persistence remains via the profile's `cordis.patch.yml`.
68
+
69
+ ## Quick Install
70
+
71
+ Prerequisites: Node.js and the dsh CLI installed (`dsh plugin` forwards to pnpm internally).
72
+
73
+ ### Install from npm (recommended)
74
+
75
+ A single package ships both the server-side plugin and the front-end Capability Management tab; once installed it shows up under Settings → General Settings:
76
+
77
+ ```sh
78
+ dsh plugin --profile web add @daweifu/capability-menu
79
+ ```
80
+
81
+ ### Install from source
82
+
83
+ ```sh
84
+ git clone https://github.com/PKUfudawei/dsh-capability-menu.git
85
+ cd dsh-capability-menu
86
+ pnpm install # the prepare script builds lib/ (server) and lib/client.js (front-end)
87
+
88
+ dsh plugin --profile web add ./dsh-capability-menu
89
+ ```
90
+
91
+ ### Verify the install
92
+
93
+ ```sh
94
+ dsh --profile web --dump-config | grep -E 'capability-menu'
95
+ ```
96
+
97
+ ```
98
+ # == @daweifu/capability-menu
99
+ - id: capability-menu-registry
100
+ name: '@daweifu/capability-menu/registry'
101
+ - id: capability-menu-search
102
+ name: '@daweifu/capability-menu/search'
103
+ - id: capability-menu-invoke
104
+ name: '@daweifu/capability-menu/invoke'
105
+ - id: capability-menu-policy
106
+ name: '@daweifu/capability-menu/policy'
107
+ - id: capability-menu
108
+ name: '@daweifu/capability-menu'
109
+ ```
110
+
111
+ ### Uninstall
112
+
113
+ ```sh
114
+ dsh plugin --profile web remove @daweifu/capability-menu
115
+ ```
116
+
117
+ ## Exposure Policy
118
+
119
+ All capabilities (Tool and Skill) fall into three tiers by their **exposure level** (what the model sees in the context) and their **execution mode**:
120
+
121
+ ### Tools / Skills three-tier exposure and execution
122
+
123
+ | tier | capability | exposure (model view) | discovery | execution |
124
+ | --- | --- | --- | --- | --- |
125
+ | **Resident** | tool | full schema in `assembly.tools` → the model's `tools` request payload, visible at every step | none (already resident) | model calls it directly; at runtime it goes through the full `ctx.tools` pipeline |
126
+ | | skill | name + description in the `<available_skills>` catalog (body not in the catalog) | none (already resident) | the `skill` tool loads the body on demand (on-demand loading) |
127
+ | **On-demand** | tool | not in the payload (zero context cost) | `meta_search` list / `grep` the materialized catalog YAML (`catalogFile`) | executed by `meta_invoke` (via `ctx.tools.execute`, full pipeline); or fetch the schema through detail and call it directly |
128
+ | | skill | not in the `<available_skills>` catalog | `meta_search`, or `grep` the materialized catalog YAML (`catalogFile`) | `meta_invoke` loads the SKILL.md body (via `ctx.skills`) |
129
+ | **Disabled** | tool | not in the payload | not returned by `meta_search`, not written to the catalog YAML | refused by `meta_invoke`; hallucinated direct calls are also hard-rejected in `tools/pre-execute` |
130
+ | | skill | not in the `<available_skills>` catalog | not returned by `meta_search`, not written to the catalog YAML | refused by `meta_invoke`; the `skill` tool is hard-rejected in `tools/pre-execute` |
131
+
132
+ > The tool tiers in the table above cover both `mcp__` cataloged tools and harness-native built-in tools (native tools are grouped under the reserved `built-in` server and are managed in all three tiers just like MCP tools). **An On-demand built-in tool leaves the model's resident view**: the model reaches it via `meta_search` and executes it with `meta_invoke` (a two-hop call) — so keep high-frequency core tools Resident. The `meta_search`/`meta_invoke` tools themselves and the reserved Code Mode transport `run_code` never enter the capability catalog; they are always Resident and cannot be cycled in the Capability Management.
133
+
134
+ ## Configuration
135
+
136
+ Rules are declared under the `config` of the `capability-menu-policy` plugin entry in the profile's `cordis.patch.yml` (the outer `- insert:` / `id` / `name` is Cordis patch boilerplate and has nothing to do with the rules):
137
+
138
+ ```yaml
139
+ config:
140
+ tools:
141
+ resident:
142
+ - execute_cmd
143
+ - get_session_context
144
+ - search_kb
145
+ - 'mcp__gongfeng__*' # wildcard: everything under this server is resident
146
+ on-demand:
147
+ - 'mcp__*' # wildcard fallback
148
+ - 'server:km:*' # bulk on-demand by server prefix
149
+ disabled:
150
+ - 'mcp__secret__*' # disabled outranks everything, even resident
151
+ skills:
152
+ resident:
153
+ - debugging
154
+ - coding
155
+ on-demand:
156
+ - legacy_skill # explicit on-demand (unlisted skills default to resident)
157
+ disabled:
158
+ - forbidden_skill
159
+ metaTools:
160
+ - meta_search # always resident; cannot be disabled
161
+ - meta_invoke
162
+ ```
163
+
164
+ > Config keys are the tier words themselves: `resident` (常驻) / `on-demand` (按需) / `disabled` (禁用).
165
+
166
+ **Rule priority** (first match wins; within one tier, an exact rule beats a wildcard):
167
+
168
+ | priority | rule | example | effect |
169
+ | --- | --- | --- | --- |
170
+ | 1 | `disabled` exact | `disabled: [forbidden_skill]` | hardest deny, overrides everything |
171
+ | 2 | `disabled` wildcard | `disabled: ['mcp__secret__*']` | block a whole group |
172
+ | 3 | `resident` exact | `resident: [bash]` | keep one capability resident |
173
+ | 4 | `on-demand` exact | `on-demand: [legacy_skill]` | one capability on-demand (what a Capability Management click writes) |
174
+ | 5 | `resident` wildcard | `resident: ['mcp__gongfeng__*']` | keep a whole group resident |
175
+ | 6 | `on-demand` wildcard | `on-demand: ['mcp__*']` | bulk on-demand fallback |
176
+ | default | no rule matched | — | resident |
177
+
178
+ Key points:
179
+ - `meta_search`/`meta_invoke` are always resident and cannot be disabled.
180
+ - **Exact rules win over wildcards (even across tiers)**: e.g. with `resident: ['mcp__gongfeng__*']` in place, clicking a tool to On-demand in the Capability Management writes an exact `on-demand` rule that takes effect instead of being pushed back by the wildcard (if a higher-priority rule still overrides it, the UI reports that the classification did not apply).
181
+ - Native tools are cataloged exactly like MCP tools (under the `built-in` server); unlisted native tools default to Resident. Once overridden by `on-demand`/`disabled` a native tool leaves the model's resident view — when On-demand it stays reachable via `meta_search` → `meta_invoke`. **Do not name a real MCP server `built-in`.**
182
+
183
+ > Changes made in the Capability Management tab only write to in-memory runtime state and are not persisted. To persist them (apply with the profile, version-controllable / batch-declarable), edit the profile's `cordis.patch.yml` — that is the persistence entry point; no extra import/export buttons are needed.
184
+
185
+ ### On-demand capability catalog (`catalogFile`, the single materialized catalog, searchable with `grep`)
186
+
187
+ On-demand capabilities are materialized into **one auto-generated YAML file** the model can browse:
188
+
189
+ **tools/skills change or classification change → the registry rewrites `catalogFile` → the model `grep`s/`read`s it (or calls `meta_search`) for an id + kind → `meta_invoke(id, kind)` runs/loads it**
190
+
191
+ - Defaults to `~/.dsh/capability-catalog.yaml` (`catalogFile` configurable; empty string disables). When nothing is On-demand, the catalog pointer is not injected (saving context).
192
+ - A skill must first be **registered in `ctx.skills`** (a skill provider — e.g. its SKILL.md under a user/project skills root or `customSkillDirs`) and then switched to On-demand; there is **no separate user-maintained input file**.
193
+ - Two discovery paths for the model: `grep` the catalog file / `meta_search` (structured schema); then call `meta_invoke` with the **`kind` reported by the same entry** to load/run it. Skill ids are the bare name (e.g. `frontend-design`) and `kind` distinguishes tools from skills. Bodies load via `ctx.skills` for skills and `ctx.tools.execute` for tools.
194
+
195
+ ```yaml
196
+ # ~/.dsh/capability-catalog.yaml (auto-generated; contains only On-demand
197
+ # capabilities — Resident ones are already resident and Disabled ones must not
198
+ # be discoverable, so neither is written. Lists are emitted as `-` block
199
+ # sequences, one item per line.)
200
+ capabilities:
201
+ - id: mcp__km__search
202
+ kind: tool
203
+ name: mcp__km__search
204
+ description: Search the knowledge base
205
+ server: km
206
+ - id: legacy_skill
207
+ kind: skill
208
+ name: legacy_skill
209
+ description: A low-frequency skill for working on legacy code
210
+ whenToUse: Use when working on legacy projects
211
+ ```
212
+
213
+ > The catalog file is written under the host's `~/.dsh` by default, so the sandbox of the model-side `bash`/`read` tools must be able to reach that path. If the sandbox isolates the host directory, explicitly configure `catalogFile` to a path the sandbox can see. The default path is shared across multiple dsh instances (last-write-wins); in multi-instance deployments, give each instance its own `catalogFile`.
214
+
215
+ ## License
216
+
217
+ This project is licensed under the [Apache License 2.0](LICENSE).
package/README.md CHANGED
@@ -1,45 +1,96 @@
1
1
  <h1 align="center">dsh-capability-menu</h1>
2
2
 
3
3
  <p align="center">
4
- <strong>为 DeepSeek Harness 提供统一的能力发现与按需执行。</strong><br>
5
- 海量tools/skills也不会塞满一次请求, 节省token和上下文<br>
6
- 所有能力分为exposed/progressive/blocked三级管理暴露程度和执行方式
4
+ <strong>为 DeepSeek Harness 统一管理 Tools 和 Skills 的暴露水平(上下文占用大小)与执行方式</strong>
7
5
  </p>
8
6
 
9
7
  <p align="center">
10
- <a href="https://www.npmjs.com/package/@daweifu/capability-menu"><img src="https://img.shields.io/npm/v/@daweifu/capability-menu.svg?style=flat-square&color=cb3837&labelColor=161b22&logo=npm&logoColor=white" alt="npm version"/></a>
8
+ <a href="https://www.npmjs.com/package/@daweifu/capability-menu"><img src="https://img.shields.io/npm/v/@daweifu/capability-menu.svg?style=flat-square&color=0969DA&labelColor=161b22&logo=npm&logoColor=white" alt="npm version"/></a>
9
+ <a href="https://www.npmjs.com/package/@daweifu/capability-menu"><img src="https://img.shields.io/npm/dt/@daweifu/capability-menu.svg?style=flat-square&color=0969DA&labelColor=161b22" alt="downloads"/></a>
11
10
  <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-2EA44F?style=flat-square&labelColor=161b22" alt="license"/></a>
12
11
  <a href="https://github.com/PKUfudawei/dsh-capability-menu"><img src="https://img.shields.io/github/stars/PKUfudawei/dsh-capability-menu.svg?style=flat-square&color=dbab09&labelColor=161b22&logo=github&logoColor=white" alt="GitHub stars"/></a>
13
- <a href="https://github.com/koishijs/cordis"><img src="https://img.shields.io/badge/stack-Cordis%20bundle-58a6ff.svg?style=flat-square&labelColor=161b22&logo=cardano&logoColor=white" alt="Cordis bundle"/></a>
14
- <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/engine-DeepSeek%20Harness-7c8cff.svg?style=flat-square&labelColor=161b22&logo=deepseek&logoColor=white" alt="DeepSeek Harness"/></a>
12
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-0.1.2--rc.1-4D6BFE.svg?style=flat-square&labelColor=161b22&logo=deepseek&logoColor=white" alt="DeepSeek Harness 0.1.2-rc.1"/></a>
15
13
  <a href="https://github.com/PKUfudawei/dsh-capability-menu/actions"><img src="https://img.shields.io/github/actions/workflow/status/PKUfudawei/dsh-capability-menu/ci.yml?branch=master&label=CI&style=flat-square&labelColor=161b22&logo=github&logoColor=white" alt="CI"/></a>
16
14
  </p>
17
15
 
16
+ <p align="center">
17
+ <strong>简体中文</strong> · <a href="./README.en.md">English</a>
18
+ </p>
19
+
18
20
  <br/>
19
21
 
20
- dsh-capability-menu 是一个可独立安装的 Cordis 插件(`@daweifu/capability-menu`),为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供统一的能力目录(`ctx.meta`)、两个元工具(`meta_search` / `meta_invoke`)、以及 Exposed / Progressive / Blocked 三档能力策略(含 server 侧能力管理面)。它不修改上游源码,完全通过 Cordis 插件机制与 Harness 组合进同一个运行时。
22
+ ## 目录
23
+
24
+ - [能力总览](#能力总览)
25
+ - [快速安装](#快速安装)
26
+ - [暴露策略](#暴露策略)
27
+ - [配置文件](#配置文件)
28
+
29
+ ---
30
+
31
+ ## 能力总览
32
+
33
+ dsh-capability-menu 是 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的一个 Cordis 插件,为海量 tools / skills(MCP 工具与内置原生工具)建立统一能力目录(`ctx.capability`),并以**常驻 / 按需 / 禁用**三档管理暴露程度和执行方式——随时调整 agent 的能力边界,避免海量 tools/skills 塞满一次请求、节省 token 和上下文。调整即时生效、无需重启,纯插件机制组合进 Harness 运行时,不改上游源码。**不挂载本插件(policy)时一切照旧、全量可见;挂载但未配置任何规则时,所有能力默认常驻。**
34
+
35
+ ### 能力模型
36
+
37
+ Capability 是本插件引入的上位概念:Tool / Skill 是不同类型的 capability。
38
+
39
+ | kind | 对 Agent 提供 | action | 备注 |
40
+ | --- | --- | --- | --- |
41
+ | `tool` | 执行一个动作(MCP 工具或内置原生工具) | `execute` | 由 `ctx.tools` 索引 |
42
+ | `skill` | 某类任务的方法/流程/知识 | `load` | 由 `ctx.skills` 索引 |
43
+
44
+ 模型获得两个元工具:
45
+
46
+ | 工具 | 作用 | 对应 entry |
47
+ | --- | --- | --- |
48
+ | `meta_search` | 检索能力目录(Tool / Skill),list/detail 双模式 | `@daweifu/capability-menu/search` |
49
+ | `meta_invoke` | 统一执行面:Tool 真执行(走完整 `ctx.tools` 管线)+ Skill 加载 | `@daweifu/capability-menu/invoke` |
50
+
51
+ ### 能力管理
52
+
53
+ <p align="center">
54
+ <img src="assets/screenshot-tools.png" alt="Tools 页" width="48%"/>
55
+ <img src="assets/screenshot-skills.png" alt="Skills 页" width="48%"/>
56
+ </p>
57
+ <p align="center">
58
+ <img src="assets/screenshot-policy.png" alt="查看能力目录 · 三档策略配置" width="48%"/>
59
+ <img src="assets/screenshot-catalog.png" alt="查看能力目录 · 按需能力目录" width="48%"/>
60
+ </p>
61
+
62
+ 安装后,「设置 / 通用设置」下出现「能力管理」tab(位于「模型」与「插件」之间),用于可视化查看和调整暴露策略,改动即时生效、无需重启:
63
+
64
+ - **Tools / Skills 页签**:顶部 Tab 栏为 `Tools` 与 `Skills`,右侧是各档数量统计和「查看能力目录」按钮。Tools 页按 server 分组、可折叠:MCP 工具挂在各自 server(`gongfeng`/`km`…)下;内置原生工具(来自 agent preset 的 `bash`/`read`/`write`/`glob`/`grep`…)统一挂在保留的「系统内置」组(server 键 `built-in`)。点击某行查看模型侧工具定义 name / description / parameters。
65
+ - **Skills 页签**:内部再分「全局技能 / 项目技能」两个子页签(始终显示,空的一侧显示空态提示),顶部数量统计跟随当前子页签。点击技能行展开目录树,点文件预览 SKILL.md 等正文。
66
+ - **三态圆点与循环切换**:每个能力带一个分类圆点——实心 = 常驻、上半实心圆环 = 按需、圆环 + 斜杠(禁行标志)= 禁用;点击能力旁圆点或分类计数即可循环切换(内置原生工具与 MCP 工具同等可管),若被更高优先级规则(如通配)覆盖,界面会提示「分类未生效」。
67
+ - **查看能力目录**:点右上角按钮弹出只读弹层,含两份文件——「三档策略配置」是**生效策略的语义化视图**(默认全部能力常驻:`tools.resident` 每个 server 显示 `*`,例外只在 `on-demand`/`disabled` 里按 server → 工具名 分级列出;skills 无 server 维度,`skills.resident` 恒为 `*`),以及「按需能力目录」物化文件(`catalogFile`)的路径与内容;持久化入口仍是 profile 的 `cordis.patch.yml`。
21
68
 
22
69
  ## 快速安装
23
70
 
24
- 先构建并打包(源码仓库,`lib/` 需先产出):
71
+ 前置:已安装 Node.js 与 dsh CLI(`dsh plugin` 内部会转发给 pnpm)。
25
72
 
26
- ```bash
27
- cd dsh-capability-menu
28
- npm run build # tsc 产出 lib/(registry/search/invoke/policy/invariant/index)
29
- pnpm pack # 生成 daweifu-capability-menu-0.1.0.tgz
30
- ```
73
+ ### 从 npm 安装(推荐)
31
74
 
32
- 把 `.tgz` 交给对方安装:
75
+ 单包同时提供服务端插件与前端「能力管理」tab,装完即可在「设置 / 通用设置」下看到:
33
76
 
34
- ```bash
35
- dsh plugin --profile web add ./daweifu-capability-menu-0.1.0.tgz
77
+ ```sh
78
+ dsh plugin --profile web add @daweifu/capability-menu
36
79
  ```
37
80
 
38
- > `dsh plugin add` 一个**目录**会以 `link:` 方式安装,`lib/` 需要已构建,本地自测请用 `.tgz`。
81
+ ### 从源码安装
82
+
83
+ ```sh
84
+ git clone https://github.com/PKUfudawei/dsh-capability-menu.git
85
+ cd dsh-capability-menu
86
+ pnpm install # prepare 脚本自动构建 lib/(服务端)与 lib/client.js(前端)
87
+
88
+ dsh plugin --profile web add ./dsh-capability-menu
89
+ ```
39
90
 
40
- 验证(应看到本包自己的 patch 层):
91
+ ### 验证安装
41
92
 
42
- ```bash
93
+ ```sh
43
94
  dsh --profile web --dump-config | grep -E 'capability-menu'
44
95
  ```
45
96
 
@@ -53,37 +104,17 @@ dsh --profile web --dump-config | grep -E 'capability-menu'
53
104
  name: '@daweifu/capability-menu/invoke'
54
105
  - id: capability-menu-policy
55
106
  name: '@daweifu/capability-menu/policy'
107
+ - id: capability-menu
108
+ name: '@daweifu/capability-menu'
56
109
  ```
57
110
 
58
- 卸载:
111
+ ### 卸载
59
112
 
60
- ```bash
113
+ ```sh
61
114
  dsh plugin --profile web remove @daweifu/capability-menu
62
115
  ```
63
116
 
64
- ## 能力模型
65
-
66
- Capability 是上位概念,Tool / Skill 是不同类型的 capability,不是「两种工具」:
67
-
68
- | kind | 对 Agent 提供 | action | 备注 |
69
- | --- | --- | --- | --- |
70
- | `tool` | 执行一个动作(MCP 工具) | `execute` | 由 `ctx.tools` 索引 |
71
- | `skill` | 某类任务的方法/流程/知识 | `load` | 由 `ctx.skills` 索引 |
72
-
73
- > `execute` / `load` 是 capability 对外声明的**规范 action**(`CapabilityAction = 'execute' | 'load'`)。tool 的 `execute` 在底层由 `ctx.tools.execute` 走完整工具管线执行;skill 的 `load` 加载方法/流程正文。当前版本(`0.1.0`)只有这两种 kind 与两种 action。
74
-
75
- 模型获得两个元工具:
76
-
77
- | 工具 | 作用 | 对应 entry |
78
- | --- | --- | --- |
79
- | `meta_search` | 检索能力目录(Tool / Skill),list/detail 双模式 | `@daweifu/capability-menu/search` |
80
- | `meta_invoke` | 统一执行面:Tool 真执行(走完整 `ctx.tools` 管线)+ Skill 加载 | `@daweifu/capability-menu/invoke` |
81
-
82
- > 边界:Command / Prompt / Memory 不是可发现可调用的能力,不进 registry。需要查知识/文档时直接用底层检索类 MCP 工具(如 `mcp__km__search`),它们和其他 MCP 工具一样被 `meta_search` 编目、被 `meta_invoke` 转发。
83
- >
84
- > 边界:非 `mcp__` 前缀的原生工具(`bash` / `read` / `write` / `edit` / `read_image` / `glob` / `grep` 等)**不进 registry**——不被 `meta_search` 编目、不被 `meta_invoke` 派发、也不在能力管理(`classifyAll`)枚举中。它们只受投影链(`system-prompt/assemble` 对 `assembly.tools` 的裁剪)影响可见性;且因不可 `meta_invoke`,一旦被投影掉就真的不可调用,所以请保留在 `tools.exposed` 保活(见下方配置示例;默认即 Exposed,但若被 `progressive`/`blocked` 通配规则覆盖则不可调用)。
85
-
86
- ## 核心:Exposed / Progressive / Blocked 三档能力策略
117
+ ## 暴露策略
87
118
 
88
119
  所有能力(Tool 与 Skill)按 **暴露程度**(模型在上下文中看到什么)与 **执行方式** 分为三档:
89
120
 
@@ -91,116 +122,94 @@ Capability 是上位概念,Tool / Skill 是不同类型的 capability,不是
91
122
 
92
123
  | 档位 | 能力 | 暴露方式(模型视野) | 发现 | 执行方式 |
93
124
  | --- | --- | --- | --- | --- |
94
- | **Exposed** | tool | 完整 schema 进 `assembly.tools` → 模型请求 `tools` payload,每步可见 | 无需发现(已常驻) | 模型直接调用,运行时走完整 `ctx.tools` 管线 |
125
+ | **常驻** | tool | 完整 schema 进 `assembly.tools` → 模型请求 `tools` payload,每步可见 | 无需发现(已常驻) | 模型直接调用,运行时走完整 `ctx.tools` 管线 |
95
126
  | | skill | 名字+描述进 `<available_skills>` 目录(正文不在目录) | 无需发现(已常驻) | `skill` 工具按需加载正文(渐进加载) |
96
- | **Progressive** | tool | 不进 payload(零上下文成本) | `meta_search` list 返回 name+summary | `meta_invoke` 执行(走 `ctx.tools.execute`,管线完整);或 detail 拿 schema 后直接调 |
97
- | | skill | 不进 `<available_skills>` 目录 | `meta_search` 检索(`progressiveSkillCatalog` 条目) | `meta_invoke` 按 `path` 加载 SKILL.md 正文 |
98
- | **Blocked** | tool | 不进 payload | `meta_search` 不返回 | `meta_invoke` 拒绝,直接调用被投影排除 |
99
- | | skill | 不进目录 | `meta_search` 不返回 | `meta_invoke` 拒绝 |
127
+ | **按需** | tool | 不进 payload(零上下文成本) | `meta_search` list / `grep` 检索物化目录 YAML(`catalogFile`) | `meta_invoke` 执行(走 `ctx.tools.execute`,管线完整);或 detail 拿 schema 后直接调 |
128
+ | | skill | 不进 `<available_skills>` 目录 | `meta_search` 检索 / `grep` 检索物化目录 YAML(`catalogFile`) | `meta_invoke` 加载 SKILL.md 正文(经 `ctx.skills`) |
129
+ | **禁用** | tool | 不进 payload | `meta_search` 不返回、目录 YAML 不写入 | `meta_invoke` 拒绝;模型幻觉直调也在 `tools/pre-execute` 被硬拒绝 |
130
+ | | skill | 不进 `<available_skills>` 目录 | `meta_search` 不返回、目录 YAML 不写入 | `meta_invoke` 拒绝;`skill` 工具在 `tools/pre-execute` 硬拒绝 |
131
+
132
+ > tool 档位同时覆盖 `mcp__` 编目工具与内置原生工具(原生工具统一以 `built-in` 为 server 归组、同样三档可管)。**On-demand 的内置工具会退出模型常驻视野**,需要时经 `meta_search` 发现、`meta_invoke` 派发(两跳调用)——因此不建议把高频核心工具设为按需。`meta_search`/`meta_invoke` 自身与 Code Mode 保留传输层 `run_code` 不进能力目录,恒常驻、不可在「能力管理」切换。
100
133
 
101
- > **Exposed / Progressive 就是「高频 vs 低频」的具象化。** Exposed = 常驻、随叫随到的高频能力(拿 payload/目录体积换单跳可靠);Progressive = 归档进目录、用到才翻出来的低频能力(省 token、按需取用);Blocked = 明确禁止使用。它是**由你配置的驻留策略**(`tools.exposed`/`tools.progressive`/`tools.blocked` 规则),而不是按使用次数自动统计的标签。
102
- >
103
- > 上表的 tool 档位均指 `mcp__` 编目工具;原生工具不参与三档管理,只能以 `tools.exposed` 保活可见性(见"能力模型"边界说明)。
134
+ ## 配置文件
104
135
 
105
- ## 配置(在 `@daweifu/capability-menu/policy` 上)
136
+ 规则写在 profile 的 `cordis.patch.yml` 里 `capability-menu-policy` 插件 entry 的 `config` 下(外层 `- insert:` / `id` / `name` 是 Cordis patch 的挂载样板,与规则无关):
106
137
 
107
138
  ```yaml
108
- - insert:
109
- - id: capability-menu-policy
110
- name: '@daweifu/capability-menu/policy'
111
- config:
112
- tools:
113
- exposed:
114
- - execute_cmd
115
- - get_session_context
116
- - search_kb
117
- - 'mcp__gongfeng__*' # 通配:该 server 下全部 Exposed
118
- progressive:
119
- - 'mcp__*' # 该规则覆盖所有未显式列出的 MCP 工具
120
- - 'server:km:*' # 按 server 前缀批量 Progressive
121
- blocked:
122
- - 'mcp__secret__*' # 明确禁用(优先级最高,压过 Exposed)
123
- skills:
124
- exposed:
125
- - debugging
126
- - coding
127
- progressive:
128
- - legacy_skill # 显式 Progressive(未列出即默认 Exposed)
129
- blocked:
130
- - forbidden_skill
131
- metaTools:
132
- - meta_search # 恒 Exposed,不可被 Blocked
133
- - meta_invoke
134
- progressiveSkillCatalog: ~/.dsh/progressive-skills.yaml # Progressive skill 的 name+description+path 目录
139
+ config:
140
+ tools:
141
+ resident:
142
+ - execute_cmd
143
+ - get_session_context
144
+ - search_kb
145
+ - 'mcp__gongfeng__*' # 通配:该 server 下全部常驻
146
+ on-demand:
147
+ - 'mcp__*' # 通配兜底
148
+ - 'server:km:*' # 按 server 前缀批量按需
149
+ disabled:
150
+ - 'mcp__secret__*' # 禁用优先级最高,压过常驻
151
+ skills:
152
+ resident:
153
+ - debugging
154
+ - coding
155
+ on-demand:
156
+ - legacy_skill # 显式按需(未列出即默认常驻)
157
+ disabled:
158
+ - forbidden_skill
159
+ metaTools:
160
+ - meta_search # 恒常驻,不可被禁用
161
+ - meta_invoke
135
162
  ```
136
163
 
137
- **规则优先级**(命中即停):`blocked` 精确 > `blocked` 通配 > `exposed` 精确 > `exposed` 通配 > `progressive` 精确 > `progressive` 通配 > 默认 Exposed。**blocked 压过 exposed**(控制语义)。meta 工具(`meta_search`/`meta_invoke`)恒为 Exposed,出现在 `blocked` 里会 fail loud。
138
-
139
- > `tools.exposed` 里列原生工具名(`execute_cmd` 等)是**保活**语义:原生工具不进能力管理编目(`classifyAll` 列表里看不到它们),但投影链会裁剪其可见性,列在这里保持模型直接可见可调。不要因为"它不在能力管理里"就把它从 exposed 移除——一旦被 `progressive`/`blocked` 规则覆盖,模型既看不到也调不到。
140
-
141
- ### 默认(不配置 policy)
142
-
143
- - 不挂 `capability-menu-policy` → 全部工具/技能照旧可见(不投影)。
144
- - 挂了 policy 但没有任何规则 → 全部能力默认 Exposed(`classify` 兜底),不投影、不隐藏。需要把低频能力归档进目录时,显式配置 `progressive`(或 `blocked`)规则把它们从模型视野中移出。
145
-
146
- ### Progressive skill
147
-
148
- Progressive skill 的 name + description + path 汇总进独立 YAML(`progressiveSkillCatalog`),由 registry 索引、`meta_search` 检索;完整 SKILL.md 由 `meta_invoke` 按需加载(`ctx.skills` 未注册时按 YAML 的 `path` 读取)。Progressive skill 不进固定上下文。
149
-
150
- > 关于 `<available_skills>`:Exposed skill 走渐进加载(名字表 → load);Progressive/Blocked skill 不进入 `dsh-tool-skill` 注入的目录。目录级裁剪需要上游 `dsh-tool-skill` 提供 filter 钩子(超出本 bundle 范围);当前 Exposed skill = 会话 registry 中所有 model-invocable skill,Progressive skill = `progressiveSkillCatalog` 条目。
164
+ > 配置键即档位英文词:`resident`(常驻)/ `on-demand`(按需)/ `disabled`(禁用)。
151
165
 
152
- ## 机制设计
166
+ **规则优先级**(从上到下命中即停;同档内精确规则优先于通配):
153
167
 
154
- **核心第一性原则**:模型可见性(投影)与能力注册(registry 索引 + 执行能力)**必须解耦**。`ctx.tools.restrict` 会把工具从 `view.visible` 移除、连 `execute` 一起挡住(`UNKNOWN_TOOL`),因此本策略**不用 restrict 隐藏 Progressive**,而是在投影链 `system-prompt/assemble` 裁剪 `assembly.tools`,让 Progressive 工具保持全局注册、可检索、可执行。
155
-
156
- Progressive 的**发现层(catalog)与执行层(`ctx.tools` 管线)分离**:catalog 只存元数据(name + description),完整 schema 从 `ctx.tools` 实时解析;无论哪一档,工具执行都落在 `ctx.tools` 管线上——审批/guard/沙箱/会话日志/取消齐全,不绕过。skill 无"执行",只有正文加载。Blocked 能力保留在 catalog 中(供管理面展示),但 `meta_search` 不返回、`meta_invoke` 拒绝。
168
+ | 优先级 | 规则 | 示例 | 效果 |
169
+ | --- | --- | --- | --- |
170
+ | 1 | `disabled` 精确 | `disabled: [forbidden_skill]` | 最硬禁用,压过一切 |
171
+ | 2 | `disabled` 通配 | `disabled: ['mcp__secret__*']` | 整组禁用 |
172
+ | 3 | `resident` 精确 | `resident: [bash]` | 单个能力显式常驻 |
173
+ | 4 | `on-demand` 精确 | `on-demand: [legacy_skill]` | 单个能力显式按需(能力管理点击写入的就是这类) |
174
+ | 5 | `resident` 通配 | `resident: ['mcp__gongfeng__*']` | 整组常驻 |
175
+ | 6 | `on-demand` 通配 | `on-demand: ['mcp__*']` | 兜底批量按需 |
176
+ | 默认 | 未命中任何规则 | — | 常驻 |
157
177
 
158
- ## 能力管理(server 侧 `ctx.capabilityPolicy`)
178
+ 要点:
179
+ - `meta_search`/`meta_invoke` 恒常驻,不可被禁用(Disabled)。
180
+ - **精确规则优先于通配(跨档也成立)**:例如存在 `resident: ['mcp__gongfeng__*']` 时,在「能力管理」把某工具点成按需会写入精确 `on-demand` 规则并生效,不会被通配压回;若仍被更高优先级覆盖,界面提示「分类未生效」。
181
+ - 原生工具与 MCP 工具一样进编目(归 `built-in` server),未列出默认常驻;被 `on-demand`/`disabled` 覆盖后退出常驻视野,按需时仍可 `meta_search` → `meta_invoke` 两跳调用。**勿把真实 MCP server 命名为 `built-in`。**
159
182
 
160
- > 后端能力管理面,前端「能力菜单」tab 正是消费它。前端 React 包 `@daweifu/capability-menu-web`(本仓库 `web/`)的浏览器 bundle 与 host Typert 网关由 `web/` 的构建产出(见 `web/README.md`);`capabilityPolicy/*` remote 由网关托管,浏览器端 `ctx.remote.capabilityPolicy` 消费。
183
+ > 「能力管理」tab 的改动只写入运行时内存、不落盘;要持久化(随 profile 生效、可版本管理/批量声明),编辑 profile 的 `cordis.patch.yml` 即可——这就是持久化入口,无需额外的导入/导出按钮。
161
184
 
162
- `@daweifu/capability-menu/policy` 注册 `ctx.capabilityPolicy` 服务,同时支撑运行期投影与前端管理:
185
+ ### 按需能力目录(`catalogFile`,唯一物化目录,grep 可检索)
163
186
 
164
- | 方法 | 用途 |
165
- | --- | --- |
166
- | `getConfig()` / `updateConfig(partial)` | 读取/热更新策略配置(`tools`/`skills`/`metaTools` 等),改动立即重编译规则、无需重启。 |
167
- | `classifyAll()` | 枚举 `ctx.meta` 目录中每个能力及其当前分类,返回 `{ id, kind, name, server?, class: 'exposed'\|'progressive'\|'blocked', classLabel, mandatory }`;`classLabel` 为「Exposed · 常驻(直接调用)/ Progressive · 按需(目录渐进加载)/ Blocked · 禁用」,供前端只读分类列表展示。 |
168
- | `classifyTool`/`classifySkill`/`classifyCapability` | 单个能力的分类判定。 |
169
- | `isExposedTool`/`isExposedSkill`/`isBlockedCapability`/`metaTools`/`toolRules`/`skillRules` | 投影链与执行面消费的判定与规则视图。 |
187
+ On-demand 能力自动物化成**一个 YAML 文件**给模型检索,链路:
170
188
 
171
- 这些方法全部是纯 server 方法(可单测),前端通过 harness 的 remote/RPC 层调用。
189
+ **工具/技能变更或分类调整 → registry 自动重写 `catalogFile` → 模型 `grep`/`read`(或 `meta_search`)找到 id 与 kind → `meta_invoke(id, kind)` 执行/加载**
172
190
 
173
- ## 仓库结构
191
+ - 默认 `~/.dsh/capability-catalog.yaml`(`catalogFile` 可改,置空禁用);没有任何按需能力时不注入目录指引,省上下文。
192
+ - 技能必须**已注册进 `ctx.skills`**(SKILL.md 放用户/项目技能根或挂 `customSkillDirs`)再切按需,即自动出现;无独立手写输入清单。
193
+ - 模型侧两路发现:`grep` 目录文件 / `meta_search`(结构化 schema);再以**同一条目返回的 `kind`** 调 `meta_invoke` 加载/执行。技能 id 即裸名(`frontend-design`),tool/skill 由 `kind` 区分;工具经 `ctx.tools.execute`,技能经 `ctx.skills`。
174
194
 
175
- ```
176
- dsh-capability-menu/ # 单包 = @daweifu/capability-menu
177
- ├── package.json # exports 子路径 + dsh.bundle → ./cordis.patch.yml
178
- ├── cordis.patch.yml # insert registry/search/invoke/policy 四个子路径 entry
179
- ├── tsconfig.json / vitest.config.ts
180
- ├── src/
181
- │ ├── registry.ts # (P0)能力目录 + ctx.meta 服务(不注册工具)
182
- │ ├── search.ts # (P1)注册 meta_search
183
- │ ├── invoke.ts # (P2)注册 meta_invoke
184
- │ ├── policy.ts # (P3)Exposed/Progressive/Blocked 投影策略 + ctx.capabilityPolicy 能力管理
185
- │ ├── invariant.ts
186
- │ └── index.ts # re-export 全部
187
- ├── tests/ # registry / search / invoke / policy 四套用例
188
- └── web/ # 前端「能力菜单」tab(client bundle + host Typert 网关,见 web/README.md)
195
+ ```yaml
196
+ # ~/.dsh/capability-catalog.yaml(自动生成;仅含 On-demand 能力,
197
+ # Resident 已常驻、Disabled 不可发现,均不写入;列表以 `-` 每项一行的 block 序列写出)
198
+ capabilities:
199
+ - id: mcp__km__search
200
+ kind: tool
201
+ name: mcp__km__search
202
+ description: 搜索知识库
203
+ server: km
204
+ - id: legacy_skill
205
+ kind: skill
206
+ name: legacy_skill
207
+ description: 处理旧工程的低频技能
208
+ whenToUse: 处理旧工程时使用
189
209
  ```
190
210
 
191
- ## 开发
192
-
193
- - `src/` 为 TypeScript 源码,`lib/` 为预构建产物(`npm run build` 产出,本仓库直接分发 `lib/`)。`package.json` 的 `exports` 声明 `/registry` `/search` `/invoke` `/policy` `/invariant` 五个子路径,`cordis.patch.yml` 挂载前四个为 entry。
194
- - `@deepseek-ai/*` 依赖为 peer 依赖(运行时从 dsh 安装闭包解析);`@deepseek-ai/schemastery` 与 `js-yaml` 为运行时依赖(后者解析 `progressiveSkillCatalog`)。
195
- - 安装时自动构建:本包 `prepare` 脚本会在支持 lifecycle 的安装路径(git / 打包安装)下自动执行 `npm run build` 产出 `lib/`;前端包 `web/` 的 `prepare` 同样自动执行 `npm run bundle` 产出客户端 bundle(需 dsh-client 环境)。
196
- - 测试:`pnpm install && npx vitest run`(33 个用例,覆盖 registry / search / invoke / policy,含能力管理面用例)。
197
-
198
- ## 环境前置
199
-
200
- - 已安装 dsh CLI 和 pnpm(`dsh plugin` 内部会转发给 pnpm)。
211
+ > 目录文件默认写在宿主 `~/.dsh`,需要模型侧 `bash`/`read` 工具的沙箱能访问该路径;若沙箱隔离宿主目录,请把 `catalogFile` 显式配置到沙箱可见的路径。默认路径在多个 dsh 实例间共享(last-write-wins),多实例部署时请为每个实例配置独立的 `catalogFile`。
201
212
 
202
213
  ## License
203
214
 
204
215
  本项目遵循 [Apache License 2.0](LICENSE)。
205
-
206
- > 一个可独立安装的 Cordis 插件,为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供能力发现、按需执行与 Exposed/Progressive/Blocked 投影策略。核心的智能体、模型、工具、会话、Web UI 与插件生态都来自上游项目。