dsh-agent-skills 0.1.6 → 0.1.9
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 +36 -66
- package/lib/client.js +27 -7
- package/lib/client.js.map +2 -2
- package/lib/preset-manager.d.ts +1 -1
- package/lib/preset-manager.js +122 -26
- package/lib/preset-manager.js.map +1 -1
- package/lib/restart.js +26 -5
- package/lib/restart.js.map +1 -1
- package/lib/runtime.js +9 -1
- package/lib/runtime.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,83 +1,57 @@
|
|
|
1
1
|
# dsh-agent-skills
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/dsh-agent-skills)
|
|
4
|
+
[](https://www.npmjs.com/package/dsh-agent-skills)
|
|
4
5
|
[](./LICENSE)
|
|
5
6
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
7
|
+
[](https://github.com/zp-home/dsh-recommend)
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
在 DeepSeek Harness 的设置页中查看、启停和管理本地 Agent Skills。
|
|
8
10
|
|
|
9
11
|

|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## 功能
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- 可按目录或单个技能启停;变更会持久化,页面会提示刷新后生效。
|
|
19
|
-
- 监听技能文件变化,也可随时手动重新扫描。
|
|
20
|
-
- 不修改原始 `SKILL.md` 文件。
|
|
15
|
+
- 自动扫描 `~/.agents/skills`、`~/.claude/skills`、`~/.codex/skills`、`~/.config/opencode/skills` 和 `~/.gemini/skills`
|
|
16
|
+
- 支持自定义技能目录
|
|
17
|
+
- 按目录或单个技能启停
|
|
18
|
+
- 搜索、查看描述并监听技能文件变化
|
|
19
|
+
- 不修改原始 `SKILL.md`
|
|
21
20
|
|
|
22
21
|
## 安装
|
|
23
22
|
|
|
24
|
-
###
|
|
25
|
-
|
|
26
|
-
通过 [DSH 插件市场](https://github.com/dsh-market/dsh-market) 安装,或打开 DSH 的「设置 → 插件市场」,搜索 **Agent Skills**,点击安装。市场会优先使用 npm 包,安装速度快,也不需要在本机重新构建。
|
|
27
|
-
|
|
28
|
-
安装后继续完成下面的「开启接管 DSH 技能」步骤,页面会直接提供重启按钮。
|
|
29
|
-
|
|
30
|
-
### 方式二:从 npm 安装
|
|
23
|
+
### npm(推荐)
|
|
31
24
|
|
|
32
25
|
```bash
|
|
33
26
|
dsh plugin --profile web add dsh-agent-skills
|
|
34
27
|
```
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
dsh plugin --profile web add github:minivv/dsh-agent-skills
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
仓库包含 `prepare: npm run build`,因此 pnpm 会在 Git 安装时自动构建。DSH/pnpm 可能会要求你授权构建脚本;不想授权构建时请使用 npm 或插件市场版本,npm 包已经包含构建好的 `lib/`。
|
|
43
|
-
|
|
44
|
-
### 开启接管 DSH 技能
|
|
45
|
-
|
|
46
|
-
完成任一种安装方式后:
|
|
29
|
+
安装后打开「设置 → Agent Skills」,点击「开启接管 DSH 技能」,再点击「重启 DSH」。
|
|
47
30
|
|
|
48
|
-
|
|
49
|
-
2. 点击 **开启接管 DSH 技能**。
|
|
50
|
-
3. 点击页面出现的 **重启 DSH**,等待服务恢复并自动刷新页面。
|
|
31
|
+
### DSH 插件市场
|
|
51
32
|
|
|
52
|
-
|
|
33
|
+
在「设置 → 插件市场」中搜索 **Agent Skills**,或查看 [DSH 插件市场](https://github.com/dsh-market/dsh-market)。
|
|
53
34
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
如果页面无法定位 DSH 安装位置,可以使用备用命令:
|
|
35
|
+
### GitHub
|
|
57
36
|
|
|
58
37
|
```bash
|
|
59
|
-
|
|
60
|
-
node ~/.dsh/profiles/web/node_modules/dsh-agent-skills/scripts/install-preset.mjs
|
|
38
|
+
dsh plugin --profile web add github:minivv/dsh-agent-skills
|
|
61
39
|
```
|
|
62
40
|
|
|
63
|
-
|
|
41
|
+
Git 安装可能需要授权 pnpm 执行构建脚本。
|
|
64
42
|
|
|
65
43
|
## 使用
|
|
66
44
|
|
|
67
|
-
1.
|
|
68
|
-
2.
|
|
69
|
-
3.
|
|
70
|
-
4.
|
|
71
|
-
5. 技能区出现“n 个技能变更需刷新页面生效”后,点击「刷新页面」。
|
|
72
|
-
6. 修改磁盘上的技能后,点击「重新扫描」或等待自动刷新。
|
|
45
|
+
1. 在「设置 → Agent Skills」中检查自动发现的目录,或点击「+ 添加目录」。
|
|
46
|
+
2. 使用目录和技能开关控制可用技能。
|
|
47
|
+
3. 出现技能变更提示后,点击「刷新页面」。
|
|
48
|
+
4. 修改技能文件后,点击「重新扫描」或等待自动刷新。
|
|
73
49
|
|
|
74
|
-
|
|
50
|
+
点击「取消接管」并重启 DSH,可恢复 DSH 原来的技能来源。
|
|
75
51
|
|
|
76
|
-
|
|
77
|
-
$DSH_HOME/agent-skills/state.json
|
|
78
|
-
```
|
|
52
|
+
设置保存在 `$DSH_HOME/agent-skills/state.json`。
|
|
79
53
|
|
|
80
|
-
|
|
54
|
+
## 技能格式
|
|
81
55
|
|
|
82
56
|
```text
|
|
83
57
|
skills/
|
|
@@ -86,7 +60,7 @@ skills/
|
|
|
86
60
|
└── another-skill.md
|
|
87
61
|
```
|
|
88
62
|
|
|
89
|
-
`SKILL.md` 需要 YAML frontmatter,`name`
|
|
63
|
+
`SKILL.md` 需要 YAML frontmatter,`name` 使用小写 kebab-case:
|
|
90
64
|
|
|
91
65
|
```markdown
|
|
92
66
|
---
|
|
@@ -99,9 +73,13 @@ description: Explain when this skill should be used.
|
|
|
99
73
|
|
|
100
74
|
## 卸载
|
|
101
75
|
|
|
102
|
-
|
|
76
|
+
先在设置页点击「取消接管」和「重启 DSH」,再运行:
|
|
103
77
|
|
|
104
|
-
|
|
78
|
+
```bash
|
|
79
|
+
dsh plugin --profile web remove dsh-agent-skills
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
如果设置页无法打开,先恢复 DSH 技能来源:
|
|
105
83
|
|
|
106
84
|
```bash
|
|
107
85
|
DSH_INSTALL_ROOT="$(npm root -g)/@deepseek-ai/dsh" \
|
|
@@ -110,8 +88,6 @@ DSH_INSTALL_ROOT="$(npm root -g)/@deepseek-ai/dsh" \
|
|
|
110
88
|
dsh plugin --profile web remove dsh-agent-skills
|
|
111
89
|
```
|
|
112
90
|
|
|
113
|
-
最后重启 DSH Web。插件不会自动删除 `$DSH_HOME/agent-skills/state.json`,方便以后重装时保留设置。
|
|
114
|
-
|
|
115
91
|
## 开发
|
|
116
92
|
|
|
117
93
|
要求 Node.js 20+。
|
|
@@ -120,27 +96,21 @@ dsh plugin --profile web remove dsh-agent-skills
|
|
|
120
96
|
npm install
|
|
121
97
|
npm run typecheck
|
|
122
98
|
npm run build
|
|
99
|
+
npm test
|
|
123
100
|
npm pack --dry-run
|
|
124
101
|
```
|
|
125
102
|
|
|
126
|
-
|
|
127
|
-
- `src/preset.ts`:preset-only 入口,只注册 scoped provider。
|
|
128
|
-
- `src/client/`:设置页 UI。
|
|
129
|
-
- `src/scan.ts`:技能目录扫描和 frontmatter 解析。
|
|
130
|
-
- `lib/`:已提交的构建产物,供 npm 和免构建安装使用。
|
|
131
|
-
|
|
132
|
-
## 已知约束
|
|
103
|
+
## 注意
|
|
133
104
|
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- DSH 升级可能覆盖其内置 preset 文件;如开关不再生效,在设置页重新点击「开启接管 DSH 技能」。
|
|
105
|
+
- 技能名必须匹配 `[a-z0-9]+(?:-[a-z0-9]+)*`
|
|
106
|
+
- DSH 升级后如果开关失效,重新开启接管并重启 DSH
|
|
137
107
|
|
|
138
|
-
##
|
|
108
|
+
## 链接
|
|
139
109
|
|
|
140
110
|
- [GitHub](https://github.com/minivv/dsh-agent-skills)
|
|
141
111
|
- [npm](https://www.npmjs.com/package/dsh-agent-skills)
|
|
142
112
|
- [DSH 插件市场](https://github.com/dsh-market/dsh-market)
|
|
143
|
-
- [WeiSpot
|
|
113
|
+
- [WeiSpot](https://weispot.vercel.app/projects/dsh-agent-skills)
|
|
144
114
|
|
|
145
115
|
## License
|
|
146
116
|
|
package/lib/client.js
CHANGED
|
@@ -236,7 +236,12 @@ function AgentSkillsSection({ api, t }) {
|
|
|
236
236
|
const [view, setView] = (0, import_react.useState)(void 0);
|
|
237
237
|
const [takeover, setTakeover] = (0, import_react.useState)(void 0);
|
|
238
238
|
const [takeoverRestartRequired, setTakeoverRestartRequired] = (0, import_react.useState)(false);
|
|
239
|
-
const [restarting,
|
|
239
|
+
const [restarting, setRestartingState] = (0, import_react.useState)(false);
|
|
240
|
+
const restartingRef = (0, import_react.useRef)(false);
|
|
241
|
+
const setRestarting = (0, import_react.useCallback)((next) => {
|
|
242
|
+
restartingRef.current = next;
|
|
243
|
+
setRestartingState(next);
|
|
244
|
+
}, []);
|
|
240
245
|
const [busy, setBusy] = (0, import_react.useState)(true);
|
|
241
246
|
const [error51, setError] = (0, import_react.useState)("");
|
|
242
247
|
const [query, setQuery] = (0, import_react.useState)("");
|
|
@@ -266,24 +271,38 @@ function AgentSkillsSection({ api, t }) {
|
|
|
266
271
|
setPendingSkillCount(changed);
|
|
267
272
|
}, [rememberBaseline]);
|
|
268
273
|
const load = (0, import_react.useCallback)(async (refresh = () => api.list()) => {
|
|
274
|
+
if (restartingRef.current) return;
|
|
269
275
|
setError("");
|
|
270
|
-
|
|
276
|
+
let result2;
|
|
277
|
+
try {
|
|
278
|
+
result2 = await refresh();
|
|
279
|
+
} catch (error52) {
|
|
280
|
+
if (restartingRef.current) return;
|
|
281
|
+
setError(t("errorLoad", { message: error52 instanceof Error ? error52.message : String(error52) }));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
271
284
|
if (result2.ok) {
|
|
272
285
|
rememberBaseline(result2.value);
|
|
273
286
|
setView(result2.value);
|
|
274
|
-
} else {
|
|
287
|
+
} else if (!restartingRef.current) {
|
|
275
288
|
setError(t("errorLoad", { message: result2.error.message }));
|
|
276
289
|
}
|
|
277
290
|
}, [api, rememberBaseline, t]);
|
|
278
291
|
const loadTakeover = (0, import_react.useCallback)(async (refresh = () => api.takeoverStatus()) => {
|
|
279
|
-
|
|
292
|
+
if (restartingRef.current) return;
|
|
293
|
+
let result2;
|
|
294
|
+
try {
|
|
295
|
+
result2 = await refresh();
|
|
296
|
+
} catch {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
280
299
|
if (result2.ok) {
|
|
281
300
|
setTakeover(result2.value);
|
|
282
301
|
const pending = readPendingRestart();
|
|
283
302
|
const stillPending = result2.value.boot !== void 0 && pending?.boot === result2.value.boot && result2.value.enabled !== pending.baselineEnabled;
|
|
284
303
|
setTakeoverRestartRequired(stillPending);
|
|
285
304
|
if (pending !== void 0 && !stillPending) writePendingRestart(void 0);
|
|
286
|
-
} else {
|
|
305
|
+
} else if (!restartingRef.current) {
|
|
287
306
|
setError(t("errorLoad", { message: result2.error.message }));
|
|
288
307
|
}
|
|
289
308
|
}, [api, t]);
|
|
@@ -292,11 +311,12 @@ function AgentSkillsSection({ api, t }) {
|
|
|
292
311
|
void Promise.all([load(), loadTakeover()]).finally(() => setBusy(false));
|
|
293
312
|
}, [load, loadTakeover]);
|
|
294
313
|
(0, import_react.useEffect)(() => {
|
|
314
|
+
if (restarting) return;
|
|
295
315
|
const timer = window.setInterval(() => {
|
|
296
316
|
void load();
|
|
297
317
|
}, 5e3);
|
|
298
318
|
return () => window.clearInterval(timer);
|
|
299
|
-
}, [load]);
|
|
319
|
+
}, [load, restarting]);
|
|
300
320
|
const mutate = (0, import_react.useCallback)(async (operation, trackSkillChanges = false) => {
|
|
301
321
|
setSaving(true);
|
|
302
322
|
setError("");
|
|
@@ -386,7 +406,7 @@ function AgentSkillsSection({ api, t }) {
|
|
|
386
406
|
} catch {
|
|
387
407
|
}
|
|
388
408
|
retry();
|
|
389
|
-
}, [api, restarting, t, takeover?.boot]);
|
|
409
|
+
}, [api, restarting, setRestarting, t, takeover?.boot]);
|
|
390
410
|
const toggleDirExpanded = (path) => {
|
|
391
411
|
setDirExpanded((prev) => {
|
|
392
412
|
const next = new Set(prev);
|