joyskills-cli 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/install.js +22 -12
package/package.json
CHANGED
package/src/commands/install.js
CHANGED
|
@@ -236,10 +236,11 @@ async function resolveAndInstall(skillInput, targetDir, projectRoot, options) {
|
|
|
236
236
|
const pathPart = skillInput.slice(7); // Remove team://
|
|
237
237
|
const parts = pathPart.split('/');
|
|
238
238
|
const registryName = parts[0];
|
|
239
|
-
|
|
239
|
+
// Support sub-path skills: team://registry/subdir/skill-name
|
|
240
|
+
const skillName = parts.slice(1).join('/');
|
|
240
241
|
|
|
241
242
|
if (!registryName || !skillName) {
|
|
242
|
-
throw new Error(`Invalid team:// URL format: ${skillInput}. Expected: team://<registry>/<skill>`);
|
|
243
|
+
throw new Error(`Invalid team:// URL format: ${skillInput}. Expected: team://<registry>/<skill> or team://<registry>/<subdir>/<skill>`);
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
// Get registry path with auto-prompt for missing registries
|
|
@@ -386,7 +387,8 @@ async function tryInstallFromRegistryDir(skillName, registryDirPath, targetDir,
|
|
|
386
387
|
|
|
387
388
|
if (!skill) return false;
|
|
388
389
|
|
|
389
|
-
|
|
390
|
+
// Use skill.name for target path to maintain subdirectory structure
|
|
391
|
+
const targetPath = path.join(targetDir, skill.name);
|
|
390
392
|
copyRecursive(skill.path, targetPath);
|
|
391
393
|
|
|
392
394
|
// Get git commit for the skill source
|
|
@@ -396,7 +398,7 @@ async function tryInstallFromRegistryDir(skillName, registryDirPath, targetDir,
|
|
|
396
398
|
if (!options.global) {
|
|
397
399
|
const lockfileManager = new LockfileManager(projectRoot);
|
|
398
400
|
await lockfileManager.load();
|
|
399
|
-
lockfileManager.updateSkill(
|
|
401
|
+
lockfileManager.updateSkill(skill.name, {
|
|
400
402
|
version: skill.version || '1.0.0',
|
|
401
403
|
source: sourceLabel,
|
|
402
404
|
commit: commitHash,
|
|
@@ -405,7 +407,7 @@ async function tryInstallFromRegistryDir(skillName, registryDirPath, targetDir,
|
|
|
405
407
|
await lockfileManager.save();
|
|
406
408
|
}
|
|
407
409
|
|
|
408
|
-
console.log(chalk.green(`✅ Installed ${
|
|
410
|
+
console.log(chalk.green(`✅ Installed ${skill.name} v${skill.version || '1.0.0'} from ${sourceLabel}`));
|
|
409
411
|
return true;
|
|
410
412
|
}
|
|
411
413
|
}
|
|
@@ -595,7 +597,9 @@ async function installFromGitUrl(gitUrl, targetDir, options, subPath = '') {
|
|
|
595
597
|
}
|
|
596
598
|
|
|
597
599
|
for (const skill of selectedSkills) {
|
|
598
|
-
|
|
600
|
+
// For Git URL installs with subPath, use the last part of subPath as target name
|
|
601
|
+
const targetName = subPath ? subPath.split('/').pop() : skill.name;
|
|
602
|
+
await installSkillFiles(skill, targetDir, targetName);
|
|
599
603
|
}
|
|
600
604
|
|
|
601
605
|
// Update lockfile only for project-level installation (npm-like behavior)
|
|
@@ -603,7 +607,8 @@ async function installFromGitUrl(gitUrl, targetDir, options, subPath = '') {
|
|
|
603
607
|
const lockfileManager = new LockfileManager(process.cwd());
|
|
604
608
|
await lockfileManager.load();
|
|
605
609
|
for (const skill of selectedSkills) {
|
|
606
|
-
|
|
610
|
+
const targetName = subPath ? subPath.split('/').pop() : skill.name;
|
|
611
|
+
lockfileManager.updateSkill(targetName, {
|
|
607
612
|
version: skill.version || '1.0.0',
|
|
608
613
|
source: 'git',
|
|
609
614
|
repository: gitUrl,
|
|
@@ -689,7 +694,10 @@ async function installFromGitHub(owner, repo, skillPath, targetDir, options) {
|
|
|
689
694
|
|
|
690
695
|
// Install selected skills
|
|
691
696
|
for (const skill of selectedSkills) {
|
|
692
|
-
|
|
697
|
+
// For GitHub installs, use the last part of skillPath as target name
|
|
698
|
+
// e.g., "anthropics/skills/pdf" -> install as "pdf", not "skills/pdf"
|
|
699
|
+
const targetName = skillPath ? skillPath.split('/').pop() : skill.name;
|
|
700
|
+
await installSkillFiles(skill, targetDir, targetName);
|
|
693
701
|
}
|
|
694
702
|
|
|
695
703
|
// Update lockfile only for project-level installation (npm-like behavior)
|
|
@@ -697,7 +705,9 @@ async function installFromGitHub(owner, repo, skillPath, targetDir, options) {
|
|
|
697
705
|
const lockfileManager = new LockfileManager(process.cwd());
|
|
698
706
|
await lockfileManager.load();
|
|
699
707
|
for (const skill of selectedSkills) {
|
|
700
|
-
|
|
708
|
+
// Use the same targetName for lockfile consistency
|
|
709
|
+
const targetName = skillPath ? skillPath.split('/').pop() : skill.name;
|
|
710
|
+
lockfileManager.updateSkill(targetName, {
|
|
701
711
|
version: skill.version || '1.0.0',
|
|
702
712
|
source: 'github',
|
|
703
713
|
repository: `${owner}/${repo}`,
|
|
@@ -846,7 +856,7 @@ export async function findSkills(basePath) {
|
|
|
846
856
|
const { name, description, version } = parseSkillMd(skillMdContent);
|
|
847
857
|
|
|
848
858
|
skills.push({
|
|
849
|
-
name: relativePath
|
|
859
|
+
name: relativePath || name || path.basename(dir),
|
|
850
860
|
path: skillPath,
|
|
851
861
|
relativePath,
|
|
852
862
|
description,
|
|
@@ -902,8 +912,8 @@ function formatSize(bytes) {
|
|
|
902
912
|
return (bytes / (1024 * 1024)).toFixed(1) + 'MB';
|
|
903
913
|
}
|
|
904
914
|
|
|
905
|
-
async function installSkillFiles(skill, targetDir) {
|
|
906
|
-
const targetPath = path.join(targetDir, skill.name);
|
|
915
|
+
async function installSkillFiles(skill, targetDir, targetName = null) {
|
|
916
|
+
const targetPath = path.join(targetDir, targetName || skill.name);
|
|
907
917
|
|
|
908
918
|
if (fs.existsSync(targetPath)) {
|
|
909
919
|
fs.rmSync(targetPath, { recursive: true, force: true });
|