dsh-agent-skills 0.1.3 → 0.1.5

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
@@ -25,7 +25,7 @@
25
25
 
26
26
  通过 [DSH 插件市场](https://github.com/dsh-market/dsh-market) 安装,或打开 DSH 的「设置 → 插件市场」,搜索 **Agent Skills**,点击安装。市场会优先使用 npm 包,安装速度快,也不需要在本机重新构建。
27
27
 
28
- 安装后继续完成下面的「开启接管 DSH 技能」步骤,再重启 DSH Web。
28
+ 安装后继续完成下面的「开启接管 DSH 技能」步骤,页面会直接提供重启按钮。
29
29
 
30
30
  ### 方式二:从 npm 安装
31
31
 
@@ -47,10 +47,12 @@ dsh plugin --profile web add github:minivv/dsh-agent-skills
47
47
 
48
48
  1. 打开 DSH 的「设置 → Agent Skills」。
49
49
  2. 点击 **开启接管 DSH 技能**。
50
- 3. 看到“已开启”提示后重启 DSH Web。
50
+ 3. 点击页面出现的 **重启 DSH**,等待服务恢复并自动刷新页面。
51
51
 
52
52
  开启后,页面会在 `standard` 与 `code` preset 中用 `dsh-agent-skills/preset` 替换原来的 `skill-filesystem` provider,让目录和技能开关真正控制 Agent 可见的技能。它不会创建第二个 `agentSkills` host 服务;卸载脚本会恢复官方 provider。
53
53
 
54
+ 需要恢复 DSH 原来的技能来源时,点击 **取消接管**,再点击 **重启 DSH**。页面刷新后,`standard` 与 `code` preset 会重新使用官方 `@deepseek-ai/dsh-skill-filesystem` provider。
55
+
54
56
  如果页面无法定位 DSH 安装位置,可以使用备用命令:
55
57
 
56
58
  ```bash
@@ -58,7 +60,7 @@ DSH_INSTALL_ROOT="$(npm root -g)/@deepseek-ai/dsh" \
58
60
  node ~/.dsh/profiles/web/node_modules/dsh-agent-skills/scripts/install-preset.mjs
59
61
  ```
60
62
 
61
- 执行后重启 DSH Web。DSH 升级可能覆盖内置 preset;如果页面重新显示“开启接管 DSH 技能”,点击一次即可恢复。
63
+ 执行后重启 DSH Web。DSH 升级可能覆盖内置 preset;如果页面重新显示“开启接管 DSH 技能”,点击一次并按页面提示重启即可恢复。
62
64
 
63
65
  ## 使用
64
66
 
@@ -97,7 +99,9 @@ description: Explain when this skill should be used.
97
99
 
98
100
  ## 卸载
99
101
 
100
- 先恢复 DSH 官方的 `skill-filesystem` provider,再卸载 npm 包:
102
+ 推荐先在「设置 Agent Skills」点击 **取消接管** **重启 DSH**,再从插件市场卸载。
103
+
104
+ 如果设置页无法打开,也可以用命令恢复 DSH 官方的 `skill-filesystem` provider,再卸载 npm 包:
101
105
 
102
106
  ```bash
103
107
  DSH_INSTALL_ROOT="$(npm root -g)/@deepseek-ai/dsh" \
package/lib/client.js CHANGED
@@ -40,10 +40,16 @@ var zh = {
40
40
  takeoverDescription: "\u5F00\u542F\u540E\uFF0C\u8FD9\u91CC\u7684\u76EE\u5F55\u548C\u6280\u80FD\u5F00\u5173\u4F1A\u771F\u6B63\u63A7\u5236 Agent \u53EF\u89C1\u7684\u6280\u80FD\u3002",
41
41
  takeoverEnabledTitle: "\u5DF2\u63A5\u7BA1 DSH \u6280\u80FD",
42
42
  takeoverEnabledDescription: "\u76EE\u5F55\u548C\u6280\u80FD\u5F00\u5173\u5DF2\u63A5\u5165 standard \u4E0E code \u9884\u8BBE\u3002",
43
- takeoverRestartDescription: "\u5DF2\u5F00\u542F\uFF0C\u8BF7\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
43
+ takeoverRestartDescription: "\u63A5\u7BA1\u5DF2\u5F00\u542F\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
44
+ takeoverDisableRestartDescription: "\u63A5\u7BA1\u5DF2\u53D6\u6D88\uFF0C\u91CD\u542F DSH \u540E\u6062\u590D\u5B98\u65B9\u6280\u80FD\u6765\u6E90\u3002",
44
45
  takeoverPartialDescription: "\u5DF2\u63A5\u5165 {configured}/{total} \u4E2A\u9884\u8BBE\uFF0C\u70B9\u51FB\u7EE7\u7EED\u5B8C\u6210\u3002",
45
46
  takeoverUnavailableDescription: "\u672A\u627E\u5230 DSH \u5B89\u88C5\u4F4D\u7F6E\uFF0C\u8BF7\u786E\u8BA4\u5F53\u524D\u9875\u9762\u7531 DSH \u542F\u52A8\u540E\u91CD\u8BD5\u3002",
46
47
  takeoverAction: "\u5F00\u542F\u63A5\u7BA1 DSH \u6280\u80FD",
48
+ takeoverDisableAction: "\u53D6\u6D88\u63A5\u7BA1",
49
+ restartDsh: "\u91CD\u542F DSH",
50
+ restartingDsh: "\u6B63\u5728\u91CD\u542F\u2026",
51
+ restartFailed: "\u91CD\u542F\u5931\u8D25\uFF1A{message}",
52
+ restartTimeout: "\u7B49\u5F85 DSH \u91CD\u542F\u8D85\u65F6\uFF0C\u8BF7\u67E5\u770B\u7EC8\u7AEF\u6216\u4E34\u65F6\u76EE\u5F55\u4E2D\u7684\u91CD\u542F\u65E5\u5FD7\u3002",
47
53
  searchPlaceholder: "\u641C\u7D22\u6280\u80FD\u540D\u79F0\u6216\u63CF\u8FF0\u2026",
48
54
  sources: "\u6765\u6E90",
49
55
  validCount: "\u4E2A\u6709\u6548",
@@ -90,10 +96,16 @@ var en = {
90
96
  takeoverDescription: "Connect these source and skill switches to the skills visible to the Agent.",
91
97
  takeoverEnabledTitle: "DSH skills are managed here",
92
98
  takeoverEnabledDescription: "Source and skill switches are connected to the standard and code presets.",
93
- takeoverRestartDescription: "Enabled. Restart DSH to apply the change.",
99
+ takeoverRestartDescription: "Takeover is enabled. Restart DSH to apply it.",
100
+ takeoverDisableRestartDescription: "Takeover is cancelled. Restart DSH to restore the official skill source.",
94
101
  takeoverPartialDescription: "Connected to {configured}/{total} presets. Continue to finish setup.",
95
102
  takeoverUnavailableDescription: "DSH could not be located. Open this page from DSH and try again.",
96
103
  takeoverAction: "Enable DSH skill takeover",
104
+ takeoverDisableAction: "Cancel takeover",
105
+ restartDsh: "Restart DSH",
106
+ restartingDsh: "Restarting\u2026",
107
+ restartFailed: "Restart failed: {message}",
108
+ restartTimeout: "DSH did not restart in time. Check the terminal or the restart logs in the temporary directory.",
97
109
  searchPlaceholder: "Search skills by name or description\u2026",
98
110
  sources: "Sources",
99
111
  validCount: "valid",
@@ -137,6 +149,26 @@ var en = {
137
149
  var import_react = require("react");
138
150
  var import_jsx_runtime = require("react/jsx-runtime");
139
151
  var clamp = (value, max) => value.length <= max ? value : value.slice(0, max - 1) + "\u2026";
152
+ var TAKEOVER_RESTART_KEY = "dsh-agent-skills:takeover-restart";
153
+ function readPendingRestart() {
154
+ try {
155
+ const raw = window.sessionStorage.getItem(TAKEOVER_RESTART_KEY);
156
+ if (raw === null) return void 0;
157
+ const parsed = JSON.parse(raw);
158
+ if (typeof parsed.boot === "string" && typeof parsed.baselineEnabled === "boolean") {
159
+ return { boot: parsed.boot, baselineEnabled: parsed.baselineEnabled };
160
+ }
161
+ } catch {
162
+ }
163
+ return void 0;
164
+ }
165
+ function writePendingRestart(pending) {
166
+ try {
167
+ if (pending === void 0) window.sessionStorage.removeItem(TAKEOVER_RESTART_KEY);
168
+ else window.sessionStorage.setItem(TAKEOVER_RESTART_KEY, JSON.stringify(pending));
169
+ } catch {
170
+ }
171
+ }
140
172
  function Switch({ checked, disabled, onChange, label }) {
141
173
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "as-switch", title: label, "aria-label": label, children: [
142
174
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, disabled, onChange: (event) => onChange(event.target.checked) }),
@@ -204,6 +236,7 @@ function AgentSkillsSection({ api, t }) {
204
236
  const [view, setView] = (0, import_react.useState)(void 0);
205
237
  const [takeover, setTakeover] = (0, import_react.useState)(void 0);
206
238
  const [takeoverRestartRequired, setTakeoverRestartRequired] = (0, import_react.useState)(false);
239
+ const [restarting, setRestarting] = (0, import_react.useState)(false);
207
240
  const [busy, setBusy] = (0, import_react.useState)(true);
208
241
  const [error51, setError] = (0, import_react.useState)("");
209
242
  const [query, setQuery] = (0, import_react.useState)("");
@@ -246,6 +279,10 @@ function AgentSkillsSection({ api, t }) {
246
279
  const result2 = await refresh();
247
280
  if (result2.ok) {
248
281
  setTakeover(result2.value);
282
+ const pending = readPendingRestart();
283
+ const stillPending = result2.value.boot !== void 0 && pending?.boot === result2.value.boot && result2.value.enabled !== pending.baselineEnabled;
284
+ setTakeoverRestartRequired(stillPending);
285
+ if (pending !== void 0 && !stillPending) writePendingRestart(void 0);
249
286
  } else {
250
287
  setError(t("errorLoad", { message: result2.error.message }));
251
288
  }
@@ -275,21 +312,81 @@ function AgentSkillsSection({ api, t }) {
275
312
  setSaving(false);
276
313
  }
277
314
  }, [t, updatePendingCount]);
278
- const enableTakeover = (0, import_react.useCallback)(async () => {
315
+ const changeTakeover = (0, import_react.useCallback)(async (enabled) => {
279
316
  setSaving(true);
280
317
  setError("");
281
318
  try {
282
- const result2 = await api.enableTakeover();
319
+ const result2 = enabled ? await api.enableTakeover() : await api.disableTakeover();
283
320
  if (result2.ok) {
321
+ const pending = readPendingRestart();
322
+ const baselineEnabled2 = result2.value.boot !== void 0 && pending?.boot === result2.value.boot ? pending.baselineEnabled : takeover?.enabled ?? !enabled;
323
+ const restartRequired = result2.value.enabled !== baselineEnabled2;
284
324
  setTakeover(result2.value);
285
- setTakeoverRestartRequired(result2.value.enabled);
325
+ setTakeoverRestartRequired(restartRequired);
326
+ writePendingRestart(restartRequired && result2.value.boot !== void 0 ? { boot: result2.value.boot, baselineEnabled: baselineEnabled2 } : void 0);
286
327
  } else {
287
328
  setError(t("errorSave", { message: result2.error.message }));
288
329
  }
289
330
  } finally {
290
331
  setSaving(false);
291
332
  }
292
- }, [api, t]);
333
+ }, [api, t, takeover?.enabled]);
334
+ const restartDsh = (0, import_react.useCallback)(async () => {
335
+ if (restarting) return;
336
+ const previousBoot = takeover?.boot;
337
+ setRestarting(true);
338
+ setError("");
339
+ const deadline = Date.now() + 6e4;
340
+ let sawOffline = false;
341
+ const retry = () => {
342
+ if (Date.now() > deadline) {
343
+ setRestarting(false);
344
+ setError(t("restartTimeout"));
345
+ return;
346
+ }
347
+ window.setTimeout(() => void poll(), 700);
348
+ };
349
+ const poll = async () => {
350
+ try {
351
+ const response = await fetch(`${window.location.origin}/?dsh-agent-skills-restart=${Date.now()}`, {
352
+ cache: "no-store"
353
+ });
354
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
355
+ } catch {
356
+ sawOffline = true;
357
+ retry();
358
+ return;
359
+ }
360
+ if (previousBoot !== void 0) {
361
+ try {
362
+ const status = await api.takeoverStatus();
363
+ if (status.ok && status.value.boot !== void 0 && status.value.boot !== previousBoot) {
364
+ window.location.reload();
365
+ return;
366
+ }
367
+ } catch {
368
+ sawOffline = true;
369
+ retry();
370
+ return;
371
+ }
372
+ }
373
+ if (sawOffline) {
374
+ window.location.reload();
375
+ return;
376
+ }
377
+ retry();
378
+ };
379
+ try {
380
+ const result2 = await api.restartDsh();
381
+ if (!result2.ok) {
382
+ setRestarting(false);
383
+ setError(t("restartFailed", { message: result2.error.message }));
384
+ return;
385
+ }
386
+ } catch {
387
+ }
388
+ retry();
389
+ }, [api, restarting, t, takeover?.boot]);
293
390
  const toggleDirExpanded = (path) => {
294
391
  setDirExpanded((prev) => {
295
392
  const next = new Set(prev);
@@ -338,9 +435,34 @@ function AgentSkillsSection({ api, t }) {
338
435
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "as-takeover-icon", "aria-hidden": "true", children: takeover.enabled ? "\u2713" : "\u2192" }),
339
436
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "as-takeover-copy", children: [
340
437
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: takeover.enabled ? t("takeoverEnabledTitle") : t("takeoverTitle") }),
341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: takeoverRestartRequired ? t("takeoverRestartDescription") : takeover.enabled ? t("takeoverEnabledDescription") : takeover.available && takeover.configured > 0 ? t("takeoverPartialDescription", { configured: takeover.configured, total: takeover.total }) : takeover.available ? t("takeoverDescription") : t("takeoverUnavailableDescription") })
438
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: takeoverRestartRequired ? takeover.enabled ? t("takeoverRestartDescription") : t("takeoverDisableRestartDescription") : takeover.enabled ? t("takeoverEnabledDescription") : takeover.available && takeover.configured > 0 ? t("takeoverPartialDescription", { configured: takeover.configured, total: takeover.total }) : takeover.available ? t("takeoverDescription") : t("takeoverUnavailableDescription") })
342
439
  ] }),
343
- !takeover.enabled && takeover.available && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "as-btn as-btn-primary as-takeover-action", disabled: saving, onClick: () => void enableTakeover(), children: t("takeoverAction") })
440
+ takeover.available && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "as-takeover-actions", children: [
441
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
442
+ "button",
443
+ {
444
+ type: "button",
445
+ className: takeover.enabled || takeoverRestartRequired ? "as-btn as-takeover-action" : "as-btn as-btn-primary as-takeover-action",
446
+ disabled: saving || restarting,
447
+ onClick: () => void changeTakeover(!takeover.enabled),
448
+ children: takeover.enabled ? t("takeoverDisableAction") : t("takeoverAction")
449
+ }
450
+ ),
451
+ takeoverRestartRequired && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
452
+ "button",
453
+ {
454
+ type: "button",
455
+ className: "as-btn as-btn-primary as-takeover-action",
456
+ disabled: saving || restarting,
457
+ onClick: () => void restartDsh(),
458
+ children: [
459
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\u21BB" }),
460
+ " ",
461
+ restarting ? t("restartingDsh") : t("restartDsh")
462
+ ]
463
+ }
464
+ )
465
+ ] })
344
466
  ] }),
345
467
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
346
468
  "input",
@@ -533,7 +655,8 @@ var CSS = `
533
655
  .as-takeover-copy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
534
656
  .as-takeover-copy strong { font-size: 13px; font-weight: 600; line-height: 1.35; text-wrap: balance; }
535
657
  .as-takeover-copy span { font-size: 12px; line-height: 1.45; color: var(--as-muted); text-wrap: pretty; }
536
- .as-takeover-action { min-height: 40px; flex: none; transition-property: transform, background-color; transition-duration: 120ms; }
658
+ .as-takeover-actions { display: flex; align-items: center; gap: 7px; flex: none; }
659
+ .as-takeover-action { min-height: 32px; flex: none; transition-property: transform, background-color; transition-duration: 120ms; }
537
660
  .as-takeover-action:active:not(:disabled) { transform: scale(0.96); }
538
661
 
539
662
  .as-sources-row { display: flex; align-items: baseline; gap: 10px; }
@@ -582,10 +705,10 @@ var CSS = `
582
705
  .as-skills-header { display: flex; align-items: baseline; gap: 7px; font-size: 13px; font-weight: 550; margin: 4px 0 0; text-wrap: balance; }
583
706
  .as-skills-header-title { color: var(--as-text); }
584
707
  .as-skills-header-stats { font-size: 11px; font-weight: 450; color: var(--as-muted-2); font-variant-numeric: tabular-nums; }
585
- .as-refresh-card { display: flex; align-items: center; gap: 9px; min-height: 48px; padding: 4px 5px 4px 11px; border: 1px solid rgba(210, 153, 34, 0.28); border-radius: var(--as-radius); background: var(--as-warning-soft); box-sizing: border-box; }
586
- .as-refresh-icon { flex: none; color: var(--as-warning); font-size: 17px; line-height: 1; }
587
- .as-refresh-message { flex: 1; min-width: 0; color: var(--as-text); font-size: 12px; line-height: 1.45; font-variant-numeric: tabular-nums; text-wrap: pretty; }
588
- .as-refresh-action { min-height: 40px; flex: none; border-color: rgba(210, 153, 34, 0.42); background: rgba(210, 153, 34, 0.08); transition-property: transform, background-color; transition-duration: 120ms; }
708
+ .as-refresh-card { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 3px 4px 3px 9px; border: 1px solid rgba(210, 153, 34, 0.28); border-radius: var(--as-radius); background: var(--as-warning-soft); box-sizing: border-box; }
709
+ .as-refresh-icon { flex: none; color: var(--as-warning); font-size: 15px; line-height: 1; }
710
+ .as-refresh-message { flex: 1; min-width: 0; color: var(--as-text); font-size: 12px; line-height: 1.3; font-variant-numeric: tabular-nums; }
711
+ .as-refresh-action { min-height: 28px; padding-block: 3px; flex: none; border-color: rgba(210, 153, 34, 0.42); background: rgba(210, 153, 34, 0.08); transition-property: transform, background-color; transition-duration: 120ms; }
589
712
  .as-refresh-action:hover { background: rgba(210, 153, 34, 0.14); }
590
713
  .as-refresh-action:active { transform: scale(0.96); }
591
714
  .as-skill-grid { display: flex; flex-direction: column; gap: 8px; }
@@ -638,14 +761,12 @@ var CSS = `
638
761
  flex: 1;
639
762
  }
