@lmzhen/dsh-evolution-skill-catalog 0.3.62 → 0.3.64
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 +4 -1
- package/lib/index.js +43 -4
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -23,5 +23,8 @@ Independent of request-prefix construction. This package does not alter the asse
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
- Read-only native `ctx.skills` catalog. Skill mutations still happen through `tool-skill-manage`.
|
|
26
|
-
- **Out-of-band edits need a refresh (0.3.18, E-71).** The catalog invalidates on the in-band `evolution/skill-mutated` event (all writes through SkillLibrary). Edits made outside the family — manual file edit, a git pull, another process — bypass that event and cannot be auto-detected (decision C: no filesystem watcher). A root-mtime probe re-stamps the summaries cache when the provider is re-queried after a structural change (directory add/remove/rename), but
|
|
26
|
+
- **Out-of-band edits need a refresh (0.3.18, E-71).** The catalog invalidates on the in-band `evolution/skill-mutated` event (all writes through SkillLibrary). Edits made outside the family — manual file edit, a git pull, another process — bypass that event and cannot be auto-detected (decision C: no filesystem watcher). A root-mtime probe re-stamps the summaries cache when the provider is re-queried after a structural change (directory add/remove/rename), but the probe only runs when the upstream skill registry actually consults this provider — between refreshes the registry's collect cache answers `list`/`snapshot` without calling providers (the real reason E-71's out-of-band skill stays invisible), while `get` of an already-indexed name still reaches the provider, so an out-of-band CONTENT edit of an existing skill shows fresh content there (description stays stale until refresh). Any out-of-band change is only guaranteed to be visible after `/evolution skills refresh` runs (or the process restarts).
|
|
27
|
+
- **Upstream-invalid entries are filtered, not published (P1-1, v18).** `SkillLibrary.list()` reports an empty description for a 0-byte/malformed SKILL.md (C-14 keeps it visible to the curator), and a tree entry created before the 0.3.64 name tightening can still carry a trailing/consecutive hyphen. Upstream `validateCandidate` throws on either shape, and that throw aborts the whole `ctx.skills` collection (breaking `agent/pre-step` and the `skill` tool for the session). This provider therefore skips (and warns once about) any candidate whose name is not upstream `SKILL_NAME` or whose description is empty. The entry stays visible to the curator/lifecycle; fix the SKILL.md frontmatter (or the directory name) to publish it.
|
|
28
|
+
- **`whenToUse` is published, `metadata` is not (E-11, v18).** A non-empty single-line `whenToUse` from the frontmatter is forwarded to the platform catalog (the upstream filesystem provider does the same, and the host/UI read it for routing hints). `metadata` needs a real YAML parse and stays unpublished by this provider.
|
|
29
|
+
- **Protection markers are best-effort per entry (A1-17, v18).** When the directory listing AND the per-marker probes fail, `SkillSummary.protectionUnknown` is true and consumers (curator, maintenance) treat the entry as protected rather than unprotected.
|
|
27
30
|
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import { SkillLibrary, evolutionIoAdapter, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
|
|
2
|
+
import { SKILL_NAME_RE, SkillLibrary, evolutionIoAdapter, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
//#region lib/types/index.js
|
|
5
5
|
/**
|
|
@@ -39,6 +39,22 @@ const Config = z.object({
|
|
|
39
39
|
* pins the "lower rank wins" resolution on the registry side.
|
|
40
40
|
*/
|
|
41
41
|
const EVOLUTION_SKILL_RANK = 390;
|
|
42
|
+
/**
|
|
43
|
+
* The mirror's `SKILL_NAME_RE` now carries the same shape (计划 B-4, v18), but
|
|
44
|
+
* this provider still filters: an EXISTING tree entry created before the
|
|
45
|
+
* tightening (trailing/consecutive hyphen) must not be forwarded, because
|
|
46
|
+
* upstream `validateCandidate` throws on it and that throw aborts the WHOLE
|
|
47
|
+
* `ctx.skills` collection (the caller is outside the provider try/catch),
|
|
48
|
+
* taking down `agent/pre-step` and the `skill` tool for the session.
|
|
49
|
+
*/
|
|
50
|
+
const UPSTREAM_SKILL_NAME_RE = SKILL_NAME_RE;
|
|
51
|
+
/** Upstream `validateCandidate` also refuses an empty description; the
|
|
52
|
+
* mirror's `SkillLibrary.list()` legitimately reports `''` for a 0-byte or
|
|
53
|
+
* malformed SKILL.md (C-14 keeps it visible to the curator). Such an entry
|
|
54
|
+
* must not reach the platform registry. */
|
|
55
|
+
function publishableSkill(name, description) {
|
|
56
|
+
return UPSTREAM_SKILL_NAME_RE.test(name) && description.trim().length > 0;
|
|
57
|
+
}
|
|
42
58
|
function apply(ctx, rawConfig = {}) {
|
|
43
59
|
const invocation = {
|
|
44
60
|
modelInvocable: rawConfig.modelInvocable ?? true,
|
|
@@ -49,6 +65,12 @@ function apply(ctx, rawConfig = {}) {
|
|
|
49
65
|
const included = new Set(rawConfig.includeSkillNames ?? []);
|
|
50
66
|
const excluded = new Set(rawConfig.excludeSkillNames ?? []);
|
|
51
67
|
const visible = (name) => (included.size === 0 || included.has(name)) && !excluded.has(name);
|
|
68
|
+
const warnedUnpublishable = /* @__PURE__ */ new Set();
|
|
69
|
+
const warnUnpublishable = (name, description) => {
|
|
70
|
+
if (warnedUnpublishable.has(name)) return;
|
|
71
|
+
warnedUnpublishable.add(name);
|
|
72
|
+
ctx.logger.warn(`evolution-skill-catalog: not publishing "${name}" — ${description.trim().length === 0 ? "empty description" : "name is not accepted by the upstream skill registry"} (fix the SKILL.md frontmatter; the curator still sees the entry)`);
|
|
73
|
+
};
|
|
52
74
|
let control;
|
|
53
75
|
let summariesCache = null;
|
|
54
76
|
let summariesStamp = null;
|
|
@@ -66,10 +88,21 @@ function apply(ctx, rawConfig = {}) {
|
|
|
66
88
|
};
|
|
67
89
|
const provider = {
|
|
68
90
|
name: "dsh-evolution",
|
|
69
|
-
async list(
|
|
70
|
-
|
|
91
|
+
async list(options) {
|
|
92
|
+
options.signal?.throwIfAborted();
|
|
93
|
+
const all = await summaries();
|
|
94
|
+
options.signal?.throwIfAborted();
|
|
95
|
+
return all.filter((summary) => {
|
|
96
|
+
if (!visible(summary.name)) return false;
|
|
97
|
+
if (!publishableSkill(summary.name, summary.description)) {
|
|
98
|
+
warnUnpublishable(summary.name, summary.description);
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}).map((summary) => ({
|
|
71
103
|
name: summary.name,
|
|
72
104
|
description: summary.description,
|
|
105
|
+
...summary.whenToUse !== void 0 ? { whenToUse: summary.whenToUse } : {},
|
|
73
106
|
invocation,
|
|
74
107
|
source: "user-dsh",
|
|
75
108
|
provider: "dsh-evolution",
|
|
@@ -82,16 +115,22 @@ function apply(ctx, rawConfig = {}) {
|
|
|
82
115
|
}
|
|
83
116
|
}));
|
|
84
117
|
},
|
|
85
|
-
async get(candidate) {
|
|
118
|
+
async get(candidate, options) {
|
|
119
|
+
options?.signal?.throwIfAborted();
|
|
86
120
|
const name = candidate.name;
|
|
87
121
|
if (!visible(name)) return void 0;
|
|
88
122
|
const summary = (await summaries()).find((item) => item.name === name);
|
|
89
123
|
if (!summary) return void 0;
|
|
124
|
+
if (!publishableSkill(summary.name, summary.description)) {
|
|
125
|
+
warnUnpublishable(summary.name, summary.description);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
90
128
|
const content = await library.read(name);
|
|
91
129
|
if (content === null) return void 0;
|
|
92
130
|
return {
|
|
93
131
|
name,
|
|
94
132
|
description: summary.description,
|
|
133
|
+
...summary.whenToUse !== void 0 ? { whenToUse: summary.whenToUse } : {},
|
|
95
134
|
invocation,
|
|
96
135
|
source: "user-dsh",
|
|
97
136
|
provider: "dsh-evolution",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-skill-catalog",
|
|
3
3
|
"description": "Native ctx.skills provider for the evolution-managed skill tree (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.64",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,18 +31,18 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-core": "^0.3.64"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
38
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
39
39
|
"@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
|
|
40
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
40
|
+
"@lmzhen/dsh-evolution-io": "^0.3.64"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
44
44
|
"@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
|
|
45
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
46
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
45
|
+
"@lmzhen/dsh-evolution-core": "^0.3.64",
|
|
46
|
+
"@lmzhen/dsh-evolution-io": "^0.3.64"
|
|
47
47
|
}
|
|
48
48
|
}
|