@lmzhen/dsh-tool-skill-manage 0.3.68 → 0.3.69
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/lib/index.js +55 -9
- package/package.json +8 -8
package/lib/index.js
CHANGED
|
@@ -37,6 +37,12 @@ const Config = z.object({
|
|
|
37
37
|
descriptionStrict: z.boolean().default(false),
|
|
38
38
|
threatExemptLabels: z.array(z.string()).default([])
|
|
39
39
|
});
|
|
40
|
+
/** v30 REV-02: read the protected-skill list off the (optional) policy
|
|
41
|
+
* snapshot through an `unknown` boundary — the Context augmentation types the
|
|
42
|
+
* getter non-optionally, but at runtime the row can be absent. */
|
|
43
|
+
function policySnapshotOf(source) {
|
|
44
|
+
return source?.get?.();
|
|
45
|
+
}
|
|
40
46
|
function apply(ctx, rawConfig = {}) {
|
|
41
47
|
const systemPrompt = ctx.get("systemPrompt");
|
|
42
48
|
if (systemPrompt) ctx.effect(() => systemPrompt.section({
|
|
@@ -64,18 +70,32 @@ function apply(ctx, rawConfig = {}) {
|
|
|
64
70
|
async function executeCore(args, origin = "foreground") {
|
|
65
71
|
const action = args.action;
|
|
66
72
|
const name = args.name ?? "";
|
|
67
|
-
if (action === "review")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
if (action === "review") try {
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
message: await buildSkillReviewText(),
|
|
77
|
+
skills: []
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
message: `skill_manage review: skill tree scan failed (${error instanceof Error ? error.message : String(error)}).`,
|
|
83
|
+
skills: []
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (action === "list") try {
|
|
73
87
|
const list = await library.list();
|
|
74
88
|
return {
|
|
75
89
|
ok: true,
|
|
76
90
|
message: `Listed ${list.length} skills.`,
|
|
77
91
|
skills: list.map((s) => s.name)
|
|
78
92
|
};
|
|
93
|
+
} catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
message: `skill_manage list: skill tree scan failed (${error instanceof Error ? error.message : String(error)}).`,
|
|
97
|
+
skills: []
|
|
98
|
+
};
|
|
79
99
|
}
|
|
80
100
|
const scalarArgs = args;
|
|
81
101
|
for (const field of [
|
|
@@ -94,7 +114,14 @@ function apply(ctx, rawConfig = {}) {
|
|
|
94
114
|
skills: []
|
|
95
115
|
};
|
|
96
116
|
}
|
|
97
|
-
|
|
117
|
+
if (origin !== "foreground") {
|
|
118
|
+
if ((policySnapshotOf(ctx.get("evolutionPolicy"))?.protectedSkillNames)?.includes(name)) return {
|
|
119
|
+
ok: false,
|
|
120
|
+
message: `skill_manage: "${name}" is protected by the current policy (protectedSkillNames); replayed/autonomous writes are refused.`,
|
|
121
|
+
skills: []
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const REQUIRED_ARGS = {
|
|
98
125
|
create: ["name", "content"],
|
|
99
126
|
edit: ["name", "content"],
|
|
100
127
|
update: ["name", "content"],
|
|
@@ -113,7 +140,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
113
140
|
restructure: ["name"],
|
|
114
141
|
pin: ["name"],
|
|
115
142
|
unpin: ["name"]
|
|
116
|
-
}
|
|
143
|
+
};
|
|
144
|
+
const missing = (action === void 0 || typeof action !== "string" || !Object.hasOwn(REQUIRED_ARGS, action) ? [] : REQUIRED_ARGS[action] ?? []).filter((field) => scalarArgs[field] === void 0 || scalarArgs[field] === null);
|
|
117
145
|
if (missing.length > 0) return {
|
|
118
146
|
ok: false,
|
|
119
147
|
message: `skill_manage ${action} requires ${missing.join(", ")}; the tool description lists the arguments per action.`,
|
|
@@ -129,6 +157,15 @@ function apply(ctx, rawConfig = {}) {
|
|
|
129
157
|
skills: []
|
|
130
158
|
};
|
|
131
159
|
}
|
|
160
|
+
if ((action === "write_file" || action === "remove_file") && typeof args.staged_from_sha256 === "string" && args.staged_from_sha256 !== "") {
|
|
161
|
+
const currentBytes = await library.readSupportFile(name, args.file_path ?? "").catch(() => void 0);
|
|
162
|
+
const actual = currentBytes === void 0 || currentBytes === null ? "absent" : contentHash(currentBytes);
|
|
163
|
+
if (currentBytes === void 0 || actual !== args.staged_from_sha256) return {
|
|
164
|
+
ok: false,
|
|
165
|
+
message: `Support file "${args.file_path ?? ""}" of "${name}" changed after this write was staged (or its state could not be verified); refusing to replay the stale snapshot. Re-stage the file operation.`,
|
|
166
|
+
skills: []
|
|
167
|
+
};
|
|
168
|
+
}
|
|
132
169
|
if ((action === "create" || action === "edit" || action === "update") && args.content) {
|
|
133
170
|
const parsed = parseFrontmatter(args.content);
|
|
134
171
|
if (parsed) {
|
|
@@ -194,7 +231,12 @@ function apply(ctx, rawConfig = {}) {
|
|
|
194
231
|
const protection = summary.protectionUnknown ? " [protection:unknown]" : summary.protectedBy ? ` [${summary.protectedBy}]` : "";
|
|
195
232
|
return `- ${summary.name} | ${record?.state ?? "active"} | use:${record?.use_count ?? 0} view:${record?.view_count ?? 0} patch:${record?.patch_count ?? 0}${quality}${protection}`;
|
|
196
233
|
});
|
|
197
|
-
const
|
|
234
|
+
const contents = /* @__PURE__ */ new Map();
|
|
235
|
+
for (let offset = 0; offset < list.length; offset += 16) await Promise.all(list.slice(offset, offset + 16).map(async (summary) => {
|
|
236
|
+
const body = await library.read(summary.name).catch(() => null);
|
|
237
|
+
contents.set(summary.name, body ?? "");
|
|
238
|
+
}));
|
|
239
|
+
const groups = computeDedupGroups({ contents });
|
|
198
240
|
const dedupLines = groups.slice(0, MAX_DEDUP_GROUPS_IN_REVIEW).map((group) => `- ${group.join(" ~ ")}`);
|
|
199
241
|
const warned = list.filter((summary) => warnedFlag(summary.name)).map((summary) => summary.name);
|
|
200
242
|
const warningLine = warned.length === 0 ? "" : `\nWarning skills (${warned.length}): ${warned.join(", ")} — low quality; consider consolidating them before authoring new skills.`;
|
|
@@ -286,6 +328,10 @@ function apply(ctx, rawConfig = {}) {
|
|
|
286
328
|
const stageCurrent = await library.read(args.name).catch(() => null);
|
|
287
329
|
if (stageCurrent !== null) args.staged_from_sha256 = contentHash(stageCurrent);
|
|
288
330
|
}
|
|
331
|
+
if ((args.action === "write_file" || args.action === "remove_file") && typeof args.name === "string" && args.name !== "" && typeof args.file_path === "string" && args.file_path !== "") {
|
|
332
|
+
const stageFile = await library.readSupportFile(args.name, args.file_path).catch(() => void 0);
|
|
333
|
+
if (stageFile !== void 0) args.staged_from_sha256 = stageFile === null ? "absent" : contentHash(stageFile);
|
|
334
|
+
}
|
|
289
335
|
const decision = await approval.request({
|
|
290
336
|
kind: "skill",
|
|
291
337
|
summary: `skill ${args.action ?? "?"} ${args.name ?? ""}`.trim(),
|
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.69",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,24 +31,24 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-approval": "^0.3.
|
|
35
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-approval": "^0.3.69",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.69"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
39
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
40
40
|
"@deepseek-ai/dsh-system-prompt": "^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.69",
|
|
43
|
+
"@lmzhen/dsh-skill-usage": "^0.3.69"
|
|
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-system-prompt": "^0.1.1-rc.2",
|
|
49
49
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
50
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
51
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
52
|
-
"@lmzhen/dsh-skill-usage": "^0.3.
|
|
50
|
+
"@lmzhen/dsh-evolution-core": "^0.3.69",
|
|
51
|
+
"@lmzhen/dsh-evolution-io": "^0.3.69",
|
|
52
|
+
"@lmzhen/dsh-skill-usage": "^0.3.69"
|
|
53
53
|
}
|
|
54
54
|
}
|