reskill 0.14.0 → 0.16.0
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/README.md +62 -31
- package/README.zh-CN.md +81 -50
- package/dist/cli/commands/completion.d.ts +13 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/index.js +856 -494
- package/dist/core/cache-manager.d.ts +13 -0
- package/dist/core/cache-manager.d.ts.map +1 -1
- package/dist/core/installer.d.ts +9 -0
- package/dist/core/installer.d.ts.map +1 -1
- package/dist/core/lock-manager.d.ts +1 -0
- package/dist/core/lock-manager.d.ts.map +1 -1
- package/dist/core/skill-manager.d.ts +8 -0
- package/dist/core/skill-manager.d.ts.map +1 -1
- package/dist/index.js +301 -239
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/update-notifier.d.ts +49 -0
- package/dist/utils/update-notifier.d.ts.map +1 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -190,12 +190,13 @@ function remove(targetPath) {
|
|
|
190
190
|
}
|
|
191
191
|
function copyDir(src, dest, options) {
|
|
192
192
|
const exclude = options?.exclude || [];
|
|
193
|
+
const excludePrefix = options?.excludePrefix || '_';
|
|
193
194
|
ensureDir(dest);
|
|
194
195
|
const entries = external_node_fs_.readdirSync(src, {
|
|
195
196
|
withFileTypes: true
|
|
196
197
|
});
|
|
197
198
|
for (const entry of entries){
|
|
198
|
-
if (exclude.includes(entry.name)) continue;
|
|
199
|
+
if (exclude.includes(entry.name) || entry.name.startsWith(excludePrefix)) continue;
|
|
199
200
|
const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
|
|
200
201
|
const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
|
|
201
202
|
if (entry.isDirectory()) copyDir(srcPath, destPath, options);
|
|
@@ -272,7 +273,7 @@ function sanitizeName(name) {
|
|
|
272
273
|
if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
|
|
273
274
|
return sanitized;
|
|
274
275
|
}
|
|
275
|
-
const
|
|
276
|
+
const git_execAsync = (0, __WEBPACK_EXTERNAL_MODULE_node_util__.promisify)(__WEBPACK_EXTERNAL_MODULE_node_child_process__.exec);
|
|
276
277
|
class GitCloneError extends Error {
|
|
277
278
|
repoUrl;
|
|
278
279
|
originalError;
|
|
@@ -320,7 +321,7 @@ class GitCloneError extends Error {
|
|
|
320
321
|
}
|
|
321
322
|
}
|
|
322
323
|
async function git(args, cwd) {
|
|
323
|
-
const { stdout } = await
|
|
324
|
+
const { stdout } = await git_execAsync(`git ${args.join(' ')}`, {
|
|
324
325
|
cwd,
|
|
325
326
|
encoding: 'utf-8'
|
|
326
327
|
});
|
|
@@ -454,6 +455,202 @@ function parseGitUrl(url) {
|
|
|
454
455
|
}
|
|
455
456
|
return null;
|
|
456
457
|
}
|
|
458
|
+
const installer_AGENTS_DIR = '.agents';
|
|
459
|
+
const installer_SKILLS_SUBDIR = 'skills';
|
|
460
|
+
const DEFAULT_EXCLUDE_FILES = [
|
|
461
|
+
'README.md',
|
|
462
|
+
'metadata.json',
|
|
463
|
+
'.reskill-commit'
|
|
464
|
+
];
|
|
465
|
+
const EXCLUDE_PREFIX = '_';
|
|
466
|
+
function installer_sanitizeName(name) {
|
|
467
|
+
let sanitized = name.replace(/[/\\:\0]/g, '');
|
|
468
|
+
sanitized = sanitized.replace(/^[.\s]+|[.\s]+$/g, '');
|
|
469
|
+
sanitized = sanitized.replace(/^\.+/, '');
|
|
470
|
+
if (!sanitized || 0 === sanitized.length) sanitized = 'unnamed-skill';
|
|
471
|
+
if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
|
|
472
|
+
return sanitized;
|
|
473
|
+
}
|
|
474
|
+
function installer_isPathSafe(basePath, targetPath) {
|
|
475
|
+
const normalizedBase = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(basePath));
|
|
476
|
+
const normalizedTarget = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(targetPath));
|
|
477
|
+
return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
|
|
478
|
+
}
|
|
479
|
+
function installer_getCanonicalSkillsDir(isGlobal, cwd) {
|
|
480
|
+
const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
|
|
481
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
|
|
482
|
+
}
|
|
483
|
+
function installer_ensureDir(dirPath) {
|
|
484
|
+
if (!external_node_fs_.existsSync(dirPath)) external_node_fs_.mkdirSync(dirPath, {
|
|
485
|
+
recursive: true
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
function installer_remove(targetPath) {
|
|
489
|
+
if (external_node_fs_.existsSync(targetPath)) external_node_fs_.rmSync(targetPath, {
|
|
490
|
+
recursive: true,
|
|
491
|
+
force: true
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
function copyDirectory(src, dest, options) {
|
|
495
|
+
const exclude = new Set(options?.exclude || DEFAULT_EXCLUDE_FILES);
|
|
496
|
+
installer_ensureDir(dest);
|
|
497
|
+
const entries = external_node_fs_.readdirSync(src, {
|
|
498
|
+
withFileTypes: true
|
|
499
|
+
});
|
|
500
|
+
for (const entry of entries){
|
|
501
|
+
if (exclude.has(entry.name) || entry.name.startsWith(EXCLUDE_PREFIX)) continue;
|
|
502
|
+
const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
|
|
503
|
+
const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
|
|
504
|
+
if (entry.isDirectory()) copyDirectory(srcPath, destPath, options);
|
|
505
|
+
else external_node_fs_.copyFileSync(srcPath, destPath);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
async function installer_createSymlink(target, linkPath) {
|
|
509
|
+
try {
|
|
510
|
+
try {
|
|
511
|
+
const stats = external_node_fs_.lstatSync(linkPath);
|
|
512
|
+
if (stats.isSymbolicLink()) {
|
|
513
|
+
const existingTarget = external_node_fs_.readlinkSync(linkPath);
|
|
514
|
+
if (__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(existingTarget) === __WEBPACK_EXTERNAL_MODULE_node_path__.resolve(target)) return true;
|
|
515
|
+
external_node_fs_.rmSync(linkPath);
|
|
516
|
+
} else external_node_fs_.rmSync(linkPath, {
|
|
517
|
+
recursive: true
|
|
518
|
+
});
|
|
519
|
+
} catch (err) {
|
|
520
|
+
if (err && 'object' == typeof err && 'code' in err) {
|
|
521
|
+
if ('ELOOP' === err.code) try {
|
|
522
|
+
external_node_fs_.rmSync(linkPath, {
|
|
523
|
+
force: true
|
|
524
|
+
});
|
|
525
|
+
} catch {}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
|
|
529
|
+
installer_ensureDir(linkDir);
|
|
530
|
+
const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
|
|
531
|
+
const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
|
|
532
|
+
external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
|
|
533
|
+
return true;
|
|
534
|
+
} catch {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
class Installer {
|
|
539
|
+
cwd;
|
|
540
|
+
isGlobal;
|
|
541
|
+
constructor(options = {}){
|
|
542
|
+
this.cwd = options.cwd || process.cwd();
|
|
543
|
+
this.isGlobal = options.global || false;
|
|
544
|
+
}
|
|
545
|
+
getCanonicalPath(skillName) {
|
|
546
|
+
const sanitized = installer_sanitizeName(skillName);
|
|
547
|
+
const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
|
|
548
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
|
|
549
|
+
}
|
|
550
|
+
getAgentSkillPath(skillName, agentType) {
|
|
551
|
+
const agent = getAgentConfig(agentType);
|
|
552
|
+
const sanitized = installer_sanitizeName(skillName);
|
|
553
|
+
const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
554
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
|
|
555
|
+
}
|
|
556
|
+
async installForAgent(sourcePath, skillName, agentType, options = {}) {
|
|
557
|
+
const agent = getAgentConfig(agentType);
|
|
558
|
+
const installMode = options.mode || 'symlink';
|
|
559
|
+
const sanitized = installer_sanitizeName(skillName);
|
|
560
|
+
const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
|
|
561
|
+
const canonicalDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
|
|
562
|
+
const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
563
|
+
const agentDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
|
|
564
|
+
if (!installer_isPathSafe(canonicalBase, canonicalDir)) return {
|
|
565
|
+
success: false,
|
|
566
|
+
path: agentDir,
|
|
567
|
+
mode: installMode,
|
|
568
|
+
error: 'Invalid skill name: potential path traversal detected'
|
|
569
|
+
};
|
|
570
|
+
if (!installer_isPathSafe(agentBase, agentDir)) return {
|
|
571
|
+
success: false,
|
|
572
|
+
path: agentDir,
|
|
573
|
+
mode: installMode,
|
|
574
|
+
error: 'Invalid skill name: potential path traversal detected'
|
|
575
|
+
};
|
|
576
|
+
try {
|
|
577
|
+
if ('copy' === installMode) {
|
|
578
|
+
installer_ensureDir(agentDir);
|
|
579
|
+
installer_remove(agentDir);
|
|
580
|
+
copyDirectory(sourcePath, agentDir);
|
|
581
|
+
return {
|
|
582
|
+
success: true,
|
|
583
|
+
path: agentDir,
|
|
584
|
+
mode: 'copy'
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
installer_ensureDir(canonicalDir);
|
|
588
|
+
installer_remove(canonicalDir);
|
|
589
|
+
copyDirectory(sourcePath, canonicalDir);
|
|
590
|
+
const symlinkCreated = await installer_createSymlink(canonicalDir, agentDir);
|
|
591
|
+
if (!symlinkCreated) {
|
|
592
|
+
try {
|
|
593
|
+
installer_remove(agentDir);
|
|
594
|
+
} catch {}
|
|
595
|
+
installer_ensureDir(agentDir);
|
|
596
|
+
copyDirectory(sourcePath, agentDir);
|
|
597
|
+
return {
|
|
598
|
+
success: true,
|
|
599
|
+
path: agentDir,
|
|
600
|
+
canonicalPath: canonicalDir,
|
|
601
|
+
mode: 'symlink',
|
|
602
|
+
symlinkFailed: true
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
return {
|
|
606
|
+
success: true,
|
|
607
|
+
path: agentDir,
|
|
608
|
+
canonicalPath: canonicalDir,
|
|
609
|
+
mode: 'symlink'
|
|
610
|
+
};
|
|
611
|
+
} catch (error) {
|
|
612
|
+
return {
|
|
613
|
+
success: false,
|
|
614
|
+
path: agentDir,
|
|
615
|
+
mode: installMode,
|
|
616
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
|
|
621
|
+
const results = new Map();
|
|
622
|
+
for (const agent of targetAgents){
|
|
623
|
+
const result = await this.installForAgent(sourcePath, skillName, agent, options);
|
|
624
|
+
results.set(agent, result);
|
|
625
|
+
}
|
|
626
|
+
return results;
|
|
627
|
+
}
|
|
628
|
+
isInstalled(skillName, agentType) {
|
|
629
|
+
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
630
|
+
return external_node_fs_.existsSync(skillPath);
|
|
631
|
+
}
|
|
632
|
+
uninstallFromAgent(skillName, agentType) {
|
|
633
|
+
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
634
|
+
if (!external_node_fs_.existsSync(skillPath)) return false;
|
|
635
|
+
installer_remove(skillPath);
|
|
636
|
+
return true;
|
|
637
|
+
}
|
|
638
|
+
uninstallFromAgents(skillName, targetAgents) {
|
|
639
|
+
const results = new Map();
|
|
640
|
+
for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
|
|
641
|
+
const canonicalPath = this.getCanonicalPath(skillName);
|
|
642
|
+
if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
|
|
643
|
+
return results;
|
|
644
|
+
}
|
|
645
|
+
listInstalledSkills(agentType) {
|
|
646
|
+
const agent = getAgentConfig(agentType);
|
|
647
|
+
const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
648
|
+
if (!external_node_fs_.existsSync(skillsDir)) return [];
|
|
649
|
+
return external_node_fs_.readdirSync(skillsDir, {
|
|
650
|
+
withFileTypes: true
|
|
651
|
+
}).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
457
654
|
class CacheManager {
|
|
458
655
|
cacheDir;
|
|
459
656
|
constructor(cacheDir){
|
|
@@ -526,9 +723,7 @@ class CacheManager {
|
|
|
526
723
|
if (!cached) throw new Error(`Skill ${parsed.raw} version ${version} not found in cache`);
|
|
527
724
|
if (exists(destPath)) remove(destPath);
|
|
528
725
|
copyDir(cached.path, destPath, {
|
|
529
|
-
exclude:
|
|
530
|
-
'.reskill-commit'
|
|
531
|
-
]
|
|
726
|
+
exclude: DEFAULT_EXCLUDE_FILES
|
|
532
727
|
});
|
|
533
728
|
}
|
|
534
729
|
clearSkill(parsed, version) {
|
|
@@ -564,6 +759,31 @@ class CacheManager {
|
|
|
564
759
|
registries
|
|
565
760
|
};
|
|
566
761
|
}
|
|
762
|
+
async getRemoteCommit(repoUrl, ref) {
|
|
763
|
+
const { exec } = await import("node:child_process");
|
|
764
|
+
const { promisify } = await import("node:util");
|
|
765
|
+
const execAsync = promisify(exec);
|
|
766
|
+
try {
|
|
767
|
+
const { stdout } = await execAsync(`git ls-remote ${repoUrl} ${ref}`, {
|
|
768
|
+
encoding: 'utf-8'
|
|
769
|
+
});
|
|
770
|
+
if (stdout.trim()) {
|
|
771
|
+
const [commit] = stdout.trim().split('\t');
|
|
772
|
+
return commit;
|
|
773
|
+
}
|
|
774
|
+
const { stdout: allRefs } = await execAsync(`git ls-remote ${repoUrl}`, {
|
|
775
|
+
encoding: 'utf-8'
|
|
776
|
+
});
|
|
777
|
+
const lines = allRefs.trim().split('\n');
|
|
778
|
+
for (const line of lines){
|
|
779
|
+
const [commit, refPath] = line.split('\t');
|
|
780
|
+
if (refPath === `refs/heads/${ref}` || refPath === `refs/tags/${ref}` || refPath === ref) return commit;
|
|
781
|
+
}
|
|
782
|
+
return '';
|
|
783
|
+
} catch {
|
|
784
|
+
return '';
|
|
785
|
+
}
|
|
786
|
+
}
|
|
567
787
|
}
|
|
568
788
|
const DEFAULT_SKILLS_JSON = {
|
|
569
789
|
skills: {},
|
|
@@ -870,200 +1090,6 @@ class GitResolver {
|
|
|
870
1090
|
};
|
|
871
1091
|
}
|
|
872
1092
|
}
|
|
873
|
-
const installer_AGENTS_DIR = '.agents';
|
|
874
|
-
const installer_SKILLS_SUBDIR = 'skills';
|
|
875
|
-
function installer_sanitizeName(name) {
|
|
876
|
-
let sanitized = name.replace(/[/\\:\0]/g, '');
|
|
877
|
-
sanitized = sanitized.replace(/^[.\s]+|[.\s]+$/g, '');
|
|
878
|
-
sanitized = sanitized.replace(/^\.+/, '');
|
|
879
|
-
if (!sanitized || 0 === sanitized.length) sanitized = 'unnamed-skill';
|
|
880
|
-
if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
|
|
881
|
-
return sanitized;
|
|
882
|
-
}
|
|
883
|
-
function installer_isPathSafe(basePath, targetPath) {
|
|
884
|
-
const normalizedBase = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(basePath));
|
|
885
|
-
const normalizedTarget = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(targetPath));
|
|
886
|
-
return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
|
|
887
|
-
}
|
|
888
|
-
function installer_getCanonicalSkillsDir(isGlobal, cwd) {
|
|
889
|
-
const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
|
|
890
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
|
|
891
|
-
}
|
|
892
|
-
function installer_ensureDir(dirPath) {
|
|
893
|
-
if (!external_node_fs_.existsSync(dirPath)) external_node_fs_.mkdirSync(dirPath, {
|
|
894
|
-
recursive: true
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
function installer_remove(targetPath) {
|
|
898
|
-
if (external_node_fs_.existsSync(targetPath)) external_node_fs_.rmSync(targetPath, {
|
|
899
|
-
recursive: true,
|
|
900
|
-
force: true
|
|
901
|
-
});
|
|
902
|
-
}
|
|
903
|
-
function copyDirectory(src, dest, options) {
|
|
904
|
-
const exclude = new Set(options?.exclude || [
|
|
905
|
-
'README.md',
|
|
906
|
-
'metadata.json',
|
|
907
|
-
'.reskill-commit'
|
|
908
|
-
]);
|
|
909
|
-
installer_ensureDir(dest);
|
|
910
|
-
const entries = external_node_fs_.readdirSync(src, {
|
|
911
|
-
withFileTypes: true
|
|
912
|
-
});
|
|
913
|
-
for (const entry of entries){
|
|
914
|
-
if (exclude.has(entry.name) || entry.name.startsWith('_')) continue;
|
|
915
|
-
const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
|
|
916
|
-
const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
|
|
917
|
-
if (entry.isDirectory()) copyDirectory(srcPath, destPath, options);
|
|
918
|
-
else external_node_fs_.copyFileSync(srcPath, destPath);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
async function installer_createSymlink(target, linkPath) {
|
|
922
|
-
try {
|
|
923
|
-
try {
|
|
924
|
-
const stats = external_node_fs_.lstatSync(linkPath);
|
|
925
|
-
if (stats.isSymbolicLink()) {
|
|
926
|
-
const existingTarget = external_node_fs_.readlinkSync(linkPath);
|
|
927
|
-
if (__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(existingTarget) === __WEBPACK_EXTERNAL_MODULE_node_path__.resolve(target)) return true;
|
|
928
|
-
external_node_fs_.rmSync(linkPath);
|
|
929
|
-
} else external_node_fs_.rmSync(linkPath, {
|
|
930
|
-
recursive: true
|
|
931
|
-
});
|
|
932
|
-
} catch (err) {
|
|
933
|
-
if (err && 'object' == typeof err && 'code' in err) {
|
|
934
|
-
if ('ELOOP' === err.code) try {
|
|
935
|
-
external_node_fs_.rmSync(linkPath, {
|
|
936
|
-
force: true
|
|
937
|
-
});
|
|
938
|
-
} catch {}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
|
|
942
|
-
installer_ensureDir(linkDir);
|
|
943
|
-
const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
|
|
944
|
-
const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
|
|
945
|
-
external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
|
|
946
|
-
return true;
|
|
947
|
-
} catch {
|
|
948
|
-
return false;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
class Installer {
|
|
952
|
-
cwd;
|
|
953
|
-
isGlobal;
|
|
954
|
-
constructor(options = {}){
|
|
955
|
-
this.cwd = options.cwd || process.cwd();
|
|
956
|
-
this.isGlobal = options.global || false;
|
|
957
|
-
}
|
|
958
|
-
getCanonicalPath(skillName) {
|
|
959
|
-
const sanitized = installer_sanitizeName(skillName);
|
|
960
|
-
const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
|
|
961
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
|
|
962
|
-
}
|
|
963
|
-
getAgentSkillPath(skillName, agentType) {
|
|
964
|
-
const agent = getAgentConfig(agentType);
|
|
965
|
-
const sanitized = installer_sanitizeName(skillName);
|
|
966
|
-
const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
967
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
|
|
968
|
-
}
|
|
969
|
-
async installForAgent(sourcePath, skillName, agentType, options = {}) {
|
|
970
|
-
const agent = getAgentConfig(agentType);
|
|
971
|
-
const installMode = options.mode || 'symlink';
|
|
972
|
-
const sanitized = installer_sanitizeName(skillName);
|
|
973
|
-
const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
|
|
974
|
-
const canonicalDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
|
|
975
|
-
const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
976
|
-
const agentDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
|
|
977
|
-
if (!installer_isPathSafe(canonicalBase, canonicalDir)) return {
|
|
978
|
-
success: false,
|
|
979
|
-
path: agentDir,
|
|
980
|
-
mode: installMode,
|
|
981
|
-
error: 'Invalid skill name: potential path traversal detected'
|
|
982
|
-
};
|
|
983
|
-
if (!installer_isPathSafe(agentBase, agentDir)) return {
|
|
984
|
-
success: false,
|
|
985
|
-
path: agentDir,
|
|
986
|
-
mode: installMode,
|
|
987
|
-
error: 'Invalid skill name: potential path traversal detected'
|
|
988
|
-
};
|
|
989
|
-
try {
|
|
990
|
-
if ('copy' === installMode) {
|
|
991
|
-
installer_ensureDir(agentDir);
|
|
992
|
-
installer_remove(agentDir);
|
|
993
|
-
copyDirectory(sourcePath, agentDir);
|
|
994
|
-
return {
|
|
995
|
-
success: true,
|
|
996
|
-
path: agentDir,
|
|
997
|
-
mode: 'copy'
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
installer_ensureDir(canonicalDir);
|
|
1001
|
-
installer_remove(canonicalDir);
|
|
1002
|
-
copyDirectory(sourcePath, canonicalDir);
|
|
1003
|
-
const symlinkCreated = await installer_createSymlink(canonicalDir, agentDir);
|
|
1004
|
-
if (!symlinkCreated) {
|
|
1005
|
-
try {
|
|
1006
|
-
installer_remove(agentDir);
|
|
1007
|
-
} catch {}
|
|
1008
|
-
installer_ensureDir(agentDir);
|
|
1009
|
-
copyDirectory(sourcePath, agentDir);
|
|
1010
|
-
return {
|
|
1011
|
-
success: true,
|
|
1012
|
-
path: agentDir,
|
|
1013
|
-
canonicalPath: canonicalDir,
|
|
1014
|
-
mode: 'symlink',
|
|
1015
|
-
symlinkFailed: true
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
return {
|
|
1019
|
-
success: true,
|
|
1020
|
-
path: agentDir,
|
|
1021
|
-
canonicalPath: canonicalDir,
|
|
1022
|
-
mode: 'symlink'
|
|
1023
|
-
};
|
|
1024
|
-
} catch (error) {
|
|
1025
|
-
return {
|
|
1026
|
-
success: false,
|
|
1027
|
-
path: agentDir,
|
|
1028
|
-
mode: installMode,
|
|
1029
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
|
|
1034
|
-
const results = new Map();
|
|
1035
|
-
for (const agent of targetAgents){
|
|
1036
|
-
const result = await this.installForAgent(sourcePath, skillName, agent, options);
|
|
1037
|
-
results.set(agent, result);
|
|
1038
|
-
}
|
|
1039
|
-
return results;
|
|
1040
|
-
}
|
|
1041
|
-
isInstalled(skillName, agentType) {
|
|
1042
|
-
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
1043
|
-
return external_node_fs_.existsSync(skillPath);
|
|
1044
|
-
}
|
|
1045
|
-
uninstallFromAgent(skillName, agentType) {
|
|
1046
|
-
const skillPath = this.getAgentSkillPath(skillName, agentType);
|
|
1047
|
-
if (!external_node_fs_.existsSync(skillPath)) return false;
|
|
1048
|
-
installer_remove(skillPath);
|
|
1049
|
-
return true;
|
|
1050
|
-
}
|
|
1051
|
-
uninstallFromAgents(skillName, targetAgents) {
|
|
1052
|
-
const results = new Map();
|
|
1053
|
-
for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
|
|
1054
|
-
const canonicalPath = this.getCanonicalPath(skillName);
|
|
1055
|
-
if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
|
|
1056
|
-
return results;
|
|
1057
|
-
}
|
|
1058
|
-
listInstalledSkills(agentType) {
|
|
1059
|
-
const agent = getAgentConfig(agentType);
|
|
1060
|
-
const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
|
|
1061
|
-
if (!external_node_fs_.existsSync(skillsDir)) return [];
|
|
1062
|
-
return external_node_fs_.readdirSync(skillsDir, {
|
|
1063
|
-
withFileTypes: true
|
|
1064
|
-
}).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
1093
|
const LOCKFILE_VERSION = 1;
|
|
1068
1094
|
class LockManager {
|
|
1069
1095
|
projectRoot;
|
|
@@ -1127,6 +1153,7 @@ class LockManager {
|
|
|
1127
1153
|
const lockedSkill = {
|
|
1128
1154
|
source: options.source,
|
|
1129
1155
|
version: options.version,
|
|
1156
|
+
ref: options.ref,
|
|
1130
1157
|
resolved: options.resolved,
|
|
1131
1158
|
commit: options.commit,
|
|
1132
1159
|
installedAt: new Date().toISOString()
|
|
@@ -1164,7 +1191,7 @@ class LockManager {
|
|
|
1164
1191
|
this.lockData = null;
|
|
1165
1192
|
}
|
|
1166
1193
|
}
|
|
1167
|
-
const
|
|
1194
|
+
const logger_logger = {
|
|
1168
1195
|
info (message) {
|
|
1169
1196
|
console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue('ℹ'), message);
|
|
1170
1197
|
},
|
|
@@ -1247,35 +1274,43 @@ class SkillManager {
|
|
|
1247
1274
|
const { force = false, save = true } = options;
|
|
1248
1275
|
const resolved = await this.resolver.resolve(ref);
|
|
1249
1276
|
const { parsed, repoUrl } = resolved;
|
|
1250
|
-
const
|
|
1277
|
+
const gitRef = resolved.ref;
|
|
1251
1278
|
const skillName = parsed.subPath ? __WEBPACK_EXTERNAL_MODULE_node_path__.basename(parsed.subPath) : parsed.repo;
|
|
1252
1279
|
const skillPath = this.getSkillPath(skillName);
|
|
1253
1280
|
if (exists(skillPath) && !force) {
|
|
1254
1281
|
const locked = this.lockManager.get(skillName);
|
|
1255
|
-
|
|
1256
|
-
|
|
1282
|
+
const lockedRef = locked?.ref || locked?.version;
|
|
1283
|
+
if (locked && lockedRef === gitRef) {
|
|
1284
|
+
logger_logger.info(`${skillName}@${gitRef} is already installed`);
|
|
1257
1285
|
const installed = this.getInstalledSkill(skillName);
|
|
1258
1286
|
if (installed) return installed;
|
|
1259
1287
|
}
|
|
1260
1288
|
if (!force) {
|
|
1261
|
-
|
|
1289
|
+
logger_logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
|
|
1262
1290
|
const installed = this.getInstalledSkill(skillName);
|
|
1263
1291
|
if (installed) return installed;
|
|
1264
1292
|
}
|
|
1265
1293
|
}
|
|
1266
|
-
|
|
1267
|
-
let cacheResult = await this.cache.get(parsed,
|
|
1268
|
-
if (cacheResult)
|
|
1294
|
+
logger_logger["package"](`Installing ${skillName}@${gitRef}...`);
|
|
1295
|
+
let cacheResult = await this.cache.get(parsed, gitRef);
|
|
1296
|
+
if (cacheResult) logger_logger.debug(`Using cached ${skillName}@${gitRef}`);
|
|
1269
1297
|
else {
|
|
1270
|
-
|
|
1271
|
-
cacheResult = await this.cache.cache(repoUrl, parsed,
|
|
1298
|
+
logger_logger.debug(`Caching ${skillName}@${gitRef} from ${repoUrl}`);
|
|
1299
|
+
cacheResult = await this.cache.cache(repoUrl, parsed, gitRef, gitRef);
|
|
1272
1300
|
}
|
|
1273
1301
|
ensureDir(this.getInstallDir());
|
|
1274
1302
|
if (exists(skillPath)) remove(skillPath);
|
|
1275
|
-
await this.cache.copyTo(parsed,
|
|
1303
|
+
await this.cache.copyTo(parsed, gitRef, skillPath);
|
|
1304
|
+
let semanticVersion = gitRef;
|
|
1305
|
+
const skillJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(skillPath, 'skill.json');
|
|
1306
|
+
if (exists(skillJsonPath)) try {
|
|
1307
|
+
const skillJson = readJson(skillJsonPath);
|
|
1308
|
+
if (skillJson.version) semanticVersion = skillJson.version;
|
|
1309
|
+
} catch {}
|
|
1276
1310
|
if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
|
|
1277
1311
|
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
|
|
1278
|
-
version,
|
|
1312
|
+
version: semanticVersion,
|
|
1313
|
+
ref: gitRef,
|
|
1279
1314
|
resolved: repoUrl,
|
|
1280
1315
|
commit: cacheResult.commit
|
|
1281
1316
|
});
|
|
@@ -1283,8 +1318,9 @@ class SkillManager {
|
|
|
1283
1318
|
this.config.ensureExists();
|
|
1284
1319
|
this.config.addSkill(skillName, ref);
|
|
1285
1320
|
}
|
|
1321
|
+
const displayVersion = semanticVersion !== gitRef ? `${semanticVersion} (${gitRef})` : gitRef;
|
|
1286
1322
|
const locationHint = this.isGlobal ? '(global)' : '';
|
|
1287
|
-
|
|
1323
|
+
logger_logger.success(`Installed ${skillName}@${displayVersion} to ${skillPath} ${locationHint}`.trim());
|
|
1288
1324
|
const installed = this.getInstalledSkill(skillName);
|
|
1289
1325
|
if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
|
|
1290
1326
|
return installed;
|
|
@@ -1299,7 +1335,7 @@ class SkillManager {
|
|
|
1299
1335
|
});
|
|
1300
1336
|
installed.push(skill);
|
|
1301
1337
|
} catch (error) {
|
|
1302
|
-
|
|
1338
|
+
logger_logger.error(`Failed to install ${name}: ${error.message}`);
|
|
1303
1339
|
}
|
|
1304
1340
|
return installed;
|
|
1305
1341
|
}
|
|
@@ -1307,22 +1343,33 @@ class SkillManager {
|
|
|
1307
1343
|
const skillPath = this.getSkillPath(name);
|
|
1308
1344
|
if (!exists(skillPath)) {
|
|
1309
1345
|
const location = this.isGlobal ? '(global)' : '';
|
|
1310
|
-
|
|
1346
|
+
logger_logger.warn(`Skill ${name} is not installed ${location}`.trim());
|
|
1311
1347
|
return false;
|
|
1312
1348
|
}
|
|
1313
1349
|
remove(skillPath);
|
|
1314
1350
|
if (!this.isGlobal) this.lockManager.remove(name);
|
|
1315
1351
|
if (!this.isGlobal && this.config.exists()) this.config.removeSkill(name);
|
|
1316
1352
|
const locationHint = this.isGlobal ? '(global)' : '';
|
|
1317
|
-
|
|
1353
|
+
logger_logger.success(`Uninstalled ${name} ${locationHint}`.trim());
|
|
1318
1354
|
return true;
|
|
1319
1355
|
}
|
|
1356
|
+
checkNeedsUpdate(name, remoteCommit) {
|
|
1357
|
+
const locked = this.lockManager.get(name);
|
|
1358
|
+
if (!locked?.commit) return true;
|
|
1359
|
+
return locked.commit !== remoteCommit;
|
|
1360
|
+
}
|
|
1320
1361
|
async update(name) {
|
|
1321
1362
|
const updated = [];
|
|
1322
1363
|
if (name) {
|
|
1323
1364
|
const ref = this.config.getSkillRef(name);
|
|
1324
1365
|
if (!ref) {
|
|
1325
|
-
|
|
1366
|
+
logger_logger.error(`Skill ${name} not found in skills.json`);
|
|
1367
|
+
return [];
|
|
1368
|
+
}
|
|
1369
|
+
const resolved = await this.resolver.resolve(ref);
|
|
1370
|
+
const remoteCommit = await this.cache.getRemoteCommit(resolved.repoUrl, resolved.ref);
|
|
1371
|
+
if (!this.checkNeedsUpdate(name, remoteCommit)) {
|
|
1372
|
+
logger_logger.info(`${name} is already up to date`);
|
|
1326
1373
|
return [];
|
|
1327
1374
|
}
|
|
1328
1375
|
const skill = await this.install(ref, {
|
|
@@ -1333,13 +1380,19 @@ class SkillManager {
|
|
|
1333
1380
|
} else {
|
|
1334
1381
|
const skills = this.config.getSkills();
|
|
1335
1382
|
for (const [skillName, ref] of Object.entries(skills))try {
|
|
1383
|
+
const resolved = await this.resolver.resolve(ref);
|
|
1384
|
+
const remoteCommit = await this.cache.getRemoteCommit(resolved.repoUrl, resolved.ref);
|
|
1385
|
+
if (!this.checkNeedsUpdate(skillName, remoteCommit)) {
|
|
1386
|
+
logger_logger.info(`${skillName} is already up to date`);
|
|
1387
|
+
continue;
|
|
1388
|
+
}
|
|
1336
1389
|
const skill = await this.install(ref, {
|
|
1337
1390
|
force: true,
|
|
1338
1391
|
save: false
|
|
1339
1392
|
});
|
|
1340
1393
|
updated.push(skill);
|
|
1341
1394
|
} catch (error) {
|
|
1342
|
-
|
|
1395
|
+
logger_logger.error(`Failed to update ${skillName}: ${error.message}`);
|
|
1343
1396
|
}
|
|
1344
1397
|
}
|
|
1345
1398
|
return updated;
|
|
@@ -1356,7 +1409,7 @@ class SkillManager {
|
|
|
1356
1409
|
const linkPath = this.getSkillPath(skillName);
|
|
1357
1410
|
ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
|
|
1358
1411
|
createSymlink(absolutePath, linkPath);
|
|
1359
|
-
|
|
1412
|
+
logger_logger.success(`Linked ${skillName} → ${absolutePath}`);
|
|
1360
1413
|
return {
|
|
1361
1414
|
name: skillName,
|
|
1362
1415
|
path: linkPath,
|
|
@@ -1368,15 +1421,15 @@ class SkillManager {
|
|
|
1368
1421
|
unlink(name) {
|
|
1369
1422
|
const skillPath = this.getSkillPath(name);
|
|
1370
1423
|
if (!exists(skillPath)) {
|
|
1371
|
-
|
|
1424
|
+
logger_logger.warn(`Skill ${name} is not installed`);
|
|
1372
1425
|
return false;
|
|
1373
1426
|
}
|
|
1374
1427
|
if (!isSymlink(skillPath)) {
|
|
1375
|
-
|
|
1428
|
+
logger_logger.warn(`Skill ${name} is not a linked skill`);
|
|
1376
1429
|
return false;
|
|
1377
1430
|
}
|
|
1378
1431
|
remove(skillPath);
|
|
1379
|
-
|
|
1432
|
+
logger_logger.success(`Unlinked ${name}`);
|
|
1380
1433
|
return true;
|
|
1381
1434
|
}
|
|
1382
1435
|
list() {
|
|
@@ -1446,7 +1499,8 @@ class SkillManager {
|
|
|
1446
1499
|
const skills = this.config.getSkills();
|
|
1447
1500
|
for (const [name, ref] of Object.entries(skills))try {
|
|
1448
1501
|
const locked = this.lockManager.get(name);
|
|
1449
|
-
const
|
|
1502
|
+
const currentRef = locked?.ref || locked?.version || 'unknown';
|
|
1503
|
+
const currentVersion = locked?.version || 'unknown';
|
|
1450
1504
|
const parsed = this.resolver.parseRef(ref);
|
|
1451
1505
|
const repoUrl = this.resolver.buildRepoUrl(parsed);
|
|
1452
1506
|
const latestResolved = await this.resolver.resolveVersion(repoUrl, {
|
|
@@ -1455,15 +1509,15 @@ class SkillManager {
|
|
|
1455
1509
|
raw: 'latest'
|
|
1456
1510
|
});
|
|
1457
1511
|
const latest = latestResolved.ref;
|
|
1458
|
-
const updateAvailable =
|
|
1512
|
+
const updateAvailable = currentRef !== latest && 'unknown' !== currentRef;
|
|
1459
1513
|
results.push({
|
|
1460
1514
|
name,
|
|
1461
|
-
current,
|
|
1515
|
+
current: currentVersion !== currentRef ? `${currentVersion} (${currentRef})` : currentRef,
|
|
1462
1516
|
latest,
|
|
1463
1517
|
updateAvailable
|
|
1464
1518
|
});
|
|
1465
1519
|
} catch (error) {
|
|
1466
|
-
|
|
1520
|
+
logger_logger.debug(`Failed to check ${name}: ${error.message}`);
|
|
1467
1521
|
results.push({
|
|
1468
1522
|
name,
|
|
1469
1523
|
current: 'unknown',
|
|
@@ -1477,16 +1531,22 @@ class SkillManager {
|
|
|
1477
1531
|
const { save = true, mode = 'symlink' } = options;
|
|
1478
1532
|
const resolved = await this.resolver.resolve(ref);
|
|
1479
1533
|
const { parsed, repoUrl } = resolved;
|
|
1480
|
-
const
|
|
1534
|
+
const gitRef = resolved.ref;
|
|
1481
1535
|
const skillName = parsed.subPath ? __WEBPACK_EXTERNAL_MODULE_node_path__.basename(parsed.subPath) : parsed.repo;
|
|
1482
|
-
|
|
1483
|
-
let cacheResult = await this.cache.get(parsed,
|
|
1484
|
-
if (cacheResult)
|
|
1536
|
+
logger_logger["package"](`Installing ${skillName}@${gitRef} to ${targetAgents.length} agent(s)...`);
|
|
1537
|
+
let cacheResult = await this.cache.get(parsed, gitRef);
|
|
1538
|
+
if (cacheResult) logger_logger.debug(`Using cached ${skillName}@${gitRef}`);
|
|
1485
1539
|
else {
|
|
1486
|
-
|
|
1487
|
-
cacheResult = await this.cache.cache(repoUrl, parsed,
|
|
1540
|
+
logger_logger.debug(`Caching ${skillName}@${gitRef} from ${repoUrl}`);
|
|
1541
|
+
cacheResult = await this.cache.cache(repoUrl, parsed, gitRef, gitRef);
|
|
1488
1542
|
}
|
|
1489
|
-
const sourcePath = this.cache.getCachePath(parsed,
|
|
1543
|
+
const sourcePath = this.cache.getCachePath(parsed, gitRef);
|
|
1544
|
+
let semanticVersion = gitRef;
|
|
1545
|
+
const skillJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(sourcePath, 'skill.json');
|
|
1546
|
+
if (exists(skillJsonPath)) try {
|
|
1547
|
+
const skillJson = readJson(skillJsonPath);
|
|
1548
|
+
if (skillJson.version) semanticVersion = skillJson.version;
|
|
1549
|
+
} catch {}
|
|
1490
1550
|
const installer = new Installer({
|
|
1491
1551
|
cwd: this.projectRoot,
|
|
1492
1552
|
global: this.isGlobal
|
|
@@ -1496,7 +1556,8 @@ class SkillManager {
|
|
|
1496
1556
|
});
|
|
1497
1557
|
if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
|
|
1498
1558
|
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
|
|
1499
|
-
version,
|
|
1559
|
+
version: semanticVersion,
|
|
1560
|
+
ref: gitRef,
|
|
1500
1561
|
resolved: repoUrl,
|
|
1501
1562
|
commit: cacheResult.commit
|
|
1502
1563
|
});
|
|
@@ -1506,12 +1567,13 @@ class SkillManager {
|
|
|
1506
1567
|
}
|
|
1507
1568
|
const successCount = Array.from(results.values()).filter((r)=>r.success).length;
|
|
1508
1569
|
const failCount = results.size - successCount;
|
|
1509
|
-
|
|
1510
|
-
|
|
1570
|
+
const displayVersion = semanticVersion !== gitRef ? `${semanticVersion} (${gitRef})` : gitRef;
|
|
1571
|
+
if (0 === failCount) logger_logger.success(`Installed ${skillName}@${displayVersion} to ${successCount} agent(s)`);
|
|
1572
|
+
else logger_logger.warn(`Installed ${skillName}@${displayVersion} to ${successCount} agent(s), ${failCount} failed`);
|
|
1511
1573
|
const skill = {
|
|
1512
1574
|
name: skillName,
|
|
1513
1575
|
path: sourcePath,
|
|
1514
|
-
version,
|
|
1576
|
+
version: semanticVersion,
|
|
1515
1577
|
source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
|
|
1516
1578
|
};
|
|
1517
1579
|
return {
|
|
@@ -1551,7 +1613,7 @@ class SkillManager {
|
|
|
1551
1613
|
if (!this.isGlobal) this.lockManager.remove(name);
|
|
1552
1614
|
if (!this.isGlobal && this.config.exists()) this.config.removeSkill(name);
|
|
1553
1615
|
const successCount = Array.from(results.values()).filter((r)=>r).length;
|
|
1554
|
-
|
|
1616
|
+
logger_logger.success(`Uninstalled ${name} from ${successCount} agent(s)`);
|
|
1555
1617
|
return results;
|
|
1556
1618
|
}
|
|
1557
1619
|
}
|
|
@@ -1698,4 +1760,4 @@ function generateSkillMd(skill) {
|
|
|
1698
1760
|
frontmatter.push('');
|
|
1699
1761
|
return frontmatter.join('\n') + skill.content;
|
|
1700
1762
|
}
|
|
1701
|
-
export { CacheManager, ConfigLoader, DEFAULT_REGISTRIES, GitResolver, Installer, LockManager, SkillManager, SkillValidationError, agents, detectInstalledAgents, generateSkillMd, getAgentConfig, getAgentSkillsDir, getAllAgentTypes, getCanonicalSkillPath, getCanonicalSkillsDir, hasValidSkillMd, isPathSafe, isValidAgentType, logger, parseSkillFromDir, parseSkillMd, parseSkillMdFile, sanitizeName, shortenPath, validateSkillDescription, validateSkillName };
|
|
1763
|
+
export { CacheManager, ConfigLoader, DEFAULT_REGISTRIES, GitResolver, Installer, LockManager, SkillManager, SkillValidationError, agents, detectInstalledAgents, generateSkillMd, getAgentConfig, getAgentSkillsDir, getAllAgentTypes, getCanonicalSkillPath, getCanonicalSkillsDir, hasValidSkillMd, isPathSafe, isValidAgentType, logger_logger as logger, parseSkillFromDir, parseSkillMd, parseSkillMdFile, sanitizeName, shortenPath, validateSkillDescription, validateSkillName };
|