@supertiny99/easy-skill 1.0.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.
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getRemoteBranches = getRemoteBranches;
7
+ exports.exploreRepository = exploreRepository;
8
+ exports.copySkillFromExplore = copySkillFromExplore;
9
+ exports.cleanupExplore = cleanupExplore;
10
+ const path_1 = __importDefault(require("path"));
11
+ const fs_extra_1 = __importDefault(require("fs-extra"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const simple_git_1 = __importDefault(require("simple-git"));
14
+ const git = (0, simple_git_1.default)();
15
+ /**
16
+ * Get remote branches from a Git repository URL
17
+ */
18
+ async function getRemoteBranches(url) {
19
+ try {
20
+ const result = await git.listRemote(['--heads', url]);
21
+ const branches = [];
22
+ const lines = result.split('\n').filter(line => line.trim());
23
+ for (const line of lines) {
24
+ const match = line.match(/refs\/heads\/(.+)$/);
25
+ if (match) {
26
+ const name = match[1];
27
+ branches.push({
28
+ name,
29
+ isDefault: name === 'main' || name === 'master'
30
+ });
31
+ }
32
+ }
33
+ // Sort: default branches first, then alphabetically
34
+ branches.sort((a, b) => {
35
+ if (a.isDefault && !b.isDefault)
36
+ return -1;
37
+ if (!a.isDefault && b.isDefault)
38
+ return 1;
39
+ return a.name.localeCompare(b.name);
40
+ });
41
+ return branches;
42
+ }
43
+ catch (err) {
44
+ throw new Error(`Failed to fetch branches: ${err.message}`);
45
+ }
46
+ }
47
+ /**
48
+ * Clone repository to temp directory and explore its structure
49
+ */
50
+ async function exploreRepository(url, branch) {
51
+ const tempDir = path_1.default.join(os_1.default.tmpdir(), `easy-skill-explore-${Date.now()}`);
52
+ try {
53
+ // Shallow clone
54
+ const cloneOptions = ['--depth', '1'];
55
+ if (branch) {
56
+ cloneOptions.push('--branch', branch);
57
+ }
58
+ await git.clone(url, tempDir, cloneOptions);
59
+ // Find skill candidates
60
+ const skills = await findSkillCandidates(tempDir);
61
+ // Get branches if not already provided
62
+ let branches = [];
63
+ if (!branch) {
64
+ branches = await getRemoteBranches(url);
65
+ }
66
+ return {
67
+ branches,
68
+ skills,
69
+ tempPath: tempDir
70
+ };
71
+ }
72
+ catch (err) {
73
+ // Cleanup on error
74
+ await fs_extra_1.default.remove(tempDir).catch(() => { });
75
+ throw new Error(`Failed to explore repository: ${err.message}`);
76
+ }
77
+ }
78
+ /**
79
+ * Find skill candidates in a directory
80
+ * Recursively scans all directories to find skills
81
+ */
82
+ async function findSkillCandidates(repoPath, maxDepth = 3) {
83
+ const candidates = [];
84
+ const skipDirs = new Set(['node_modules', 'dist', 'build', '.git', 'test', 'tests', '__tests__', 'docs', 'coverage', '.vscode', '.idea']);
85
+ async function scanDirectory(dirPath, relativePath, depth) {
86
+ if (depth > maxDepth)
87
+ return;
88
+ try {
89
+ const entries = await fs_extra_1.default.readdir(dirPath, { withFileTypes: true });
90
+ for (const entry of entries) {
91
+ if (!entry.isDirectory() || entry.name.startsWith('.') || skipDirs.has(entry.name.toLowerCase())) {
92
+ continue;
93
+ }
94
+ const fullPath = path_1.default.join(dirPath, entry.name);
95
+ const entryRelativePath = relativePath ? path_1.default.join(relativePath, entry.name) : entry.name;
96
+ const candidate = await checkSkillCandidate(entry.name, fullPath, entryRelativePath);
97
+ if (candidate) {
98
+ candidates.push(candidate);
99
+ }
100
+ // Recursively scan subdirectories
101
+ await scanDirectory(fullPath, entryRelativePath, depth + 1);
102
+ }
103
+ }
104
+ catch (err) {
105
+ // Ignore permission errors
106
+ }
107
+ }
108
+ // Start scanning from root
109
+ await scanDirectory(repoPath, '', 0);
110
+ // Check if root itself is a skill
111
+ const rootCandidate = await checkSkillCandidate(path_1.default.basename(repoPath), repoPath, '.');
112
+ if (rootCandidate && rootCandidate.hasSkillFile) {
113
+ candidates.unshift(rootCandidate);
114
+ }
115
+ // Sort by path depth (shallower first), then alphabetically
116
+ candidates.sort((a, b) => {
117
+ const depthA = a.path.split('/').length;
118
+ const depthB = b.path.split('/').length;
119
+ if (depthA !== depthB)
120
+ return depthA - depthB;
121
+ return a.path.localeCompare(b.path);
122
+ });
123
+ return candidates;
124
+ }
125
+ /**
126
+ * Check if a directory is a skill candidate
127
+ */
128
+ async function checkSkillCandidate(name, dirPath, relativePath) {
129
+ // Look for skill indicator files
130
+ const skillIndicators = [
131
+ 'skill.json',
132
+ 'skill.yaml',
133
+ 'skill.yml',
134
+ 'skill.md',
135
+ 'SKILL.md',
136
+ 'index.md',
137
+ 'README.md'
138
+ ];
139
+ let hasSkillFile = false;
140
+ let description;
141
+ for (const indicator of skillIndicators) {
142
+ const indicatorPath = path_1.default.join(dirPath, indicator);
143
+ if (await fs_extra_1.default.pathExists(indicatorPath)) {
144
+ hasSkillFile = true;
145
+ // Try to read description from skill.json
146
+ if (indicator === 'skill.json') {
147
+ try {
148
+ const content = await fs_extra_1.default.readJson(indicatorPath);
149
+ description = content.description || content.name;
150
+ }
151
+ catch { }
152
+ }
153
+ // Try to read first line/title from markdown as description
154
+ else if (indicator.endsWith('.md')) {
155
+ try {
156
+ const content = await fs_extra_1.default.readFile(indicatorPath, 'utf-8');
157
+ const lines = content.split('\n');
158
+ // First try to get the title (# heading)
159
+ const titleLine = lines.find(l => l.trim().startsWith('# '));
160
+ if (titleLine) {
161
+ description = titleLine.replace(/^#\s*/, '').trim().substring(0, 100);
162
+ }
163
+ else {
164
+ // Otherwise get first non-empty, non-heading line
165
+ const firstLine = lines.find(l => l.trim() && !l.startsWith('#'));
166
+ if (firstLine) {
167
+ description = firstLine.trim().substring(0, 100);
168
+ }
169
+ }
170
+ }
171
+ catch { }
172
+ }
173
+ break;
174
+ }
175
+ }
176
+ // Always include directories that have content files (even without skill indicator)
177
+ const files = await fs_extra_1.default.readdir(dirPath);
178
+ const contentFiles = files.filter(f => !f.startsWith('.') &&
179
+ (f.endsWith('.md') || f.endsWith('.txt') || f.endsWith('.json') || f.endsWith('.yaml') || f.endsWith('.yml')));
180
+ // Skip empty directories or directories without any useful files
181
+ if (contentFiles.length === 0 && !hasSkillFile) {
182
+ return null;
183
+ }
184
+ return {
185
+ name,
186
+ path: relativePath || name,
187
+ hasSkillFile,
188
+ description
189
+ };
190
+ }
191
+ /**
192
+ * Copy skill from temp explore directory to target
193
+ */
194
+ async function copySkillFromExplore(tempPath, skillPath, targetDir, skillId) {
195
+ const sourcePath = skillPath === '.' ? tempPath : path_1.default.join(tempPath, skillPath);
196
+ const destPath = path_1.default.join(targetDir, skillId);
197
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(destPath));
198
+ if (await fs_extra_1.default.pathExists(destPath)) {
199
+ await fs_extra_1.default.remove(destPath);
200
+ }
201
+ await fs_extra_1.default.copy(sourcePath, destPath);
202
+ // Remove .git if exists
203
+ const gitDir = path_1.default.join(destPath, '.git');
204
+ if (await fs_extra_1.default.pathExists(gitDir)) {
205
+ await fs_extra_1.default.remove(gitDir);
206
+ }
207
+ return destPath;
208
+ }
209
+ /**
210
+ * Cleanup temp explore directory
211
+ */
212
+ async function cleanupExplore(tempPath) {
213
+ try {
214
+ await fs_extra_1.default.remove(tempPath);
215
+ }
216
+ catch { }
217
+ }
218
+ //# sourceMappingURL=explorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../../../src/lib/skill/explorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { IDEType, IDE_SKILL_PATHS, LinkTarget, SUPPORTED_IDES } from './schema';
2
+ export declare function getIDESkillsPath(ide: IDEType, projectRoot?: string): string;
3
+ export declare function getGlobalIDESkillsPath(ide: IDEType): string;
4
+ export declare function createSymlink(sourcePath: string, targetPath: string): Promise<void>;
5
+ export declare function removeSymlink(targetPath: string): Promise<void>;
6
+ export declare function linkSkillToIDE(skillPath: string, skillId: string, ide: IDEType, projectRoot?: string): Promise<LinkTarget>;
7
+ export declare function unlinkSkillFromIDE(skillId: string, ide: IDEType, projectRoot?: string): Promise<void>;
8
+ export declare function getLinkedSkills(ide: IDEType, projectRoot?: string): Promise<{
9
+ skillId: string;
10
+ targetPath: string;
11
+ sourcePath: string | null;
12
+ }[]>;
13
+ export declare function checkSymlinkStatus(skillId: string, ide: IDEType, projectRoot?: string): Promise<{
14
+ exists: boolean;
15
+ valid: boolean;
16
+ sourcePath: string | null;
17
+ }>;
18
+ export { SUPPORTED_IDES, IDE_SKILL_PATHS };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.IDE_SKILL_PATHS = exports.SUPPORTED_IDES = void 0;
7
+ exports.getIDESkillsPath = getIDESkillsPath;
8
+ exports.getGlobalIDESkillsPath = getGlobalIDESkillsPath;
9
+ exports.createSymlink = createSymlink;
10
+ exports.removeSymlink = removeSymlink;
11
+ exports.linkSkillToIDE = linkSkillToIDE;
12
+ exports.unlinkSkillFromIDE = unlinkSkillFromIDE;
13
+ exports.getLinkedSkills = getLinkedSkills;
14
+ exports.checkSymlinkStatus = checkSymlinkStatus;
15
+ const path_1 = __importDefault(require("path"));
16
+ const fs_extra_1 = __importDefault(require("fs-extra"));
17
+ const os_1 = __importDefault(require("os"));
18
+ const schema_1 = require("./schema");
19
+ Object.defineProperty(exports, "IDE_SKILL_PATHS", { enumerable: true, get: function () { return schema_1.IDE_SKILL_PATHS; } });
20
+ Object.defineProperty(exports, "SUPPORTED_IDES", { enumerable: true, get: function () { return schema_1.SUPPORTED_IDES; } });
21
+ function getIDESkillsPath(ide, projectRoot) {
22
+ const basePath = projectRoot || process.cwd();
23
+ return path_1.default.join(basePath, schema_1.IDE_SKILL_PATHS[ide]);
24
+ }
25
+ function getGlobalIDESkillsPath(ide) {
26
+ const homeDir = os_1.default.homedir();
27
+ return path_1.default.join(homeDir, schema_1.IDE_SKILL_PATHS[ide]);
28
+ }
29
+ async function createSymlink(sourcePath, targetPath) {
30
+ // Ensure target parent directory exists
31
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
32
+ // Remove existing symlink or file
33
+ if (await fs_extra_1.default.pathExists(targetPath)) {
34
+ const stat = await fs_extra_1.default.lstat(targetPath);
35
+ if (stat.isSymbolicLink() || stat.isFile()) {
36
+ await fs_extra_1.default.remove(targetPath);
37
+ }
38
+ else if (stat.isDirectory()) {
39
+ throw new Error(`Target path is a directory, not a symlink: ${targetPath}`);
40
+ }
41
+ }
42
+ // Create symlink
43
+ await fs_extra_1.default.symlink(sourcePath, targetPath, 'dir');
44
+ }
45
+ async function removeSymlink(targetPath) {
46
+ if (await fs_extra_1.default.pathExists(targetPath)) {
47
+ const stat = await fs_extra_1.default.lstat(targetPath);
48
+ if (stat.isSymbolicLink()) {
49
+ await fs_extra_1.default.remove(targetPath);
50
+ }
51
+ }
52
+ }
53
+ async function linkSkillToIDE(skillPath, skillId, ide, projectRoot) {
54
+ const absoluteSkillPath = path_1.default.resolve(skillPath);
55
+ const ideSkillsDir = getIDESkillsPath(ide, projectRoot);
56
+ const targetPath = path_1.default.join(ideSkillsDir, skillId);
57
+ await createSymlink(absoluteSkillPath, targetPath);
58
+ return {
59
+ ide,
60
+ skillId,
61
+ sourcePath: absoluteSkillPath,
62
+ targetPath
63
+ };
64
+ }
65
+ async function unlinkSkillFromIDE(skillId, ide, projectRoot) {
66
+ const ideSkillsDir = getIDESkillsPath(ide, projectRoot);
67
+ const targetPath = path_1.default.join(ideSkillsDir, skillId);
68
+ await removeSymlink(targetPath);
69
+ }
70
+ async function getLinkedSkills(ide, projectRoot) {
71
+ const ideSkillsDir = getIDESkillsPath(ide, projectRoot);
72
+ if (!(await fs_extra_1.default.pathExists(ideSkillsDir))) {
73
+ return [];
74
+ }
75
+ const entries = await fs_extra_1.default.readdir(ideSkillsDir, { withFileTypes: true });
76
+ const result = [];
77
+ for (const entry of entries) {
78
+ const fullPath = path_1.default.join(ideSkillsDir, entry.name);
79
+ let sourcePath = null;
80
+ if (entry.isSymbolicLink()) {
81
+ try {
82
+ sourcePath = await fs_extra_1.default.readlink(fullPath);
83
+ }
84
+ catch {
85
+ sourcePath = null;
86
+ }
87
+ }
88
+ result.push({
89
+ skillId: entry.name,
90
+ targetPath: fullPath,
91
+ sourcePath
92
+ });
93
+ }
94
+ return result;
95
+ }
96
+ async function checkSymlinkStatus(skillId, ide, projectRoot) {
97
+ const ideSkillsDir = getIDESkillsPath(ide, projectRoot);
98
+ const targetPath = path_1.default.join(ideSkillsDir, skillId);
99
+ if (!(await fs_extra_1.default.pathExists(targetPath))) {
100
+ return { exists: false, valid: false, sourcePath: null };
101
+ }
102
+ try {
103
+ const stat = await fs_extra_1.default.lstat(targetPath);
104
+ if (!stat.isSymbolicLink()) {
105
+ return { exists: true, valid: false, sourcePath: null };
106
+ }
107
+ const sourcePath = await fs_extra_1.default.readlink(targetPath);
108
+ const sourceExists = await fs_extra_1.default.pathExists(sourcePath);
109
+ return { exists: true, valid: sourceExists, sourcePath };
110
+ }
111
+ catch {
112
+ return { exists: true, valid: false, sourcePath: null };
113
+ }
114
+ }
115
+ //# sourceMappingURL=linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linker.js","sourceRoot":"","sources":["../../../src/lib/skill/linker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface SkillSource {
2
+ type: 'git' | 'local' | 'url';
3
+ url: string;
4
+ branch?: string;
5
+ subdir?: string;
6
+ }
7
+ export interface SkillInfo {
8
+ id: string;
9
+ name: string;
10
+ description?: string;
11
+ source: SkillSource;
12
+ localPath?: string;
13
+ linkedTo?: string[];
14
+ }
15
+ export interface SkillRegistry {
16
+ skills: SkillInfo[];
17
+ lastUpdated?: string;
18
+ }
19
+ export type IDEType = 'claude' | 'trae';
20
+ export interface LinkTarget {
21
+ ide: IDEType;
22
+ skillId: string;
23
+ sourcePath: string;
24
+ targetPath: string;
25
+ }
26
+ export declare const IDE_SKILL_PATHS: Record<IDEType, string>;
27
+ export declare const SUPPORTED_IDES: IDEType[];
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SUPPORTED_IDES = exports.IDE_SKILL_PATHS = void 0;
4
+ exports.IDE_SKILL_PATHS = {
5
+ claude: '.claude/skills',
6
+ trae: '.trae/skills'
7
+ };
8
+ exports.SUPPORTED_IDES = ['claude', 'trae'];
9
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/lib/skill/schema.ts"],"names":[],"mappings":";;;AA8Ba,QAAA,eAAe,GAA4B;IACtD,MAAM,EAAE,gBAAgB;IACxB,IAAI,EAAE,cAAc;CACrB,CAAC;AAEW,QAAA,cAAc,GAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function quickSelect(): Promise<void>;