skillbox 0.3.0 → 0.3.1

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/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ import { registerRemove } from "./commands/remove.js";
12
12
  import { registerStatus } from "./commands/status.js";
13
13
  import { registerUpdate } from "./commands/update.js";
14
14
  const program = new Command();
15
- program.name("skillbox").description("Local-first, agent-agnostic skills manager").version("0.3.0");
15
+ program.name("skillbox").description("Local-first, agent-agnostic skills manager").version("0.3.1");
16
16
  registerAdd(program);
17
17
  registerAgent(program);
18
18
  registerConfig(program);
@@ -41,8 +41,8 @@ async function installSkillTargets(skillName, options, installs) {
41
41
  const written = results
42
42
  .filter((result) => result.mode !== "skipped")
43
43
  .map((result) => result.path);
44
- const warning = buildSymlinkWarning(agent, results);
45
- if (warning) {
44
+ const warnings = buildSymlinkWarning(agent, results);
45
+ for (const warning of warnings) {
46
46
  printInfo(warning);
47
47
  }
48
48
  for (const target of written) {
@@ -74,8 +74,8 @@ export function registerAdd(program) {
74
74
  const written = results
75
75
  .filter((result) => result.mode !== "skipped")
76
76
  .map((result) => result.path);
77
- const warning = buildSymlinkWarning(agent, results);
78
- if (warning) {
77
+ const warnings = buildSymlinkWarning(agent, results);
78
+ for (const warning of warnings) {
79
79
  printInfo(warning);
80
80
  }
81
81
  if (written.length > 0) {
package/dist/lib/sync.js CHANGED
@@ -17,18 +17,43 @@ async function copyFiles(sourceDir, targetDir) {
17
17
  await fs.copyFile(sourcePath, destPath);
18
18
  }
19
19
  }
20
+ async function isSymlinkTo(targetDir, expectedSource) {
21
+ try {
22
+ const stat = await fs.lstat(targetDir);
23
+ if (!stat.isSymbolicLink()) {
24
+ return false;
25
+ }
26
+ const linkTarget = await fs.readlink(targetDir);
27
+ return linkTarget === expectedSource;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
20
33
  async function createSymlink(sourceDir, targetDir) {
34
+ if (await isSymlinkTo(targetDir, sourceDir)) {
35
+ return "exists";
36
+ }
21
37
  await fs.symlink(sourceDir, targetDir, "dir");
38
+ return "created";
22
39
  }
23
40
  export function buildSymlinkWarning(agent, results) {
24
41
  const skipped = results.filter((result) => result.mode === "skipped");
25
42
  if (skipped.length === 0) {
26
- return null;
43
+ return [];
44
+ }
45
+ const warnings = [];
46
+ for (const result of skipped) {
47
+ const skillName = path.basename(result.path);
48
+ const isExists = result.error?.includes("EEXIST");
49
+ if (isExists) {
50
+ warnings.push(` ⚠ ${skillName} (${agent}): already exists at target, remove manually or use --install-mode copy`);
51
+ }
52
+ else {
53
+ warnings.push(` ⚠ ${skillName} (${agent}): ${result.error ?? "unknown error"}`);
54
+ }
27
55
  }
28
- const details = skipped
29
- .map((result) => `${result.path}: ${result.error ?? "unknown error"}`)
30
- .join("; ");
31
- return `Warning: symlink failed for ${agent}. ${details}. Remove the existing target or run "skillbox config set --install-mode copy" to use file copies.`;
56
+ return warnings;
32
57
  }
33
58
  export async function installSkillToTargets(skillName, targets, config) {
34
59
  const sourceDir = skillDir(skillName);
@@ -38,8 +63,8 @@ export async function installSkillToTargets(skillName, targets, config) {
38
63
  await ensureDir(targetRoot);
39
64
  if (config.installMode === "symlink") {
40
65
  try {
41
- await createSymlink(sourceDir, targetDir);
42
- results.push({ path: targetDir, mode: "symlink" });
66
+ const status = await createSymlink(sourceDir, targetDir);
67
+ results.push({ path: targetDir, mode: status === "exists" ? "symlink" : "symlink" });
43
68
  }
44
69
  catch (error) {
45
70
  const message = getErrorMessage(error, "unknown error");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillbox",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Local-first, agent-agnostic skills manager",
5
5
  "license": "MIT",
6
6
  "author": "Christian Anagnostou",