@lmzhen/dsh-tool-skill-manage 0.3.16 → 0.3.18
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 +10 -0
- package/lib/index.js +20 -13
- package/lib/types/index.d.ts +7 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -18,6 +18,16 @@ Adds the `skill_manage` tool schema to the request catalog; result tokens scale
|
|
|
18
18
|
|
|
19
19
|
Tool schema is prefix-stable. Skill writes do not alter the current request prompt; catalog invalidation affects the next request.
|
|
20
20
|
|
|
21
|
+
## Safety model
|
|
22
|
+
|
|
23
|
+
### Approval seam
|
|
24
|
+
|
|
25
|
+
Mutations (create/edit/update/patch/delete/write_file/remove_file/restructure) pass through the evolution approval seam when `evolution-approval` is mounted; approved/staged writes are replayed by the registered runner with the library origin preserved.
|
|
26
|
+
|
|
27
|
+
### pin/unpin: explicit exception (0.3.18, E-70)
|
|
28
|
+
|
|
29
|
+
`pin` and `unpin` are deliberately **outside** the approval seam. Pinning only lifts/restores the curator-lifecycle freeze — it changes a lifecycle flag, never content — and is fully reversible by the same tool. Routing it through `policy:'ask'` would let a staged-but-never-approved request hold the library in a pinned state invisibly. Tradeoff accepted: no approval on a lifecycle-flag flip; if product policy changes, pin/unpin should be wired into the same staging path as `patch`.
|
|
30
|
+
|
|
21
31
|
## Known Limitations and Deferred Work
|
|
22
32
|
|
|
23
33
|
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
2
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3
|
-
import { DEFAULT_SKILL_LIMITS, DSH_AUTHORING_STANDARDS, SKILLS_GUIDANCE, SkillLibrary, authoringFeedback, computeDedupGroups, evolutionIoAdapter, parseFrontmatter, resolveOrigins } from "@lmzhen/dsh-evolution-core";
|
|
3
|
+
import { DEFAULT_SKILL_LIMITS, DSH_AUTHORING_STANDARDS, SKILLS_GUIDANCE, SkillLibrary, authoringFeedback, computeDedupGroups, evolutionIoAdapter, parseFrontmatter, resolveOrigins, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
|
|
4
4
|
//#region lib/types/index.js
|
|
5
5
|
/**
|
|
6
6
|
* Model-facing skill_manage tool over ctx.evolutionIo + ctx.skillUsage.
|
|
@@ -9,6 +9,13 @@ import { DEFAULT_SKILL_LIMITS, DSH_AUTHORING_STANDARDS, SKILLS_GUIDANCE, SkillLi
|
|
|
9
9
|
* approved/staged background writes are replayed by the registered runner.
|
|
10
10
|
* The skill library itself never hard-deletes: archive is the maximum
|
|
11
11
|
* destructive action and every curator mutation is snapshot-reversible.
|
|
12
|
+
*
|
|
13
|
+
* 0.3.18 (E-70) — pin/unpin are deliberately OUTSIDE the approval seam:
|
|
14
|
+
* pinning only lifts/restores the curator-lifecycle freeze and is fully
|
|
15
|
+
* reversible by the same tool; routing it through `policy:'ask'` would let a
|
|
16
|
+
* staged-then-stale request hold the library in a pinned state invisibly.
|
|
17
|
+
* The tradeoff (no approval on a lifecycle-flag flip) is accepted and
|
|
18
|
+
* documented in the README Safety model section.
|
|
12
19
|
* @module @lmzhen/dsh-tool-skill-manage
|
|
13
20
|
*/
|
|
14
21
|
const name = "tool-skill-manage";
|
|
@@ -17,12 +24,15 @@ const inject = [
|
|
|
17
24
|
"skillUsage",
|
|
18
25
|
"evolutionIo"
|
|
19
26
|
];
|
|
27
|
+
/** 0.3.18 (E-70): review output lists at most this many near-duplicate groups
|
|
28
|
+
* (a cap, not a per-group limit) — the one named bound for the slice below. */
|
|
29
|
+
const MAX_DEDUP_GROUPS_IN_REVIEW = 3;
|
|
20
30
|
const Config = z.object({
|
|
21
31
|
root: z.string().default(""),
|
|
22
|
-
maxSkillNameLength: z.number().default(DEFAULT_SKILL_LIMITS.maxNameLength),
|
|
23
|
-
maxDescriptionLength: z.number().default(DEFAULT_SKILL_LIMITS.maxDescriptionLength),
|
|
24
|
-
maxSkillContentChars: z.number().default(DEFAULT_SKILL_LIMITS.maxSkillContentChars),
|
|
25
|
-
maxSkillFileBytes: z.number().default(DEFAULT_SKILL_LIMITS.maxSkillFileBytes),
|
|
32
|
+
maxSkillNameLength: z.number().min(1).default(DEFAULT_SKILL_LIMITS.maxNameLength),
|
|
33
|
+
maxDescriptionLength: z.number().min(1).default(DEFAULT_SKILL_LIMITS.maxDescriptionLength),
|
|
34
|
+
maxSkillContentChars: z.number().min(1).default(DEFAULT_SKILL_LIMITS.maxSkillContentChars),
|
|
35
|
+
maxSkillFileBytes: z.number().min(1).default(DEFAULT_SKILL_LIMITS.maxSkillFileBytes),
|
|
26
36
|
descriptionStrict: z.boolean().default(false)
|
|
27
37
|
});
|
|
28
38
|
/**
|
|
@@ -44,7 +54,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
44
54
|
text: SKILLS_GUIDANCE
|
|
45
55
|
}), "tool-skill-manage.skills-guidance");
|
|
46
56
|
const io = evolutionIoAdapter(() => ctx.evolutionIo.provider());
|
|
47
|
-
const library = new SkillLibrary(rawConfig
|
|
57
|
+
const library = new SkillLibrary(resolveSkillsRoot(rawConfig), io, {
|
|
48
58
|
maxNameLength: rawConfig.maxSkillNameLength ?? DEFAULT_SKILL_LIMITS.maxNameLength,
|
|
49
59
|
maxDescriptionLength: rawConfig.maxDescriptionLength ?? DEFAULT_SKILL_LIMITS.maxDescriptionLength,
|
|
50
60
|
maxSkillContentChars: rawConfig.maxSkillContentChars ?? DEFAULT_SKILL_LIMITS.maxSkillContentChars,
|
|
@@ -106,12 +116,9 @@ function apply(ctx, rawConfig = {}) {
|
|
|
106
116
|
if (result.ok) {
|
|
107
117
|
if (result.normalizedFrontmatterFields && result.normalizedFrontmatterFields.length > 0) feedbackLines.push(`frontmatter auto-quoted (YAML compatibility): ${result.normalizedFrontmatterFields.join(", ")}`);
|
|
108
118
|
const mutating = action !== "list" && action !== "review" && action !== "skip" && action !== "pin" && action !== "unpin";
|
|
109
|
-
if (name && action === "create")
|
|
110
|
-
await ctx.skillUsage.ensureRecord(name);
|
|
111
|
-
if (origin !== "foreground") await ctx.skillUsage.markAgentCreated(name);
|
|
112
|
-
}
|
|
119
|
+
if (name && action === "create") await ctx.skillUsage.ensureRecordCreated(name, origin !== "foreground");
|
|
113
120
|
if (name && action === "delete") await ctx.skillUsage.markArchived(name);
|
|
114
|
-
else if (name && mutating && action !== "create") await ctx.skillUsage.record(name, "patch");
|
|
121
|
+
else if (name && mutating && action !== "create" && result.noop !== true) await ctx.skillUsage.record(name, "patch");
|
|
115
122
|
}
|
|
116
123
|
return {
|
|
117
124
|
ok: result.ok,
|
|
@@ -128,7 +135,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
128
135
|
return `- ${summary.name} | ${record?.state ?? "active"} | use:${record?.use_count ?? 0} view:${record?.view_count ?? 0} patch:${record?.patch_count ?? 0}${quality}${summary.protectedBy ? ` [${summary.protectedBy}]` : ""}`;
|
|
129
136
|
});
|
|
130
137
|
const groups = computeDedupGroups({ contents: new Map(await Promise.all(list.map(async (summary) => [summary.name, await library.read(summary.name) ?? ""]))) });
|
|
131
|
-
const dedupLines = groups.slice(0,
|
|
138
|
+
const dedupLines = groups.slice(0, MAX_DEDUP_GROUPS_IN_REVIEW).map((group) => `- ${group.join(" ~ ")}`);
|
|
132
139
|
const warned = list.filter((summary) => report.get(summary.name)?.quality_warn === true).map((summary) => summary.name);
|
|
133
140
|
const warningLine = warned.length === 0 ? "" : `\nWarning skills (${warned.length}): ${warned.join(", ")} — low quality; consider consolidating them before authoring new skills.`;
|
|
134
141
|
return [
|
|
@@ -231,7 +238,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
231
238
|
ok: true,
|
|
232
239
|
message: decision.message,
|
|
233
240
|
skills: [],
|
|
234
|
-
pending_id: decision.pendingId
|
|
241
|
+
...decision.pendingId !== void 0 ? { pending_id: decision.pendingId } : {}
|
|
235
242
|
};
|
|
236
243
|
}
|
|
237
244
|
return await executeCore(args, libraryOrigin);
|
package/lib/types/index.d.ts
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
* approved/staged background writes are replayed by the registered runner.
|
|
6
6
|
* The skill library itself never hard-deletes: archive is the maximum
|
|
7
7
|
* destructive action and every curator mutation is snapshot-reversible.
|
|
8
|
+
*
|
|
9
|
+
* 0.3.18 (E-70) — pin/unpin are deliberately OUTSIDE the approval seam:
|
|
10
|
+
* pinning only lifts/restores the curator-lifecycle freeze and is fully
|
|
11
|
+
* reversible by the same tool; routing it through `policy:'ask'` would let a
|
|
12
|
+
* staged-then-stale request hold the library in a pinned state invisibly.
|
|
13
|
+
* The tradeoff (no approval on a lifecycle-flag flip) is accepted and
|
|
14
|
+
* documented in the README Safety model section.
|
|
8
15
|
* @module @deepseek-ai/dsh-tool-skill-manage
|
|
9
16
|
*/
|
|
10
17
|
import type { Context } from '@deepseek-ai/cordis';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-tool-skill-manage",
|
|
3
3
|
"description": "Model-facing skill_manage tool (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.18",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,21 +33,21 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
36
|
+
"@lmzhen/dsh-evolution-core": "^0.3.18"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
40
40
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
41
41
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
42
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
43
|
-
"@lmzhen/dsh-skill-usage": "^0.3.
|
|
42
|
+
"@lmzhen/dsh-evolution-io": "^0.3.18",
|
|
43
|
+
"@lmzhen/dsh-skill-usage": "^0.3.18"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.1-rc.2",
|
|
47
47
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
48
48
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
49
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
50
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
51
|
-
"@lmzhen/dsh-skill-usage": "^0.3.
|
|
49
|
+
"@lmzhen/dsh-evolution-core": "^0.3.18",
|
|
50
|
+
"@lmzhen/dsh-evolution-io": "^0.3.18",
|
|
51
|
+
"@lmzhen/dsh-skill-usage": "^0.3.18"
|
|
52
52
|
}
|
|
53
53
|
}
|