@empjs/skill 1.0.5 → 1.0.6
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/index.cjs +345 -326
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +344 -325
- package/dist/index.js.map +1 -1
- package/package.json +2 -6
package/dist/index.cjs
CHANGED
|
@@ -23,82 +23,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
mod
|
|
24
24
|
));
|
|
25
25
|
|
|
26
|
-
// node_modules/tsup/assets/cjs_shims.js
|
|
26
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
|
|
27
27
|
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
28
28
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var import_commander = require("commander");
|
|
32
32
|
var import_fs = require("fs");
|
|
33
|
-
var import_url = require("url");
|
|
34
33
|
var import_path = require("path");
|
|
34
|
+
var import_url = require("url");
|
|
35
35
|
|
|
36
|
-
// src/commands/
|
|
37
|
-
var
|
|
38
|
-
var import_node_util2 = require("util");
|
|
39
|
-
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
40
|
-
var import_node_path5 = __toESM(require("path"), 1);
|
|
36
|
+
// src/commands/agents.ts
|
|
37
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
41
38
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
42
|
-
|
|
43
|
-
// src/utils/logger.ts
|
|
44
39
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
45
|
-
var import_ora = __toESM(require("ora"), 1);
|
|
46
|
-
var Logger = class {
|
|
47
|
-
spinner = null;
|
|
48
|
-
info(message) {
|
|
49
|
-
if (this.spinner) this.spinner.stop();
|
|
50
|
-
console.log(import_chalk.default.blue("\u2139"), message);
|
|
51
|
-
}
|
|
52
|
-
success(message) {
|
|
53
|
-
if (this.spinner) this.spinner.stop();
|
|
54
|
-
console.log(import_chalk.default.green("\u2713"), message);
|
|
55
|
-
}
|
|
56
|
-
warn(message) {
|
|
57
|
-
if (this.spinner) this.spinner.stop();
|
|
58
|
-
console.log(import_chalk.default.yellow("\u26A0"), message);
|
|
59
|
-
}
|
|
60
|
-
error(message) {
|
|
61
|
-
if (this.spinner) this.spinner.stop();
|
|
62
|
-
console.log(import_chalk.default.red("\u2717"), message);
|
|
63
|
-
}
|
|
64
|
-
start(message) {
|
|
65
|
-
if (this.spinner) this.spinner.stop();
|
|
66
|
-
this.spinner = (0, import_ora.default)(message).start();
|
|
67
|
-
return this.spinner;
|
|
68
|
-
}
|
|
69
|
-
stopSpinner() {
|
|
70
|
-
if (this.spinner) {
|
|
71
|
-
this.spinner.stop();
|
|
72
|
-
this.spinner = null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Update spinner text without stopping it
|
|
77
|
-
*/
|
|
78
|
-
updateSpinner(message) {
|
|
79
|
-
if (this.spinner) {
|
|
80
|
-
this.spinner.text = message;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Log info without stopping spinner (for background info)
|
|
85
|
-
*/
|
|
86
|
-
infoWithoutStop(message) {
|
|
87
|
-
if (this.spinner) {
|
|
88
|
-
const currentText = this.spinner.text;
|
|
89
|
-
this.spinner.stop();
|
|
90
|
-
console.log(import_chalk.default.blue("\u2139"), message);
|
|
91
|
-
this.spinner.start(currentText);
|
|
92
|
-
} else {
|
|
93
|
-
console.log(import_chalk.default.blue("\u2139"), message);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
var logger = new Logger();
|
|
98
|
-
|
|
99
|
-
// src/utils/paths.ts
|
|
100
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
101
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
102
40
|
|
|
103
41
|
// src/config/agents.ts
|
|
104
42
|
var import_node_os = __toESM(require("os"), 1);
|
|
@@ -216,7 +154,213 @@ var SHARED_SKILLS_DIR = import_node_path.default.join(HOME, ".emp-agent", "skill
|
|
|
216
154
|
var CONFIG_FILE = import_node_path.default.join(HOME, ".emp-agent", "config.json");
|
|
217
155
|
var CACHE_DIR = import_node_path.default.join(HOME, ".emp-agent", "cache");
|
|
218
156
|
|
|
157
|
+
// src/commands/agents.ts
|
|
158
|
+
function agents() {
|
|
159
|
+
const cwd = process.cwd();
|
|
160
|
+
console.log(import_chalk.default.bold("\n\u{1F4CB} Supported AI Agents:\n"));
|
|
161
|
+
for (const agent of AGENTS) {
|
|
162
|
+
const skillsDirs = getAgentSkillsDirs(agent, cwd);
|
|
163
|
+
const dirsInfo = skillsDirs.length > 1 ? ` (${skillsDirs.length} directories)` : "";
|
|
164
|
+
console.log(import_chalk.default.bold(agent.displayName));
|
|
165
|
+
console.log(import_chalk.default.gray(` Name: ${agent.name}`));
|
|
166
|
+
if (skillsDirs.length === 0) {
|
|
167
|
+
console.log(import_chalk.default.yellow(" \u26A0\uFE0F No directories configured"));
|
|
168
|
+
} else {
|
|
169
|
+
console.log(import_chalk.default.gray(` Directories${dirsInfo}:`));
|
|
170
|
+
for (const dir of skillsDirs) {
|
|
171
|
+
const exists = import_node_fs.default.existsSync(dir);
|
|
172
|
+
const status = exists ? import_chalk.default.green("\u2713") : import_chalk.default.gray("\u25CB");
|
|
173
|
+
const pathColor = exists ? import_chalk.default.white : import_chalk.default.gray;
|
|
174
|
+
console.log(` ${status} ${pathColor(dir)}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
console.log("");
|
|
178
|
+
}
|
|
179
|
+
console.log(import_chalk.default.bold("\u{1F4E6} Shared Skills Directory:"));
|
|
180
|
+
const sharedExists = import_node_fs.default.existsSync(SHARED_SKILLS_DIR);
|
|
181
|
+
const sharedStatus = sharedExists ? import_chalk.default.green("\u2713") : import_chalk.default.gray("\u25CB");
|
|
182
|
+
const sharedPathColor = sharedExists ? import_chalk.default.white : import_chalk.default.gray;
|
|
183
|
+
console.log(` ${sharedStatus} ${sharedPathColor(SHARED_SKILLS_DIR)}`);
|
|
184
|
+
console.log("");
|
|
185
|
+
const home = import_node_os2.default.homedir();
|
|
186
|
+
if (cwd !== home) {
|
|
187
|
+
console.log(import_chalk.default.gray(`Current working directory: ${cwd}`));
|
|
188
|
+
console.log(import_chalk.default.gray("(Project-level directories are shown above)\n"));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/commands/install.ts
|
|
193
|
+
var import_node_child_process2 = require("child_process");
|
|
194
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
195
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
196
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
197
|
+
var import_node_util2 = require("util");
|
|
198
|
+
|
|
199
|
+
// src/utils/git.ts
|
|
200
|
+
function parseGitUrl(url) {
|
|
201
|
+
const githubPatterns = [
|
|
202
|
+
// https://github.com/owner/repo/tree/branch/path/to/dir
|
|
203
|
+
/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)(?:\/(.+))?$/,
|
|
204
|
+
// https://github.com/owner/repo
|
|
205
|
+
/^https?:\/\/github\.com\/([^/]+)\/([^/]+)(?:\/)?$/,
|
|
206
|
+
// git@github.com:owner/repo.git
|
|
207
|
+
/^git@github\.com:([^/]+)\/([^/]+)(?:\.git)?$/
|
|
208
|
+
];
|
|
209
|
+
const gitlabPatterns = [
|
|
210
|
+
// https://host/group/repo/-/tree/branch/path (self-hosted + gitlab.com)
|
|
211
|
+
/^https?:\/\/([^/]+)\/(.+)\/-\/tree\/([^/]+)(?:\/(.+))?$/,
|
|
212
|
+
// https://gitlab.com/owner/repo
|
|
213
|
+
/^https?:\/\/gitlab\.com\/([^/]+)\/([^/]+)(?:\/)?$/,
|
|
214
|
+
// git@gitlab.com:owner/repo.git or git@host:group/repo.git
|
|
215
|
+
/^git@([^:]+):(.+)(?:\.git)?$/
|
|
216
|
+
];
|
|
217
|
+
for (let i = 0; i < githubPatterns.length; i++) {
|
|
218
|
+
const pattern = githubPatterns[i];
|
|
219
|
+
const match = url.match(pattern);
|
|
220
|
+
if (match) {
|
|
221
|
+
const owner = match[1];
|
|
222
|
+
const repo = match[2].replace(/\.git$/, "");
|
|
223
|
+
let branch;
|
|
224
|
+
let path7;
|
|
225
|
+
if (i === 0) {
|
|
226
|
+
branch = match[3];
|
|
227
|
+
path7 = match[4];
|
|
228
|
+
} else if (i === 1) {
|
|
229
|
+
branch = "main";
|
|
230
|
+
} else {
|
|
231
|
+
branch = "main";
|
|
232
|
+
}
|
|
233
|
+
const gitUrl = `https://github.com/${owner}/${repo}.git`;
|
|
234
|
+
return {
|
|
235
|
+
type: "github",
|
|
236
|
+
owner,
|
|
237
|
+
repo,
|
|
238
|
+
branch,
|
|
239
|
+
path: path7,
|
|
240
|
+
gitUrl,
|
|
241
|
+
installUrl: gitUrl
|
|
242
|
+
// Will be used for git clone
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
for (let i = 0; i < gitlabPatterns.length; i++) {
|
|
247
|
+
const pattern = gitlabPatterns[i];
|
|
248
|
+
const match = url.match(pattern);
|
|
249
|
+
if (match) {
|
|
250
|
+
let owner;
|
|
251
|
+
let repo;
|
|
252
|
+
let branch;
|
|
253
|
+
let path7;
|
|
254
|
+
let gitUrl;
|
|
255
|
+
if (i === 0) {
|
|
256
|
+
const host = match[1];
|
|
257
|
+
const repoPath = match[2].replace(/\.git$/, "");
|
|
258
|
+
branch = match[3];
|
|
259
|
+
path7 = match[4];
|
|
260
|
+
const parts = repoPath.split("/");
|
|
261
|
+
repo = parts.pop() || repoPath;
|
|
262
|
+
owner = parts.join("/") || repo;
|
|
263
|
+
gitUrl = `https://${host}/${repoPath}.git`;
|
|
264
|
+
} else if (i === 1) {
|
|
265
|
+
owner = match[1];
|
|
266
|
+
repo = match[2].replace(/\.git$/, "");
|
|
267
|
+
branch = "main";
|
|
268
|
+
gitUrl = `https://gitlab.com/${owner}/${repo}.git`;
|
|
269
|
+
} else {
|
|
270
|
+
const host = match[1];
|
|
271
|
+
const repoPath = match[2].replace(/\.git$/, "");
|
|
272
|
+
branch = "main";
|
|
273
|
+
const parts = repoPath.split("/");
|
|
274
|
+
repo = parts.pop() || repoPath;
|
|
275
|
+
owner = parts.join("/") || repo;
|
|
276
|
+
gitUrl = `https://${host}/${repoPath}.git`;
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
type: "gitlab",
|
|
280
|
+
owner,
|
|
281
|
+
repo,
|
|
282
|
+
branch,
|
|
283
|
+
path: path7,
|
|
284
|
+
gitUrl,
|
|
285
|
+
installUrl: gitUrl
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (url.startsWith("git+") || url.startsWith("git://")) {
|
|
290
|
+
return {
|
|
291
|
+
type: "other",
|
|
292
|
+
owner: "",
|
|
293
|
+
repo: "",
|
|
294
|
+
gitUrl: url.replace(/^git\+/, ""),
|
|
295
|
+
installUrl: url.startsWith("git+") ? url : `git+${url}`
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
function isGitUrl(str) {
|
|
301
|
+
return str.includes("github.com") || str.includes("gitlab.com") || str.includes("/-/tree/") || // GitLab web URL pattern (self-hosted)
|
|
302
|
+
str.startsWith("git@") || str.startsWith("git+") || str.startsWith("git://");
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/utils/logger.ts
|
|
306
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
307
|
+
var import_ora = __toESM(require("ora"), 1);
|
|
308
|
+
var Logger = class {
|
|
309
|
+
spinner = null;
|
|
310
|
+
info(message) {
|
|
311
|
+
if (this.spinner) this.spinner.stop();
|
|
312
|
+
console.log(import_chalk2.default.blue("\u2139"), message);
|
|
313
|
+
}
|
|
314
|
+
success(message) {
|
|
315
|
+
if (this.spinner) this.spinner.stop();
|
|
316
|
+
console.log(import_chalk2.default.green("\u2713"), message);
|
|
317
|
+
}
|
|
318
|
+
warn(message) {
|
|
319
|
+
if (this.spinner) this.spinner.stop();
|
|
320
|
+
console.log(import_chalk2.default.yellow("\u26A0"), message);
|
|
321
|
+
}
|
|
322
|
+
error(message) {
|
|
323
|
+
if (this.spinner) this.spinner.stop();
|
|
324
|
+
console.log(import_chalk2.default.red("\u2717"), message);
|
|
325
|
+
}
|
|
326
|
+
start(message) {
|
|
327
|
+
if (this.spinner) this.spinner.stop();
|
|
328
|
+
this.spinner = (0, import_ora.default)(message).start();
|
|
329
|
+
return this.spinner;
|
|
330
|
+
}
|
|
331
|
+
stopSpinner() {
|
|
332
|
+
if (this.spinner) {
|
|
333
|
+
this.spinner.stop();
|
|
334
|
+
this.spinner = null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Update spinner text without stopping it
|
|
339
|
+
*/
|
|
340
|
+
updateSpinner(message) {
|
|
341
|
+
if (this.spinner) {
|
|
342
|
+
this.spinner.text = message;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Log info without stopping spinner (for background info)
|
|
347
|
+
*/
|
|
348
|
+
infoWithoutStop(message) {
|
|
349
|
+
if (this.spinner) {
|
|
350
|
+
const currentText = this.spinner.text;
|
|
351
|
+
this.spinner.stop();
|
|
352
|
+
console.log(import_chalk2.default.blue("\u2139"), message);
|
|
353
|
+
this.spinner.start(currentText);
|
|
354
|
+
} else {
|
|
355
|
+
console.log(import_chalk2.default.blue("\u2139"), message);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
var logger = new Logger();
|
|
360
|
+
|
|
219
361
|
// src/utils/paths.ts
|
|
362
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
363
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
220
364
|
function getSharedSkillPath(skillName) {
|
|
221
365
|
return import_node_path2.default.join(SHARED_SKILLS_DIR, skillName);
|
|
222
366
|
}
|
|
@@ -229,8 +373,8 @@ function getAgentSkillPaths(agentName, skillName, cwd) {
|
|
|
229
373
|
return skillsDirs.map((dir) => import_node_path2.default.join(dir, skillName));
|
|
230
374
|
}
|
|
231
375
|
function ensureSharedDir() {
|
|
232
|
-
if (!
|
|
233
|
-
|
|
376
|
+
if (!import_node_fs2.default.existsSync(SHARED_SKILLS_DIR)) {
|
|
377
|
+
import_node_fs2.default.mkdirSync(SHARED_SKILLS_DIR, { recursive: true });
|
|
234
378
|
}
|
|
235
379
|
}
|
|
236
380
|
function detectInstalledAgents(cwd) {
|
|
@@ -238,7 +382,7 @@ function detectInstalledAgents(cwd) {
|
|
|
238
382
|
try {
|
|
239
383
|
const skillsDirs = getAgentSkillsDirs(agent, cwd);
|
|
240
384
|
return skillsDirs.some((dir) => {
|
|
241
|
-
return
|
|
385
|
+
return import_node_fs2.default.existsSync(dir) || import_node_fs2.default.existsSync(import_node_path2.default.dirname(dir));
|
|
242
386
|
});
|
|
243
387
|
} catch {
|
|
244
388
|
return false;
|
|
@@ -257,32 +401,93 @@ function extractSkillName(nameOrPath) {
|
|
|
257
401
|
return import_node_path2.default.basename(nameOrPath);
|
|
258
402
|
}
|
|
259
403
|
|
|
260
|
-
// src/utils/
|
|
261
|
-
var
|
|
404
|
+
// src/utils/registry.ts
|
|
405
|
+
var import_node_child_process = require("child_process");
|
|
406
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
262
407
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
408
|
+
var import_node_util = require("util");
|
|
409
|
+
var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
410
|
+
function findNpmrc(startDir) {
|
|
411
|
+
let currentDir = import_node_path3.default.resolve(startDir);
|
|
412
|
+
while (currentDir !== import_node_path3.default.dirname(currentDir)) {
|
|
413
|
+
const npmrcPath = import_node_path3.default.join(currentDir, ".npmrc");
|
|
414
|
+
if (import_node_fs3.default.existsSync(npmrcPath)) {
|
|
415
|
+
return npmrcPath;
|
|
416
|
+
}
|
|
417
|
+
currentDir = import_node_path3.default.dirname(currentDir);
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
function parseNpmrc(npmrcPath) {
|
|
422
|
+
try {
|
|
423
|
+
const content = import_node_fs3.default.readFileSync(npmrcPath, "utf-8");
|
|
424
|
+
const lines = content.split("\n");
|
|
425
|
+
for (const line of lines) {
|
|
426
|
+
const trimmed = line.trim();
|
|
427
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const registryMatch = trimmed.match(/^(?:@[^:]+:)?registry\s*=\s*(.+)$/);
|
|
431
|
+
if (registryMatch) {
|
|
432
|
+
return registryMatch[1].trim();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} catch (error) {
|
|
436
|
+
}
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
async function getGlobalRegistry() {
|
|
440
|
+
try {
|
|
441
|
+
const { stdout } = await execAsync("npm config get registry");
|
|
442
|
+
const registry = stdout.trim();
|
|
443
|
+
if (registry && registry !== "undefined") {
|
|
444
|
+
return registry;
|
|
445
|
+
}
|
|
446
|
+
} catch (error) {
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
async function getRegistry(cwd = process.cwd()) {
|
|
451
|
+
const npmrcPath = findNpmrc(cwd);
|
|
452
|
+
if (npmrcPath) {
|
|
453
|
+
const registry = parseNpmrc(npmrcPath);
|
|
454
|
+
if (registry) {
|
|
455
|
+
return registry;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const globalRegistry = await getGlobalRegistry();
|
|
459
|
+
if (globalRegistry) {
|
|
460
|
+
return globalRegistry;
|
|
461
|
+
}
|
|
462
|
+
return "https://registry.npmjs.org/";
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// src/utils/symlink.ts
|
|
466
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
467
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
263
468
|
function createSymlink(skillName, agent, cwd) {
|
|
264
469
|
const source = getSharedSkillPath(skillName);
|
|
265
|
-
if (!
|
|
470
|
+
if (!import_node_fs4.default.existsSync(source)) {
|
|
266
471
|
logger.error(`Skill not found: ${source}`);
|
|
267
472
|
return false;
|
|
268
473
|
}
|
|
269
474
|
const targets = getAgentSkillPaths(agent.name, skillName, cwd);
|
|
270
475
|
let successCount = 0;
|
|
271
476
|
for (const target of targets) {
|
|
272
|
-
const targetDir =
|
|
273
|
-
if (!
|
|
477
|
+
const targetDir = import_node_path4.default.dirname(target);
|
|
478
|
+
if (!import_node_fs4.default.existsSync(targetDir)) {
|
|
274
479
|
try {
|
|
275
|
-
|
|
480
|
+
import_node_fs4.default.mkdirSync(targetDir, { recursive: true });
|
|
276
481
|
} catch (error) {
|
|
277
482
|
logger.error(`Failed to create directory ${targetDir}: ${error.message}`);
|
|
278
483
|
continue;
|
|
279
484
|
}
|
|
280
485
|
}
|
|
281
|
-
if (
|
|
486
|
+
if (import_node_fs4.default.existsSync(target)) {
|
|
282
487
|
try {
|
|
283
|
-
const stats =
|
|
488
|
+
const stats = import_node_fs4.default.lstatSync(target);
|
|
284
489
|
if (stats.isSymbolicLink()) {
|
|
285
|
-
|
|
490
|
+
import_node_fs4.default.unlinkSync(target);
|
|
286
491
|
} else {
|
|
287
492
|
logger.warn(`Target exists but is not a symlink, skipping: ${target}`);
|
|
288
493
|
continue;
|
|
@@ -293,7 +498,7 @@ function createSymlink(skillName, agent, cwd) {
|
|
|
293
498
|
}
|
|
294
499
|
}
|
|
295
500
|
try {
|
|
296
|
-
|
|
501
|
+
import_node_fs4.default.symlinkSync(source, target, "dir");
|
|
297
502
|
successCount++;
|
|
298
503
|
} catch (error) {
|
|
299
504
|
logger.error(`Failed to create symlink at ${target}: ${error.message}`);
|
|
@@ -310,13 +515,13 @@ function removeSymlink(skillName, agent, cwd) {
|
|
|
310
515
|
const targets = getAgentSkillPaths(agent.name, skillName, cwd);
|
|
311
516
|
let removedCount = 0;
|
|
312
517
|
for (const target of targets) {
|
|
313
|
-
if (!
|
|
518
|
+
if (!import_node_fs4.default.existsSync(target)) {
|
|
314
519
|
continue;
|
|
315
520
|
}
|
|
316
521
|
try {
|
|
317
|
-
const stats =
|
|
522
|
+
const stats = import_node_fs4.default.lstatSync(target);
|
|
318
523
|
if (stats.isSymbolicLink()) {
|
|
319
|
-
|
|
524
|
+
import_node_fs4.default.unlinkSync(target);
|
|
320
525
|
removedCount++;
|
|
321
526
|
} else {
|
|
322
527
|
logger.warn(`Not a symlink: ${target}`);
|
|
@@ -334,7 +539,7 @@ function removeSymlink(skillName, agent, cwd) {
|
|
|
334
539
|
}
|
|
335
540
|
function isSymlink(filePath) {
|
|
336
541
|
try {
|
|
337
|
-
const stats =
|
|
542
|
+
const stats = import_node_fs4.default.lstatSync(filePath);
|
|
338
543
|
return stats.isSymbolicLink();
|
|
339
544
|
} catch {
|
|
340
545
|
return false;
|
|
@@ -342,164 +547,12 @@ function isSymlink(filePath) {
|
|
|
342
547
|
}
|
|
343
548
|
function readSymlink(filePath) {
|
|
344
549
|
try {
|
|
345
|
-
return
|
|
550
|
+
return import_node_fs4.default.readlinkSync(filePath);
|
|
346
551
|
} catch {
|
|
347
552
|
return null;
|
|
348
553
|
}
|
|
349
554
|
}
|
|
350
555
|
|
|
351
|
-
// src/utils/registry.ts
|
|
352
|
-
var import_node_child_process = require("child_process");
|
|
353
|
-
var import_node_util = require("util");
|
|
354
|
-
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
355
|
-
var import_node_path4 = __toESM(require("path"), 1);
|
|
356
|
-
var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
357
|
-
function findNpmrc(startDir) {
|
|
358
|
-
let currentDir = import_node_path4.default.resolve(startDir);
|
|
359
|
-
while (currentDir !== import_node_path4.default.dirname(currentDir)) {
|
|
360
|
-
const npmrcPath = import_node_path4.default.join(currentDir, ".npmrc");
|
|
361
|
-
if (import_node_fs3.default.existsSync(npmrcPath)) {
|
|
362
|
-
return npmrcPath;
|
|
363
|
-
}
|
|
364
|
-
currentDir = import_node_path4.default.dirname(currentDir);
|
|
365
|
-
}
|
|
366
|
-
return null;
|
|
367
|
-
}
|
|
368
|
-
function parseNpmrc(npmrcPath) {
|
|
369
|
-
try {
|
|
370
|
-
const content = import_node_fs3.default.readFileSync(npmrcPath, "utf-8");
|
|
371
|
-
const lines = content.split("\n");
|
|
372
|
-
for (const line of lines) {
|
|
373
|
-
const trimmed = line.trim();
|
|
374
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
const registryMatch = trimmed.match(/^(?:@[^:]+:)?registry\s*=\s*(.+)$/);
|
|
378
|
-
if (registryMatch) {
|
|
379
|
-
return registryMatch[1].trim();
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
} catch (error) {
|
|
383
|
-
}
|
|
384
|
-
return null;
|
|
385
|
-
}
|
|
386
|
-
async function getGlobalRegistry() {
|
|
387
|
-
try {
|
|
388
|
-
const { stdout } = await execAsync("npm config get registry");
|
|
389
|
-
const registry = stdout.trim();
|
|
390
|
-
if (registry && registry !== "undefined") {
|
|
391
|
-
return registry;
|
|
392
|
-
}
|
|
393
|
-
} catch (error) {
|
|
394
|
-
}
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
async function getRegistry(cwd = process.cwd()) {
|
|
398
|
-
const npmrcPath = findNpmrc(cwd);
|
|
399
|
-
if (npmrcPath) {
|
|
400
|
-
const registry = parseNpmrc(npmrcPath);
|
|
401
|
-
if (registry) {
|
|
402
|
-
return registry;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
const globalRegistry = await getGlobalRegistry();
|
|
406
|
-
if (globalRegistry) {
|
|
407
|
-
return globalRegistry;
|
|
408
|
-
}
|
|
409
|
-
return "https://registry.npmjs.org/";
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// src/utils/git.ts
|
|
413
|
-
function parseGitUrl(url) {
|
|
414
|
-
const githubPatterns = [
|
|
415
|
-
// https://github.com/owner/repo/tree/branch/path/to/dir
|
|
416
|
-
/^https?:\/\/github\.com\/([^\/]+)\/([^\/]+)\/tree\/([^\/]+)(?:\/(.+))?$/,
|
|
417
|
-
// https://github.com/owner/repo
|
|
418
|
-
/^https?:\/\/github\.com\/([^\/]+)\/([^\/]+)(?:\/)?$/,
|
|
419
|
-
// git@github.com:owner/repo.git
|
|
420
|
-
/^git@github\.com:([^\/]+)\/([^\/]+)(?:\.git)?$/
|
|
421
|
-
];
|
|
422
|
-
const gitlabPatterns = [
|
|
423
|
-
// https://gitlab.com/owner/repo/-/tree/branch/path/to/dir
|
|
424
|
-
/^https?:\/\/gitlab\.com\/([^\/]+)\/([^\/]+)\/-\/tree\/([^\/]+)(?:\/(.+))?$/,
|
|
425
|
-
// https://gitlab.com/owner/repo
|
|
426
|
-
/^https?:\/\/gitlab\.com\/([^\/]+)\/([^\/]+)(?:\/)?$/,
|
|
427
|
-
// git@gitlab.com:owner/repo.git
|
|
428
|
-
/^git@gitlab\.com:([^\/]+)\/([^\/]+)(?:\.git)?$/
|
|
429
|
-
];
|
|
430
|
-
for (let i = 0; i < githubPatterns.length; i++) {
|
|
431
|
-
const pattern = githubPatterns[i];
|
|
432
|
-
const match = url.match(pattern);
|
|
433
|
-
if (match) {
|
|
434
|
-
const owner = match[1];
|
|
435
|
-
const repo = match[2].replace(/\.git$/, "");
|
|
436
|
-
let branch;
|
|
437
|
-
let path7;
|
|
438
|
-
if (i === 0) {
|
|
439
|
-
branch = match[3];
|
|
440
|
-
path7 = match[4];
|
|
441
|
-
} else if (i === 1) {
|
|
442
|
-
branch = "main";
|
|
443
|
-
} else {
|
|
444
|
-
branch = "main";
|
|
445
|
-
}
|
|
446
|
-
const gitUrl = `https://github.com/${owner}/${repo}.git`;
|
|
447
|
-
return {
|
|
448
|
-
type: "github",
|
|
449
|
-
owner,
|
|
450
|
-
repo,
|
|
451
|
-
branch,
|
|
452
|
-
path: path7,
|
|
453
|
-
gitUrl,
|
|
454
|
-
installUrl: gitUrl
|
|
455
|
-
// Will be used for git clone
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
for (let i = 0; i < gitlabPatterns.length; i++) {
|
|
460
|
-
const pattern = gitlabPatterns[i];
|
|
461
|
-
const match = url.match(pattern);
|
|
462
|
-
if (match) {
|
|
463
|
-
const owner = match[1];
|
|
464
|
-
const repo = match[2].replace(/\.git$/, "");
|
|
465
|
-
let branch;
|
|
466
|
-
let path7;
|
|
467
|
-
if (i === 0) {
|
|
468
|
-
branch = match[3];
|
|
469
|
-
path7 = match[4];
|
|
470
|
-
} else if (i === 1) {
|
|
471
|
-
branch = "main";
|
|
472
|
-
} else {
|
|
473
|
-
branch = "main";
|
|
474
|
-
}
|
|
475
|
-
const gitUrl = `https://gitlab.com/${owner}/${repo}.git`;
|
|
476
|
-
return {
|
|
477
|
-
type: "gitlab",
|
|
478
|
-
owner,
|
|
479
|
-
repo,
|
|
480
|
-
branch,
|
|
481
|
-
path: path7,
|
|
482
|
-
gitUrl,
|
|
483
|
-
installUrl: gitUrl
|
|
484
|
-
// Will be used for git clone
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
if (url.startsWith("git+") || url.startsWith("git://")) {
|
|
489
|
-
return {
|
|
490
|
-
type: "other",
|
|
491
|
-
owner: "",
|
|
492
|
-
repo: "",
|
|
493
|
-
gitUrl: url.replace(/^git\+/, ""),
|
|
494
|
-
installUrl: url.startsWith("git+") ? url : `git+${url}`
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
return null;
|
|
498
|
-
}
|
|
499
|
-
function isGitUrl(str) {
|
|
500
|
-
return str.includes("github.com") || str.includes("gitlab.com") || str.startsWith("git@") || str.startsWith("git+") || str.startsWith("git://");
|
|
501
|
-
}
|
|
502
|
-
|
|
503
556
|
// src/commands/install.ts
|
|
504
557
|
var execAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.exec);
|
|
505
558
|
async function execWithTimeout(command, timeout = 12e4, env) {
|
|
@@ -511,10 +564,7 @@ async function execWithTimeout(command, timeout = 12e4, env) {
|
|
|
511
564
|
});
|
|
512
565
|
try {
|
|
513
566
|
const execOptions = env ? { env } : {};
|
|
514
|
-
const result = await Promise.race([
|
|
515
|
-
execAsync2(command, execOptions),
|
|
516
|
-
timeoutPromise
|
|
517
|
-
]);
|
|
567
|
+
const result = await Promise.race([execAsync2(command, execOptions), timeoutPromise]);
|
|
518
568
|
if (timeoutId) {
|
|
519
569
|
clearTimeout(timeoutId);
|
|
520
570
|
}
|
|
@@ -552,7 +602,7 @@ async function install(skillNameOrPath, options = {}) {
|
|
|
552
602
|
logger.infoWithoutStop(`Path: ${gitInfo.path}`);
|
|
553
603
|
}
|
|
554
604
|
logger.infoWithoutStop(`Timeout: ${timeout / 1e3}s`);
|
|
555
|
-
|
|
605
|
+
import_node_fs5.default.mkdirSync(tempDir, { recursive: true });
|
|
556
606
|
const branchFlag = gitInfo.branch ? `-b ${gitInfo.branch}` : "";
|
|
557
607
|
const cloneCommand = branchFlag ? `git clone ${branchFlag} ${gitInfo.gitUrl} ${cloneDir} --depth 1 --quiet` : `git clone ${gitInfo.gitUrl} ${cloneDir} --depth 1 --quiet`;
|
|
558
608
|
try {
|
|
@@ -574,7 +624,7 @@ async function install(skillNameOrPath, options = {}) {
|
|
|
574
624
|
}
|
|
575
625
|
if (gitInfo.path) {
|
|
576
626
|
skillPath = import_node_path5.default.join(cloneDir, gitInfo.path);
|
|
577
|
-
if (!
|
|
627
|
+
if (!import_node_fs5.default.existsSync(skillPath)) {
|
|
578
628
|
logger.error(`Path not found in repository: ${gitInfo.path}`);
|
|
579
629
|
logger.info(`Repository cloned to: ${cloneDir}`);
|
|
580
630
|
process.exit(1);
|
|
@@ -583,7 +633,7 @@ async function install(skillNameOrPath, options = {}) {
|
|
|
583
633
|
skillPath = cloneDir;
|
|
584
634
|
}
|
|
585
635
|
const skillMdPath = import_node_path5.default.join(skillPath, "SKILL.md");
|
|
586
|
-
if (!
|
|
636
|
+
if (!import_node_fs5.default.existsSync(skillMdPath)) {
|
|
587
637
|
logger.warn(`Warning: SKILL.md not found in ${skillPath}`);
|
|
588
638
|
logger.info("The directory may not be a valid skill package");
|
|
589
639
|
}
|
|
@@ -605,16 +655,16 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
605
655
|
}
|
|
606
656
|
process.exit(1);
|
|
607
657
|
}
|
|
608
|
-
} else if (options.link ||
|
|
658
|
+
} else if (options.link || import_node_fs5.default.existsSync(skillNameOrPath)) {
|
|
609
659
|
skillPath = import_node_path5.default.resolve(skillNameOrPath);
|
|
610
|
-
if (!
|
|
660
|
+
if (!import_node_fs5.default.existsSync(skillPath)) {
|
|
611
661
|
logger.error(`Path not found: ${skillPath}`);
|
|
612
662
|
process.exit(1);
|
|
613
663
|
}
|
|
614
664
|
const pkgPath = import_node_path5.default.join(skillPath, "package.json");
|
|
615
|
-
if (
|
|
665
|
+
if (import_node_fs5.default.existsSync(pkgPath)) {
|
|
616
666
|
try {
|
|
617
|
-
const pkg = JSON.parse(
|
|
667
|
+
const pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgPath, "utf-8"));
|
|
618
668
|
skillName = extractSkillName(pkg.name);
|
|
619
669
|
} catch {
|
|
620
670
|
skillName = extractSkillName(import_node_path5.default.basename(skillPath));
|
|
@@ -631,12 +681,12 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
631
681
|
const spinner = logger.start(`Installing ${skillNameOrPath}...`);
|
|
632
682
|
logger.infoWithoutStop(`Registry: ${registry}`);
|
|
633
683
|
logger.infoWithoutStop(`Timeout: ${timeout / 1e3}s`);
|
|
634
|
-
|
|
684
|
+
import_node_fs5.default.mkdirSync(tempDir, { recursive: true });
|
|
635
685
|
logger.updateSpinner(`Downloading ${skillNameOrPath} from ${registry}...`);
|
|
636
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE ||
|
|
686
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || import_node_os3.default.homedir();
|
|
637
687
|
const npmCacheDir = import_node_path5.default.join(homeDir, ".npm");
|
|
638
688
|
const npmConfigPrefix = import_node_path5.default.join(homeDir, ".npm-global");
|
|
639
|
-
|
|
689
|
+
import_node_fs5.default.mkdirSync(npmCacheDir, { recursive: true });
|
|
640
690
|
const installCommand = `npm install ${skillNameOrPath} --prefix ${tempDir} --registry=${registry} --no-save --silent --no-bin-links --prefer-offline`;
|
|
641
691
|
const env = {
|
|
642
692
|
...process.env,
|
|
@@ -661,7 +711,9 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
661
711
|
logger.info("");
|
|
662
712
|
logger.info("Suggestions:");
|
|
663
713
|
logger.info(` - Try again: eskill add ${skillNameOrPath}`);
|
|
664
|
-
logger.info(
|
|
714
|
+
logger.info(
|
|
715
|
+
` - Use a different registry: eskill add ${skillNameOrPath} --registry=https://registry.npmjs.org/`
|
|
716
|
+
);
|
|
665
717
|
logger.info(` - Increase timeout: eskill add ${skillNameOrPath} --timeout=300000`);
|
|
666
718
|
} else if (errorMessage.includes("EACCES") || errorMessage.includes("permission denied") || errorMessage.includes("Permission denied")) {
|
|
667
719
|
logger.error("Permission denied error detected");
|
|
@@ -700,7 +752,9 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
700
752
|
logger.info("Please check:");
|
|
701
753
|
logger.info(" - Your internet connection");
|
|
702
754
|
logger.info(` - Registry accessibility: ${registry}`);
|
|
703
|
-
logger.info(
|
|
755
|
+
logger.info(
|
|
756
|
+
` - Try a different registry: eskill add ${skillNameOrPath} --registry=https://registry.npmjs.org/`
|
|
757
|
+
);
|
|
704
758
|
} else {
|
|
705
759
|
logger.error(`Failed to download: ${errorMessage}`);
|
|
706
760
|
logger.info("");
|
|
@@ -713,7 +767,7 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
713
767
|
process.exit(1);
|
|
714
768
|
}
|
|
715
769
|
skillPath = import_node_path5.default.join(tempDir, "node_modules", skillNameOrPath);
|
|
716
|
-
if (!
|
|
770
|
+
if (!import_node_fs5.default.existsSync(skillPath)) {
|
|
717
771
|
logger.error(`Failed to download package: ${skillNameOrPath}`);
|
|
718
772
|
process.exit(1);
|
|
719
773
|
}
|
|
@@ -723,10 +777,10 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
723
777
|
}
|
|
724
778
|
}
|
|
725
779
|
const targetPath = getSharedSkillPath(skillName);
|
|
726
|
-
if (
|
|
780
|
+
if (import_node_fs5.default.existsSync(targetPath)) {
|
|
727
781
|
if (options.force) {
|
|
728
782
|
logger.warn("Removing existing installation...");
|
|
729
|
-
|
|
783
|
+
import_node_fs5.default.rmSync(targetPath, { recursive: true, force: true });
|
|
730
784
|
} else {
|
|
731
785
|
logger.error(`Skill already exists: ${targetPath}`);
|
|
732
786
|
logger.info("Use --force to overwrite");
|
|
@@ -734,7 +788,7 @@ Tried to clone: ${gitInfo.gitUrl}`);
|
|
|
734
788
|
}
|
|
735
789
|
}
|
|
736
790
|
if (options.link) {
|
|
737
|
-
|
|
791
|
+
import_node_fs5.default.symlinkSync(skillPath, targetPath, "dir");
|
|
738
792
|
logger.success(`Linked to shared directory (dev mode)`);
|
|
739
793
|
} else {
|
|
740
794
|
copyDir(skillPath, targetPath);
|
|
@@ -780,8 +834,8 @@ Linked to ${successCount}/${targetAgents.length} agents`);
|
|
|
780
834
|
}
|
|
781
835
|
}
|
|
782
836
|
function copyDir(src, dest) {
|
|
783
|
-
|
|
784
|
-
const entries =
|
|
837
|
+
import_node_fs5.default.mkdirSync(dest, { recursive: true });
|
|
838
|
+
const entries = import_node_fs5.default.readdirSync(src, { withFileTypes: true });
|
|
785
839
|
for (const entry of entries) {
|
|
786
840
|
const srcPath = import_node_path5.default.join(src, entry.name);
|
|
787
841
|
const destPath = import_node_path5.default.join(dest, entry.name);
|
|
@@ -791,44 +845,44 @@ function copyDir(src, dest) {
|
|
|
791
845
|
if (entry.isDirectory()) {
|
|
792
846
|
copyDir(srcPath, destPath);
|
|
793
847
|
} else {
|
|
794
|
-
|
|
848
|
+
import_node_fs5.default.copyFileSync(srcPath, destPath);
|
|
795
849
|
}
|
|
796
850
|
}
|
|
797
851
|
}
|
|
798
852
|
|
|
799
853
|
// src/commands/list.ts
|
|
800
|
-
var
|
|
854
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
801
855
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
802
|
-
var
|
|
856
|
+
var import_chalk3 = __toESM(require("chalk"), 1);
|
|
803
857
|
function list() {
|
|
804
|
-
if (!
|
|
858
|
+
if (!import_node_fs6.default.existsSync(SHARED_SKILLS_DIR)) {
|
|
805
859
|
logger.info("No skills installed");
|
|
806
860
|
logger.info(`
|
|
807
|
-
To install a skill, run: ${
|
|
861
|
+
To install a skill, run: ${import_chalk3.default.cyan("eskill install <skill-name>")}`);
|
|
808
862
|
return;
|
|
809
863
|
}
|
|
810
|
-
const skills =
|
|
864
|
+
const skills = import_node_fs6.default.readdirSync(SHARED_SKILLS_DIR);
|
|
811
865
|
if (skills.length === 0) {
|
|
812
866
|
logger.info("No skills installed");
|
|
813
867
|
logger.info(`
|
|
814
|
-
To install a skill, run: ${
|
|
868
|
+
To install a skill, run: ${import_chalk3.default.cyan("eskill install <skill-name>")}`);
|
|
815
869
|
return;
|
|
816
870
|
}
|
|
817
|
-
console.log(
|
|
871
|
+
console.log(import_chalk3.default.bold(`
|
|
818
872
|
Installed skills in ${SHARED_SKILLS_DIR}:
|
|
819
873
|
`));
|
|
820
874
|
for (const skill of skills) {
|
|
821
875
|
const skillPath = import_node_path6.default.join(SHARED_SKILLS_DIR, skill);
|
|
822
876
|
try {
|
|
823
|
-
const stats =
|
|
877
|
+
const stats = import_node_fs6.default.lstatSync(skillPath);
|
|
824
878
|
if (!stats.isDirectory() && !stats.isSymbolicLink()) {
|
|
825
879
|
continue;
|
|
826
880
|
}
|
|
827
881
|
let version2 = "unknown";
|
|
828
882
|
const pkgPath = import_node_path6.default.join(skillPath, "package.json");
|
|
829
|
-
if (
|
|
883
|
+
if (import_node_fs6.default.existsSync(pkgPath)) {
|
|
830
884
|
try {
|
|
831
|
-
const pkgContent =
|
|
885
|
+
const pkgContent = import_node_fs6.default.readFileSync(pkgPath, "utf-8");
|
|
832
886
|
const pkg = JSON.parse(pkgContent);
|
|
833
887
|
if (pkg.version && typeof pkg.version === "string") {
|
|
834
888
|
version2 = pkg.version;
|
|
@@ -838,9 +892,9 @@ Installed skills in ${SHARED_SKILLS_DIR}:
|
|
|
838
892
|
}
|
|
839
893
|
if (version2 === "unknown") {
|
|
840
894
|
const skillMdPath = import_node_path6.default.join(skillPath, "SKILL.md");
|
|
841
|
-
if (
|
|
895
|
+
if (import_node_fs6.default.existsSync(skillMdPath)) {
|
|
842
896
|
try {
|
|
843
|
-
const skillMdContent =
|
|
897
|
+
const skillMdContent = import_node_fs6.default.readFileSync(skillMdPath, "utf-8");
|
|
844
898
|
const frontmatterMatch = skillMdContent.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
845
899
|
if (frontmatterMatch) {
|
|
846
900
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -858,8 +912,8 @@ Installed skills in ${SHARED_SKILLS_DIR}:
|
|
|
858
912
|
const targetPath = readSymlink(skillPath);
|
|
859
913
|
if (targetPath) {
|
|
860
914
|
const targetPkgPath = import_node_path6.default.join(targetPath, "package.json");
|
|
861
|
-
if (
|
|
862
|
-
const pkg = JSON.parse(
|
|
915
|
+
if (import_node_fs6.default.existsSync(targetPkgPath)) {
|
|
916
|
+
const pkg = JSON.parse(import_node_fs6.default.readFileSync(targetPkgPath, "utf-8"));
|
|
863
917
|
if (pkg.version && typeof pkg.version === "string") {
|
|
864
918
|
version2 = pkg.version;
|
|
865
919
|
}
|
|
@@ -869,16 +923,16 @@ Installed skills in ${SHARED_SKILLS_DIR}:
|
|
|
869
923
|
}
|
|
870
924
|
}
|
|
871
925
|
const isDev = isSymlink(skillPath);
|
|
872
|
-
const devTag = isDev ?
|
|
873
|
-
const versionDisplay = version2 !== "unknown" ?
|
|
874
|
-
console.log(
|
|
926
|
+
const devTag = isDev ? import_chalk3.default.yellow(" (dev)") : "";
|
|
927
|
+
const versionDisplay = version2 !== "unknown" ? import_chalk3.default.gray(`(v${version2})`) : "";
|
|
928
|
+
console.log(import_chalk3.default.green("\u{1F4E6}") + ` ${import_chalk3.default.bold(skill)}${versionDisplay ? " " + versionDisplay : ""}${devTag}`);
|
|
875
929
|
const cwd = process.cwd();
|
|
876
930
|
const linkedAgents = [];
|
|
877
931
|
for (const agent of AGENTS) {
|
|
878
932
|
const skillsDirs = getAgentSkillsDirs(agent, cwd);
|
|
879
933
|
const hasSymlink = skillsDirs.some((dir) => {
|
|
880
934
|
const agentSkillPath = import_node_path6.default.join(dir, skill);
|
|
881
|
-
if (
|
|
935
|
+
if (import_node_fs6.default.existsSync(agentSkillPath) && isSymlink(agentSkillPath)) {
|
|
882
936
|
const target = readSymlink(agentSkillPath);
|
|
883
937
|
return target === skillPath;
|
|
884
938
|
}
|
|
@@ -889,29 +943,28 @@ Installed skills in ${SHARED_SKILLS_DIR}:
|
|
|
889
943
|
}
|
|
890
944
|
}
|
|
891
945
|
if (linkedAgents.length > 0) {
|
|
892
|
-
console.log(
|
|
946
|
+
console.log(import_chalk3.default.gray(` \u2192 Linked to: ${linkedAgents.join(", ")}`));
|
|
893
947
|
} else {
|
|
894
|
-
console.log(
|
|
948
|
+
console.log(import_chalk3.default.yellow(` \u2192 Not linked to any agent`));
|
|
895
949
|
}
|
|
896
950
|
if (isDev) {
|
|
897
951
|
const target = readSymlink(skillPath);
|
|
898
952
|
if (target) {
|
|
899
|
-
console.log(
|
|
953
|
+
console.log(import_chalk3.default.gray(` \u2192 Source: ${target}`));
|
|
900
954
|
}
|
|
901
955
|
}
|
|
902
956
|
console.log("");
|
|
903
957
|
} catch (error) {
|
|
904
|
-
continue;
|
|
905
958
|
}
|
|
906
959
|
}
|
|
907
960
|
}
|
|
908
961
|
|
|
909
962
|
// src/commands/remove.ts
|
|
910
|
-
var
|
|
963
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
911
964
|
async function remove(skillName, options = {}) {
|
|
912
965
|
const extractedName = extractSkillName(skillName);
|
|
913
966
|
const sharedPath = getSharedSkillPath(extractedName);
|
|
914
|
-
const skillExists =
|
|
967
|
+
const skillExists = import_node_fs7.default.existsSync(sharedPath);
|
|
915
968
|
if (!skillExists) {
|
|
916
969
|
logger.error(`Skill not found: ${extractedName}`);
|
|
917
970
|
logger.info(`Location: ${sharedPath}`);
|
|
@@ -947,12 +1000,12 @@ Installed agents: ${installedAgents.map((a) => a.name).join(", ")}`);
|
|
|
947
1000
|
}
|
|
948
1001
|
logger.info("Removing skill from shared directory...");
|
|
949
1002
|
try {
|
|
950
|
-
const stats =
|
|
1003
|
+
const stats = import_node_fs7.default.lstatSync(sharedPath);
|
|
951
1004
|
if (stats.isSymbolicLink()) {
|
|
952
|
-
|
|
1005
|
+
import_node_fs7.default.unlinkSync(sharedPath);
|
|
953
1006
|
logger.success("Removed symlink from shared directory");
|
|
954
1007
|
} else {
|
|
955
|
-
|
|
1008
|
+
import_node_fs7.default.rmSync(sharedPath, { recursive: true, force: true });
|
|
956
1009
|
logger.success("Removed skill from shared directory");
|
|
957
1010
|
}
|
|
958
1011
|
} catch (error) {
|
|
@@ -963,7 +1016,7 @@ Installed agents: ${installedAgents.map((a) => a.name).join(", ")}`);
|
|
|
963
1016
|
for (const agent of AGENTS) {
|
|
964
1017
|
const agentSkillPaths = getAgentSkillPaths(agent.name, extractedName, cwd);
|
|
965
1018
|
const hasSymlink = agentSkillPaths.some((path7) => {
|
|
966
|
-
return
|
|
1019
|
+
return import_node_fs7.default.existsSync(path7) && isSymlink(path7);
|
|
967
1020
|
});
|
|
968
1021
|
if (hasSymlink) {
|
|
969
1022
|
remainingSymlinks.push(agent.displayName);
|
|
@@ -981,44 +1034,6 @@ Installed agents: ${installedAgents.map((a) => a.name).join(", ")}`);
|
|
|
981
1034
|
}
|
|
982
1035
|
}
|
|
983
1036
|
|
|
984
|
-
// src/commands/agents.ts
|
|
985
|
-
var import_chalk3 = __toESM(require("chalk"), 1);
|
|
986
|
-
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
987
|
-
var import_node_os3 = __toESM(require("os"), 1);
|
|
988
|
-
function agents() {
|
|
989
|
-
const cwd = process.cwd();
|
|
990
|
-
console.log(import_chalk3.default.bold("\n\u{1F4CB} Supported AI Agents:\n"));
|
|
991
|
-
for (const agent of AGENTS) {
|
|
992
|
-
const skillsDirs = getAgentSkillsDirs(agent, cwd);
|
|
993
|
-
const dirsInfo = skillsDirs.length > 1 ? ` (${skillsDirs.length} directories)` : "";
|
|
994
|
-
console.log(import_chalk3.default.bold(agent.displayName));
|
|
995
|
-
console.log(import_chalk3.default.gray(` Name: ${agent.name}`));
|
|
996
|
-
if (skillsDirs.length === 0) {
|
|
997
|
-
console.log(import_chalk3.default.yellow(" \u26A0\uFE0F No directories configured"));
|
|
998
|
-
} else {
|
|
999
|
-
console.log(import_chalk3.default.gray(` Directories${dirsInfo}:`));
|
|
1000
|
-
for (const dir of skillsDirs) {
|
|
1001
|
-
const exists = import_node_fs7.default.existsSync(dir);
|
|
1002
|
-
const status = exists ? import_chalk3.default.green("\u2713") : import_chalk3.default.gray("\u25CB");
|
|
1003
|
-
const pathColor = exists ? import_chalk3.default.white : import_chalk3.default.gray;
|
|
1004
|
-
console.log(` ${status} ${pathColor(dir)}`);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
console.log("");
|
|
1008
|
-
}
|
|
1009
|
-
console.log(import_chalk3.default.bold("\u{1F4E6} Shared Skills Directory:"));
|
|
1010
|
-
const sharedExists = import_node_fs7.default.existsSync(SHARED_SKILLS_DIR);
|
|
1011
|
-
const sharedStatus = sharedExists ? import_chalk3.default.green("\u2713") : import_chalk3.default.gray("\u25CB");
|
|
1012
|
-
const sharedPathColor = sharedExists ? import_chalk3.default.white : import_chalk3.default.gray;
|
|
1013
|
-
console.log(` ${sharedStatus} ${sharedPathColor(SHARED_SKILLS_DIR)}`);
|
|
1014
|
-
console.log("");
|
|
1015
|
-
const home = import_node_os3.default.homedir();
|
|
1016
|
-
if (cwd !== home) {
|
|
1017
|
-
console.log(import_chalk3.default.gray(`Current working directory: ${cwd}`));
|
|
1018
|
-
console.log(import_chalk3.default.gray("(Project-level directories are shown above)\n"));
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
1037
|
// src/index.ts
|
|
1023
1038
|
var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
|
|
1024
1039
|
var __dirname = (0, import_path.dirname)(__filename2);
|
|
@@ -1027,7 +1042,11 @@ var packageJson = JSON.parse((0, import_fs.readFileSync)(packageJsonPath, "utf-8
|
|
|
1027
1042
|
var version = packageJson.version;
|
|
1028
1043
|
var program = new import_commander.Command();
|
|
1029
1044
|
program.name("eskill").description("Unified CLI tool for managing AI agent skills").version(version);
|
|
1030
|
-
program.command("install <skill>").alias("add").description("Install a skill from NPM, Git URL, or local directory").option("-a, --agent <name>", "Install for specific agent (claude, cursor, windsurf, or all)").option("-l, --link", "Dev mode: symlink from local directory").option("-f, --force", "Force reinstall if already exists").option("-r, --registry <url>", "NPM registry URL (overrides .npmrc and global config)").option(
|
|
1045
|
+
program.command("install <skill>").alias("add").description("Install a skill from NPM, Git URL, or local directory").option("-a, --agent <name>", "Install for specific agent (claude, cursor, windsurf, or all)").option("-l, --link", "Dev mode: symlink from local directory").option("-f, --force", "Force reinstall if already exists").option("-r, --registry <url>", "NPM registry URL (overrides .npmrc and global config)").option(
|
|
1046
|
+
"-t, --timeout <ms>",
|
|
1047
|
+
"Timeout in milliseconds (default: 180000 for npm, 120000 for git)",
|
|
1048
|
+
(value) => Number.parseInt(value, 10)
|
|
1049
|
+
).action(async (skill, options) => {
|
|
1031
1050
|
try {
|
|
1032
1051
|
await install(skill, options);
|
|
1033
1052
|
} catch (error) {
|