@chakresh/kresh 0.1.1 → 0.1.3
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 +5 -4
- package/src/commands/search.js +1 -0
- package/src/services/filesystem.js +128 -17
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chakresh/kresh",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"bin": {
|
|
5
5
|
"kresh": "./src/index.js"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"
|
|
9
|
+
"@chakresh/kresh": "^0.1.2",
|
|
10
10
|
"axios": "^1.6.8",
|
|
11
11
|
"chalk": "^5.3.0",
|
|
12
|
-
"
|
|
13
|
-
"inquirer": "^9.2.16"
|
|
12
|
+
"commander": "^11.1.0",
|
|
13
|
+
"inquirer": "^9.2.16",
|
|
14
|
+
"ora": "^8.0.1"
|
|
14
15
|
},
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
package/src/commands/search.js
CHANGED
|
@@ -2,13 +2,59 @@ import fs from 'fs/promises';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Helper to find the workspace or project root directory by scanning up.
|
|
6
|
+
*/
|
|
7
|
+
async function getWorkspaceRoot(startDir = process.cwd()) {
|
|
8
|
+
let currentDir = startDir;
|
|
9
|
+
while (true) {
|
|
10
|
+
try {
|
|
11
|
+
const hasPackageJson = await fs.access(path.join(currentDir, 'package.json')).then(() => true).catch(() => false);
|
|
12
|
+
const isKreshRoot = await fs.access(path.join(currentDir, 'next.config.mjs')).then(() => true).catch(() => false);
|
|
13
|
+
|
|
14
|
+
if (hasPackageJson && isKreshRoot) {
|
|
15
|
+
return currentDir;
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {
|
|
18
|
+
// Ignore
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const parentDir = path.dirname(currentDir);
|
|
22
|
+
if (parentDir === currentDir) {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
currentDir = parentDir;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Secondary check: look for any package.json up the tree
|
|
29
|
+
currentDir = startDir;
|
|
30
|
+
while (true) {
|
|
31
|
+
try {
|
|
32
|
+
const hasPackageJson = await fs.access(path.join(currentDir, 'package.json')).then(() => true).catch(() => false);
|
|
33
|
+
if (hasPackageJson) {
|
|
34
|
+
return currentDir;
|
|
35
|
+
}
|
|
36
|
+
} catch (e) {
|
|
37
|
+
// Ignore
|
|
38
|
+
}
|
|
39
|
+
const parentDir = path.dirname(currentDir);
|
|
40
|
+
if (parentDir === currentDir) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
currentDir = parentDir;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return startDir;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Writes the SKILL.md and metadata.json files directly in a folder named after the skill's slug (excluding @owner scope folder) inside the skills folder.
|
|
6
51
|
*/
|
|
7
52
|
export async function writeLocalSkill(slug, skillContent, metadata) {
|
|
8
53
|
try {
|
|
9
|
-
|
|
10
|
-
const folderName = slug || metadata.slug;
|
|
11
|
-
const targetDir = path.join(
|
|
54
|
+
const rootDir = await getWorkspaceRoot();
|
|
55
|
+
const folderName = (slug || metadata.slug).split('/').pop();
|
|
56
|
+
const targetDir = path.join(rootDir, 'skills', folderName);
|
|
57
|
+
|
|
12
58
|
await fs.mkdir(targetDir, { recursive: true });
|
|
13
59
|
await fs.writeFile(path.join(targetDir, 'SKILL.md'), skillContent, 'utf8');
|
|
14
60
|
await fs.writeFile(path.join(targetDir, 'metadata.json'), JSON.stringify(metadata, null, 2), 'utf8');
|
|
@@ -24,11 +70,21 @@ export async function writeLocalSkill(slug, skillContent, metadata) {
|
|
|
24
70
|
*/
|
|
25
71
|
export async function readLocalSkillMetadata(slug) {
|
|
26
72
|
try {
|
|
27
|
-
const
|
|
73
|
+
const rootDir = await getWorkspaceRoot();
|
|
74
|
+
const folderName = slug.split('/').pop();
|
|
75
|
+
const metadataPath = path.join(rootDir, 'skills', folderName, 'metadata.json');
|
|
28
76
|
const data = await fs.readFile(metadataPath, 'utf8');
|
|
29
77
|
return JSON.parse(data);
|
|
30
78
|
} catch (error) {
|
|
31
|
-
|
|
79
|
+
// Also try legacy path for backwards compatibility
|
|
80
|
+
try {
|
|
81
|
+
const rootDir = await getWorkspaceRoot();
|
|
82
|
+
const legacyPath = path.join(rootDir, 'skills', slug, 'metadata.json');
|
|
83
|
+
const data = await fs.readFile(legacyPath, 'utf8');
|
|
84
|
+
return JSON.parse(data);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
32
88
|
}
|
|
33
89
|
}
|
|
34
90
|
|
|
@@ -37,8 +93,28 @@ export async function readLocalSkillMetadata(slug) {
|
|
|
37
93
|
*/
|
|
38
94
|
export async function removeLocalSkill(slug) {
|
|
39
95
|
try {
|
|
40
|
-
const
|
|
96
|
+
const rootDir = await getWorkspaceRoot();
|
|
97
|
+
const folderName = slug.split('/').pop();
|
|
98
|
+
const targetDir = path.join(rootDir, 'skills', folderName);
|
|
41
99
|
await fs.rm(targetDir, { recursive: true, force: true });
|
|
100
|
+
|
|
101
|
+
// Also clean up legacy directory if it exists
|
|
102
|
+
const legacyDir = path.join(rootDir, 'skills', slug);
|
|
103
|
+
await fs.rm(legacyDir, { recursive: true, force: true });
|
|
104
|
+
|
|
105
|
+
// Clean up empty parent directory (e.g. @username) if it becomes empty
|
|
106
|
+
if (slug.includes('/')) {
|
|
107
|
+
const parts = slug.split('/');
|
|
108
|
+
const parentDir = path.join(rootDir, 'skills', parts[0]);
|
|
109
|
+
try {
|
|
110
|
+
const files = await fs.readdir(parentDir);
|
|
111
|
+
if (files.length === 0) {
|
|
112
|
+
await fs.rmdir(parentDir);
|
|
113
|
+
}
|
|
114
|
+
} catch (e) {
|
|
115
|
+
// Ignore
|
|
116
|
+
}
|
|
117
|
+
}
|
|
42
118
|
return true;
|
|
43
119
|
} catch (error) {
|
|
44
120
|
console.error('Failed to remove skill files from the skills directory:', error);
|
|
@@ -51,7 +127,8 @@ export async function removeLocalSkill(slug) {
|
|
|
51
127
|
*/
|
|
52
128
|
export async function listLocalSkills() {
|
|
53
129
|
try {
|
|
54
|
-
const
|
|
130
|
+
const rootDir = await getWorkspaceRoot();
|
|
131
|
+
const skillsDir = path.join(rootDir, 'skills');
|
|
55
132
|
let entries = [];
|
|
56
133
|
try {
|
|
57
134
|
entries = await fs.readdir(skillsDir, { withFileTypes: true });
|
|
@@ -63,15 +140,49 @@ export async function listLocalSkills() {
|
|
|
63
140
|
const skills = [];
|
|
64
141
|
for (const entry of entries) {
|
|
65
142
|
if (entry.isDirectory()) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
143
|
+
if (entry.name.startsWith('@')) {
|
|
144
|
+
// Legacy support: It's a user scope directory, scan subdirectories inside it
|
|
145
|
+
const scopeDir = path.join(skillsDir, entry.name);
|
|
146
|
+
let subEntries = [];
|
|
147
|
+
try {
|
|
148
|
+
subEntries = await fs.readdir(scopeDir, { withFileTypes: true });
|
|
149
|
+
} catch (e) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (const subEntry of subEntries) {
|
|
154
|
+
if (subEntry.isDirectory()) {
|
|
155
|
+
const scopedSlug = `${entry.name}/${subEntry.name}`;
|
|
156
|
+
const metadata = await readLocalSkillMetadata(scopedSlug);
|
|
157
|
+
if (metadata) {
|
|
158
|
+
skills.push({
|
|
159
|
+
slug: metadata.slug || scopedSlug,
|
|
160
|
+
installed: true,
|
|
161
|
+
version: metadata.version || metadata.currentVersion || 'unknown',
|
|
162
|
+
name: metadata.name || 'unknown',
|
|
163
|
+
description: metadata.description || ''
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
// New format: Directly under skills/
|
|
170
|
+
try {
|
|
171
|
+
const metadataPath = path.join(skillsDir, entry.name, 'metadata.json');
|
|
172
|
+
const data = await fs.readFile(metadataPath, 'utf8');
|
|
173
|
+
const metadata = JSON.parse(data);
|
|
174
|
+
if (metadata) {
|
|
175
|
+
skills.push({
|
|
176
|
+
slug: metadata.slug || entry.name,
|
|
177
|
+
installed: true,
|
|
178
|
+
version: metadata.version || metadata.currentVersion || 'unknown',
|
|
179
|
+
name: metadata.name || 'unknown',
|
|
180
|
+
description: metadata.description || ''
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
} catch (e) {
|
|
184
|
+
// Ignore if metadata is invalid/missing
|
|
185
|
+
}
|
|
75
186
|
}
|
|
76
187
|
}
|
|
77
188
|
}
|