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

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 +33 -3
  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) {
@@ -100,8 +126,8 @@ function apply(ctx, rawConfig = {}) {
100
126
  else if (action === "restructure") {
101
127
  const moves = Array.isArray(args.restructure) ? args.restructure : [];
102
128
  result = await library.restructure(name, moves.map((move) => ({
103
- heading: move.heading ?? "",
104
- toFile: move.to_file ?? ""
129
+ heading: typeof move.heading === "string" ? move.heading : "",
130
+ toFile: typeof move.to_file === "string" ? move.to_file : ""
105
131
  })), origin);
106
132
  } else if (action === "pin") result = await library.setPinned(name, true, origin);
107
133
  else if (action === "unpin") result = await library.setPinned(name, false, origin);
@@ -224,6 +250,10 @@ function apply(ctx, rawConfig = {}) {
224
250
  const sessionPolicy = effectiveSessionPolicy(ctx, exec.agent?.session);
225
251
  const approval = ctx.get("evolutionApproval");
226
252
  if (approval && args.action !== "list" && args.action !== "review" && args.action !== "pin" && args.action !== "unpin") {
253
+ if ((args.action === "update" || args.action === "edit") && typeof args.name === "string" && args.name !== "") {
254
+ const stageCurrent = await library.read(args.name).catch(() => null);
255
+ if (stageCurrent !== null) args.staged_from_sha256 = contentHash(stageCurrent);
256
+ }
227
257
  const decision = await approval.request({
228
258
  kind: "skill",
229
259
  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.66",
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.66",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.66"
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.66",
43
+ "@lmzhen/dsh-skill-usage": "^0.3.66"
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.66",
51
+ "@lmzhen/dsh-evolution-io": "^0.3.66",
52
+ "@lmzhen/dsh-skill-usage": "^0.3.66"
53
53
  }
54
54
  }