@michengai/dsh-skills-manager 0.1.37 → 0.1.40
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 +11 -3
- package/CHANGELOG.zh-CN.md +11 -3
- package/README.md +2 -1
- package/README.zh-CN.md +2 -1
- package/lib/client.js +4 -2
- package/lib/core.js +42 -49
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,11 +6,19 @@ The five most recent published versions are listed below.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.1.40 - 2026-09-05
|
|
10
|
+
|
|
11
|
+
- 修复禁用的外部同名技能遮蔽已启用 DSH 技能的问题,统一管理页与运行时的赢家选择。
|
|
12
|
+
- 冲突时为用户和项目级原生赢家提供作用域候选,保留禁用阻断、工作区隔离及来源文件不变性。
|
|
13
|
+
- 显式声明作用域注册表回归所需的开发依赖,确保 CI 干净安装可执行完整检查。
|
|
14
|
+
|
|
15
|
+
## 0.1.38 - 2026-09-03
|
|
16
|
+
|
|
17
|
+
- Added Cursor as a read-only, locally toggleable Skill source at `%USERPROFILE%\.cursor\skills`, with `DSH_CURSOR_HOME` override and state-file migration.
|
|
18
|
+
|
|
9
19
|
## 0.1.37 - 2026-09-03
|
|
10
20
|
|
|
11
|
-
-
|
|
12
|
-
- Rebased the dependency-version regression assertion on RC.1 and verified the complete package gate.
|
|
13
|
-
- Verified plugin registration, the Skill provider, SessionStore access, and the HTTP state endpoint against the real RC.1 Cordis host services.
|
|
21
|
+
- Added compatibility with DeepSeek Harness `0.1.2-rc.1`.
|
|
14
22
|
|
|
15
23
|
## 0.1.36 - 2026-09-03
|
|
16
24
|
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -6,11 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
## 未发布
|
|
8
8
|
|
|
9
|
+
## 0.1.40 - 2026-09-05
|
|
10
|
+
|
|
11
|
+
- 修复禁用的外部同名技能遮蔽已启用 DSH 技能的问题,统一管理页与运行时的赢家选择。
|
|
12
|
+
- 冲突时为用户和项目级原生赢家提供作用域候选,保留禁用阻断、工作区隔离及来源文件不变性。
|
|
13
|
+
- 显式声明作用域注册表回归所需的开发依赖,确保 CI 干净安装可执行完整检查。
|
|
14
|
+
|
|
15
|
+
## 0.1.38 - 2026-09-03
|
|
16
|
+
|
|
17
|
+
- 新增 Cursor 用户级只读技能来源,默认读取 `%USERPROFILE%\.cursor\skills`,支持 `DSH_CURSOR_HOME` 覆盖,并兼容迁移既有状态文件。
|
|
18
|
+
|
|
9
19
|
## 0.1.37 - 2026-09-03
|
|
10
20
|
|
|
11
|
-
-
|
|
12
|
-
- 将依赖版本回归断言同步到 RC.1,并完成完整发布门禁验证。
|
|
13
|
-
- 使用真实 RC.1 Cordis 宿主服务验证插件注册、Skill Provider、SessionStore 访问和 HTTP 状态接口。
|
|
21
|
+
- 支持 DeepSeek Harness `0.1.2-rc.1`。
|
|
14
22
|
|
|
15
23
|
## 0.1.36 - 2026-09-03
|
|
16
24
|
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
## Features
|
|
24
24
|
|
|
25
|
-
- Discover and load user-level skills from `.agents`, CC Switch, Codex, Claude, Gemini, and
|
|
25
|
+
- Discover and load user-level skills from `.agents`, CC Switch, Codex, Claude, Gemini, OpenCode, and Cursor into DSH.
|
|
26
26
|
- Discover project-level `.dsh/skills` and `.agents/skills` from active Session workspaces, grouped by project; every valid Skill can be enabled or disabled through non-mutating local policy.
|
|
27
27
|
- Persist every per-Skill toggle under `$DSH_HOME/skills-manager/state.json` without rewriting any source Skill file.
|
|
28
28
|
- Inspect Markdown bodies, frontmatter, invocation state, duplicate shadowing, and format diagnostics in a source-first UI.
|
|
@@ -153,6 +153,7 @@ Escape closes only the frontmost upload or confirmation dialog and leaves Settin
|
|
|
153
153
|
| `$DSH_HOME\skills` | Yes | Manager state only | Yes | Moves to Trash |
|
|
154
154
|
| `$DSH_AGENTS_HOME\skills` | Yes | Manager state only | No | No |
|
|
155
155
|
| `~\.cc-switch\skills` | Yes, enabled by default | Manager state only | No | No |
|
|
156
|
+
| `%USERPROFILE%\.cursor\skills` (or `$DSH_CURSOR_HOME\skills`) | Yes | Manager state only | No | No |
|
|
156
157
|
| `~/.codex/skills`, `~/.claude/skills`, `~/.gemini/skills`, `~/.config/opencode/skills` | Yes | Manager state only | No | No |
|
|
157
158
|
| `<project>/.dsh/skills` | Yes, for active Session workspaces | Manager state only | Create in Settings | Moves to Trash and restores to the original project |
|
|
158
159
|
| `<project>/.agents/skills` | Yes, for active Session workspaces | Manager state only | No | No |
|
package/README.zh-CN.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
## 功能概览
|
|
24
24
|
|
|
25
|
-
- 自动发现并把 `.agents`、CC Switch、Codex、Claude、Gemini 和
|
|
25
|
+
- 自动发现并把 `.agents`、CC Switch、Codex、Claude、Gemini、OpenCode 和 Cursor 的用户级技能真正加载进 DSH。
|
|
26
26
|
- 从活动 Session 工作区发现项目级 `.dsh/skills` 与 `.agents/skills` 并按项目分组;所有有效 Skill 都可通过不改源文件的本地策略启停。
|
|
27
27
|
- 所有逐 Skill 启停都只写入 `$DSH_HOME\skills-manager\state.json`,绝不改写任何来源 Skill 文件。
|
|
28
28
|
- 按来源折叠、搜索和筛选,并查看技能正文、frontmatter、调用状态、重名遮蔽与格式诊断。
|
|
@@ -153,6 +153,7 @@ dsh --profile web --dump-config
|
|
|
153
153
|
| `$DSH_HOME\skills` | 支持 | 仅写 manager 状态 | 支持 | 进入回收站 |
|
|
154
154
|
| `$DSH_AGENTS_HOME\skills` | 支持 | 仅写 manager 状态 | 不支持 | 不支持 |
|
|
155
155
|
| `~\.cc-switch\skills` | 支持,默认开启 | 仅写 manager 状态 | 不支持 | 不支持 |
|
|
156
|
+
| `%USERPROFILE%\.cursor\skills`(或 `$DSH_CURSOR_HOME\skills`) | 支持 | 仅写 manager 状态 | 不支持 | 不支持 |
|
|
156
157
|
| `~/.codex/skills`、`~/.claude/skills`、`~/.gemini/skills`、`~/.config/opencode/skills` | 支持 | 仅写 manager 状态 | 不支持 | 不支持 |
|
|
157
158
|
| `<project>/.dsh/skills` | 支持活动 Session 工作区 | 仅写 manager 状态 | 设置页支持创建 | 进入回收站并恢复到原项目 |
|
|
158
159
|
| `<project>/.agents/skills` | 支持活动 Session 工作区 | 仅写 manager 状态 | 不支持 | 不支持 |
|
package/lib/client.js
CHANGED
|
@@ -186,7 +186,8 @@
|
|
|
186
186
|
"root.codex": "Codex",
|
|
187
187
|
"root.claude": "Claude",
|
|
188
188
|
"root.gemini": "Gemini",
|
|
189
|
-
"root.opencode": "OpenCode"
|
|
189
|
+
"root.opencode": "OpenCode",
|
|
190
|
+
"root.cursor": "Cursor"
|
|
190
191
|
},
|
|
191
192
|
en: {
|
|
192
193
|
"title": "Skills",
|
|
@@ -364,7 +365,8 @@
|
|
|
364
365
|
"root.codex": "Codex",
|
|
365
366
|
"root.claude": "Claude",
|
|
366
367
|
"root.gemini": "Gemini",
|
|
367
|
-
"root.opencode": "OpenCode"
|
|
368
|
+
"root.opencode": "OpenCode",
|
|
369
|
+
"root.cursor": "Cursor"
|
|
368
370
|
}
|
|
369
371
|
};
|
|
370
372
|
var CSS = `
|
package/lib/core.js
CHANGED
|
@@ -41,7 +41,8 @@ function userRoots() {
|
|
|
41
41
|
{ key: "codex", path: join(process.env.DSH_CODEX_HOME || join(homedir(), ".codex"), "skills"), label: "Codex", mutable: false, toggleable: true, native: false, rank: 520 },
|
|
42
42
|
{ key: "claude", path: join(process.env.DSH_CLAUDE_HOME || join(homedir(), ".claude"), "skills"), label: "Claude", mutable: false, toggleable: true, native: false, rank: 530 },
|
|
43
43
|
{ key: "gemini", path: join(process.env.DSH_GEMINI_HOME || join(homedir(), ".gemini"), "skills"), label: "Gemini", mutable: false, toggleable: true, native: false, rank: 540 },
|
|
44
|
-
{ key: "opencode", path: join(process.env.DSH_OPENCODE_HOME || join(homedir(), ".config", "opencode"), "skills"), label: "OpenCode", mutable: false, toggleable: true, native: false, rank: 550 }
|
|
44
|
+
{ key: "opencode", path: join(process.env.DSH_OPENCODE_HOME || join(homedir(), ".config", "opencode"), "skills"), label: "OpenCode", mutable: false, toggleable: true, native: false, rank: 550 },
|
|
45
|
+
{ key: "cursor", path: join(process.env.DSH_CURSOR_HOME || join(homedir(), ".cursor"), "skills"), label: "Cursor", mutable: false, toggleable: true, native: false, rank: 560 }
|
|
45
46
|
];
|
|
46
47
|
}
|
|
47
48
|
function projectIdentity(path) {
|
|
@@ -647,6 +648,9 @@ function migrateManagerStateDocument(value) {
|
|
|
647
648
|
if (value.sources && typeof value.sources === "object" && !Array.isArray(value.sources) && value.sources.ccswitch === void 0) value.sources.ccswitch = true;
|
|
648
649
|
if (value.disabledSkills && typeof value.disabledSkills === "object" && !Array.isArray(value.disabledSkills) && value.disabledSkills.ccswitch === void 0) value.disabledSkills.ccswitch = [];
|
|
649
650
|
if (value.enabledSkills && typeof value.enabledSkills === "object" && !Array.isArray(value.enabledSkills) && value.enabledSkills.ccswitch === void 0) value.enabledSkills.ccswitch = [];
|
|
651
|
+
if (value.sources && typeof value.sources === "object" && !Array.isArray(value.sources) && value.sources.cursor === void 0) value.sources.cursor = true;
|
|
652
|
+
if (value.disabledSkills && typeof value.disabledSkills === "object" && !Array.isArray(value.disabledSkills) && value.disabledSkills.cursor === void 0) value.disabledSkills.cursor = [];
|
|
653
|
+
if (value.enabledSkills && typeof value.enabledSkills === "object" && !Array.isArray(value.enabledSkills) && value.enabledSkills.cursor === void 0) value.enabledSkills.cursor = [];
|
|
650
654
|
return value;
|
|
651
655
|
}
|
|
652
656
|
function normalizeManagerState(value) {
|
|
@@ -1378,52 +1382,35 @@ async function listProviderCandidates(options = {}) {
|
|
|
1378
1382
|
const candidates = [];
|
|
1379
1383
|
const user = userRoots();
|
|
1380
1384
|
const userScans = await scanDeduplicatedUserRoots(user);
|
|
1381
|
-
|
|
1382
|
-
const scanned = userScans.get(root.key);
|
|
1383
|
-
for (const entry of scanned.entries) {
|
|
1384
|
-
if (!entry.loadable) continue;
|
|
1385
|
-
const policy = effectiveSkillPolicy(policyResult, root, entry);
|
|
1386
|
-
const needsOverlay = root.key !== "dsh" || policy.override !== void 0 || !entry.invocationPolicyValid || policyResult.writable === false;
|
|
1387
|
-
if (!needsOverlay) continue;
|
|
1388
|
-
candidates.push({
|
|
1389
|
-
name: entry.declaredName,
|
|
1390
|
-
description: entry.description,
|
|
1391
|
-
invocation: { modelInvocable: policy.modelInvocable, userInvocable: policy.userInvocable },
|
|
1392
|
-
provider: "dsh-skills-manager-external",
|
|
1393
|
-
source: root.key === "dsh" ? "user-dsh" : `agent-${root.key}`,
|
|
1394
|
-
rank: root.key === "dsh" ? USER_DSH_POLICY_RANK : entry.providerRank ?? root.rank,
|
|
1395
|
-
locator: { rootKey: root.key, entryName: entry.name, path: entry.docPath, realEntryPath: entry.realEntryPath, realDocPath: entry.realDocPath },
|
|
1396
|
-
resourceBase: { kind: "directory", path: entry.kind === "bundle" ? entry.realEntryPath : root.path },
|
|
1397
|
-
path: entry.docPath,
|
|
1398
|
-
metadata: { dshSkillsManager: { root: root.key, readOnly: !root.mutable, sourceReadOnly: !root.mutable, policyOnly: root.key === "dsh" } }
|
|
1399
|
-
});
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1385
|
+
const items = user.flatMap((root) => userScans.get(root.key).entries.map((entry) => ({ root, entry })));
|
|
1402
1386
|
const cwd = options && typeof options.cwd === "string" ? options.cwd : void 0;
|
|
1403
1387
|
if (cwd) {
|
|
1404
1388
|
const roots = await projectRoots([cwd]);
|
|
1405
1389
|
for (const root of roots) {
|
|
1406
1390
|
const scanned = await scanEntries(root.path);
|
|
1407
|
-
for (const entry of scanned.entries) {
|
|
1408
|
-
if (!entry.loadable) continue;
|
|
1409
|
-
const policy = effectiveSkillPolicy(policyResult, root, entry);
|
|
1410
|
-
const needsOverlay = policy.override !== void 0 || !entry.invocationPolicyValid || policyResult.writable === false;
|
|
1411
|
-
if (!needsOverlay) continue;
|
|
1412
|
-
candidates.push({
|
|
1413
|
-
name: entry.declaredName,
|
|
1414
|
-
description: entry.description,
|
|
1415
|
-
invocation: { modelInvocable: policy.modelInvocable, userInvocable: policy.userInvocable },
|
|
1416
|
-
provider: "dsh-skills-manager-external",
|
|
1417
|
-
source: root.kind,
|
|
1418
|
-
rank: root.rank - 1,
|
|
1419
|
-
locator: { rootKey: root.key, entryName: entry.name, path: entry.docPath, realEntryPath: entry.realEntryPath, realDocPath: entry.realDocPath },
|
|
1420
|
-
resourceBase: { kind: "directory", path: entry.kind === "bundle" ? entry.realEntryPath : root.path },
|
|
1421
|
-
path: entry.docPath,
|
|
1422
|
-
metadata: { dshSkillsManager: { root: root.key, readOnly: !root.mutable, sourceReadOnly: !root.mutable, policyOnly: true } }
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1391
|
+
for (const entry of scanned.entries) items.push({ root, entry });
|
|
1425
1392
|
}
|
|
1426
1393
|
}
|
|
1394
|
+
for (const group of groupLoadableSkillsByName(items).values()) {
|
|
1395
|
+
const { root, entry } = group[0];
|
|
1396
|
+
const project = root.scope === "project";
|
|
1397
|
+
const policyOnly = project || root.key === "dsh";
|
|
1398
|
+
const policy = effectiveSkillPolicy(policyResult, root, entry);
|
|
1399
|
+
const needsOverlay = !policyOnly || group.length > 1 || policy.override !== void 0 || !entry.invocationPolicyValid || policyResult.writable === false;
|
|
1400
|
+
if (!needsOverlay) continue;
|
|
1401
|
+
candidates.push({
|
|
1402
|
+
name: entry.declaredName,
|
|
1403
|
+
description: entry.description,
|
|
1404
|
+
invocation: { modelInvocable: policy.modelInvocable, userInvocable: policy.userInvocable },
|
|
1405
|
+
provider: "dsh-skills-manager-external",
|
|
1406
|
+
source: project ? root.kind : root.key === "dsh" ? "user-dsh" : `agent-${root.key}`,
|
|
1407
|
+
rank: project ? root.rank - 1 : root.key === "dsh" ? USER_DSH_POLICY_RANK : entry.providerRank ?? root.rank,
|
|
1408
|
+
locator: { rootKey: root.key, entryName: entry.name, path: entry.docPath, realEntryPath: entry.realEntryPath, realDocPath: entry.realDocPath },
|
|
1409
|
+
resourceBase: { kind: "directory", path: entry.kind === "bundle" ? entry.realEntryPath : root.path },
|
|
1410
|
+
path: entry.docPath,
|
|
1411
|
+
metadata: { dshSkillsManager: { root: root.key, readOnly: !root.mutable, sourceReadOnly: !root.mutable, policyOnly } }
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1427
1414
|
return candidates;
|
|
1428
1415
|
}
|
|
1429
1416
|
async function getProviderSkill(candidate, options = {}) {
|
|
@@ -1460,18 +1447,24 @@ async function getProviderSkill(candidate, options = {}) {
|
|
|
1460
1447
|
function canonicalSkillName(item) {
|
|
1461
1448
|
return item.entry.declaredName || item.entry.name;
|
|
1462
1449
|
}
|
|
1463
|
-
function
|
|
1464
|
-
const
|
|
1450
|
+
function groupLoadableSkillsByName(items) {
|
|
1451
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1465
1452
|
for (const item of [...items].sort((a, b) => a.root.rank - b.root.rank)) {
|
|
1466
|
-
const canonicalName = canonicalSkillName(item);
|
|
1467
1453
|
if (!item.entry.loadable) continue;
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
}
|
|
1454
|
+
const name = canonicalSkillName(item);
|
|
1455
|
+
const group = groups.get(name) || [];
|
|
1456
|
+
group.push(item);
|
|
1457
|
+
groups.set(name, group);
|
|
1473
1458
|
}
|
|
1474
|
-
|
|
1459
|
+
return groups;
|
|
1460
|
+
}
|
|
1461
|
+
function markWinners(items, options = {}) {
|
|
1462
|
+
const winners = /* @__PURE__ */ new Map();
|
|
1463
|
+
for (const [canonicalName, [winner, ...shadowed]] of groupLoadableSkillsByName(items)) {
|
|
1464
|
+
winners.set(canonicalName, winner);
|
|
1465
|
+
if (options.markShadowed !== false) {
|
|
1466
|
+
for (const item of shadowed) item.view.shadowedBy = { root: winner.root.key, name: winner.entry.name };
|
|
1467
|
+
}
|
|
1475
1468
|
if (options.markWinner !== false) winner.view.winner = true;
|
|
1476
1469
|
winner.view.enabled = winner.policy.enabled;
|
|
1477
1470
|
winner.view.canonicalName = canonicalName;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-skills-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
4
4
|
"description": "NPM-installable DSH Web plugin for safely loading and managing skills across DSH and common local Agents.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -64,11 +64,13 @@
|
|
|
64
64
|
"react": "^18.2.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
67
68
|
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
68
69
|
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
|
|
69
70
|
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
|
|
70
71
|
"@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1",
|
|
71
72
|
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
73
|
+
"@deepseek-ai/dsh-scope": "0.1.2-rc.1",
|
|
72
74
|
"@deepseek-ai/dsh-skill": "0.1.2-rc.1",
|
|
73
75
|
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
74
76
|
"@deepseek-ai/dsh-web-app": "0.1.2-rc.1",
|