itismyskillmarket 1.3.25 → 1.3.26
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.js +190 -176
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -135,11 +135,30 @@ var SKILL_SCOPES = process.env.SKM_NPM_SCOPES ? process.env.SKM_NPM_SCOPES.split
|
|
|
135
135
|
var SKM_URL = process.env.SKM_URL || fileConfig.skmUrl || `https://www.npmjs.com/package/${NPM_SCOPE}`;
|
|
136
136
|
|
|
137
137
|
// src/commands/npm.ts
|
|
138
|
+
var npmCache = /* @__PURE__ */ new Map();
|
|
139
|
+
function getCached(key) {
|
|
140
|
+
const entry = npmCache.get(key);
|
|
141
|
+
if (!entry) return null;
|
|
142
|
+
if (Date.now() > entry.expiry) {
|
|
143
|
+
npmCache.delete(key);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return entry.data;
|
|
147
|
+
}
|
|
148
|
+
function setCache(key, data, ttlMs = 3e4) {
|
|
149
|
+
npmCache.set(key, { data, expiry: Date.now() + ttlMs });
|
|
150
|
+
}
|
|
138
151
|
async function fetchNpmPackage(packageName, retries = 1) {
|
|
152
|
+
const cacheKey = `pkg:${packageName}`;
|
|
153
|
+
const cached = getCached(cacheKey);
|
|
154
|
+
if (cached) return cached;
|
|
139
155
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
140
156
|
try {
|
|
141
157
|
const result = await fetchNpmPackageOnce(packageName);
|
|
142
|
-
if (result !== null)
|
|
158
|
+
if (result !== null) {
|
|
159
|
+
setCache(cacheKey, result);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
143
162
|
} catch {
|
|
144
163
|
if (attempt === retries) return null;
|
|
145
164
|
}
|
|
@@ -452,8 +471,8 @@ Status: Not installed (use skm install ${skillId} to install)`);
|
|
|
452
471
|
}
|
|
453
472
|
|
|
454
473
|
// src/commands/install.ts
|
|
455
|
-
import
|
|
456
|
-
import
|
|
474
|
+
import fs9 from "fs-extra";
|
|
475
|
+
import path8 from "path";
|
|
457
476
|
import { exec } from "child_process";
|
|
458
477
|
import { promisify } from "util";
|
|
459
478
|
|
|
@@ -599,52 +618,48 @@ var VSCodeAdapter = class extends BaseAdapter {
|
|
|
599
618
|
};
|
|
600
619
|
|
|
601
620
|
// src/adapters/openclaw.ts
|
|
602
|
-
import
|
|
603
|
-
import
|
|
604
|
-
import
|
|
605
|
-
|
|
606
|
-
var OpenClawAdapter = class {
|
|
621
|
+
import path6 from "path";
|
|
622
|
+
import os6 from "os";
|
|
623
|
+
import fs7 from "fs-extra";
|
|
624
|
+
var OpenClawAdapter = class extends BaseAdapter {
|
|
607
625
|
id = "openclaw";
|
|
608
626
|
name = "OpenClaw";
|
|
609
|
-
skillDir =
|
|
627
|
+
skillDir = path6.join(os6.homedir(), ".openclaw", "skills");
|
|
610
628
|
async isAvailable() {
|
|
611
629
|
try {
|
|
612
|
-
return
|
|
630
|
+
return await fs7.pathExists(path6.join(os6.homedir(), ".openclaw"));
|
|
613
631
|
} catch {
|
|
614
632
|
return false;
|
|
615
633
|
}
|
|
616
634
|
}
|
|
617
635
|
async isInstalled(skillId) {
|
|
618
636
|
try {
|
|
619
|
-
|
|
620
|
-
return existsSync2(skillPath);
|
|
637
|
+
return await fs7.pathExists(path6.join(this.skillDir, skillId));
|
|
621
638
|
} catch {
|
|
622
639
|
return false;
|
|
623
640
|
}
|
|
624
641
|
}
|
|
625
642
|
async install(skillId, sourceDir) {
|
|
626
|
-
|
|
627
|
-
const targetDir =
|
|
628
|
-
if (
|
|
629
|
-
|
|
643
|
+
await fs7.ensureDir(this.skillDir);
|
|
644
|
+
const targetDir = path6.join(this.skillDir, skillId);
|
|
645
|
+
if (await fs7.pathExists(targetDir)) {
|
|
646
|
+
await fs7.remove(targetDir);
|
|
630
647
|
}
|
|
631
|
-
|
|
648
|
+
await fs7.copy(sourceDir, targetDir, { recursive: true });
|
|
632
649
|
}
|
|
633
650
|
async uninstall(skillId) {
|
|
634
|
-
const targetDir =
|
|
635
|
-
if (
|
|
636
|
-
|
|
651
|
+
const targetDir = path6.join(this.skillDir, skillId);
|
|
652
|
+
if (await fs7.pathExists(targetDir)) {
|
|
653
|
+
await fs7.remove(targetDir);
|
|
637
654
|
}
|
|
638
655
|
}
|
|
639
656
|
async listInstalled() {
|
|
640
657
|
try {
|
|
641
|
-
if (!
|
|
658
|
+
if (!await fs7.pathExists(this.skillDir)) {
|
|
642
659
|
return [];
|
|
643
660
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return existsSync2(fullPath) && name !== ".";
|
|
647
|
-
});
|
|
661
|
+
const entries = await fs7.readdir(this.skillDir, { withFileTypes: true });
|
|
662
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
648
663
|
} catch {
|
|
649
664
|
return [];
|
|
650
665
|
}
|
|
@@ -652,55 +667,48 @@ var OpenClawAdapter = class {
|
|
|
652
667
|
};
|
|
653
668
|
|
|
654
669
|
// src/adapters/hermes.ts
|
|
655
|
-
import
|
|
656
|
-
import
|
|
657
|
-
import
|
|
658
|
-
|
|
659
|
-
var HermesAdapter = class {
|
|
670
|
+
import path7 from "path";
|
|
671
|
+
import os7 from "os";
|
|
672
|
+
import fs8 from "fs-extra";
|
|
673
|
+
var HermesAdapter = class extends BaseAdapter {
|
|
660
674
|
id = "hermes";
|
|
661
675
|
name = "Hermes Agent";
|
|
662
|
-
skillDir =
|
|
676
|
+
skillDir = path7.join(os7.homedir(), ".hermes", "skills");
|
|
663
677
|
async isAvailable() {
|
|
664
678
|
try {
|
|
665
|
-
|
|
666
|
-
return true;
|
|
667
|
-
}
|
|
668
|
-
return false;
|
|
679
|
+
return await fs8.pathExists(path7.join(os7.homedir(), ".hermes"));
|
|
669
680
|
} catch {
|
|
670
681
|
return false;
|
|
671
682
|
}
|
|
672
683
|
}
|
|
673
684
|
async isInstalled(skillId) {
|
|
674
685
|
try {
|
|
675
|
-
|
|
676
|
-
return existsSync3(skillPath);
|
|
686
|
+
return await fs8.pathExists(path7.join(this.skillDir, skillId));
|
|
677
687
|
} catch {
|
|
678
688
|
return false;
|
|
679
689
|
}
|
|
680
690
|
}
|
|
681
691
|
async install(skillId, sourceDir) {
|
|
682
|
-
|
|
683
|
-
const targetDir =
|
|
684
|
-
if (
|
|
685
|
-
|
|
692
|
+
await fs8.ensureDir(this.skillDir);
|
|
693
|
+
const targetDir = path7.join(this.skillDir, skillId);
|
|
694
|
+
if (await fs8.pathExists(targetDir)) {
|
|
695
|
+
await fs8.remove(targetDir);
|
|
686
696
|
}
|
|
687
|
-
|
|
697
|
+
await fs8.copy(sourceDir, targetDir, { recursive: true });
|
|
688
698
|
}
|
|
689
699
|
async uninstall(skillId) {
|
|
690
|
-
const targetDir =
|
|
691
|
-
if (
|
|
692
|
-
|
|
700
|
+
const targetDir = path7.join(this.skillDir, skillId);
|
|
701
|
+
if (await fs8.pathExists(targetDir)) {
|
|
702
|
+
await fs8.remove(targetDir);
|
|
693
703
|
}
|
|
694
704
|
}
|
|
695
705
|
async listInstalled() {
|
|
696
706
|
try {
|
|
697
|
-
if (!
|
|
707
|
+
if (!await fs8.pathExists(this.skillDir)) {
|
|
698
708
|
return [];
|
|
699
709
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
return existsSync3(fullPath) && name !== ".";
|
|
703
|
-
});
|
|
710
|
+
const entries = await fs8.readdir(this.skillDir, { withFileTypes: true });
|
|
711
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
704
712
|
} catch {
|
|
705
713
|
return [];
|
|
706
714
|
}
|
|
@@ -766,52 +774,52 @@ async function installSkill(skillId, version, options) {
|
|
|
766
774
|
throw new Error(`No version found for ${packageName}`);
|
|
767
775
|
}
|
|
768
776
|
const cacheDir = getCacheDir();
|
|
769
|
-
const targetDir =
|
|
770
|
-
if (!await
|
|
777
|
+
const targetDir = path8.join(cacheDir, `${packageName}@${targetVersion}`);
|
|
778
|
+
if (!await fs9.pathExists(targetDir)) {
|
|
771
779
|
console.log("Downloading package...");
|
|
772
|
-
await
|
|
780
|
+
await fs9.ensureDir(cacheDir);
|
|
773
781
|
try {
|
|
774
782
|
await execAsync(`npm pack ${packageName}@${targetVersion} --pack-destination ${cacheDir}`);
|
|
775
|
-
const files = await
|
|
783
|
+
const files = await fs9.readdir(cacheDir);
|
|
776
784
|
const tarball = files.find(
|
|
777
785
|
(f) => f.endsWith(".tgz") && f.includes(packageName.replace(/^@/, "").replace("/", "-"))
|
|
778
786
|
);
|
|
779
787
|
if (tarball) {
|
|
780
|
-
await execAsync(`tar -xzf "${
|
|
781
|
-
await
|
|
782
|
-
const extractedDir =
|
|
788
|
+
await execAsync(`tar -xzf "${path8.join(cacheDir, tarball)}" -C "${cacheDir}"`);
|
|
789
|
+
await fs9.remove(path8.join(cacheDir, tarball));
|
|
790
|
+
const extractedDir = path8.join(cacheDir, "package");
|
|
783
791
|
const finalDir = targetDir;
|
|
784
|
-
await
|
|
792
|
+
await fs9.move(extractedDir, finalDir, { overwrite: true });
|
|
785
793
|
}
|
|
786
794
|
} catch (err) {
|
|
787
795
|
throw new Error(`Failed to download package: ${err}`);
|
|
788
796
|
}
|
|
789
797
|
}
|
|
790
798
|
const skillsDir = getSkillsDir();
|
|
791
|
-
const skillVersionDir =
|
|
799
|
+
const skillVersionDir = path8.join(skillsDir, `${skillId}@${targetVersion}`);
|
|
792
800
|
console.log("Setting up skill...");
|
|
793
|
-
await
|
|
801
|
+
await fs9.ensureDir(skillVersionDir);
|
|
794
802
|
const pkgRoot = targetDir;
|
|
795
|
-
if (await
|
|
796
|
-
await
|
|
797
|
-
|
|
798
|
-
|
|
803
|
+
if (await fs9.pathExists(path8.join(pkgRoot, "SKILL.md"))) {
|
|
804
|
+
await fs9.copy(
|
|
805
|
+
path8.join(pkgRoot, "SKILL.md"),
|
|
806
|
+
path8.join(skillVersionDir, "SKILL.md")
|
|
799
807
|
);
|
|
800
808
|
}
|
|
801
|
-
if (await
|
|
802
|
-
await
|
|
803
|
-
|
|
804
|
-
|
|
809
|
+
if (await fs9.pathExists(path8.join(pkgRoot, "metadata.json"))) {
|
|
810
|
+
await fs9.copy(
|
|
811
|
+
path8.join(pkgRoot, "metadata.json"),
|
|
812
|
+
path8.join(skillVersionDir, "metadata.json")
|
|
805
813
|
);
|
|
806
814
|
}
|
|
807
|
-
const skillDir =
|
|
808
|
-
await
|
|
809
|
-
const latestLink =
|
|
815
|
+
const skillDir = path8.join(skillsDir, skillId);
|
|
816
|
+
await fs9.ensureDir(skillDir);
|
|
817
|
+
const latestLink = path8.join(skillDir, LATEST_LINK);
|
|
810
818
|
try {
|
|
811
|
-
await
|
|
812
|
-
await
|
|
819
|
+
await fs9.remove(latestLink);
|
|
820
|
+
await fs9.symlink(skillVersionDir, latestLink, "junction");
|
|
813
821
|
} catch {
|
|
814
|
-
await
|
|
822
|
+
await fs9.copy(skillVersionDir, path8.join(skillDir, LATEST_LINK), { overwrite: true });
|
|
815
823
|
}
|
|
816
824
|
let targetAdapters = [];
|
|
817
825
|
if (options?.platforms && options.platforms.length > 0) {
|
|
@@ -872,8 +880,8 @@ Installing to ${targetAdapters.length} platform(s)...
|
|
|
872
880
|
}
|
|
873
881
|
|
|
874
882
|
// src/commands/sync.ts
|
|
875
|
-
import
|
|
876
|
-
import
|
|
883
|
+
import fs10 from "fs-extra";
|
|
884
|
+
import path9 from "path";
|
|
877
885
|
async function syncPlatformLinks() {
|
|
878
886
|
await ensureMarketDirs();
|
|
879
887
|
const skillsDir = getSkillsDir();
|
|
@@ -881,20 +889,20 @@ async function syncPlatformLinks() {
|
|
|
881
889
|
const registry = await loadRegistry();
|
|
882
890
|
console.log("Syncing platform links...\n");
|
|
883
891
|
for (const platform of PLATFORMS) {
|
|
884
|
-
const platformDir =
|
|
885
|
-
await
|
|
892
|
+
const platformDir = path9.join(platformLinksDir, platform, "skills");
|
|
893
|
+
await fs10.ensureDir(platformDir);
|
|
886
894
|
for (const [skillId, skillInfo] of Object.entries(registry.skills)) {
|
|
887
|
-
const skillLatestLink =
|
|
888
|
-
const targetPlatformDir =
|
|
889
|
-
const platformSkillDir =
|
|
890
|
-
if (await
|
|
891
|
-
if (await
|
|
895
|
+
const skillLatestLink = path9.join(skillsDir, skillId, LATEST_LINK);
|
|
896
|
+
const targetPlatformDir = path9.join(skillLatestLink, platform);
|
|
897
|
+
const platformSkillDir = path9.join(platformDir, skillId);
|
|
898
|
+
if (await fs10.pathExists(skillLatestLink)) {
|
|
899
|
+
if (await fs10.pathExists(targetPlatformDir)) {
|
|
892
900
|
try {
|
|
893
|
-
await
|
|
894
|
-
await
|
|
901
|
+
await fs10.remove(platformSkillDir);
|
|
902
|
+
await fs10.symlink(targetPlatformDir, platformSkillDir, "junction");
|
|
895
903
|
console.log(` Linked: ${platform}/${skillId}`);
|
|
896
904
|
} catch {
|
|
897
|
-
await
|
|
905
|
+
await fs10.copy(targetPlatformDir, platformSkillDir, { overwrite: true });
|
|
898
906
|
console.log(` Copied: ${platform}/${skillId}`);
|
|
899
907
|
}
|
|
900
908
|
}
|
|
@@ -923,11 +931,17 @@ async function syncSkill(skillId) {
|
|
|
923
931
|
// src/commands/update.ts
|
|
924
932
|
async function updateSkill(skillId) {
|
|
925
933
|
if (skillId) {
|
|
926
|
-
const pkgInfo = await
|
|
934
|
+
const pkgInfo = await fetchSkillPackage(skillId);
|
|
927
935
|
if (pkgInfo) {
|
|
928
936
|
const latestVersion = pkgInfo["dist-tags"]?.latest;
|
|
937
|
+
if (!latestVersion) {
|
|
938
|
+
console.log(`No latest version found for ${skillId}.`);
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
929
941
|
console.log(`Updating ${skillId} to ${latestVersion}...`);
|
|
930
942
|
await installSkill(skillId, latestVersion);
|
|
943
|
+
} else {
|
|
944
|
+
console.log(`Skill "${skillId}" not found in any configured scope.`);
|
|
931
945
|
}
|
|
932
946
|
return;
|
|
933
947
|
}
|
|
@@ -940,7 +954,7 @@ async function updateSkill(skillId) {
|
|
|
940
954
|
`);
|
|
941
955
|
let hasUpdates = false;
|
|
942
956
|
for (const skill of installed) {
|
|
943
|
-
const pkgInfo = await
|
|
957
|
+
const pkgInfo = await fetchSkillPackage(skill.id);
|
|
944
958
|
if (pkgInfo) {
|
|
945
959
|
const latestVersion = pkgInfo["dist-tags"]?.latest;
|
|
946
960
|
if (latestVersion && latestVersion !== skill.version) {
|
|
@@ -954,6 +968,8 @@ async function updateSkill(skillId) {
|
|
|
954
968
|
} else {
|
|
955
969
|
console.log(` ${skill.id}: ${skill.version} (up to date)`);
|
|
956
970
|
}
|
|
971
|
+
} else {
|
|
972
|
+
console.log(` ${skill.id}: ${skill.version} (failed to fetch remote)`);
|
|
957
973
|
}
|
|
958
974
|
}
|
|
959
975
|
if (!hasUpdates) {
|
|
@@ -962,8 +978,8 @@ async function updateSkill(skillId) {
|
|
|
962
978
|
}
|
|
963
979
|
|
|
964
980
|
// src/commands/uninstall.ts
|
|
965
|
-
import
|
|
966
|
-
import
|
|
981
|
+
import fs11 from "fs-extra";
|
|
982
|
+
import path10 from "path";
|
|
967
983
|
import readline from "readline";
|
|
968
984
|
async function askConfirmation(message) {
|
|
969
985
|
const rl = readline.createInterface({
|
|
@@ -988,12 +1004,12 @@ async function getUninstallPreview(skillId, options) {
|
|
|
988
1004
|
platformNames = adapters2.map((a) => a.name);
|
|
989
1005
|
}
|
|
990
1006
|
const skillsDir = getSkillsDir();
|
|
991
|
-
const localPath =
|
|
1007
|
+
const localPath = path10.join(skillsDir, skillId);
|
|
992
1008
|
const platformLinksDir = getPlatformLinksDir();
|
|
993
1009
|
const platformLinks = [];
|
|
994
1010
|
for (const platform of PLATFORMS) {
|
|
995
|
-
const linkPath =
|
|
996
|
-
if (await
|
|
1011
|
+
const linkPath = path10.join(platformLinksDir, platform, "skills", skillId);
|
|
1012
|
+
if (await fs11.pathExists(linkPath)) {
|
|
997
1013
|
platformLinks.push(linkPath);
|
|
998
1014
|
}
|
|
999
1015
|
}
|
|
@@ -1072,17 +1088,17 @@ Uninstalling from ${validAdapters.length} platform(s)...
|
|
|
1072
1088
|
}
|
|
1073
1089
|
}
|
|
1074
1090
|
const skillsDir = getSkillsDir();
|
|
1075
|
-
const skillDir =
|
|
1076
|
-
if (await
|
|
1077
|
-
await
|
|
1091
|
+
const skillDir = path10.join(skillsDir, skillId);
|
|
1092
|
+
if (await fs11.pathExists(skillDir)) {
|
|
1093
|
+
await fs11.remove(skillDir);
|
|
1078
1094
|
console.log(`\u2705 Removed local files: ${skillDir}`);
|
|
1079
1095
|
}
|
|
1080
1096
|
const platformLinksDir = getPlatformLinksDir();
|
|
1081
1097
|
let removedLinks = 0;
|
|
1082
1098
|
for (const platform of PLATFORMS) {
|
|
1083
|
-
const linkPath =
|
|
1084
|
-
if (await
|
|
1085
|
-
await
|
|
1099
|
+
const linkPath = path10.join(platformLinksDir, platform, "skills", skillId);
|
|
1100
|
+
if (await fs11.pathExists(linkPath)) {
|
|
1101
|
+
await fs11.remove(linkPath);
|
|
1086
1102
|
removedLinks++;
|
|
1087
1103
|
}
|
|
1088
1104
|
}
|
|
@@ -1152,8 +1168,8 @@ Uninstalling all skills...
|
|
|
1152
1168
|
}
|
|
1153
1169
|
|
|
1154
1170
|
// src/commands/github-install.ts
|
|
1155
|
-
import
|
|
1156
|
-
import
|
|
1171
|
+
import fs12 from "fs-extra";
|
|
1172
|
+
import path11 from "path";
|
|
1157
1173
|
var GITHUB_URL_PATTERNS = [
|
|
1158
1174
|
/^https?:\/\/github\.com\/([^/]+)\/([^/]+)(?:\/tree\/([^/]+)(?:\/(.+))?)?$/,
|
|
1159
1175
|
/^([^/]+)\/([^/]+)(?:#(.+))?$/,
|
|
@@ -1170,13 +1186,13 @@ function parseGitHubUrl(input) {
|
|
|
1170
1186
|
const repo = match[2].replace(/\.git$/, "");
|
|
1171
1187
|
const branch = match[3] || "main";
|
|
1172
1188
|
const commitOrPath = match[4] || match[3];
|
|
1173
|
-
const
|
|
1189
|
+
const path14 = match[5] || void 0;
|
|
1174
1190
|
return {
|
|
1175
1191
|
owner,
|
|
1176
1192
|
repo,
|
|
1177
1193
|
branch: commitOrPath && !commitOrPath.includes("/") ? commitOrPath : branch,
|
|
1178
1194
|
commit: commitOrPath?.match(/^[0-9a-f]{40}$/) ? commitOrPath : void 0,
|
|
1179
|
-
path:
|
|
1195
|
+
path: path14
|
|
1180
1196
|
};
|
|
1181
1197
|
}
|
|
1182
1198
|
}
|
|
@@ -1275,17 +1291,17 @@ async function detectSkillFromGitHub(source) {
|
|
|
1275
1291
|
}
|
|
1276
1292
|
async function generatePlatformAdapters(skillId, existingPlatforms, targetPlatforms, sourceDir) {
|
|
1277
1293
|
const skillsDir = getSkillsDir();
|
|
1278
|
-
const skillVersionDir =
|
|
1294
|
+
const skillVersionDir = path11.join(skillsDir, `${skillId}@github`);
|
|
1279
1295
|
for (const platform of targetPlatforms) {
|
|
1280
1296
|
if (existingPlatforms.includes(platform)) {
|
|
1281
1297
|
continue;
|
|
1282
1298
|
}
|
|
1283
|
-
const platformDir =
|
|
1284
|
-
await
|
|
1285
|
-
const sourceSkillMd =
|
|
1286
|
-
const targetSkillMd =
|
|
1287
|
-
if (await
|
|
1288
|
-
await
|
|
1299
|
+
const platformDir = path11.join(skillVersionDir, platform);
|
|
1300
|
+
await fs12.ensureDir(platformDir);
|
|
1301
|
+
const sourceSkillMd = path11.join(sourceDir, "SKILL.md");
|
|
1302
|
+
const targetSkillMd = path11.join(platformDir, "SKILL.md");
|
|
1303
|
+
if (await fs12.pathExists(sourceSkillMd)) {
|
|
1304
|
+
await fs12.copy(sourceSkillMd, targetSkillMd);
|
|
1289
1305
|
}
|
|
1290
1306
|
if (platform === "opencode" || platform === "cursor" || platform === "codex" || platform === "antigravity") {
|
|
1291
1307
|
} else if (platform === "vscode") {
|
|
@@ -1294,14 +1310,14 @@ async function generatePlatformAdapters(skillId, existingPlatforms, targetPlatfo
|
|
|
1294
1310
|
description: `Skill: ${skillId}`,
|
|
1295
1311
|
version: "1.0.0"
|
|
1296
1312
|
};
|
|
1297
|
-
await
|
|
1313
|
+
await fs12.writeJson(path11.join(platformDir, "skill.json"), skillJson, { spaces: 2 });
|
|
1298
1314
|
} else if (platform === "claude") {
|
|
1299
1315
|
const skillJson = {
|
|
1300
1316
|
name: skillId,
|
|
1301
1317
|
description: `Skill: ${skillId}`,
|
|
1302
1318
|
version: "1.0.0"
|
|
1303
1319
|
};
|
|
1304
|
-
await
|
|
1320
|
+
await fs12.writeJson(path11.join(platformDir, "skill.json"), skillJson, { spaces: 2 });
|
|
1305
1321
|
}
|
|
1306
1322
|
}
|
|
1307
1323
|
}
|
|
@@ -1330,26 +1346,26 @@ async function installFromGitHub(input, options) {
|
|
|
1330
1346
|
Setting up skill: ${skillId}@${version}`);
|
|
1331
1347
|
await ensureMarketDirs();
|
|
1332
1348
|
const skillsDir = getSkillsDir();
|
|
1333
|
-
const skillVersionDir =
|
|
1334
|
-
await
|
|
1349
|
+
const skillVersionDir = path11.join(skillsDir, `${skillId}@${version}`);
|
|
1350
|
+
await fs12.ensureDir(skillVersionDir);
|
|
1335
1351
|
console.log("Downloading files...");
|
|
1336
1352
|
const basePath = source.path || "";
|
|
1337
1353
|
const skillMdPath = basePath ? `${basePath}/SKILL.md` : "SKILL.md";
|
|
1338
1354
|
const skillMdContent = await fetchGitHubFile(source, skillMdPath);
|
|
1339
1355
|
if (skillMdContent) {
|
|
1340
|
-
await
|
|
1356
|
+
await fs12.writeFile(path11.join(skillVersionDir, "SKILL.md"), skillMdContent);
|
|
1341
1357
|
console.log(" \u2705 SKILL.md");
|
|
1342
1358
|
}
|
|
1343
1359
|
const packageJsonPath = basePath ? `${basePath}/package.json` : "package.json";
|
|
1344
1360
|
const packageJsonContent = await fetchGitHubFile(source, packageJsonPath);
|
|
1345
1361
|
if (packageJsonContent) {
|
|
1346
|
-
await
|
|
1362
|
+
await fs12.writeFile(path11.join(skillVersionDir, "package.json"), packageJsonContent);
|
|
1347
1363
|
console.log(" \u2705 package.json");
|
|
1348
1364
|
}
|
|
1349
1365
|
const metadataPath = basePath ? `${basePath}/metadata.json` : "metadata.json";
|
|
1350
1366
|
const metadataContent = await fetchGitHubFile(source, metadataPath);
|
|
1351
1367
|
if (metadataContent) {
|
|
1352
|
-
await
|
|
1368
|
+
await fs12.writeFile(path11.join(skillVersionDir, "metadata.json"), metadataContent);
|
|
1353
1369
|
console.log(" \u2705 metadata.json");
|
|
1354
1370
|
}
|
|
1355
1371
|
const targetPlatforms = options?.platforms || detected.platforms;
|
|
@@ -1361,14 +1377,14 @@ Generating adapters for missing platforms: ${missingPlatforms.join(", ")}`);
|
|
|
1361
1377
|
await generatePlatformAdapters(skillId, existingPlatforms, targetPlatforms, skillVersionDir);
|
|
1362
1378
|
console.log(" \u2705 Platform adapters generated");
|
|
1363
1379
|
}
|
|
1364
|
-
const skillDir =
|
|
1365
|
-
await
|
|
1366
|
-
const latestLink =
|
|
1380
|
+
const skillDir = path11.join(skillsDir, skillId);
|
|
1381
|
+
await fs12.ensureDir(skillDir);
|
|
1382
|
+
const latestLink = path11.join(skillDir, "latest");
|
|
1367
1383
|
try {
|
|
1368
|
-
await
|
|
1369
|
-
await
|
|
1384
|
+
await fs12.remove(latestLink);
|
|
1385
|
+
await fs12.symlink(skillVersionDir, latestLink, "junction");
|
|
1370
1386
|
} catch {
|
|
1371
|
-
await
|
|
1387
|
+
await fs12.copy(skillVersionDir, path11.join(skillDir, "latest"), { overwrite: true });
|
|
1372
1388
|
}
|
|
1373
1389
|
console.log(`
|
|
1374
1390
|
Installing to ${targetPlatforms.length} platform(s)...
|
|
@@ -1401,9 +1417,6 @@ Installing to ${targetPlatforms.length} platform(s)...
|
|
|
1401
1417
|
const failed = results.filter((r) => r.status === "failed").length;
|
|
1402
1418
|
console.log(`
|
|
1403
1419
|
\u{1F4CA} Summary: ${installed} installed, ${skipped} skipped, ${failed} failed`);
|
|
1404
|
-
console.log(`
|
|
1405
|
-
Installing to platforms: ${targetPlatforms.join(", ")}`);
|
|
1406
|
-
console.log(" (Platform installation logic needs to be completed)");
|
|
1407
1420
|
const registry = await loadRegistry();
|
|
1408
1421
|
registry.skills[skillId] = {
|
|
1409
1422
|
id: skillId,
|
|
@@ -1419,15 +1432,15 @@ Installing to platforms: ${targetPlatforms.join(", ")}`);
|
|
|
1419
1432
|
|
|
1420
1433
|
// src/commands/publish.ts
|
|
1421
1434
|
import { execSync } from "child_process";
|
|
1422
|
-
import { existsSync as
|
|
1423
|
-
import { join as
|
|
1435
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1436
|
+
import { join as join2 } from "path";
|
|
1424
1437
|
import { fileURLToPath } from "url";
|
|
1425
1438
|
async function publishSkill(skillName, options) {
|
|
1426
1439
|
const __dirname4 = fileURLToPath(new URL(".", import.meta.url));
|
|
1427
|
-
const projectRoot =
|
|
1428
|
-
const skillDir =
|
|
1440
|
+
const projectRoot = join2(__dirname4, "..", "..");
|
|
1441
|
+
const skillDir = join2(projectRoot, "skills", skillName);
|
|
1429
1442
|
console.log(`Publishing ${skillName}...`);
|
|
1430
|
-
if (!
|
|
1443
|
+
if (!existsSync2(skillDir)) {
|
|
1431
1444
|
throw new Error(`Skill '${skillName}' not found in skills/ directory`);
|
|
1432
1445
|
}
|
|
1433
1446
|
if (!options?.skipInstall) {
|
|
@@ -1467,29 +1480,29 @@ async function publishSkill(skillName, options) {
|
|
|
1467
1480
|
}
|
|
1468
1481
|
|
|
1469
1482
|
// src/commands/verify.ts
|
|
1470
|
-
import
|
|
1471
|
-
import
|
|
1483
|
+
import fs13 from "fs-extra";
|
|
1484
|
+
import path12 from "path";
|
|
1472
1485
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1473
1486
|
var __filename = fileURLToPath2(import.meta.url);
|
|
1474
|
-
var __dirname =
|
|
1487
|
+
var __dirname = path12.dirname(__filename);
|
|
1475
1488
|
async function verifySkill(skillName) {
|
|
1476
1489
|
try {
|
|
1477
1490
|
console.log(`
|
|
1478
1491
|
\u{1F50D} Verifying skill: ${skillName}
|
|
1479
1492
|
`);
|
|
1480
|
-
const skillDir =
|
|
1481
|
-
if (!await
|
|
1493
|
+
const skillDir = path12.join(process.env.HOME || process.env.USERPROFILE || "", ".skillmarket", "skills", skillName);
|
|
1494
|
+
if (!await fs13.pathExists(skillDir)) {
|
|
1482
1495
|
console.error(`\u274C Skill "${skillName}" not found locally.`);
|
|
1483
1496
|
console.log(` Try: skm install ${skillName}`);
|
|
1484
1497
|
process.exit(1);
|
|
1485
1498
|
}
|
|
1486
1499
|
let passed = 0;
|
|
1487
1500
|
let failed = 0;
|
|
1488
|
-
const skillMdPath =
|
|
1489
|
-
if (await
|
|
1501
|
+
const skillMdPath = path12.join(skillDir, "SKILL.md");
|
|
1502
|
+
if (await fs13.pathExists(skillMdPath)) {
|
|
1490
1503
|
console.log(`\u2705 SKILL.md exists`);
|
|
1491
1504
|
passed++;
|
|
1492
|
-
const content = await
|
|
1505
|
+
const content = await fs13.readFile(skillMdPath, "utf-8");
|
|
1493
1506
|
if (content.trim().length > 0) {
|
|
1494
1507
|
console.log(`\u2705 SKILL.md is not empty (${content.length} chars)`);
|
|
1495
1508
|
passed++;
|
|
@@ -1501,12 +1514,12 @@ async function verifySkill(skillName) {
|
|
|
1501
1514
|
console.log(`\u274C SKILL.md not found`);
|
|
1502
1515
|
failed++;
|
|
1503
1516
|
}
|
|
1504
|
-
const pkgPath =
|
|
1505
|
-
if (await
|
|
1517
|
+
const pkgPath = path12.join(skillDir, "package.json");
|
|
1518
|
+
if (await fs13.pathExists(pkgPath)) {
|
|
1506
1519
|
console.log(`\u2705 package.json exists`);
|
|
1507
1520
|
passed++;
|
|
1508
1521
|
try {
|
|
1509
|
-
const pkg = await
|
|
1522
|
+
const pkg = await fs13.readJson(pkgPath);
|
|
1510
1523
|
const requiredFields = ["name", "version", "description"];
|
|
1511
1524
|
for (const field of requiredFields) {
|
|
1512
1525
|
if (pkg[field]) {
|
|
@@ -1524,12 +1537,13 @@ async function verifySkill(skillName) {
|
|
|
1524
1537
|
} else {
|
|
1525
1538
|
console.log(`\u26A0\uFE0F package.json not found (optional for basic skills)`);
|
|
1526
1539
|
}
|
|
1527
|
-
const registryPath =
|
|
1528
|
-
if (await
|
|
1540
|
+
const registryPath = path12.join(process.env.HOME || process.env.USERPROFILE || "", ".skillmarket", "registry.json");
|
|
1541
|
+
if (await fs13.pathExists(registryPath)) {
|
|
1529
1542
|
try {
|
|
1530
|
-
const registry = await
|
|
1531
|
-
|
|
1532
|
-
|
|
1543
|
+
const registry = await fs13.readJson(registryPath);
|
|
1544
|
+
const registered = registry.skills?.[skillName];
|
|
1545
|
+
if (registered) {
|
|
1546
|
+
console.log(`\u2705 Skill registered in registry (v${registered.version})`);
|
|
1533
1547
|
passed++;
|
|
1534
1548
|
} else {
|
|
1535
1549
|
console.log(`\u26A0\uFE0F Skill not found in registry`);
|
|
@@ -1561,8 +1575,8 @@ async function verifySkill(skillName) {
|
|
|
1561
1575
|
|
|
1562
1576
|
// src/commands/ui.ts
|
|
1563
1577
|
import { createServer } from "http";
|
|
1564
|
-
import { readFileSync as readFileSync2, existsSync as
|
|
1565
|
-
import { join as
|
|
1578
|
+
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
|
|
1579
|
+
import { join as join3, extname, dirname } from "path";
|
|
1566
1580
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1567
1581
|
|
|
1568
1582
|
// src/commands/admin.ts
|
|
@@ -2029,9 +2043,9 @@ async function adminAccess(skillId, level) {
|
|
|
2029
2043
|
// src/commands/ui.ts
|
|
2030
2044
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
2031
2045
|
var __dirname2 = dirname(__filename2);
|
|
2032
|
-
var guiDir =
|
|
2046
|
+
var guiDir = join3(__dirname2, "..", "gui");
|
|
2033
2047
|
var cache = /* @__PURE__ */ new Map();
|
|
2034
|
-
function
|
|
2048
|
+
function getCached2(key) {
|
|
2035
2049
|
const entry = cache.get(key);
|
|
2036
2050
|
if (!entry) return null;
|
|
2037
2051
|
if (Date.now() > entry.expiry) {
|
|
@@ -2040,7 +2054,7 @@ function getCached(key) {
|
|
|
2040
2054
|
}
|
|
2041
2055
|
return entry.data;
|
|
2042
2056
|
}
|
|
2043
|
-
function
|
|
2057
|
+
function setCache2(key, data, ttlMs = 6e4) {
|
|
2044
2058
|
cache.set(key, { data, expiry: Date.now() + ttlMs });
|
|
2045
2059
|
}
|
|
2046
2060
|
async function throttledMap(items, fn, concurrency = 3) {
|
|
@@ -2100,7 +2114,7 @@ API_ROUTES.GET["/api/skills"] = async (_req, res, url) => {
|
|
|
2100
2114
|
const sort = url.searchParams.get("sort") || "name";
|
|
2101
2115
|
const platform = url.searchParams.get("platform") || "";
|
|
2102
2116
|
const cacheKey = `search:${search}:limit:${limit}`;
|
|
2103
|
-
let searchResult =
|
|
2117
|
+
let searchResult = getCached2(cacheKey);
|
|
2104
2118
|
if (!searchResult) {
|
|
2105
2119
|
searchResult = await searchSkillmarketPackages({
|
|
2106
2120
|
from: 0,
|
|
@@ -2108,17 +2122,17 @@ API_ROUTES.GET["/api/skills"] = async (_req, res, url) => {
|
|
|
2108
2122
|
// 一次拉取更多,避免分页
|
|
2109
2123
|
keyword: search || void 0
|
|
2110
2124
|
});
|
|
2111
|
-
|
|
2125
|
+
setCache2(cacheKey, searchResult, 3e4);
|
|
2112
2126
|
}
|
|
2113
2127
|
const { packages, total } = searchResult;
|
|
2114
2128
|
let fetchErrors = 0;
|
|
2115
2129
|
const skillDetails = await throttledMap(packages, async (pkgName) => {
|
|
2116
2130
|
try {
|
|
2117
2131
|
const pkgCacheKey = `pkg:${pkgName}`;
|
|
2118
|
-
let info =
|
|
2132
|
+
let info = getCached2(pkgCacheKey);
|
|
2119
2133
|
if (!info) {
|
|
2120
2134
|
info = await fetchNpmPackage(pkgName);
|
|
2121
|
-
if (info)
|
|
2135
|
+
if (info) setCache2(pkgCacheKey, info, 3e4);
|
|
2122
2136
|
}
|
|
2123
2137
|
if (!info) {
|
|
2124
2138
|
fetchErrors++;
|
|
@@ -2252,10 +2266,10 @@ API_ROUTES.GET["/api/skill-info"] = async (_req, res, url) => {
|
|
|
2252
2266
|
return;
|
|
2253
2267
|
}
|
|
2254
2268
|
const cacheKey = `skill-info:${skillName}`;
|
|
2255
|
-
let info =
|
|
2269
|
+
let info = getCached2(cacheKey);
|
|
2256
2270
|
if (!info) {
|
|
2257
2271
|
info = await fetchSkillPackage(skillName);
|
|
2258
|
-
if (info)
|
|
2272
|
+
if (info) setCache2(cacheKey, info, 3e4);
|
|
2259
2273
|
}
|
|
2260
2274
|
if (!info) {
|
|
2261
2275
|
jsonResponse(res, 404, { error: `Skill "${skillName}" not found` });
|
|
@@ -2286,7 +2300,7 @@ API_ROUTES.GET["/api/skill-info"] = async (_req, res, url) => {
|
|
|
2286
2300
|
};
|
|
2287
2301
|
API_ROUTES.GET["/api/version"] = async (_req, res, _url) => {
|
|
2288
2302
|
try {
|
|
2289
|
-
const pkgPath =
|
|
2303
|
+
const pkgPath = join3(__dirname2, "..", "package.json");
|
|
2290
2304
|
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
2291
2305
|
jsonResponse(res, 200, { version: pkg.version || "1.0.0" });
|
|
2292
2306
|
} catch {
|
|
@@ -2524,7 +2538,7 @@ API_ROUTES.POST["/api/update"] = async (req, res, _url) => {
|
|
|
2524
2538
|
}
|
|
2525
2539
|
};
|
|
2526
2540
|
function serveStaticFile(res, filePath) {
|
|
2527
|
-
if (!
|
|
2541
|
+
if (!existsSync3(filePath)) {
|
|
2528
2542
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
2529
2543
|
res.end("Not Found");
|
|
2530
2544
|
return;
|
|
@@ -2557,7 +2571,7 @@ async function handleRequest(req, res) {
|
|
|
2557
2571
|
jsonResponse(res, 404, { error: `Unknown API endpoint: ${method} ${pathname}` });
|
|
2558
2572
|
return;
|
|
2559
2573
|
}
|
|
2560
|
-
const filePath =
|
|
2574
|
+
const filePath = join3(guiDir, pathname === "/" ? "index.html" : pathname);
|
|
2561
2575
|
if (filePath.startsWith(guiDir)) {
|
|
2562
2576
|
serveStaticFile(res, filePath);
|
|
2563
2577
|
} else {
|
|
@@ -2586,9 +2600,9 @@ Press Ctrl+C to stop
|
|
|
2586
2600
|
}
|
|
2587
2601
|
|
|
2588
2602
|
// src/commands/config.ts
|
|
2589
|
-
import
|
|
2590
|
-
import
|
|
2591
|
-
import
|
|
2603
|
+
import path13 from "path";
|
|
2604
|
+
import fs14 from "fs-extra";
|
|
2605
|
+
import os8 from "os";
|
|
2592
2606
|
var CONFIG_DEFINITIONS = [
|
|
2593
2607
|
{
|
|
2594
2608
|
key: "npmScope",
|
|
@@ -2622,13 +2636,13 @@ var CONFIG_DEFINITIONS = [
|
|
|
2622
2636
|
}
|
|
2623
2637
|
];
|
|
2624
2638
|
function getConfigPath() {
|
|
2625
|
-
return
|
|
2639
|
+
return path13.join(os8.homedir(), ".skillmarket", "config.json");
|
|
2626
2640
|
}
|
|
2627
2641
|
async function readConfigFile() {
|
|
2628
2642
|
try {
|
|
2629
2643
|
const configPath = getConfigPath();
|
|
2630
|
-
if (await
|
|
2631
|
-
const data = await
|
|
2644
|
+
if (await fs14.pathExists(configPath)) {
|
|
2645
|
+
const data = await fs14.readJson(configPath);
|
|
2632
2646
|
const valid = {};
|
|
2633
2647
|
for (const def of CONFIG_DEFINITIONS) {
|
|
2634
2648
|
if (data[def.key] !== void 0) {
|
|
@@ -2643,11 +2657,11 @@ async function readConfigFile() {
|
|
|
2643
2657
|
}
|
|
2644
2658
|
async function writeConfigFile(updates) {
|
|
2645
2659
|
const configPath = getConfigPath();
|
|
2646
|
-
await
|
|
2660
|
+
await fs14.ensureDir(path13.dirname(configPath));
|
|
2647
2661
|
let existing = {};
|
|
2648
2662
|
try {
|
|
2649
|
-
if (await
|
|
2650
|
-
existing = await
|
|
2663
|
+
if (await fs14.pathExists(configPath)) {
|
|
2664
|
+
existing = await fs14.readJson(configPath);
|
|
2651
2665
|
}
|
|
2652
2666
|
} catch {
|
|
2653
2667
|
}
|
|
@@ -2657,25 +2671,25 @@ async function writeConfigFile(updates) {
|
|
|
2657
2671
|
delete merged[key];
|
|
2658
2672
|
}
|
|
2659
2673
|
}
|
|
2660
|
-
await
|
|
2674
|
+
await fs14.writeJson(configPath, merged, { spaces: 2 });
|
|
2661
2675
|
return merged;
|
|
2662
2676
|
}
|
|
2663
2677
|
async function removeConfigKeys(keys) {
|
|
2664
2678
|
const configPath = getConfigPath();
|
|
2665
|
-
if (!await
|
|
2679
|
+
if (!await fs14.pathExists(configPath)) return;
|
|
2666
2680
|
try {
|
|
2667
|
-
const existing = await
|
|
2681
|
+
const existing = await fs14.readJson(configPath);
|
|
2668
2682
|
for (const key of keys) {
|
|
2669
2683
|
delete existing[key];
|
|
2670
2684
|
}
|
|
2671
|
-
await
|
|
2685
|
+
await fs14.writeJson(configPath, existing, { spaces: 2 });
|
|
2672
2686
|
} catch {
|
|
2673
2687
|
}
|
|
2674
2688
|
}
|
|
2675
2689
|
async function removeConfigFile() {
|
|
2676
2690
|
const configPath = getConfigPath();
|
|
2677
|
-
if (await
|
|
2678
|
-
await
|
|
2691
|
+
if (await fs14.pathExists(configPath)) {
|
|
2692
|
+
await fs14.remove(configPath);
|
|
2679
2693
|
}
|
|
2680
2694
|
}
|
|
2681
2695
|
async function getAllConfig() {
|