@daweifu/capability-menu 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,45 +1,76 @@
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>
11
9
  <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-2EA44F?style=flat-square&labelColor=161b22" alt="license"/></a>
12
10
  <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>
11
+ <a href="https://github.com/cordiverse/cordis"><img src="https://img.shields.io/badge/stack-Cordis%20bundle-7FBDF1.svg?style=flat-square&labelColor=161b22&logo=cardano&logoColor=white" alt="Cordis bundle"/></a>
12
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-0.1.1--rc.1-4D6BFE.svg?style=flat-square&labelColor=161b22&logo=deepseek&logoColor=white" alt="DeepSeek Harness 0.1.1-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
 
18
16
  <br/>
19
17
 
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 组合进同一个运行时。
18
+ ## 目录
19
+
20
+ - [能力菜单](#能力菜单)
21
+ - [快速安装](#快速安装)
22
+ - [能力模型](#能力模型)
23
+ - [暴露策略](#暴露策略)
24
+ - [配置文件](#配置文件)
25
+
26
+ ---
27
+
28
+ dsh-capability-menu 是 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的一个 Cordis 插件,为海量 MCP tools / skills 建立统一能力目录(`ctx.capability`),并以**常驻 / 按需 / 禁用**三档管理暴露程度和执行方式——随时调整 agent 的能力边界,避免海量 tools/skills 塞满一次请求、节省 token 和上下文:
29
+
30
+ - **统一能力目录**:编目所有 MCP 工具与 Skill,模型经 `meta_search` 检索、`meta_invoke` 执行。
31
+ - **三档能力策略**:常驻 = 高频能力随叫随到;按需 = 低频能力归档进目录、用到才翻出来;禁用 = 明确禁止。这是你配置的驻留策略,不是按使用次数自动统计的标签。
32
+ - **可视化配置**:「能力菜单」设置 tab(MCP tools / Skills 两栏,分类可点击循环切换),调整即时生效。
33
+ - **零侵入**:不改上游源码,经 Cordis 插件机制与 Harness 组合进同一运行时。
34
+
35
+ ## 能力菜单
36
+
37
+ <p align="center">
38
+ <img src="assets/screenshot-mcp-tools.png" alt="MCP tools tab" width="45%"/>
39
+ <img src="assets/screenshot-skills.png" alt="Skills tab" width="45%"/>
40
+ </p>
41
+
42
+ 安装后,「设置 / 通用设置」下出现「能力菜单」tab(位于「模型」与「插件」之间),用于可视化查看和调整暴露策略,改动即时生效、无需重启:
43
+
44
+ - **两栏**:MCP 工具(按 server 分组、可折叠)与 Skills。
45
+ - **三态圆点 + 统计**:每个能力带一个分类圆点(实心 = 常驻、半实心 = 按需、空心 = 禁用),栏顶部显示各档数量统计。
46
+ - **点击循环切换**:点击能力旁的圆点或分类计数即可循环切换分类;MCP 工具还可以点击整行查看模型侧工具定义(name / description / parameters)。
47
+ - **Skills 目录浏览**:展开某个 skill 可浏览其文件目录,点击文件预览 SKILL.md 等正文内容。
21
48
 
22
49
  ## 快速安装
23
50
 
24
- 先构建并打包(源码仓库,`lib/` 需先产出):
51
+ 前置:已安装 Node.js 与 dsh CLI(`dsh plugin` 内部会转发给 pnpm)。
25
52
 
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
- ```
53
+ ### 从 npm 安装(推荐)
31
54
 
32
- 把 `.tgz` 交给对方安装:
55
+ 单包同时提供服务端插件与前端「能力菜单」tab,装完即可在「设置 / 通用设置」下看到:
33
56
 
34
- ```bash
35
- dsh plugin --profile web add ./daweifu-capability-menu-0.1.0.tgz
57
+ ```sh
58
+ dsh plugin --profile web add @daweifu/capability-menu
36
59
  ```
37
60
 
38
- > `dsh plugin add` 一个**目录**会以 `link:` 方式安装,`lib/` 需要已构建,本地自测请用 `.tgz`。
61
+ ### 从源码安装
62
+
63
+ ```sh
64
+ git clone https://github.com/PKUfudawei/dsh-capability-menu.git
65
+ cd dsh-capability-menu
66
+ pnpm install # prepare 脚本自动构建 lib/(服务端)与 lib/client.js(前端)
67
+
68
+ dsh plugin --profile web add ./dsh-capability-menu
69
+ ```
39
70
 
40
- 验证(应看到本包自己的 patch 层):
71
+ ### 验证安装
41
72
 
42
- ```bash
73
+ ```sh
43
74
  dsh --profile web --dump-config | grep -E 'capability-menu'
44
75
  ```
45
76
 
@@ -53,25 +84,25 @@ dsh --profile web --dump-config | grep -E 'capability-menu'
53
84
  name: '@daweifu/capability-menu/invoke'
54
85
  - id: capability-menu-policy
55
86
  name: '@daweifu/capability-menu/policy'
87
+ - id: capability-menu
88
+ name: '@daweifu/capability-menu'
56
89
  ```
57
90
 
58
- 卸载:
91
+ ### 卸载
59
92
 
60
- ```bash
93
+ ```sh
61
94
  dsh plugin --profile web remove @daweifu/capability-menu
62
95
  ```
63
96
 
64
97
  ## 能力模型
65
98
 
66
- Capability 是上位概念,Tool / Skill 是不同类型的 capability,不是「两种工具」:
99
+ Capability 是本插件引入的上位概念:Tool / Skill 是不同类型的 capability。
67
100
 
68
101
  | kind | 对 Agent 提供 | action | 备注 |
69
102
  | --- | --- | --- | --- |
70
103
  | `tool` | 执行一个动作(MCP 工具) | `execute` | 由 `ctx.tools` 索引 |
71
104
  | `skill` | 某类任务的方法/流程/知识 | `load` | 由 `ctx.skills` 索引 |
72
105
 
73
- > `execute` / `load` 是 capability 对外声明的**规范 action**(`CapabilityAction = 'execute' | 'load'`)。tool 的 `execute` 在底层由 `ctx.tools.execute` 走完整工具管线执行;skill 的 `load` 加载方法/流程正文。当前版本(`0.1.0`)只有这两种 kind 与两种 action。
74
-
75
106
  模型获得两个元工具:
76
107
 
77
108
  | 工具 | 作用 | 对应 entry |
@@ -79,11 +110,7 @@ Capability 是上位概念,Tool / Skill 是不同类型的 capability,不是
79
110
  | `meta_search` | 检索能力目录(Tool / Skill),list/detail 双模式 | `@daweifu/capability-menu/search` |
80
111
  | `meta_invoke` | 统一执行面:Tool 真执行(走完整 `ctx.tools` 管线)+ Skill 加载 | `@daweifu/capability-menu/invoke` |
81
112
 
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 三档能力策略
113
+ ## 暴露策略
87
114
 
88
115
  所有能力(Tool 与 Skill)按 **暴露程度**(模型在上下文中看到什么)与 **执行方式** 分为三档:
89
116
 
@@ -91,116 +118,55 @@ Capability 是上位概念,Tool / Skill 是不同类型的 capability,不是
91
118
 
92
119
  | 档位 | 能力 | 暴露方式(模型视野) | 发现 | 执行方式 |
93
120
  | --- | --- | --- | --- | --- |
94
- | **Exposed** | tool | 完整 schema 进 `assembly.tools` → 模型请求 `tools` payload,每步可见 | 无需发现(已常驻) | 模型直接调用,运行时走完整 `ctx.tools` 管线 |
121
+ | **常驻** | tool | 完整 schema 进 `assembly.tools` → 模型请求 `tools` payload,每步可见 | 无需发现(已常驻) | 模型直接调用,运行时走完整 `ctx.tools` 管线 |
95
122
  | | skill | 名字+描述进 `<available_skills>` 目录(正文不在目录) | 无需发现(已常驻) | `skill` 工具按需加载正文(渐进加载) |
96
- | **Progressive** | tool | 不进 payload(零上下文成本) | `meta_search` list 返回 name+summary | `meta_invoke` 执行(走 `ctx.tools.execute`,管线完整);或 detail 拿 schema 后直接调 |
123
+ | **按需** | tool | 不进 payload(零上下文成本) | `meta_search` list 返回 name+summary | `meta_invoke` 执行(走 `ctx.tools.execute`,管线完整);或 detail 拿 schema 后直接调 |
97
124
  | | skill | 不进 `<available_skills>` 目录 | `meta_search` 检索(`progressiveSkillCatalog` 条目) | `meta_invoke` 按 `path` 加载 SKILL.md 正文 |
98
- | **Blocked** | tool | 不进 payload | `meta_search` 不返回 | `meta_invoke` 拒绝,直接调用被投影排除 |
125
+ | **禁用** | tool | 不进 payload | `meta_search` 不返回 | `meta_invoke` 拒绝,直接调用被投影排除 |
99
126
  | | skill | 不进目录 | `meta_search` 不返回 | `meta_invoke` 拒绝 |
100
127
 
101
- > **Exposed / Progressive 就是「高频 vs 低频」的具象化。** Exposed = 常驻、随叫随到的高频能力(拿 payload/目录体积换单跳可靠);Progressive = 归档进目录、用到才翻出来的低频能力(省 token、按需取用);Blocked = 明确禁止使用。它是**由你配置的驻留策略**(`tools.exposed`/`tools.progressive`/`tools.blocked` 规则),而不是按使用次数自动统计的标签。
102
- >
103
- > 上表的 tool 档位均指 `mcp__` 编目工具;原生工具不参与三档管理,只能以 `tools.exposed` 保活可见性(见"能力模型"边界说明)。
128
+ > 上表的 tool 档位均指 `mcp__` 编目工具;原生工具不参与三档管理,只能以 `tools.exposed` 保活可见性(见下方配置文件示例)。
129
+
130
+ ## 配置文件
104
131
 
105
- ## 配置(在 `@daweifu/capability-menu/policy` 上)
132
+ 规则写在 profile 的 `cordis.patch.yml` 里 `capability-menu-policy` 插件 entry 的 `config` 下(外层 `- insert:` / `id` / `name` 是 Cordis patch 的挂载样板,与规则无关):
106
133
 
107
134
  ```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 目录
135
+ config:
136
+ tools:
137
+ exposed: [execute_cmd, get_session_context, search_kb, 'mcp__gongfeng__*'] # 通配:该 server 下全部常驻
138
+ progressive: ['mcp__*', 'server:km:*'] # 通配兜底 + 按 server 前缀批量按需
139
+ blocked: ['mcp__secret__*'] # 禁用优先级最高,压过常驻
140
+ skills:
141
+ exposed: [debugging, coding]
142
+ progressive: [legacy_skill] # 显式按需(未列出即默认常驻)
143
+ blocked: [forbidden_skill]
144
+ metaTools: [meta_search, meta_invoke] # 恒常驻,不可被禁用
145
+ progressiveSkillCatalog: ~/.dsh/progressive-skills.yaml
135
146
  ```
136
147
 
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` 条目。
151
-
152
- ## 机制设计
153
-
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` 拒绝。
157
-
158
- ## 能力管理(server 侧 `ctx.capabilityPolicy`)
148
+ **规则优先级**(命中即停,同级内精确匹配先于通配):`blocked` > `exposed` > `progressive`,未命中任何规则默认 Exposed;`blocked` 是最硬的控制(压过 `exposed`),meta 工具(`meta_search`/`meta_invoke`)恒为 Exposed 且不可被 blocked。`tools.exposed` 里列原生工具名(`execute_cmd` 等)是**保活**:原生工具不进能力编目、只受投影链裁剪可见性,列在这里保持模型可见可调——一旦被 progressive/blocked 覆盖,模型就看不到也调不到。
159
149
 
160
- > 后端能力管理面,前端「能力菜单」tab 正是消费它。前端 React 包 `@daweifu/capability-menu-web`(本仓库 `web/`)的浏览器 bundle 与 host Typert 网关由 `web/` 的构建产出(见 `web/README.md`);`capabilityPolicy/*` remote 由网关托管,浏览器端 `ctx.remote.capabilityPolicy` 消费。
150
+ > 「能力菜单」tab 的改动只写入运行时内存、不落盘;要持久化(随 profile 生效、可版本管理/批量声明),编辑 profile 的 `cordis.patch.yml` 即可——这就是持久化入口,无需额外的导入/导出按钮。
161
151
 
162
- `@daweifu/capability-menu/policy` 注册 `ctx.capabilityPolicy` 服务,同时支撑运行期投影与前端管理:
152
+ ### 渐进技能目录(`progressiveSkillCatalog`)
163
153
 
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` | 投影链与执行面消费的判定与规则视图。 |
154
+ 按需(Progressive)技能不进固定上下文,也可能根本没注册进 `ctx.skills`。为了让它们仍可被发现,用一份独立 YAML 存 name + description + path,由 registry 索引、`meta_search` 检索;完整 SKILL.md 由 `meta_invoke` 按需加载(`ctx.skills` 未注册时按 YAML 的 `path` 读取):
170
155
 
171
- 这些方法全部是纯 server 方法(可单测),前端通过 harness 的 remote/RPC 层调用。
172
-
173
- ## 仓库结构
174
-
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)
156
+ ```yaml
157
+ # ~/.dsh/progressive-skills.yaml
158
+ skills:
159
+ - name: legacy_skill # 对应 skills.progressive 里的规则名
160
+ description: 旧版迁移技能,低频使用
161
+ whenToUse: 处理旧工程时使用
162
+ path: /path/to/legacy_skill # 含 SKILL.md 的目录
189
163
  ```
190
164
 
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
- ## 环境前置
165
+ ### 默认(不配置 policy)
199
166
 
200
- - 已安装 dsh CLI 和 pnpm(`dsh plugin` 内部会转发给 pnpm)。
167
+ - 不挂 `capability-menu-policy` → 全部工具/技能照旧可见(不投影)。
168
+ - 挂了 policy 但没有任何规则 → 全部能力默认 Exposed(`classify` 兜底),不投影、不隐藏。需要把低频能力归档进目录时,显式配置 `progressive`(或 `blocked`)规则把它们从模型视野中移出。
201
169
 
202
170
  ## License
203
171
 
204
172
  本项目遵循 [Apache License 2.0](LICENSE)。
205
-
206
- > 一个可独立安装的 Cordis 插件,为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供能力发现、按需执行与 Exposed/Progressive/Blocked 投影策略。核心的智能体、模型、工具、会话、Web UI 与插件生态都来自上游项目。
package/cordis.patch.yml CHANGED
@@ -1,9 +1,11 @@
1
1
  # dsh-capability-menu aggregate bundle patch: mounts the meta plugins in one
2
2
  # layer, from a single installable package.
3
3
  #
4
- # One package, four plugin entries — each mounts a subpath of
4
+ # One package, five plugin entries — four mount a subpath of
5
5
  # `@daweifu/capability-menu` (the loader resolves package subpath exports; see
6
- # `@deepseek-ai/dsh-web-app/startup` for the same pattern in the harness):
6
+ # `@deepseek-ai/dsh-web-app/startup` for the same pattern in the harness), and
7
+ # the root entry loads the package main to mount the browser-facing gateway
8
+ # (and thereby registers the package itself as a `dsh.client` loader entry):
7
9
  #
8
10
  # - id: capability-menu-registry
9
11
  # name: '@daweifu/capability-menu/registry'
@@ -34,7 +36,7 @@
34
36
  # progressiveSkillCatalog: ~/.dsh/progressive-skills.yaml
35
37
  #
36
38
  # - `capability-menu-registry` (P0): builds/indexes the capability catalog and
37
- # exposes the `ctx.meta` service (search/get/getDetail/refresh). It registers
39
+ # exposes the `ctx.capability` service (search/get/getDetail/refresh). It registers
38
40
  # no model-facing tool itself. Indexes the GLOBAL registry (no visibility
39
41
  # filter) and additionally indexes Progressive skills from
40
42
  # `progressiveSkillCatalog` (§7.2).
@@ -85,3 +87,9 @@
85
87
  - read_image
86
88
  - glob
87
89
  - grep
90
+ # Root entry: loads the package main, which mounts the Typert gateway that
91
+ # exposes ctx.capabilityPolicy to the browser. Makes this package a loader
92
+ # entry itself so @deepseek-ai/dsh-client-modules discovers its `dsh.client`
93
+ # declaration and serves the 能力菜单 browser bundle (`./client`).
94
+ - id: capability-menu
95
+ name: '@daweifu/capability-menu'
@@ -0,0 +1,156 @@
1
+ window.__ModuleLoader__.load({ id: "@daweifu/capability-menu", factory: (require) => {
2
+ var module = { exports: {} };
3
+ var exports = module.exports;
4
+
5
+ import { ClientContext } from "@deepseek-ai/dsh-client-runtime/client";
6
+ //#region src/client/store.d.ts
7
+ /**
8
+ * ⚠️ VERIFIED AGAINST REAL rc.8 CLIENT API.
9
+ *
10
+ * Types + small helpers for the 能力菜单 (Capability Menu) settings
11
+ * section. The component reads/writes the Host `ctx.capabilityPolicy` through
12
+ * the generated `remote.capabilityPolicy` face (see `./remote.ts`), mirroring
13
+ * how `dsh-client-ui-settings-plugin-inventory` consumes
14
+ * `ctx.remote.pluginInventory`.
15
+ */
16
+ /** One capability's Exposed/Progressive/Blocked row, as surfaced by the server. */
17
+ interface CapabilityRow {
18
+ readonly id: string;
19
+ readonly kind: 'tool' | 'skill';
20
+ readonly name: string;
21
+ readonly server?: string;
22
+ readonly class: 'exposed' | 'progressive' | 'blocked';
23
+ /** Human-friendly display: `Exposed · 常驻(直接调用)` / `Progressive · 按需(目录渐进加载)` / `Blocked · 禁用`. */
24
+ readonly classLabel?: string;
25
+ readonly mandatory: boolean;
26
+ }
27
+ /** Snapshot of the management surface. */
28
+ interface CapabilitySnapshot {
29
+ readonly rows: readonly CapabilityRow[];
30
+ }
31
+ /** One direct child in a skill directory listing. */
32
+ interface SkillFileEntry {
33
+ readonly name: string;
34
+ readonly type: 'file' | 'directory';
35
+ }
36
+ /** Full detail projection of one capability (schema, description, stats). */
37
+ interface ToolDetail {
38
+ readonly id: string;
39
+ readonly kind: 'tool' | 'skill';
40
+ readonly actions: readonly string[];
41
+ readonly name: string;
42
+ readonly description: string;
43
+ readonly whenToUse?: string;
44
+ readonly parameters: Record<string, unknown>;
45
+ readonly output?: Record<string, unknown>;
46
+ readonly origin: {
47
+ readonly provider: string;
48
+ readonly serverName?: string;
49
+ readonly path?: string;
50
+ };
51
+ readonly tags: readonly string[];
52
+ readonly stats: {
53
+ readonly uses: number;
54
+ readonly successes: number;
55
+ readonly failures: number;
56
+ readonly totalMs: number;
57
+ readonly lastUsedAt?: number;
58
+ };
59
+ }
60
+ /** The Host `capabilityPolicy` remote face (generated contribution). */
61
+ interface CapabilityPolicyRemote {
62
+ getConfig(): Promise<{
63
+ ok: true;
64
+ value: Record<string, unknown>;
65
+ } | {
66
+ ok: false;
67
+ error: {
68
+ code: string;
69
+ message: string;
70
+ };
71
+ }>;
72
+ updateConfig(partial: Record<string, unknown>): Promise<{
73
+ ok: true;
74
+ value: void;
75
+ } | {
76
+ ok: false;
77
+ error: {
78
+ code: string;
79
+ message: string;
80
+ };
81
+ }>;
82
+ classifyAll(): Promise<{
83
+ ok: true;
84
+ value: CapabilityRow[];
85
+ } | {
86
+ ok: false;
87
+ error: {
88
+ code: string;
89
+ message: string;
90
+ };
91
+ }>;
92
+ listSkillDir(id: string, relPath?: string): Promise<{
93
+ ok: true;
94
+ value: SkillFileEntry[] | undefined;
95
+ } | {
96
+ ok: false;
97
+ error: {
98
+ code: string;
99
+ message: string;
100
+ };
101
+ }>;
102
+ readSkillFile(id: string, relPath: string): Promise<{
103
+ ok: true;
104
+ value: string | undefined;
105
+ } | {
106
+ ok: false;
107
+ error: {
108
+ code: string;
109
+ message: string;
110
+ };
111
+ }>;
112
+ getDetail(id: string): Promise<{
113
+ ok: true;
114
+ value: ToolDetail | undefined;
115
+ } | {
116
+ ok: false;
117
+ error: {
118
+ code: string;
119
+ message: string;
120
+ };
121
+ }>;
122
+ }
123
+ //#endregion
124
+ //#region src/client/CapabilitySection.d.ts
125
+ /** Props injected by the settings.section registration (see index.ts). */
126
+ interface CapabilitySectionInjected {
127
+ remote: CapabilityPolicyRemote;
128
+ t(key: CapabilityKey, params?: Record<string, unknown>): string;
129
+ /** Diagnostic: `$mount` failure surfaced instead of crashing the section. */
130
+ mountError?: string;
131
+ /** Diagnostic: namespace methods actually installed on `ctx.remote.capabilityPolicy`. */
132
+ remoteKeys?: string;
133
+ }
134
+ type CapabilitySectionProps = CapabilitySectionInjected;
135
+ type CapabilityKey = 'nav' | 'title' | 'desc' | 'exposed' | 'progressive' | 'blocked' | 'kind' | 'class' | 'tool' | 'skill' | 'mandatory' | 'rules' | 'toolsGroup' | 'skillsGroup' | 'emptyTools' | 'emptySkills' | 'toolCount' | 'exposedShort' | 'progressiveShort' | 'blockedShort' | 'cycleHint' | 'notPreviewable' | 'previewClose' | 'detailNotFound';
136
+ //#endregion
137
+ //#region src/client/index.d.ts
138
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
139
+ interface LocaleNamespaceMap {
140
+ /** 能力菜单 tab copy. */
141
+ 'settings.capability': Record<CapabilityKey, string>;
142
+ }
143
+ }
144
+ /** Required services (cordis fiber inject). `remote.capabilityPolicy` is NOT
145
+ * injected: we mount it in `apply`, so declaring it would deadlock the boot
146
+ * ("waiting for service"). Access it via `ctx.get('remote.capabilityPolicy')`,
147
+ * which resolves the mounted namespace service without the inject gate. */
148
+ declare const inject: string[];
149
+ /** Register the 能力菜单 section once `settings.section` is on the ledger. */
150
+ declare function apply(ctx: ClientContext): Promise<() => void>;
151
+ //#endregion
152
+ export { type CapabilityKey, type CapabilityPolicyRemote, type CapabilityRow, type CapabilitySectionInjected, type CapabilitySectionProps, type CapabilitySnapshot, apply, inject };
153
+
154
+ return module.exports;
155
+ }});
156
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client/store.ts","../src/client/CapabilitySection.tsx","../src/client/index.ts"],"mappings":";;;;;;;;;;;;;;;;UAWiB;WACN;WACA;WACA;WACA;WACA;;WAEA;WACA;;;UAIM;WACN,eAAe;;;UAIT;WACN;WACA;;;UAIM;WACN;WACA;WACA;WACA;WACA;WACA;WACA,YAAY;WACZ,SAAS;WACT;aAAmB;aAA2B;aAA8B;;WAC5E;WACA;aACE;aACA;aACA;aACA;aACA;;;;UAKI;EACf,aAAa;IAAU;IAAU,OAAO;;IAA8B;IAAW;MAAS;MAAc;;;EACxG,aAAa,SAAS,0BAA0B;IAAU;IAAU;;IAAkB;IAAW;MAAS;MAAc;;;EACxH,eAAe;IAAU;IAAU,OAAO;;IAAsB;IAAW;MAAS;MAAc;;;EAClG,aAAa,YAAY,mBAAmB;IAAU;IAAU,OAAO;;IAAmC;IAAW;MAAS;MAAc;;;EAC5I,cAAc,YAAY,kBAAkB;IAAU;IAAU;;IAAgC;IAAW;MAAS;MAAc;;;EAClI,UAAU,aAAa;IAAU;IAAU,OAAO;;IAA6B;IAAW;MAAS;MAAc;;;;;;;UCtClG;EACf,QAAQ;EACR,EAAE,KAAK,eAAe,SAAS;;EAE/B;;EAEA;;KAGU,yBAAyB;KAEzB;;;;YCVA;;IAER,uBAAuB,OAAO;;;;;;;cAQrB;;iBAGS,MAAM,KAAK,gBAAgB"}