@lmzhen/dsh-tool-skill-manage 0.3.65 → 0.3.67

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.
Files changed (2) hide show
  1. package/lib/index.js +41 -4
  2. package/package.json +8 -8
package/lib/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { effectiveSessionPolicy } from "@lmzhen/dsh-evolution-approval";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { defineTool } from "@deepseek-ai/dsh-tools";
4
- import { DEFAULT_SKILL_LIMITS, DSH_AUTHORING_STANDARDS, SKILLS_GUIDANCE, SkillLibrary, authoringFeedback, clampedNumber, computeDedupGroups, evolutionIoAdapter, parseFrontmatter, resolveOrigins, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
4
+ import { DEFAULT_SKILL_LIMITS, DSH_AUTHORING_STANDARDS, SKILLS_GUIDANCE, SkillLibrary, authoringFeedback, clampedNumber, computeDedupGroups, contentHash, evolutionIoAdapter, parseFrontmatter, resolveOrigins, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
5
5
  //#region lib/types/index.js
6
6
  /**
7
7
  * Model-facing skill_manage tool over ctx.evolutionIo + ctx.skillUsage.
@@ -77,7 +77,33 @@ function apply(ctx, rawConfig = {}) {
77
77
  skills: list.map((s) => s.name)
78
78
  };
79
79
  }
80
+ const scalarArgs = args;
81
+ for (const field of [
82
+ "name",
83
+ "content",
84
+ "old_string",
85
+ "new_string",
86
+ "file_path",
87
+ "file_content",
88
+ "absorbed_into"
89
+ ]) {
90
+ const value = scalarArgs[field];
91
+ if (value !== void 0 && value !== null && typeof value !== "string") return {
92
+ ok: false,
93
+ message: `skill_manage: "${field}" must be a string (got ${typeof value}); refusing the write.`,
94
+ skills: []
95
+ };
96
+ }
80
97
  let feedbackLines = [];
98
+ if ((action === "edit" || action === "update") && typeof args.staged_from_sha256 === "string" && args.staged_from_sha256 !== "") {
99
+ const currentContent = await library.read(name).catch(() => null);
100
+ const actual = contentHash(currentContent ?? "");
101
+ if (currentContent === null || actual !== args.staged_from_sha256) return {
102
+ ok: false,
103
+ message: `Skill "${name}" changed after this write was staged (content ${currentContent === null ? "no longer exists" : "hash mismatch"}); refusing to replay the stale snapshot. Re-apply the edit to stage a fresh copy.`,
104
+ skills: []
105
+ };
106
+ }
81
107
  if ((action === "create" || action === "edit" || action === "update") && args.content) {
82
108
  const parsed = parseFrontmatter(args.content);
83
109
  if (parsed) {
@@ -99,9 +125,16 @@ function apply(ctx, rawConfig = {}) {
99
125
  else if (action === "remove_file") result = await library.removeSupportFile(name, args.file_path ?? "", origin);
100
126
  else if (action === "restructure") {
101
127
  const moves = Array.isArray(args.restructure) ? args.restructure : [];
102
- result = await library.restructure(name, moves.map((move) => ({
103
- heading: move.heading ?? "",
104
- toFile: move.to_file ?? ""
128
+ if (moves.some((move) => {
129
+ const raw = move;
130
+ return raw === null || typeof raw !== "object";
131
+ })) result = {
132
+ ok: false,
133
+ message: "Every entry of restructure must be an object with heading and to_file."
134
+ };
135
+ else result = await library.restructure(name, moves.map((move) => ({
136
+ heading: typeof move.heading === "string" ? move.heading : "",
137
+ toFile: typeof move.to_file === "string" ? move.to_file : ""
105
138
  })), origin);
106
139
  } else if (action === "pin") result = await library.setPinned(name, true, origin);
107
140
  else if (action === "unpin") result = await library.setPinned(name, false, origin);
@@ -224,6 +257,10 @@ function apply(ctx, rawConfig = {}) {
224
257
  const sessionPolicy = effectiveSessionPolicy(ctx, exec.agent?.session);
225
258
  const approval = ctx.get("evolutionApproval");
226
259
  if (approval && args.action !== "list" && args.action !== "review" && args.action !== "pin" && args.action !== "unpin") {
260
+ if ((args.action === "update" || args.action === "edit") && typeof args.name === "string" && args.name !== "") {
261
+ const stageCurrent = await library.read(args.name).catch(() => null);
262
+ if (stageCurrent !== null) args.staged_from_sha256 = contentHash(stageCurrent);
263
+ }
227
264
  const decision = await approval.request({
228
265
  kind: "skill",
229
266
  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.65",
4
+ "version": "0.3.67",
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.65",
35
- "@lmzhen/dsh-evolution-core": "^0.3.65"
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.67",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.67"
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.65",
43
- "@lmzhen/dsh-skill-usage": "^0.3.65"
42
+ "@lmzhen/dsh-evolution-io": "^0.3.67",
43
+ "@lmzhen/dsh-skill-usage": "^0.3.67"
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.65",
51
- "@lmzhen/dsh-evolution-io": "^0.3.65",
52
- "@lmzhen/dsh-skill-usage": "^0.3.65"
50
+ "@lmzhen/dsh-evolution-core": "^0.3.67",
51
+ "@lmzhen/dsh-evolution-io": "^0.3.67",
52
+ "@lmzhen/dsh-skill-usage": "^0.3.67"
53
53
  }
54
54
  }