From 7a5182092755a225bfd7569513eb9ed94b887574 Mon Sep 17 00:00:00 2001 From: xiaofeilovecoding Date: Thu, 22 Oct 2026 19:07:57 +0800 Subject: [PATCH] fix: run skill-digester helper as CommonJS Use an explicit .cjs entry point so bundled and project-installed skills work under both ESM and CommonJS package scopes. Keep the documented invocation synchronized and cover actual skill lookup in subprocess tests. Fixes #374 --- .../core/src/tests/skill-digester.test.ts | 49 +++++++++++++++++++ .../skills/bundled/skill-digester/SKILL.md | 6 +-- .../scripts/{find-skill.js => find-skill.cjs} | 2 +- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 packages/core/src/tests/skill-digester.test.ts rename packages/core/templates/skills/bundled/skill-digester/scripts/{find-skill.js => find-skill.cjs} (98%) diff --git a/packages/core/src/tests/skill-digester.test.ts b/packages/core/src/tests/skill-digester.test.ts new file mode 100644 index 00000000..18b118dc --- /dev/null +++ b/packages/core/src/tests/skill-digester.test.ts @@ -0,0 +1,49 @@ +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { cpSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; + +const skillSource = fileURLToPath(new URL("../../templates/skills/bundled/skill-digester/", import.meta.url)); + +for (const type of ["module", "commonjs"]) { + test(`skill-digester's documented helper finds skills inside a ${type} package`, () => { + const root = mkdtempSync(join(tmpdir(), "deepcode-skill-digester-")); + try { + const project = join(root, "project"); + const home = join(root, "home"); + const installed = join(project, ".agents", "skills", "skill-digester"); + cpSync(skillSource, installed, { recursive: true }); + mkdirSync(home); + writeFileSync(join(project, "package.json"), JSON.stringify({ type })); + const target = join(project, ".agents", "skills", "work-log", "SKILL.md"); + mkdirSync(dirname(target), { recursive: true }); + writeFileSync(target, '---\nname: worklog\ndescription: "Project work log"\n---\n# Work Log\n'); + const instructions = readFileSync(join(installed, "SKILL.md"), "utf8"); + const documentedScript = instructions.match(/scripts\/find-skill\.(?:cjs|js)/)?.[0]; + assert.ok(documentedScript, "the skill must document its helper entry point"); + + const result = spawnSync(process.execPath, [join(installed, documentedScript), "worklog", project], { + cwd: project, + encoding: "utf8", + timeout: 10000, + env: { ...process.env, HOME: home, USERPROFILE: home, NODE_PATH: "" }, + }); + + assert.equal(result.status, 0, result.stderr); + const output = JSON.parse(result.stdout); + assert.equal(output.found, true); + assert.equal(output.activeMatches.length, 1); + assert.equal(output.activeMatches[0].path, target); + assert.equal(output.activeMatches[0].description, "Project work log"); + assert.equal( + output.activeMatches[0].digestTarget.path, + join(project, ".deepcode", "skills", "work-log", "SKILL.md") + ); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); +} diff --git a/packages/core/templates/skills/bundled/skill-digester/SKILL.md b/packages/core/templates/skills/bundled/skill-digester/SKILL.md index 3b829b00..d795f153 100644 --- a/packages/core/templates/skills/bundled/skill-digester/SKILL.md +++ b/packages/core/templates/skills/bundled/skill-digester/SKILL.md @@ -28,10 +28,10 @@ First classify the request: - Locate the skill by running the bundled Node script from this skill directory: ```bash - node ~/.deepcode/skills/skill-digester/scripts/find-skill.js "" "" + node ~/.deepcode/skills/skill-digester/scripts/find-skill.cjs "" "" ``` - If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.js` file next to this `SKILL.md` instead. + If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.cjs` file next to this `SKILL.md` instead. - The script searches the same roots Deep Code CLI scans, in priority order: 1. Project native skills: `./.deepcode/skills//SKILL.md` @@ -103,7 +103,7 @@ Use this workflow when the user asks to install an Agent Skill. Installation alw - `./...` relative to the current project root. - Absolute paths as written. - A `SKILL.md` path means its parent directory is the source skill directory. - - If the user provided a skill name instead of a path, locate it with `scripts/find-skill.js` using the same command and match rules as the digest workflow. + - If the user provided a skill name instead of a path, locate it with `scripts/find-skill.cjs` using the same command and match rules as the digest workflow. - If the user did not provide a skill name or path, use `AskUserQuestion` to ask for the source skill name or path. - The source directory must contain `SKILL.md`. If it does not, report that the path is not an Agent Skill and ask for another source only if the user still wants to install. diff --git a/packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.js b/packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.cjs similarity index 98% rename from packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.js rename to packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.cjs index 2067e023..a71bd92d 100755 --- a/packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.js +++ b/packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.cjs @@ -6,7 +6,7 @@ const os = require("os"); const path = require("path"); function usage() { - return "Usage: node scripts/find-skill.js [project-root]"; + return "Usage: node scripts/find-skill.cjs [project-root]"; } function loadMatter() {