pi-toggle-skills 0.1.3 → 0.1.4
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/package.json +1 -1
- package/src/skill-discovery.ts +16 -6
- package/src/skill-selector.ts +1 -1
package/package.json
CHANGED
package/src/skill-discovery.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "./index.js";
|
|
15
15
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
16
16
|
import matter from "gray-matter";
|
|
17
|
-
import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
17
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync, statSync, realpathSync } from "node:fs";
|
|
18
18
|
import { homedir } from "node:os";
|
|
19
19
|
import { join, basename, dirname } from "node:path";
|
|
20
20
|
|
|
@@ -52,11 +52,14 @@ function getAllSkillDirs(cwd: string): SkillDir[] {
|
|
|
52
52
|
for (const path of getProjectSkillDirs(cwd)) {
|
|
53
53
|
dirs.push({ path, source: "project-pi" });
|
|
54
54
|
}
|
|
55
|
-
// Deduplicate by path
|
|
55
|
+
// Deduplicate by resolved (real) path so that symlinked directories
|
|
56
|
+
// (e.g. ~/.agents/skills → ~/.pi/agent/skills) are not scanned twice.
|
|
56
57
|
const seen = new Set<string>();
|
|
57
58
|
return dirs.filter((d) => {
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
let resolved = d.path;
|
|
60
|
+
try { resolved = realpathSync(d.path); } catch { /* path doesn't exist yet */ }
|
|
61
|
+
if (seen.has(resolved)) return false;
|
|
62
|
+
seen.add(resolved);
|
|
60
63
|
return true;
|
|
61
64
|
});
|
|
62
65
|
}
|
|
@@ -172,11 +175,18 @@ function loadSkillFromFile(filePath: string): ToggleSkill | null {
|
|
|
172
175
|
// Skills without description are not loaded by pi — skip them
|
|
173
176
|
if (!description || description.trim() === "") return null;
|
|
174
177
|
|
|
178
|
+
// Resolve symlinks so that the same physical SKILL.md reached via
|
|
179
|
+
// different alias paths (e.g. ~/.agents/skills/x vs ~/.pi/agent/skills/x)
|
|
180
|
+
// gets the same filePath and is correctly deduplicated.
|
|
181
|
+
let realFilePath = filePath;
|
|
182
|
+
try { realFilePath = realpathSync(filePath); } catch { /* keep as-is */ }
|
|
183
|
+
const realBaseDir = dirname(realFilePath);
|
|
184
|
+
|
|
175
185
|
return {
|
|
176
186
|
name,
|
|
177
187
|
description,
|
|
178
|
-
filePath,
|
|
179
|
-
baseDir:
|
|
188
|
+
filePath: realFilePath,
|
|
189
|
+
baseDir: realBaseDir,
|
|
180
190
|
disabled: isDisabled(frontmatter),
|
|
181
191
|
};
|
|
182
192
|
} catch {
|
package/src/skill-selector.ts
CHANGED
|
@@ -297,7 +297,7 @@ export class ToggleSkillSelectorComponent implements Component {
|
|
|
297
297
|
? this.theme.fg("accent", item.name)
|
|
298
298
|
: item.name;
|
|
299
299
|
const status = item.disabled
|
|
300
|
-
? this.theme.fg("
|
|
300
|
+
? this.theme.fg("dim", " ✗")
|
|
301
301
|
: this.theme.fg("success", " ✓");
|
|
302
302
|
|
|
303
303
|
this.listContainer.addChild(
|