640
763
  .as-takeover { align-items: flex-start; flex-wrap: wrap; }
641
- .as-takeover-action { width: 100%; }
764
+ .as-takeover-actions { width: 100%; justify-content: flex-end; flex-wrap: wrap; }
642
765
  .as-actions-row { flex-wrap: wrap; }
643
766
  .as-dir-row { align-items: flex-start; flex-wrap: wrap; }
644
767
  .as-dir-path { flex: 1; min-width: 120px; }
645
768
  .as-skill-row { align-items: flex-start; flex-wrap: wrap; }
646
- .as-refresh-card { flex-wrap: wrap; padding: 8px 9px; }
647
- .as-refresh-message { min-width: calc(100% - 34px); }
648
- .as-refresh-action { width: 100%; }
769
+ .as-refresh-card { padding: 3px 4px 3px 8px; }
649
770
  }
650
771
  `;
651
772
  var installed;
@@ -15242,7 +15363,12 @@ var presetTakeoverStatusSchema = external_exports.object({
15242
15363
  /** Number of preset files that already contain the managed row. */
15243
15364
  configured: external_exports.number().int().min(0),
15244
15365
  /** Number of supported preset files found in this DSH installation. */
15245
- total: external_exports.number().int().min(0)
15366
+ total: external_exports.number().int().min(0),
15367
+ /** Identifies the running DSH process; changes after a successful restart. */
15368
+ boot: external_exports.string().optional()
15369
+ });
15370
+ var restartResultSchema = external_exports.object({
15371
+ scheduled: external_exports.literal(true)
15246
15372
  });
15247
15373
  var toggleSkillInputSchema = external_exports.object({
15248
15374
  name: external_exports.string(),
@@ -15298,6 +15424,24 @@ var TYPERT_REMOTE = {
15298
15424
  parameters: [],
15299
15425
  result: result("PresetTakeoverStatus", presetTakeoverStatusSchema)
15300
15426
  },
15427
+ {
15428
+ id: `${PKG}#agentSkills/disableTakeover`,
15429
+ service: "agentSkills",
15430
+ namespace: "agentSkills",
15431
+ method: "disableTakeover",
15432
+ invocation: direct,
15433
+ parameters: [],
15434
+ result: result("PresetTakeoverStatus", presetTakeoverStatusSchema)
15435
+ },
15436
+ {
15437
+ id: `${PKG}#agentSkills/restartDsh`,
15438
+ service: "agentSkills",
15439
+ namespace: "agentSkills",
15440
+ method: "restartDsh",
15441
+ invocation: direct,
15442
+ parameters: [],
15443
+ result: result("RestartResult", restartResultSchema)
15444
+ },
15301
15445
  {
15302
15446
  id: `${PKG}#agentSkills/toggleSkill`,
15303
15447
  service: "agentSkills",