@anytio/pspm 0.8.0 → 0.9.2
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/CHANGELOG.md +53 -0
- package/CLI_GUIDE.md +2 -2
- package/README.md +371 -188
- package/dist/index.js +1580 -305
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ import { join, dirname, basename, resolve, relative } from 'path';
|
|
|
5
5
|
import * as ini from 'ini';
|
|
6
6
|
import ignore from 'ignore';
|
|
7
7
|
import { createHash, randomBytes } from 'crypto';
|
|
8
|
-
import * as
|
|
9
|
-
import
|
|
8
|
+
import * as semver2 from 'semver';
|
|
9
|
+
import semver2__default from 'semver';
|
|
10
10
|
import { checkbox } from '@inquirer/prompts';
|
|
11
11
|
import { readFileSync } from 'fs';
|
|
12
12
|
import { fileURLToPath, URL as URL$1 } from 'url';
|
|
@@ -74,7 +74,7 @@ var init_fetcher = __esm({
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
// src/sdk/generated/index.ts
|
|
77
|
-
var getMeUrl, me, getDeleteSkillUrl, deleteSkill, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getDeleteSkillVersionUrl, deleteSkillVersion, getPublishSkillUrl, publishSkill;
|
|
77
|
+
var getMeUrl, me, getExplorePublicSkillsUrl, explorePublicSkills, getDeleteSkillUrl, deleteSkill, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getDeleteSkillVersionUrl, deleteSkillVersion, getPublishSkillUrl, publishSkill;
|
|
78
78
|
var init_generated = __esm({
|
|
79
79
|
"src/sdk/generated/index.ts"() {
|
|
80
80
|
init_fetcher();
|
|
@@ -90,6 +90,25 @@ var init_generated = __esm({
|
|
|
90
90
|
}
|
|
91
91
|
);
|
|
92
92
|
};
|
|
93
|
+
getExplorePublicSkillsUrl = (params) => {
|
|
94
|
+
const normalizedParams = new URLSearchParams();
|
|
95
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
96
|
+
if (value !== void 0) {
|
|
97
|
+
normalizedParams.append(key, value === null ? "null" : value.toString());
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const stringifiedParams = normalizedParams.toString();
|
|
101
|
+
return stringifiedParams.length > 0 ? `/api/skills/-/explore?${stringifiedParams}` : `/api/skills/-/explore`;
|
|
102
|
+
};
|
|
103
|
+
explorePublicSkills = async (params, options) => {
|
|
104
|
+
return customFetch(
|
|
105
|
+
getExplorePublicSkillsUrl(params),
|
|
106
|
+
{
|
|
107
|
+
...options,
|
|
108
|
+
method: "GET"
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
};
|
|
93
112
|
getDeleteSkillUrl = (username, name) => {
|
|
94
113
|
return `/api/skills/@user/${username}/${name}`;
|
|
95
114
|
};
|
|
@@ -239,6 +258,58 @@ async function undeprecateSkillVersion(username, skillName, version3) {
|
|
|
239
258
|
};
|
|
240
259
|
}
|
|
241
260
|
}
|
|
261
|
+
async function listGithubSkillVersions(owner, repo, name) {
|
|
262
|
+
const config2 = getConfig();
|
|
263
|
+
try {
|
|
264
|
+
const response = await fetch(
|
|
265
|
+
`${config2.baseUrl}/api/skills/@github/${owner}/${repo}/${name}/versions`,
|
|
266
|
+
{
|
|
267
|
+
method: "GET",
|
|
268
|
+
headers: {
|
|
269
|
+
"Content-Type": "application/json",
|
|
270
|
+
...config2.apiKey ? { Authorization: `Bearer ${config2.apiKey}` } : {}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
if (!response.ok) {
|
|
275
|
+
const error = await response.text();
|
|
276
|
+
return { status: response.status, error };
|
|
277
|
+
}
|
|
278
|
+
const data = await response.json();
|
|
279
|
+
return { status: response.status, data };
|
|
280
|
+
} catch (error) {
|
|
281
|
+
return {
|
|
282
|
+
status: 500,
|
|
283
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function getGithubSkillVersion(owner, repo, name, version3) {
|
|
288
|
+
const config2 = getConfig();
|
|
289
|
+
try {
|
|
290
|
+
const response = await fetch(
|
|
291
|
+
`${config2.baseUrl}/api/skills/@github/${owner}/${repo}/${name}/versions/${version3}`,
|
|
292
|
+
{
|
|
293
|
+
method: "GET",
|
|
294
|
+
headers: {
|
|
295
|
+
"Content-Type": "application/json",
|
|
296
|
+
...config2.apiKey ? { Authorization: `Bearer ${config2.apiKey}` } : {}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
if (!response.ok) {
|
|
301
|
+
const error = await response.text();
|
|
302
|
+
return { status: response.status, error };
|
|
303
|
+
}
|
|
304
|
+
const data = await response.json();
|
|
305
|
+
return { status: response.status, data };
|
|
306
|
+
} catch (error) {
|
|
307
|
+
return {
|
|
308
|
+
status: 500,
|
|
309
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
242
313
|
async function changeSkillAccess(username, skillName, input) {
|
|
243
314
|
const config2 = getConfig();
|
|
244
315
|
if (!config2) {
|
|
@@ -368,22 +439,54 @@ var init_errors = __esm({
|
|
|
368
439
|
};
|
|
369
440
|
}
|
|
370
441
|
});
|
|
442
|
+
|
|
443
|
+
// src/config.ts
|
|
444
|
+
var config_exports = {};
|
|
445
|
+
__export(config_exports, {
|
|
446
|
+
clearCredentials: () => clearCredentials,
|
|
447
|
+
findProjectConfig: () => findProjectConfig,
|
|
448
|
+
getCacheDir: () => getCacheDir,
|
|
449
|
+
getConfigPath: () => getConfigPath,
|
|
450
|
+
getLegacyLockfilePath: () => getLegacyLockfilePath,
|
|
451
|
+
getLegacySkillsDir: () => getLegacySkillsDir,
|
|
452
|
+
getLockfilePath: () => getLockfilePath,
|
|
453
|
+
getPspmDir: () => getPspmDir,
|
|
454
|
+
getRegistryUrl: () => getRegistryUrl,
|
|
455
|
+
getSkillsDir: () => getSkillsDir,
|
|
456
|
+
getTokenForRegistry: () => getTokenForRegistry,
|
|
457
|
+
isGlobalMode: () => isGlobalMode,
|
|
458
|
+
isLoggedIn: () => isLoggedIn,
|
|
459
|
+
readUserConfig: () => readUserConfig,
|
|
460
|
+
requireApiKey: () => requireApiKey,
|
|
461
|
+
resolveConfig: () => resolveConfig,
|
|
462
|
+
setCredentials: () => setCredentials,
|
|
463
|
+
setGlobalMode: () => setGlobalMode,
|
|
464
|
+
writeUserConfig: () => writeUserConfig
|
|
465
|
+
});
|
|
371
466
|
function getConfigPath() {
|
|
372
467
|
return join(homedir(), ".pspmrc");
|
|
373
468
|
}
|
|
374
469
|
function getLegacyConfigPath() {
|
|
375
470
|
return join(homedir(), ".pspm", "config.json");
|
|
376
471
|
}
|
|
472
|
+
function setGlobalMode(global) {
|
|
473
|
+
_globalMode = global;
|
|
474
|
+
}
|
|
475
|
+
function isGlobalMode() {
|
|
476
|
+
return _globalMode;
|
|
477
|
+
}
|
|
377
478
|
function getPspmDir() {
|
|
479
|
+
if (_globalMode) return join(homedir(), ".pspm");
|
|
378
480
|
return join(process.cwd(), ".pspm");
|
|
379
481
|
}
|
|
380
482
|
function getSkillsDir() {
|
|
381
|
-
return join(
|
|
483
|
+
return join(getPspmDir(), "skills");
|
|
382
484
|
}
|
|
383
485
|
function getCacheDir() {
|
|
384
|
-
return join(
|
|
486
|
+
return join(getPspmDir(), "cache");
|
|
385
487
|
}
|
|
386
488
|
function getLockfilePath() {
|
|
489
|
+
if (_globalMode) return join(homedir(), ".pspm", "pspm-lock.json");
|
|
387
490
|
return join(process.cwd(), "pspm-lock.json");
|
|
388
491
|
}
|
|
389
492
|
function getLegacyLockfilePath() {
|
|
@@ -637,11 +740,12 @@ async function getRegistryUrl() {
|
|
|
637
740
|
const resolved = await resolveConfig();
|
|
638
741
|
return resolved.registryUrl;
|
|
639
742
|
}
|
|
640
|
-
var DEFAULT_REGISTRY_URL;
|
|
743
|
+
var DEFAULT_REGISTRY_URL, _globalMode;
|
|
641
744
|
var init_config = __esm({
|
|
642
745
|
"src/config.ts"() {
|
|
643
746
|
init_errors();
|
|
644
747
|
DEFAULT_REGISTRY_URL = "https://registry.pspm.dev";
|
|
748
|
+
_globalMode = false;
|
|
645
749
|
}
|
|
646
750
|
});
|
|
647
751
|
async function loadIgnorePatterns(cwd = process.cwd()) {
|
|
@@ -734,22 +838,98 @@ var init_manifest = __esm({
|
|
|
734
838
|
PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
|
|
735
839
|
}
|
|
736
840
|
});
|
|
737
|
-
|
|
738
|
-
|
|
841
|
+
var init_integrity2 = __esm({
|
|
842
|
+
"../../packages/shared/pspm-types/src/integrity.ts"() {
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
// ../../packages/shared/pspm-types/src/local.ts
|
|
847
|
+
var init_local = __esm({
|
|
848
|
+
"../../packages/shared/pspm-types/src/local.ts"() {
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
|
|
852
|
+
// ../../packages/shared/pspm-types/src/lockfile.ts
|
|
853
|
+
var init_lockfile2 = __esm({
|
|
854
|
+
"../../packages/shared/pspm-types/src/lockfile.ts"() {
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
// ../../packages/shared/pspm-types/src/manifest.ts
|
|
859
|
+
var init_manifest2 = __esm({
|
|
860
|
+
"../../packages/shared/pspm-types/src/manifest.ts"() {
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
// ../../packages/shared/pspm-types/src/specifier.ts
|
|
865
|
+
function parseRegistrySpecifier(specifier) {
|
|
866
|
+
const match = specifier.match(REGISTRY_SPECIFIER_PATTERN);
|
|
867
|
+
if (!match) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
const namespace = match[1];
|
|
871
|
+
const owner = match[2];
|
|
872
|
+
const name = match[3];
|
|
873
|
+
const subname = match[4];
|
|
874
|
+
const versionRange = match[5];
|
|
875
|
+
if (!owner || !name) {
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
if (namespace === "github" && !subname) {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
if (namespace !== "github" && subname) {
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
return {
|
|
885
|
+
namespace,
|
|
886
|
+
owner,
|
|
887
|
+
name,
|
|
888
|
+
subname: subname || void 0,
|
|
889
|
+
versionRange: versionRange || void 0
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
var REGISTRY_SPECIFIER_PATTERN;
|
|
893
|
+
var init_specifier = __esm({
|
|
894
|
+
"../../packages/shared/pspm-types/src/specifier.ts"() {
|
|
895
|
+
REGISTRY_SPECIFIER_PATTERN = /^@(user|org|github)\/([a-zA-Z0-9_-]+)\/([a-zA-Z0-9._-]+)(?:\/([a-z][a-z0-9-]*))?(?:@(.+))?$/;
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
var init_version = __esm({
|
|
899
|
+
"../../packages/shared/pspm-types/src/version.ts"() {
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
// ../../packages/shared/pspm-types/src/index.ts
|
|
904
|
+
var init_src = __esm({
|
|
905
|
+
"../../packages/shared/pspm-types/src/index.ts"() {
|
|
906
|
+
init_integrity2();
|
|
907
|
+
init_local();
|
|
908
|
+
init_lockfile2();
|
|
909
|
+
init_manifest2();
|
|
910
|
+
init_specifier();
|
|
911
|
+
init_version();
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
function resolveVersion2(range, availableVersions) {
|
|
915
|
+
const sorted = availableVersions.filter((v) => semver2.valid(v)).sort((a, b) => semver2.rcompare(a, b));
|
|
739
916
|
if (!range || range === "latest" || range === "*") {
|
|
740
917
|
return sorted[0] ?? null;
|
|
741
918
|
}
|
|
742
|
-
return
|
|
919
|
+
return semver2.maxSatisfying(sorted, range);
|
|
920
|
+
}
|
|
921
|
+
function isNewerVersion2(a, b) {
|
|
922
|
+
return semver2.gt(a, b);
|
|
743
923
|
}
|
|
744
924
|
function findHighestSatisfying(ranges, availableVersions) {
|
|
745
|
-
const sorted = availableVersions.filter((v) =>
|
|
925
|
+
const sorted = availableVersions.filter((v) => semver2.valid(v)).sort((a, b) => semver2.rcompare(a, b));
|
|
746
926
|
if (sorted.length === 0) return null;
|
|
747
927
|
const normalizedRanges = ranges.map(
|
|
748
928
|
(r) => !r || r === "latest" || r === "*" ? "*" : r
|
|
749
929
|
);
|
|
750
930
|
for (const version3 of sorted) {
|
|
751
931
|
const satisfiesAll = normalizedRanges.every(
|
|
752
|
-
(range) =>
|
|
932
|
+
(range) => semver2.satisfies(version3, range)
|
|
753
933
|
);
|
|
754
934
|
if (satisfiesAll) {
|
|
755
935
|
return version3;
|
|
@@ -757,7 +937,7 @@ function findHighestSatisfying(ranges, availableVersions) {
|
|
|
757
937
|
}
|
|
758
938
|
return null;
|
|
759
939
|
}
|
|
760
|
-
var
|
|
940
|
+
var init_version2 = __esm({
|
|
761
941
|
"src/lib/version.ts"() {
|
|
762
942
|
}
|
|
763
943
|
});
|
|
@@ -820,8 +1000,8 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
820
1000
|
continue;
|
|
821
1001
|
}
|
|
822
1002
|
processing.add(name);
|
|
823
|
-
const
|
|
824
|
-
if (!
|
|
1003
|
+
const parsed = parseRegistrySpecifier(name);
|
|
1004
|
+
if (!parsed) {
|
|
825
1005
|
graph.errors.push({
|
|
826
1006
|
type: "package_not_found",
|
|
827
1007
|
package: name,
|
|
@@ -829,10 +1009,23 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
829
1009
|
});
|
|
830
1010
|
continue;
|
|
831
1011
|
}
|
|
832
|
-
const [, username, skillName] = match;
|
|
833
1012
|
try {
|
|
834
|
-
|
|
835
|
-
|
|
1013
|
+
let versionsData;
|
|
1014
|
+
let versionsStatus;
|
|
1015
|
+
if (parsed.namespace === "github" && parsed.subname) {
|
|
1016
|
+
const resp = await listGithubSkillVersions(
|
|
1017
|
+
parsed.owner,
|
|
1018
|
+
parsed.name,
|
|
1019
|
+
parsed.subname
|
|
1020
|
+
);
|
|
1021
|
+
versionsStatus = resp.status;
|
|
1022
|
+
versionsData = resp.data;
|
|
1023
|
+
} else {
|
|
1024
|
+
const resp = await listSkillVersions(parsed.owner, parsed.name);
|
|
1025
|
+
versionsStatus = resp.status;
|
|
1026
|
+
versionsData = resp.status === 200 ? resp.data : void 0;
|
|
1027
|
+
}
|
|
1028
|
+
if (versionsStatus !== 200 || !versionsData) {
|
|
836
1029
|
graph.errors.push({
|
|
837
1030
|
type: "package_not_found",
|
|
838
1031
|
package: name,
|
|
@@ -840,8 +1033,7 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
840
1033
|
});
|
|
841
1034
|
continue;
|
|
842
1035
|
}
|
|
843
|
-
|
|
844
|
-
if (versions.length === 0) {
|
|
1036
|
+
if (versionsData.length === 0) {
|
|
845
1037
|
graph.errors.push({
|
|
846
1038
|
type: "package_not_found",
|
|
847
1039
|
package: name,
|
|
@@ -849,7 +1041,7 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
849
1041
|
});
|
|
850
1042
|
continue;
|
|
851
1043
|
}
|
|
852
|
-
const availableVersions =
|
|
1044
|
+
const availableVersions = versionsData.map((v) => v.version);
|
|
853
1045
|
const resolvedVersion = findHighestSatisfying(
|
|
854
1046
|
[versionRange],
|
|
855
1047
|
availableVersions
|
|
@@ -862,12 +1054,28 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
862
1054
|
});
|
|
863
1055
|
continue;
|
|
864
1056
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1057
|
+
let versionData = null;
|
|
1058
|
+
if (parsed.namespace === "github" && parsed.subname) {
|
|
1059
|
+
const resp = await getGithubSkillVersion(
|
|
1060
|
+
parsed.owner,
|
|
1061
|
+
parsed.name,
|
|
1062
|
+
parsed.subname,
|
|
1063
|
+
resolvedVersion
|
|
1064
|
+
);
|
|
1065
|
+
if (resp.status === 200 && resp.data) {
|
|
1066
|
+
versionData = resp.data;
|
|
1067
|
+
}
|
|
1068
|
+
} else {
|
|
1069
|
+
const resp = await getSkillVersion(
|
|
1070
|
+
parsed.owner,
|
|
1071
|
+
parsed.name,
|
|
1072
|
+
resolvedVersion
|
|
1073
|
+
);
|
|
1074
|
+
if (resp.status === 200 && resp.data) {
|
|
1075
|
+
versionData = resp.data;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (!versionData) {
|
|
871
1079
|
graph.errors.push({
|
|
872
1080
|
type: "fetch_error",
|
|
873
1081
|
package: name,
|
|
@@ -875,20 +1083,19 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
875
1083
|
});
|
|
876
1084
|
continue;
|
|
877
1085
|
}
|
|
878
|
-
const
|
|
879
|
-
const manifest = versionInfo.manifest;
|
|
1086
|
+
const manifest = versionData.manifest;
|
|
880
1087
|
const dependencies = manifest?.dependencies ?? {};
|
|
881
1088
|
const node = {
|
|
882
1089
|
name,
|
|
883
1090
|
version: resolvedVersion,
|
|
884
1091
|
versionRange,
|
|
885
|
-
downloadUrl:
|
|
886
|
-
integrity: `sha256-${Buffer.from(
|
|
1092
|
+
downloadUrl: versionData.downloadUrl,
|
|
1093
|
+
integrity: `sha256-${Buffer.from(versionData.checksum, "hex").toString("base64")}`,
|
|
887
1094
|
depth,
|
|
888
1095
|
dependencies,
|
|
889
1096
|
dependents: [dependent],
|
|
890
1097
|
isDirect: depth === 0,
|
|
891
|
-
deprecated:
|
|
1098
|
+
deprecated: versionData.deprecationMessage ?? void 0
|
|
892
1099
|
};
|
|
893
1100
|
graph.nodes.set(name, node);
|
|
894
1101
|
for (const [depName, depRange] of Object.entries(dependencies)) {
|
|
@@ -915,14 +1122,23 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
915
1122
|
const uniqueDependents = [...new Set(ranges.map((r) => r.dependent))];
|
|
916
1123
|
node.dependents = uniqueDependents;
|
|
917
1124
|
const allRanges = ranges.map((r) => r.range);
|
|
918
|
-
const
|
|
919
|
-
if (!
|
|
920
|
-
const [, username, skillName] = match;
|
|
1125
|
+
const p2Parsed = parseRegistrySpecifier(name);
|
|
1126
|
+
if (!p2Parsed) continue;
|
|
921
1127
|
try {
|
|
922
|
-
|
|
923
|
-
if (
|
|
924
|
-
|
|
925
|
-
|
|
1128
|
+
let p2Versions;
|
|
1129
|
+
if (p2Parsed.namespace === "github" && p2Parsed.subname) {
|
|
1130
|
+
const resp = await listGithubSkillVersions(
|
|
1131
|
+
p2Parsed.owner,
|
|
1132
|
+
p2Parsed.name,
|
|
1133
|
+
p2Parsed.subname
|
|
1134
|
+
);
|
|
1135
|
+
p2Versions = resp.status === 200 ? resp.data : void 0;
|
|
1136
|
+
} else {
|
|
1137
|
+
const resp = await listSkillVersions(p2Parsed.owner, p2Parsed.name);
|
|
1138
|
+
p2Versions = resp.status === 200 ? resp.data : void 0;
|
|
1139
|
+
}
|
|
1140
|
+
if (!p2Versions) continue;
|
|
1141
|
+
const availableVersions = p2Versions.map((v) => v.version);
|
|
926
1142
|
const finalVersion = findHighestSatisfying(allRanges, availableVersions);
|
|
927
1143
|
if (!finalVersion) {
|
|
928
1144
|
graph.conflicts.push({
|
|
@@ -941,18 +1157,33 @@ async function resolveRecursive(rootDeps, config2) {
|
|
|
941
1157
|
continue;
|
|
942
1158
|
}
|
|
943
1159
|
if (finalVersion !== node.version) {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1160
|
+
let p2VersionData = null;
|
|
1161
|
+
if (p2Parsed.namespace === "github" && p2Parsed.subname) {
|
|
1162
|
+
const resp = await getGithubSkillVersion(
|
|
1163
|
+
p2Parsed.owner,
|
|
1164
|
+
p2Parsed.name,
|
|
1165
|
+
p2Parsed.subname,
|
|
1166
|
+
finalVersion
|
|
1167
|
+
);
|
|
1168
|
+
if (resp.status === 200 && resp.data) {
|
|
1169
|
+
p2VersionData = resp.data;
|
|
1170
|
+
}
|
|
1171
|
+
} else {
|
|
1172
|
+
const resp = await getSkillVersion(
|
|
1173
|
+
p2Parsed.owner,
|
|
1174
|
+
p2Parsed.name,
|
|
1175
|
+
finalVersion
|
|
1176
|
+
);
|
|
1177
|
+
if (resp.status === 200 && resp.data) {
|
|
1178
|
+
p2VersionData = resp.data;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
if (p2VersionData) {
|
|
951
1182
|
node.version = finalVersion;
|
|
952
|
-
node.downloadUrl =
|
|
953
|
-
node.integrity = `sha256-${Buffer.from(
|
|
954
|
-
node.deprecated =
|
|
955
|
-
const manifest =
|
|
1183
|
+
node.downloadUrl = p2VersionData.downloadUrl;
|
|
1184
|
+
node.integrity = `sha256-${Buffer.from(p2VersionData.checksum, "hex").toString("base64")}`;
|
|
1185
|
+
node.deprecated = p2VersionData.deprecationMessage ?? void 0;
|
|
1186
|
+
const manifest = p2VersionData.manifest;
|
|
956
1187
|
node.dependencies = manifest?.dependencies ?? {};
|
|
957
1188
|
}
|
|
958
1189
|
}
|
|
@@ -1067,30 +1298,55 @@ function printResolutionErrors(errors, conflicts = []) {
|
|
|
1067
1298
|
var MAX_DEPENDENCY_DEPTH;
|
|
1068
1299
|
var init_resolver = __esm({
|
|
1069
1300
|
"src/lib/resolver.ts"() {
|
|
1301
|
+
init_src();
|
|
1070
1302
|
init_api_client();
|
|
1071
|
-
|
|
1303
|
+
init_version2();
|
|
1072
1304
|
MAX_DEPENDENCY_DEPTH = 5;
|
|
1073
1305
|
}
|
|
1074
1306
|
});
|
|
1075
1307
|
|
|
1076
1308
|
// src/lib/specifier.ts
|
|
1077
|
-
function
|
|
1078
|
-
const match = specifier.match(
|
|
1309
|
+
function parseRegistrySpecifier2(specifier) {
|
|
1310
|
+
const match = specifier.match(REGISTRY_SPECIFIER_PATTERN2);
|
|
1079
1311
|
if (!match) {
|
|
1080
1312
|
return null;
|
|
1081
1313
|
}
|
|
1082
|
-
const
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1314
|
+
const namespace = match[1];
|
|
1315
|
+
const owner = match[2];
|
|
1316
|
+
const name = match[3];
|
|
1317
|
+
const subname = match[4];
|
|
1318
|
+
const versionRange = match[5];
|
|
1319
|
+
if (!owner || !name) {
|
|
1320
|
+
return null;
|
|
1321
|
+
}
|
|
1322
|
+
if (namespace === "github" && !subname) {
|
|
1323
|
+
return null;
|
|
1324
|
+
}
|
|
1325
|
+
if (namespace !== "github" && subname) {
|
|
1085
1326
|
return null;
|
|
1086
1327
|
}
|
|
1087
1328
|
return {
|
|
1088
|
-
|
|
1329
|
+
namespace,
|
|
1330
|
+
owner,
|
|
1089
1331
|
name,
|
|
1090
|
-
|
|
1332
|
+
subname: subname || void 0,
|
|
1333
|
+
versionRange: versionRange || void 0
|
|
1091
1334
|
};
|
|
1092
1335
|
}
|
|
1093
|
-
function
|
|
1336
|
+
function generateRegistryIdentifier2(spec) {
|
|
1337
|
+
let base = `@${spec.namespace}/${spec.owner}/${spec.name}`;
|
|
1338
|
+
if (spec.subname) {
|
|
1339
|
+
base += `/${spec.subname}`;
|
|
1340
|
+
}
|
|
1341
|
+
if (spec.versionRange) {
|
|
1342
|
+
base += `@${spec.versionRange}`;
|
|
1343
|
+
}
|
|
1344
|
+
return base;
|
|
1345
|
+
}
|
|
1346
|
+
function isRegistrySpecifier2(specifier) {
|
|
1347
|
+
return specifier.startsWith("@user/") || specifier.startsWith("@org/") || specifier.startsWith("@github/");
|
|
1348
|
+
}
|
|
1349
|
+
function parseGitHubSpecifier2(specifier) {
|
|
1094
1350
|
const match = specifier.match(GITHUB_SPECIFIER_PATTERN);
|
|
1095
1351
|
if (!match) {
|
|
1096
1352
|
return null;
|
|
@@ -1107,7 +1363,7 @@ function parseGitHubSpecifier(specifier) {
|
|
|
1107
1363
|
ref: ref || void 0
|
|
1108
1364
|
};
|
|
1109
1365
|
}
|
|
1110
|
-
function
|
|
1366
|
+
function formatGitHubSpecifier2(spec) {
|
|
1111
1367
|
let result = `github:${spec.owner}/${spec.repo}`;
|
|
1112
1368
|
if (spec.path) {
|
|
1113
1369
|
result += `/${spec.path}`;
|
|
@@ -1117,7 +1373,7 @@ function formatGitHubSpecifier(spec) {
|
|
|
1117
1373
|
}
|
|
1118
1374
|
return result;
|
|
1119
1375
|
}
|
|
1120
|
-
function
|
|
1376
|
+
function getGitHubSkillName2(spec) {
|
|
1121
1377
|
if (spec.path) {
|
|
1122
1378
|
const segments = spec.path.split("/").filter(Boolean);
|
|
1123
1379
|
const lastSegment = segments[segments.length - 1];
|
|
@@ -1127,14 +1383,60 @@ function getGitHubSkillName(spec) {
|
|
|
1127
1383
|
}
|
|
1128
1384
|
return spec.repo;
|
|
1129
1385
|
}
|
|
1130
|
-
function
|
|
1386
|
+
function isGitHubSpecifier2(specifier) {
|
|
1131
1387
|
return specifier.startsWith("github:");
|
|
1132
1388
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1389
|
+
function isGitHubUrl(input) {
|
|
1390
|
+
return /^https?:\/\/github\.com\/[^/]+\/[^/]+/.test(input);
|
|
1391
|
+
}
|
|
1392
|
+
function parseGitHubUrl(input) {
|
|
1393
|
+
const treeMatch = input.match(GITHUB_URL_TREE_PATTERN);
|
|
1394
|
+
if (treeMatch) {
|
|
1395
|
+
const [, owner, repo, ref, path] = treeMatch;
|
|
1396
|
+
if (!owner || !repo || !ref) return null;
|
|
1397
|
+
return {
|
|
1398
|
+
owner,
|
|
1399
|
+
repo,
|
|
1400
|
+
ref,
|
|
1401
|
+
path: path || void 0
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
const repoMatch = input.match(GITHUB_URL_PATTERN);
|
|
1405
|
+
if (repoMatch) {
|
|
1406
|
+
const [, owner, repo] = repoMatch;
|
|
1407
|
+
if (!owner || !repo) return null;
|
|
1408
|
+
return { owner, repo };
|
|
1409
|
+
}
|
|
1410
|
+
return null;
|
|
1411
|
+
}
|
|
1412
|
+
function isGitHubShorthand(input) {
|
|
1413
|
+
if (input.includes(":") || input.startsWith(".") || input.startsWith("/") || input.startsWith("@")) {
|
|
1414
|
+
return false;
|
|
1415
|
+
}
|
|
1416
|
+
return GITHUB_SHORTHAND_PATTERN.test(input);
|
|
1417
|
+
}
|
|
1418
|
+
function parseGitHubShorthand(input) {
|
|
1419
|
+
if (input.includes(":") || input.startsWith(".") || input.startsWith("/") || input.startsWith("@")) {
|
|
1420
|
+
return null;
|
|
1421
|
+
}
|
|
1422
|
+
const match = input.match(GITHUB_SHORTHAND_PATTERN);
|
|
1423
|
+
if (!match) return null;
|
|
1424
|
+
const [, owner, repo, path] = match;
|
|
1425
|
+
if (!owner || !repo) return null;
|
|
1426
|
+
return {
|
|
1427
|
+
owner,
|
|
1428
|
+
repo,
|
|
1429
|
+
path: path || void 0
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
var REGISTRY_SPECIFIER_PATTERN2, GITHUB_SPECIFIER_PATTERN, GITHUB_URL_TREE_PATTERN, GITHUB_URL_PATTERN, GITHUB_SHORTHAND_PATTERN;
|
|
1433
|
+
var init_specifier2 = __esm({
|
|
1135
1434
|
"src/lib/specifier.ts"() {
|
|
1136
|
-
|
|
1435
|
+
REGISTRY_SPECIFIER_PATTERN2 = /^@(user|org|github)\/([a-zA-Z0-9_-]+)\/([a-zA-Z0-9._-]+)(?:\/([a-z][a-z0-9-]*))?(?:@(.+))?$/;
|
|
1137
1436
|
GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
|
|
1437
|
+
GITHUB_URL_TREE_PATTERN = /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)(?:\/(.+))?$/;
|
|
1438
|
+
GITHUB_URL_PATTERN = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/;
|
|
1439
|
+
GITHUB_SHORTHAND_PATTERN = /^([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(?:\/(.+))?$/;
|
|
1138
1440
|
}
|
|
1139
1441
|
});
|
|
1140
1442
|
|
|
@@ -1146,16 +1448,19 @@ var init_lib = __esm({
|
|
|
1146
1448
|
init_lockfile();
|
|
1147
1449
|
init_manifest();
|
|
1148
1450
|
init_resolver();
|
|
1149
|
-
|
|
1150
|
-
|
|
1451
|
+
init_specifier2();
|
|
1452
|
+
init_version2();
|
|
1151
1453
|
}
|
|
1152
1454
|
});
|
|
1153
|
-
function resolveAgentConfig(name, overrides) {
|
|
1154
|
-
if (overrides?.[name]) {
|
|
1455
|
+
function resolveAgentConfig(name, overrides, global) {
|
|
1456
|
+
if (!global && overrides?.[name]) {
|
|
1155
1457
|
return overrides[name];
|
|
1156
1458
|
}
|
|
1157
|
-
if (name in
|
|
1158
|
-
|
|
1459
|
+
if (name in AGENT_INFO) {
|
|
1460
|
+
const info = AGENT_INFO[name];
|
|
1461
|
+
return {
|
|
1462
|
+
skillsDir: global ? info.globalSkillsDir : info.skillsDir
|
|
1463
|
+
};
|
|
1159
1464
|
}
|
|
1160
1465
|
return null;
|
|
1161
1466
|
}
|
|
@@ -1193,47 +1498,221 @@ var AGENT_INFO, DEFAULT_AGENT_CONFIGS, ALL_AGENTS;
|
|
|
1193
1498
|
var init_agents = __esm({
|
|
1194
1499
|
"src/agents.ts"() {
|
|
1195
1500
|
AGENT_INFO = {
|
|
1501
|
+
adal: {
|
|
1502
|
+
displayName: "AdaL",
|
|
1503
|
+
skillsDir: ".adal/skills",
|
|
1504
|
+
globalSkillsDir: ".adal/skills"
|
|
1505
|
+
},
|
|
1506
|
+
amp: {
|
|
1507
|
+
displayName: "Amp",
|
|
1508
|
+
skillsDir: ".agents/skills",
|
|
1509
|
+
globalSkillsDir: ".config/agents/skills"
|
|
1510
|
+
},
|
|
1511
|
+
antigravity: {
|
|
1512
|
+
displayName: "Antigravity",
|
|
1513
|
+
skillsDir: ".agent/skills",
|
|
1514
|
+
globalSkillsDir: ".gemini/antigravity/skills"
|
|
1515
|
+
},
|
|
1516
|
+
augment: {
|
|
1517
|
+
displayName: "Augment",
|
|
1518
|
+
skillsDir: ".augment/skills",
|
|
1519
|
+
globalSkillsDir: ".augment/skills"
|
|
1520
|
+
},
|
|
1196
1521
|
"claude-code": {
|
|
1197
1522
|
displayName: "Claude Code",
|
|
1198
|
-
skillsDir: ".claude/skills"
|
|
1523
|
+
skillsDir: ".claude/skills",
|
|
1524
|
+
globalSkillsDir: ".claude/skills"
|
|
1525
|
+
},
|
|
1526
|
+
cline: {
|
|
1527
|
+
displayName: "Cline",
|
|
1528
|
+
skillsDir: ".agents/skills",
|
|
1529
|
+
globalSkillsDir: ".agents/skills"
|
|
1530
|
+
},
|
|
1531
|
+
codebuddy: {
|
|
1532
|
+
displayName: "CodeBuddy",
|
|
1533
|
+
skillsDir: ".codebuddy/skills",
|
|
1534
|
+
globalSkillsDir: ".codebuddy/skills"
|
|
1199
1535
|
},
|
|
1200
1536
|
codex: {
|
|
1201
1537
|
displayName: "Codex",
|
|
1202
|
-
skillsDir: ".
|
|
1538
|
+
skillsDir: ".agents/skills",
|
|
1539
|
+
globalSkillsDir: ".codex/skills"
|
|
1540
|
+
},
|
|
1541
|
+
"command-code": {
|
|
1542
|
+
displayName: "Command Code",
|
|
1543
|
+
skillsDir: ".commandcode/skills",
|
|
1544
|
+
globalSkillsDir: ".commandcode/skills"
|
|
1545
|
+
},
|
|
1546
|
+
continue: {
|
|
1547
|
+
displayName: "Continue",
|
|
1548
|
+
skillsDir: ".continue/skills",
|
|
1549
|
+
globalSkillsDir: ".continue/skills"
|
|
1550
|
+
},
|
|
1551
|
+
cortex: {
|
|
1552
|
+
displayName: "Cortex Code",
|
|
1553
|
+
skillsDir: ".cortex/skills",
|
|
1554
|
+
globalSkillsDir: ".snowflake/cortex/skills"
|
|
1555
|
+
},
|
|
1556
|
+
crush: {
|
|
1557
|
+
displayName: "Crush",
|
|
1558
|
+
skillsDir: ".crush/skills",
|
|
1559
|
+
globalSkillsDir: ".config/crush/skills"
|
|
1203
1560
|
},
|
|
1204
1561
|
cursor: {
|
|
1205
1562
|
displayName: "Cursor",
|
|
1206
|
-
skillsDir: ".
|
|
1563
|
+
skillsDir: ".agents/skills",
|
|
1564
|
+
globalSkillsDir: ".cursor/skills"
|
|
1565
|
+
},
|
|
1566
|
+
droid: {
|
|
1567
|
+
displayName: "Droid",
|
|
1568
|
+
skillsDir: ".factory/skills",
|
|
1569
|
+
globalSkillsDir: ".factory/skills"
|
|
1207
1570
|
},
|
|
1208
|
-
gemini: {
|
|
1571
|
+
"gemini-cli": {
|
|
1209
1572
|
displayName: "Gemini CLI",
|
|
1210
|
-
skillsDir: ".
|
|
1573
|
+
skillsDir: ".agents/skills",
|
|
1574
|
+
globalSkillsDir: ".gemini/skills"
|
|
1575
|
+
},
|
|
1576
|
+
"github-copilot": {
|
|
1577
|
+
displayName: "GitHub Copilot",
|
|
1578
|
+
skillsDir: ".agents/skills",
|
|
1579
|
+
globalSkillsDir: ".copilot/skills"
|
|
1580
|
+
},
|
|
1581
|
+
goose: {
|
|
1582
|
+
displayName: "Goose",
|
|
1583
|
+
skillsDir: ".goose/skills",
|
|
1584
|
+
globalSkillsDir: ".config/goose/skills"
|
|
1211
1585
|
},
|
|
1212
|
-
|
|
1586
|
+
"iflow-cli": {
|
|
1587
|
+
displayName: "iFlow CLI",
|
|
1588
|
+
skillsDir: ".iflow/skills",
|
|
1589
|
+
globalSkillsDir: ".iflow/skills"
|
|
1590
|
+
},
|
|
1591
|
+
junie: {
|
|
1592
|
+
displayName: "Junie",
|
|
1593
|
+
skillsDir: ".junie/skills",
|
|
1594
|
+
globalSkillsDir: ".junie/skills"
|
|
1595
|
+
},
|
|
1596
|
+
kilo: {
|
|
1597
|
+
displayName: "Kilo Code",
|
|
1598
|
+
skillsDir: ".kilocode/skills",
|
|
1599
|
+
globalSkillsDir: ".kilocode/skills"
|
|
1600
|
+
},
|
|
1601
|
+
"kimi-cli": {
|
|
1602
|
+
displayName: "Kimi Code CLI",
|
|
1603
|
+
skillsDir: ".agents/skills",
|
|
1604
|
+
globalSkillsDir: ".config/agents/skills"
|
|
1605
|
+
},
|
|
1606
|
+
"kiro-cli": {
|
|
1213
1607
|
displayName: "Kiro CLI",
|
|
1214
|
-
skillsDir: ".kiro/skills"
|
|
1608
|
+
skillsDir: ".kiro/skills",
|
|
1609
|
+
globalSkillsDir: ".kiro/skills"
|
|
1610
|
+
},
|
|
1611
|
+
kode: {
|
|
1612
|
+
displayName: "Kode",
|
|
1613
|
+
skillsDir: ".kode/skills",
|
|
1614
|
+
globalSkillsDir: ".kode/skills"
|
|
1615
|
+
},
|
|
1616
|
+
mcpjam: {
|
|
1617
|
+
displayName: "MCPJam",
|
|
1618
|
+
skillsDir: ".mcpjam/skills",
|
|
1619
|
+
globalSkillsDir: ".mcpjam/skills"
|
|
1620
|
+
},
|
|
1621
|
+
"mistral-vibe": {
|
|
1622
|
+
displayName: "Mistral Vibe",
|
|
1623
|
+
skillsDir: ".vibe/skills",
|
|
1624
|
+
globalSkillsDir: ".vibe/skills"
|
|
1625
|
+
},
|
|
1626
|
+
mux: {
|
|
1627
|
+
displayName: "Mux",
|
|
1628
|
+
skillsDir: ".mux/skills",
|
|
1629
|
+
globalSkillsDir: ".mux/skills"
|
|
1630
|
+
},
|
|
1631
|
+
neovate: {
|
|
1632
|
+
displayName: "Neovate",
|
|
1633
|
+
skillsDir: ".neovate/skills",
|
|
1634
|
+
globalSkillsDir: ".neovate/skills"
|
|
1635
|
+
},
|
|
1636
|
+
openclaw: {
|
|
1637
|
+
displayName: "OpenClaw",
|
|
1638
|
+
skillsDir: "skills",
|
|
1639
|
+
globalSkillsDir: ".openclaw/skills"
|
|
1215
1640
|
},
|
|
1216
1641
|
opencode: {
|
|
1217
1642
|
displayName: "OpenCode",
|
|
1218
|
-
skillsDir: ".
|
|
1643
|
+
skillsDir: ".agents/skills",
|
|
1644
|
+
globalSkillsDir: ".config/opencode/skills"
|
|
1645
|
+
},
|
|
1646
|
+
openhands: {
|
|
1647
|
+
displayName: "OpenHands",
|
|
1648
|
+
skillsDir: ".openhands/skills",
|
|
1649
|
+
globalSkillsDir: ".openhands/skills"
|
|
1650
|
+
},
|
|
1651
|
+
pi: {
|
|
1652
|
+
displayName: "Pi",
|
|
1653
|
+
skillsDir: ".pi/skills",
|
|
1654
|
+
globalSkillsDir: ".pi/agent/skills"
|
|
1655
|
+
},
|
|
1656
|
+
pochi: {
|
|
1657
|
+
displayName: "Pochi",
|
|
1658
|
+
skillsDir: ".pochi/skills",
|
|
1659
|
+
globalSkillsDir: ".pochi/skills"
|
|
1660
|
+
},
|
|
1661
|
+
qoder: {
|
|
1662
|
+
displayName: "Qoder",
|
|
1663
|
+
skillsDir: ".qoder/skills",
|
|
1664
|
+
globalSkillsDir: ".qoder/skills"
|
|
1665
|
+
},
|
|
1666
|
+
"qwen-code": {
|
|
1667
|
+
displayName: "Qwen Code",
|
|
1668
|
+
skillsDir: ".qwen/skills",
|
|
1669
|
+
globalSkillsDir: ".qwen/skills"
|
|
1670
|
+
},
|
|
1671
|
+
replit: {
|
|
1672
|
+
displayName: "Replit",
|
|
1673
|
+
skillsDir: ".agents/skills",
|
|
1674
|
+
globalSkillsDir: ".config/agents/skills"
|
|
1675
|
+
},
|
|
1676
|
+
roo: {
|
|
1677
|
+
displayName: "Roo Code",
|
|
1678
|
+
skillsDir: ".roo/skills",
|
|
1679
|
+
globalSkillsDir: ".roo/skills"
|
|
1680
|
+
},
|
|
1681
|
+
trae: {
|
|
1682
|
+
displayName: "Trae",
|
|
1683
|
+
skillsDir: ".trae/skills",
|
|
1684
|
+
globalSkillsDir: ".trae/skills"
|
|
1685
|
+
},
|
|
1686
|
+
"trae-cn": {
|
|
1687
|
+
displayName: "Trae CN",
|
|
1688
|
+
skillsDir: ".trae/skills",
|
|
1689
|
+
globalSkillsDir: ".trae-cn/skills"
|
|
1690
|
+
},
|
|
1691
|
+
universal: {
|
|
1692
|
+
displayName: "Universal",
|
|
1693
|
+
skillsDir: ".agents/skills",
|
|
1694
|
+
globalSkillsDir: ".config/agents/skills"
|
|
1695
|
+
},
|
|
1696
|
+
windsurf: {
|
|
1697
|
+
displayName: "Windsurf",
|
|
1698
|
+
skillsDir: ".windsurf/skills",
|
|
1699
|
+
globalSkillsDir: ".codeium/windsurf/skills"
|
|
1700
|
+
},
|
|
1701
|
+
zencoder: {
|
|
1702
|
+
displayName: "Zencoder",
|
|
1703
|
+
skillsDir: ".zencoder/skills",
|
|
1704
|
+
globalSkillsDir: ".zencoder/skills"
|
|
1219
1705
|
}
|
|
1220
1706
|
};
|
|
1221
|
-
DEFAULT_AGENT_CONFIGS =
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
"claude-code",
|
|
1231
|
-
"codex",
|
|
1232
|
-
"cursor",
|
|
1233
|
-
"gemini",
|
|
1234
|
-
"kiro",
|
|
1235
|
-
"opencode"
|
|
1236
|
-
];
|
|
1707
|
+
DEFAULT_AGENT_CONFIGS = Object.fromEntries(
|
|
1708
|
+
Object.entries(AGENT_INFO).map(([key, info]) => [
|
|
1709
|
+
key,
|
|
1710
|
+
{ skillsDir: info.skillsDir }
|
|
1711
|
+
])
|
|
1712
|
+
);
|
|
1713
|
+
ALL_AGENTS = Object.keys(
|
|
1714
|
+
AGENT_INFO
|
|
1715
|
+
).sort();
|
|
1237
1716
|
}
|
|
1238
1717
|
});
|
|
1239
1718
|
function getGitHubHeaders() {
|
|
@@ -1331,13 +1810,13 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
|
|
|
1331
1810
|
const sourcePath = join(tempDir, extractedDir);
|
|
1332
1811
|
const copySource = spec.path ? join(sourcePath, spec.path) : sourcePath;
|
|
1333
1812
|
if (spec.path) {
|
|
1334
|
-
const
|
|
1335
|
-
if (!
|
|
1813
|
+
const pathExists2 = await lstat(copySource).catch(() => null);
|
|
1814
|
+
if (!pathExists2) {
|
|
1336
1815
|
const rootEntries = await readdir(sourcePath);
|
|
1337
1816
|
const dirs = [];
|
|
1338
1817
|
for (const entry of rootEntries) {
|
|
1339
|
-
const
|
|
1340
|
-
if (
|
|
1818
|
+
const stat9 = await lstat(join(sourcePath, entry)).catch(() => null);
|
|
1819
|
+
if (stat9?.isDirectory() && !entry.startsWith(".")) {
|
|
1341
1820
|
dirs.push(entry);
|
|
1342
1821
|
}
|
|
1343
1822
|
}
|
|
@@ -1485,6 +1964,9 @@ async function writeLockfile(lockfile) {
|
|
|
1485
1964
|
if (lockfile.localPackages && Object.keys(lockfile.localPackages).length > 0) {
|
|
1486
1965
|
normalized.localPackages = lockfile.localPackages;
|
|
1487
1966
|
}
|
|
1967
|
+
if (lockfile.wellKnownPackages && Object.keys(lockfile.wellKnownPackages).length > 0) {
|
|
1968
|
+
normalized.wellKnownPackages = lockfile.wellKnownPackages;
|
|
1969
|
+
}
|
|
1488
1970
|
await writeFile(lockfilePath, `${JSON.stringify(normalized, null, 2)}
|
|
1489
1971
|
`);
|
|
1490
1972
|
}
|
|
@@ -1589,13 +2071,39 @@ async function addLocalToLockfile(specifier, entry) {
|
|
|
1589
2071
|
lockfile.localPackages[specifier] = entry;
|
|
1590
2072
|
await writeLockfile(lockfile);
|
|
1591
2073
|
}
|
|
1592
|
-
|
|
2074
|
+
async function addWellKnownToLockfile(specifier, entry) {
|
|
2075
|
+
let lockfile = await readLockfile();
|
|
2076
|
+
if (!lockfile) {
|
|
2077
|
+
lockfile = await createEmptyLockfile();
|
|
2078
|
+
}
|
|
2079
|
+
if (!lockfile.wellKnownPackages) {
|
|
2080
|
+
lockfile.wellKnownPackages = {};
|
|
2081
|
+
}
|
|
2082
|
+
lockfile.wellKnownPackages[specifier] = entry;
|
|
2083
|
+
await writeLockfile(lockfile);
|
|
2084
|
+
}
|
|
2085
|
+
async function listLockfileWellKnownPackages() {
|
|
2086
|
+
const lockfile = await readLockfile();
|
|
2087
|
+
if (!lockfile?.wellKnownPackages) {
|
|
2088
|
+
return [];
|
|
2089
|
+
}
|
|
2090
|
+
return Object.entries(lockfile.wellKnownPackages).map(
|
|
2091
|
+
([specifier, entry]) => ({
|
|
2092
|
+
specifier,
|
|
2093
|
+
entry
|
|
2094
|
+
})
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
var init_lockfile3 = __esm({
|
|
1593
2098
|
"src/lockfile.ts"() {
|
|
1594
2099
|
init_config();
|
|
1595
2100
|
init_lib();
|
|
1596
2101
|
}
|
|
1597
2102
|
});
|
|
1598
2103
|
function getManifestPath() {
|
|
2104
|
+
if (isGlobalMode()) {
|
|
2105
|
+
return join(homedir(), ".pspm", "pspm.json");
|
|
2106
|
+
}
|
|
1599
2107
|
return join(process.cwd(), "pspm.json");
|
|
1600
2108
|
}
|
|
1601
2109
|
async function readManifest() {
|
|
@@ -1674,8 +2182,23 @@ async function addLocalDependency(specifier, version3 = "*") {
|
|
|
1674
2182
|
manifest.localDependencies[specifier] = version3;
|
|
1675
2183
|
await writeManifest(manifest);
|
|
1676
2184
|
}
|
|
1677
|
-
|
|
2185
|
+
async function addWellKnownDependency(baseUrl, skillNames) {
|
|
2186
|
+
const manifest = await ensureManifest();
|
|
2187
|
+
if (!manifest.wellKnownDependencies) {
|
|
2188
|
+
manifest.wellKnownDependencies = {};
|
|
2189
|
+
}
|
|
2190
|
+
const existing = manifest.wellKnownDependencies[baseUrl];
|
|
2191
|
+
if (Array.isArray(existing)) {
|
|
2192
|
+
const merged = [.../* @__PURE__ */ new Set([...existing, ...skillNames])];
|
|
2193
|
+
manifest.wellKnownDependencies[baseUrl] = merged;
|
|
2194
|
+
} else {
|
|
2195
|
+
manifest.wellKnownDependencies[baseUrl] = skillNames;
|
|
2196
|
+
}
|
|
2197
|
+
await writeManifest(manifest);
|
|
2198
|
+
}
|
|
2199
|
+
var init_manifest3 = __esm({
|
|
1678
2200
|
"src/manifest.ts"() {
|
|
2201
|
+
init_config();
|
|
1679
2202
|
}
|
|
1680
2203
|
});
|
|
1681
2204
|
async function createAgentSymlinks(skills, options) {
|
|
@@ -1684,7 +2207,7 @@ async function createAgentSymlinks(skills, options) {
|
|
|
1684
2207
|
return;
|
|
1685
2208
|
}
|
|
1686
2209
|
for (const agentName of agents) {
|
|
1687
|
-
const config2 = resolveAgentConfig(agentName, agentConfigs);
|
|
2210
|
+
const config2 = resolveAgentConfig(agentName, agentConfigs, options.global);
|
|
1688
2211
|
if (!config2) {
|
|
1689
2212
|
console.warn(`Warning: Unknown agent "${agentName}", skipping symlinks`);
|
|
1690
2213
|
continue;
|
|
@@ -1744,8 +2267,19 @@ async function removeAgentSymlinks(skillName, options) {
|
|
|
1744
2267
|
}
|
|
1745
2268
|
}
|
|
1746
2269
|
}
|
|
1747
|
-
function getRegistrySkillPath(
|
|
1748
|
-
|
|
2270
|
+
function getRegistrySkillPath(ownerOrNamespace, skillNameOrOwner, skillName) {
|
|
2271
|
+
if (skillName !== void 0) {
|
|
2272
|
+
const namespace = ownerOrNamespace;
|
|
2273
|
+
const owner = skillNameOrOwner;
|
|
2274
|
+
if (namespace === "org") {
|
|
2275
|
+
return `.pspm/skills/_org/${owner}/${skillName}`;
|
|
2276
|
+
}
|
|
2277
|
+
if (namespace === "github") {
|
|
2278
|
+
return `.pspm/skills/_github-registry/${owner}/${skillName}`;
|
|
2279
|
+
}
|
|
2280
|
+
return `.pspm/skills/${owner}/${skillName}`;
|
|
2281
|
+
}
|
|
2282
|
+
return `.pspm/skills/${ownerOrNamespace}/${skillNameOrOwner}`;
|
|
1749
2283
|
}
|
|
1750
2284
|
function getGitHubSkillPath(owner, repo, path) {
|
|
1751
2285
|
if (path) {
|
|
@@ -1756,6 +2290,9 @@ function getGitHubSkillPath(owner, repo, path) {
|
|
|
1756
2290
|
function getLocalSkillPath(skillName) {
|
|
1757
2291
|
return `.pspm/skills/_local/${skillName}`;
|
|
1758
2292
|
}
|
|
2293
|
+
function getWellKnownSkillPath(hostname, skillName) {
|
|
2294
|
+
return `.pspm/skills/_wellknown/${hostname}/${skillName}`;
|
|
2295
|
+
}
|
|
1759
2296
|
async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
|
|
1760
2297
|
const linkedAgents = [];
|
|
1761
2298
|
for (const agentName of agents) {
|
|
@@ -1777,13 +2314,189 @@ var init_symlinks = __esm({
|
|
|
1777
2314
|
init_agents();
|
|
1778
2315
|
}
|
|
1779
2316
|
});
|
|
2317
|
+
function isWellKnownSpecifier(input) {
|
|
2318
|
+
if (!input.startsWith("http://") && !input.startsWith("https://")) {
|
|
2319
|
+
return false;
|
|
2320
|
+
}
|
|
2321
|
+
try {
|
|
2322
|
+
const parsed = new URL(input);
|
|
2323
|
+
if (EXCLUDED_HOSTS.includes(parsed.hostname)) {
|
|
2324
|
+
return false;
|
|
2325
|
+
}
|
|
2326
|
+
if (input.endsWith(".git")) {
|
|
2327
|
+
return false;
|
|
2328
|
+
}
|
|
2329
|
+
return true;
|
|
2330
|
+
} catch {
|
|
2331
|
+
return false;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
function getWellKnownHostname(url) {
|
|
2335
|
+
try {
|
|
2336
|
+
const parsed = new URL(url);
|
|
2337
|
+
return parsed.hostname.replace(/^www\./, "");
|
|
2338
|
+
} catch {
|
|
2339
|
+
return url;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
function isValidSkillEntry(entry) {
|
|
2343
|
+
if (!entry || typeof entry !== "object") return false;
|
|
2344
|
+
const e = entry;
|
|
2345
|
+
if (typeof e.name !== "string" || e.name.length === 0) return false;
|
|
2346
|
+
if (typeof e.description !== "string" || e.description.length === 0)
|
|
2347
|
+
return false;
|
|
2348
|
+
if (!SKILL_NAME_PATTERN.test(e.name)) return false;
|
|
2349
|
+
if (!Array.isArray(e.files) || e.files.length === 0) return false;
|
|
2350
|
+
let hasSkillMd = false;
|
|
2351
|
+
for (const file of e.files) {
|
|
2352
|
+
if (typeof file !== "string") return false;
|
|
2353
|
+
if (file.startsWith("/") || file.startsWith("\\")) return false;
|
|
2354
|
+
if (file.includes("..")) return false;
|
|
2355
|
+
if (file.toLowerCase() === "skill.md") hasSkillMd = true;
|
|
2356
|
+
}
|
|
2357
|
+
if (!hasSkillMd) return false;
|
|
2358
|
+
return true;
|
|
2359
|
+
}
|
|
2360
|
+
function isValidIndex(data) {
|
|
2361
|
+
if (!data || typeof data !== "object") return false;
|
|
2362
|
+
const d = data;
|
|
2363
|
+
if (!Array.isArray(d.skills)) return false;
|
|
2364
|
+
return d.skills.every(isValidSkillEntry);
|
|
2365
|
+
}
|
|
2366
|
+
async function fetchWellKnownIndex(baseUrl) {
|
|
2367
|
+
const parsed = new URL(baseUrl);
|
|
2368
|
+
const pathRelativeUrl = `${baseUrl.replace(/\/$/, "")}/${WELL_KNOWN_PATH}/${INDEX_FILE}`;
|
|
2369
|
+
const pathRelativeBase = `${baseUrl.replace(/\/$/, "")}/${WELL_KNOWN_PATH}`;
|
|
2370
|
+
try {
|
|
2371
|
+
const response = await fetch(pathRelativeUrl, {
|
|
2372
|
+
signal: AbortSignal.timeout(1e4)
|
|
2373
|
+
});
|
|
2374
|
+
if (response.ok) {
|
|
2375
|
+
const data = await response.json();
|
|
2376
|
+
if (isValidIndex(data)) {
|
|
2377
|
+
return { index: data, resolvedBaseUrl: pathRelativeBase };
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
} catch {
|
|
2381
|
+
}
|
|
2382
|
+
const rootUrl = `${parsed.protocol}//${parsed.host}/${WELL_KNOWN_PATH}/${INDEX_FILE}`;
|
|
2383
|
+
const rootBase = `${parsed.protocol}//${parsed.host}/${WELL_KNOWN_PATH}`;
|
|
2384
|
+
if (rootUrl !== pathRelativeUrl) {
|
|
2385
|
+
try {
|
|
2386
|
+
const response = await fetch(rootUrl, {
|
|
2387
|
+
signal: AbortSignal.timeout(1e4)
|
|
2388
|
+
});
|
|
2389
|
+
if (response.ok) {
|
|
2390
|
+
const data = await response.json();
|
|
2391
|
+
if (isValidIndex(data)) {
|
|
2392
|
+
return { index: data, resolvedBaseUrl: rootBase };
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
} catch {
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
return null;
|
|
2399
|
+
}
|
|
2400
|
+
async function fetchSkillFiles(baseUrl, entry) {
|
|
2401
|
+
const skillBaseUrl = `${baseUrl}/${entry.name}`;
|
|
2402
|
+
const files = /* @__PURE__ */ new Map();
|
|
2403
|
+
let skillMdContent = "";
|
|
2404
|
+
const results = await Promise.allSettled(
|
|
2405
|
+
entry.files.map(async (filePath) => {
|
|
2406
|
+
const fileUrl = `${skillBaseUrl}/${filePath}`;
|
|
2407
|
+
const response = await fetch(fileUrl, {
|
|
2408
|
+
signal: AbortSignal.timeout(1e4)
|
|
2409
|
+
});
|
|
2410
|
+
if (!response.ok) {
|
|
2411
|
+
throw new Error(`Failed to fetch ${fileUrl}: ${response.status}`);
|
|
2412
|
+
}
|
|
2413
|
+
const content = await response.text();
|
|
2414
|
+
return { filePath, content };
|
|
2415
|
+
})
|
|
2416
|
+
);
|
|
2417
|
+
for (const result of results) {
|
|
2418
|
+
if (result.status === "fulfilled") {
|
|
2419
|
+
files.set(result.value.filePath, result.value.content);
|
|
2420
|
+
if (result.value.filePath.toLowerCase() === "skill.md") {
|
|
2421
|
+
skillMdContent = result.value.content;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
if (!skillMdContent) {
|
|
2426
|
+
return null;
|
|
2427
|
+
}
|
|
2428
|
+
return {
|
|
2429
|
+
name: entry.name,
|
|
2430
|
+
description: entry.description,
|
|
2431
|
+
content: skillMdContent,
|
|
2432
|
+
files,
|
|
2433
|
+
sourceUrl: `${skillBaseUrl}/SKILL.md`,
|
|
2434
|
+
indexEntry: entry
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
async function fetchWellKnownSkills(url) {
|
|
2438
|
+
const result = await fetchWellKnownIndex(url);
|
|
2439
|
+
if (!result) return null;
|
|
2440
|
+
const { index, resolvedBaseUrl } = result;
|
|
2441
|
+
const hostname = getWellKnownHostname(url);
|
|
2442
|
+
const skillResults = await Promise.allSettled(
|
|
2443
|
+
index.skills.map((entry) => fetchSkillFiles(resolvedBaseUrl, entry))
|
|
2444
|
+
);
|
|
2445
|
+
const skills = [];
|
|
2446
|
+
for (const r of skillResults) {
|
|
2447
|
+
if (r.status === "fulfilled" && r.value) {
|
|
2448
|
+
skills.push(r.value);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
if (skills.length === 0) return null;
|
|
2452
|
+
return { skills, resolvedBaseUrl, hostname };
|
|
2453
|
+
}
|
|
2454
|
+
async function extractWellKnownSkill(skill, hostname, skillsDir) {
|
|
2455
|
+
const destPath = join(skillsDir, "_wellknown", hostname, skill.name);
|
|
2456
|
+
await rm(destPath, { recursive: true, force: true });
|
|
2457
|
+
await mkdir(destPath, { recursive: true });
|
|
2458
|
+
for (const [filePath, content] of skill.files) {
|
|
2459
|
+
const fullPath = join(destPath, filePath);
|
|
2460
|
+
if (!fullPath.startsWith(destPath)) {
|
|
2461
|
+
continue;
|
|
2462
|
+
}
|
|
2463
|
+
const { dirname: dirname7 } = await import('path');
|
|
2464
|
+
await mkdir(dirname7(fullPath), { recursive: true });
|
|
2465
|
+
await writeFile(fullPath, content, "utf-8");
|
|
2466
|
+
}
|
|
2467
|
+
return `.pspm/skills/_wellknown/${hostname}/${skill.name}`;
|
|
2468
|
+
}
|
|
2469
|
+
function calculateWellKnownIntegrity(skill) {
|
|
2470
|
+
const sortedEntries = [...skill.files.entries()].sort(
|
|
2471
|
+
([a], [b]) => a.localeCompare(b)
|
|
2472
|
+
);
|
|
2473
|
+
const combined = sortedEntries.map(([path, content]) => `${path}:${content}`).join("\n");
|
|
2474
|
+
return calculateIntegrity(Buffer.from(combined, "utf-8"));
|
|
2475
|
+
}
|
|
2476
|
+
function getWellKnownDisplayName(hostname, skillName) {
|
|
2477
|
+
return `${hostname}/${skillName} (well-known)`;
|
|
2478
|
+
}
|
|
2479
|
+
var WELL_KNOWN_PATH, INDEX_FILE, SKILL_NAME_PATTERN, EXCLUDED_HOSTS;
|
|
2480
|
+
var init_wellknown = __esm({
|
|
2481
|
+
"src/wellknown.ts"() {
|
|
2482
|
+
init_lib();
|
|
2483
|
+
WELL_KNOWN_PATH = ".well-known/skills";
|
|
2484
|
+
INDEX_FILE = "index.json";
|
|
2485
|
+
SKILL_NAME_PATTERN = /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
2486
|
+
EXCLUDED_HOSTS = [
|
|
2487
|
+
"github.com",
|
|
2488
|
+
"gitlab.com",
|
|
2489
|
+
"raw.githubusercontent.com"
|
|
2490
|
+
];
|
|
2491
|
+
}
|
|
2492
|
+
});
|
|
1780
2493
|
|
|
1781
2494
|
// src/commands/add.ts
|
|
1782
2495
|
var add_exports = {};
|
|
1783
2496
|
__export(add_exports, {
|
|
1784
2497
|
add: () => add
|
|
1785
2498
|
});
|
|
1786
|
-
function
|
|
2499
|
+
function isLocalSpecifier3(specifier) {
|
|
1787
2500
|
return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
|
|
1788
2501
|
}
|
|
1789
2502
|
function parseLocalPath(specifier) {
|
|
@@ -1792,27 +2505,43 @@ function parseLocalPath(specifier) {
|
|
|
1792
2505
|
}
|
|
1793
2506
|
return specifier;
|
|
1794
2507
|
}
|
|
1795
|
-
function
|
|
2508
|
+
function normalizeToFileSpecifier2(path) {
|
|
1796
2509
|
if (path.startsWith("file:")) {
|
|
1797
2510
|
return path;
|
|
1798
2511
|
}
|
|
1799
2512
|
return `file:${path}`;
|
|
1800
2513
|
}
|
|
1801
2514
|
async function add(specifiers, options) {
|
|
2515
|
+
if (options.global) {
|
|
2516
|
+
setGlobalMode(true);
|
|
2517
|
+
console.log("Installing globally to ~/.pspm/\n");
|
|
2518
|
+
}
|
|
1802
2519
|
console.log("Resolving packages...\n");
|
|
1803
2520
|
const resolvedPackages = [];
|
|
1804
2521
|
const validationErrors = [];
|
|
1805
2522
|
for (const specifier of specifiers) {
|
|
1806
2523
|
try {
|
|
1807
|
-
if (
|
|
2524
|
+
if (isLocalSpecifier3(specifier)) {
|
|
1808
2525
|
const resolved = await validateLocalPackage(specifier);
|
|
1809
2526
|
resolvedPackages.push(resolved);
|
|
1810
|
-
} else if (
|
|
2527
|
+
} else if (isGitHubSpecifier2(specifier) || isGitHubUrl(specifier) || isGitHubShorthand(specifier)) {
|
|
1811
2528
|
const resolved = await validateGitHubPackage(specifier);
|
|
1812
2529
|
resolvedPackages.push(resolved);
|
|
1813
|
-
} else {
|
|
2530
|
+
} else if (isWellKnownSpecifier(specifier)) {
|
|
2531
|
+
const resolved = await validateWellKnownPackage(specifier);
|
|
2532
|
+
resolvedPackages.push(resolved);
|
|
2533
|
+
} else if (isRegistrySpecifier2(specifier)) {
|
|
1814
2534
|
const resolved = await validateRegistryPackage(specifier);
|
|
1815
2535
|
resolvedPackages.push(resolved);
|
|
2536
|
+
} else {
|
|
2537
|
+
throw new Error(
|
|
2538
|
+
`Unknown specifier format "${specifier}". Supported formats:
|
|
2539
|
+
@user/{username}/{name}[@version] (registry)
|
|
2540
|
+
@org/{orgname}/{name}[@version] (organization)
|
|
2541
|
+
github:owner/repo[/path][@ref] (github)
|
|
2542
|
+
file:./path/to/skill (local)
|
|
2543
|
+
owner/repo (github shorthand)`
|
|
2544
|
+
);
|
|
1816
2545
|
}
|
|
1817
2546
|
} catch (error) {
|
|
1818
2547
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -1842,11 +2571,19 @@ async function add(specifiers, options) {
|
|
|
1842
2571
|
const localPackages = resolvedPackages.filter(
|
|
1843
2572
|
(p) => p.type === "local"
|
|
1844
2573
|
);
|
|
2574
|
+
const wellKnownPackages = resolvedPackages.filter(
|
|
2575
|
+
(p) => p.type === "wellknown"
|
|
2576
|
+
);
|
|
1845
2577
|
let resolutionResult = null;
|
|
1846
2578
|
if (registryPackages.length > 0) {
|
|
1847
2579
|
const rootDeps = {};
|
|
1848
2580
|
for (const pkg of registryPackages) {
|
|
1849
|
-
const fullName =
|
|
2581
|
+
const fullName = generateRegistryIdentifier2({
|
|
2582
|
+
namespace: pkg.namespace,
|
|
2583
|
+
owner: pkg.owner,
|
|
2584
|
+
name: pkg.name,
|
|
2585
|
+
subname: pkg.subname
|
|
2586
|
+
});
|
|
1850
2587
|
rootDeps[fullName] = pkg.versionRange || `^${pkg.resolvedVersion}`;
|
|
1851
2588
|
}
|
|
1852
2589
|
console.log("Resolving dependencies...");
|
|
@@ -1944,6 +2681,24 @@ async function add(specifiers, options) {
|
|
|
1944
2681
|
error: message
|
|
1945
2682
|
});
|
|
1946
2683
|
console.error(`Failed to install ${resolved.specifier}: ${message}
|
|
2684
|
+
`);
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
for (const resolved of wellKnownPackages) {
|
|
2688
|
+
try {
|
|
2689
|
+
await installWellKnownPackage(resolved, {
|
|
2690
|
+
...options,
|
|
2691
|
+
resolvedAgents: agents
|
|
2692
|
+
});
|
|
2693
|
+
results.push({ specifier: resolved.specifier, success: true });
|
|
2694
|
+
} catch (error) {
|
|
2695
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2696
|
+
results.push({
|
|
2697
|
+
specifier: resolved.specifier,
|
|
2698
|
+
success: false,
|
|
2699
|
+
error: message
|
|
2700
|
+
});
|
|
2701
|
+
console.error(`Failed to install ${resolved.specifier}: ${message}
|
|
1947
2702
|
`);
|
|
1948
2703
|
}
|
|
1949
2704
|
}
|
|
@@ -1957,12 +2712,15 @@ Summary: ${succeeded} added, ${failed} failed`);
|
|
|
1957
2712
|
}
|
|
1958
2713
|
}
|
|
1959
2714
|
}
|
|
2715
|
+
function getSymlinkRoot() {
|
|
2716
|
+
return isGlobalMode() ? homedir() : process.cwd();
|
|
2717
|
+
}
|
|
1960
2718
|
async function installFromNode(node, options) {
|
|
1961
|
-
const
|
|
1962
|
-
if (!
|
|
2719
|
+
const parsed = parseRegistrySpecifier2(node.name);
|
|
2720
|
+
if (!parsed) {
|
|
1963
2721
|
throw new Error(`Invalid package name: ${node.name}`);
|
|
1964
2722
|
}
|
|
1965
|
-
const
|
|
2723
|
+
const { namespace, owner, name, subname } = parsed;
|
|
1966
2724
|
console.log(`Installing ${node.name}@${node.version}...`);
|
|
1967
2725
|
const config2 = await resolveConfig();
|
|
1968
2726
|
const apiKey = getTokenForRegistry(config2, config2.registryUrl);
|
|
@@ -1984,18 +2742,26 @@ async function installFromNode(node, options) {
|
|
|
1984
2742
|
throw new Error("Checksum verification failed");
|
|
1985
2743
|
}
|
|
1986
2744
|
const skillsDir = getSkillsDir();
|
|
1987
|
-
const
|
|
2745
|
+
const effectiveSkillName = subname ?? name;
|
|
2746
|
+
let destDir;
|
|
2747
|
+
if (namespace === "org") {
|
|
2748
|
+
destDir = join(skillsDir, "_org", owner, effectiveSkillName);
|
|
2749
|
+
} else if (namespace === "github" && subname) {
|
|
2750
|
+
destDir = join(skillsDir, "_github-registry", owner, name, subname);
|
|
2751
|
+
} else {
|
|
2752
|
+
destDir = join(skillsDir, owner, effectiveSkillName);
|
|
2753
|
+
}
|
|
1988
2754
|
await mkdir(destDir, { recursive: true });
|
|
1989
|
-
const { writeFile:
|
|
2755
|
+
const { writeFile: writeFile11 } = await import('fs/promises');
|
|
1990
2756
|
const tempFile = join(destDir, ".temp.tgz");
|
|
1991
|
-
await
|
|
2757
|
+
await writeFile11(tempFile, tarballBuffer);
|
|
1992
2758
|
const { exec: exec2 } = await import('child_process');
|
|
1993
2759
|
const { promisify: promisify2 } = await import('util');
|
|
1994
2760
|
const execAsync = promisify2(exec2);
|
|
1995
2761
|
try {
|
|
1996
2762
|
await rm(destDir, { recursive: true, force: true });
|
|
1997
2763
|
await mkdir(destDir, { recursive: true });
|
|
1998
|
-
await
|
|
2764
|
+
await writeFile11(tempFile, tarballBuffer);
|
|
1999
2765
|
await execAsync(
|
|
2000
2766
|
`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
|
|
2001
2767
|
);
|
|
@@ -2023,14 +2789,16 @@ async function installFromNode(node, options) {
|
|
|
2023
2789
|
const agents = options.resolvedAgents;
|
|
2024
2790
|
if (agents[0] !== "none") {
|
|
2025
2791
|
const skillManifest = await readManifest();
|
|
2792
|
+
const pathSkillName = namespace === "github" && subname ? `${name}/${subname}` : name;
|
|
2026
2793
|
const skillInfo = {
|
|
2027
|
-
name,
|
|
2028
|
-
sourcePath: getRegistrySkillPath(
|
|
2794
|
+
name: effectiveSkillName,
|
|
2795
|
+
sourcePath: getRegistrySkillPath(namespace, owner, pathSkillName)
|
|
2029
2796
|
};
|
|
2030
2797
|
await createAgentSymlinks([skillInfo], {
|
|
2031
2798
|
agents,
|
|
2032
|
-
projectRoot:
|
|
2033
|
-
agentConfigs: skillManifest?.agents
|
|
2799
|
+
projectRoot: getSymlinkRoot(),
|
|
2800
|
+
agentConfigs: skillManifest?.agents,
|
|
2801
|
+
global: isGlobalMode()
|
|
2034
2802
|
});
|
|
2035
2803
|
}
|
|
2036
2804
|
console.log(`Installed ${node.name}@${node.version}`);
|
|
@@ -2040,75 +2808,127 @@ async function validateRegistryPackage(specifier) {
|
|
|
2040
2808
|
const config2 = await resolveConfig();
|
|
2041
2809
|
const registryUrl = config2.registryUrl;
|
|
2042
2810
|
const apiKey = getTokenForRegistry(config2, registryUrl);
|
|
2043
|
-
const parsed =
|
|
2811
|
+
const parsed = parseRegistrySpecifier2(specifier);
|
|
2044
2812
|
if (!parsed) {
|
|
2045
2813
|
throw new Error(
|
|
2046
|
-
`Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}]`
|
|
2814
|
+
`Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}] or @org/{orgname}/{name}[@{version}]`
|
|
2047
2815
|
);
|
|
2048
2816
|
}
|
|
2049
|
-
const {
|
|
2817
|
+
const { namespace, owner, name, subname, versionRange } = parsed;
|
|
2818
|
+
const fullName = generateRegistryIdentifier2({
|
|
2819
|
+
namespace,
|
|
2820
|
+
owner,
|
|
2821
|
+
name,
|
|
2822
|
+
subname
|
|
2823
|
+
});
|
|
2050
2824
|
configure2({ registryUrl, apiKey });
|
|
2051
2825
|
console.log(`Resolving ${specifier}...`);
|
|
2052
|
-
|
|
2053
|
-
if (
|
|
2054
|
-
|
|
2055
|
-
|
|
2826
|
+
let versions;
|
|
2827
|
+
if (namespace === "github" && subname) {
|
|
2828
|
+
const versionsResponse = await listGithubSkillVersions(
|
|
2829
|
+
owner,
|
|
2830
|
+
name,
|
|
2831
|
+
subname
|
|
2832
|
+
);
|
|
2833
|
+
if (versionsResponse.status !== 200 || !versionsResponse.data) {
|
|
2834
|
+
if (versionsResponse.status === 401) {
|
|
2056
2835
|
throw new Error(
|
|
2057
|
-
`
|
|
2836
|
+
apiKey ? `Access denied to ${fullName}. You may not have permission to access this private package.` : `Package ${fullName} requires authentication. Please run 'pspm login' to authenticate`
|
|
2058
2837
|
);
|
|
2059
2838
|
}
|
|
2060
|
-
throw new Error(
|
|
2061
|
-
|
|
2839
|
+
throw new Error(versionsResponse.error || `Skill ${fullName} not found`);
|
|
2840
|
+
}
|
|
2841
|
+
versions = versionsResponse.data;
|
|
2842
|
+
} else {
|
|
2843
|
+
const versionsResponse = await listSkillVersions(owner, name);
|
|
2844
|
+
if (versionsResponse.status !== 200) {
|
|
2845
|
+
if (versionsResponse.status === 401) {
|
|
2846
|
+
if (!apiKey) {
|
|
2847
|
+
throw new Error(
|
|
2848
|
+
`Package ${fullName} requires authentication. Please run 'pspm login' to authenticate`
|
|
2849
|
+
);
|
|
2850
|
+
}
|
|
2851
|
+
throw new Error(
|
|
2852
|
+
`Access denied to ${fullName}. You may not have permission to access this private package.`
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
const errorMessage = extractApiErrorMessage(
|
|
2856
|
+
versionsResponse,
|
|
2857
|
+
`Skill ${fullName} not found`
|
|
2062
2858
|
);
|
|
2859
|
+
throw new Error(errorMessage);
|
|
2063
2860
|
}
|
|
2064
|
-
|
|
2065
|
-
versionsResponse,
|
|
2066
|
-
`Skill @user/${username}/${name} not found`
|
|
2067
|
-
);
|
|
2068
|
-
throw new Error(errorMessage);
|
|
2861
|
+
versions = versionsResponse.data;
|
|
2069
2862
|
}
|
|
2070
|
-
const versions = versionsResponse.data;
|
|
2071
2863
|
if (versions.length === 0) {
|
|
2072
|
-
throw new Error(`Skill
|
|
2864
|
+
throw new Error(`Skill ${fullName} not found`);
|
|
2073
2865
|
}
|
|
2074
2866
|
const versionStrings = versions.map((v) => v.version);
|
|
2075
|
-
const resolvedVersion =
|
|
2867
|
+
const resolvedVersion = resolveVersion2(versionRange || "*", versionStrings);
|
|
2076
2868
|
if (!resolvedVersion) {
|
|
2077
2869
|
throw new Error(
|
|
2078
|
-
`No version matching "${versionRange || "latest"}" found for
|
|
2870
|
+
`No version matching "${versionRange || "latest"}" found for ${fullName}. Available versions: ${versionStrings.join(", ")}`
|
|
2079
2871
|
);
|
|
2080
2872
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
`Version ${resolvedVersion} not found`
|
|
2873
|
+
let downloadUrl;
|
|
2874
|
+
let checksum;
|
|
2875
|
+
if (namespace === "github" && subname) {
|
|
2876
|
+
const versionResponse = await getGithubSkillVersion(
|
|
2877
|
+
owner,
|
|
2878
|
+
name,
|
|
2879
|
+
subname,
|
|
2880
|
+
resolvedVersion
|
|
2090
2881
|
);
|
|
2091
|
-
|
|
2882
|
+
if (versionResponse.status !== 200 || !versionResponse.data) {
|
|
2883
|
+
throw new Error(`Version ${resolvedVersion} not found for ${fullName}`);
|
|
2884
|
+
}
|
|
2885
|
+
downloadUrl = versionResponse.data.downloadUrl;
|
|
2886
|
+
checksum = versionResponse.data.checksum;
|
|
2887
|
+
} else {
|
|
2888
|
+
const versionResponse = await getSkillVersion(owner, name, resolvedVersion);
|
|
2889
|
+
if (versionResponse.status !== 200 || !versionResponse.data) {
|
|
2890
|
+
const errorMessage = extractApiErrorMessage(
|
|
2891
|
+
versionResponse,
|
|
2892
|
+
`Version ${resolvedVersion} not found`
|
|
2893
|
+
);
|
|
2894
|
+
throw new Error(errorMessage);
|
|
2895
|
+
}
|
|
2896
|
+
downloadUrl = versionResponse.data.downloadUrl;
|
|
2897
|
+
checksum = versionResponse.data.checksum;
|
|
2092
2898
|
}
|
|
2093
|
-
console.log(`Resolved
|
|
2899
|
+
console.log(`Resolved ${fullName}@${resolvedVersion}`);
|
|
2094
2900
|
return {
|
|
2095
2901
|
type: "registry",
|
|
2096
2902
|
specifier,
|
|
2097
|
-
|
|
2903
|
+
namespace,
|
|
2904
|
+
owner,
|
|
2098
2905
|
name,
|
|
2906
|
+
subname,
|
|
2099
2907
|
versionRange,
|
|
2100
2908
|
resolvedVersion,
|
|
2101
|
-
versionInfo: {
|
|
2102
|
-
downloadUrl: versionResponse.data.downloadUrl,
|
|
2103
|
-
checksum: versionResponse.data.checksum
|
|
2104
|
-
}
|
|
2909
|
+
versionInfo: { downloadUrl, checksum }
|
|
2105
2910
|
};
|
|
2106
2911
|
}
|
|
2912
|
+
function parseAnyGitHubFormat(specifier) {
|
|
2913
|
+
if (isGitHubSpecifier2(specifier)) {
|
|
2914
|
+
return parseGitHubSpecifier2(specifier);
|
|
2915
|
+
}
|
|
2916
|
+
if (isGitHubUrl(specifier)) {
|
|
2917
|
+
return parseGitHubUrl(specifier);
|
|
2918
|
+
}
|
|
2919
|
+
if (isGitHubShorthand(specifier)) {
|
|
2920
|
+
return parseGitHubShorthand(specifier);
|
|
2921
|
+
}
|
|
2922
|
+
return null;
|
|
2923
|
+
}
|
|
2107
2924
|
async function validateGitHubPackage(specifier) {
|
|
2108
|
-
const parsed =
|
|
2925
|
+
const parsed = parseAnyGitHubFormat(specifier);
|
|
2109
2926
|
if (!parsed) {
|
|
2110
2927
|
throw new Error(
|
|
2111
|
-
`Invalid GitHub specifier "${specifier}".
|
|
2928
|
+
`Invalid GitHub specifier "${specifier}". Supported formats:
|
|
2929
|
+
github:owner/repo[/path][@ref]
|
|
2930
|
+
https://github.com/owner/repo[/tree/branch/path]
|
|
2931
|
+
owner/repo[/path]`
|
|
2112
2932
|
);
|
|
2113
2933
|
}
|
|
2114
2934
|
const ref = parsed.ref || "HEAD";
|
|
@@ -2134,7 +2954,7 @@ async function installGitHubPackage(resolved, options) {
|
|
|
2134
2954
|
downloadResult.buffer,
|
|
2135
2955
|
skillsDir
|
|
2136
2956
|
);
|
|
2137
|
-
const lockfileSpecifier =
|
|
2957
|
+
const lockfileSpecifier = formatGitHubSpecifier2({
|
|
2138
2958
|
owner: parsed.owner,
|
|
2139
2959
|
repo: parsed.repo,
|
|
2140
2960
|
path: parsed.path
|
|
@@ -2152,15 +2972,16 @@ async function installGitHubPackage(resolved, options) {
|
|
|
2152
2972
|
const agents = options.resolvedAgents;
|
|
2153
2973
|
if (agents[0] !== "none") {
|
|
2154
2974
|
const manifest = await readManifest();
|
|
2155
|
-
const skillName =
|
|
2975
|
+
const skillName = getGitHubSkillName2(parsed);
|
|
2156
2976
|
const skillInfo = {
|
|
2157
2977
|
name: skillName,
|
|
2158
2978
|
sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
|
|
2159
2979
|
};
|
|
2160
2980
|
await createAgentSymlinks([skillInfo], {
|
|
2161
2981
|
agents,
|
|
2162
|
-
projectRoot:
|
|
2163
|
-
agentConfigs: manifest?.agents
|
|
2982
|
+
projectRoot: getSymlinkRoot(),
|
|
2983
|
+
agentConfigs: manifest?.agents,
|
|
2984
|
+
global: isGlobalMode()
|
|
2164
2985
|
});
|
|
2165
2986
|
}
|
|
2166
2987
|
console.log(
|
|
@@ -2171,7 +2992,7 @@ async function installGitHubPackage(resolved, options) {
|
|
|
2171
2992
|
async function validateLocalPackage(specifier) {
|
|
2172
2993
|
const path = parseLocalPath(specifier);
|
|
2173
2994
|
const resolvedPath = resolve(process.cwd(), path);
|
|
2174
|
-
const normalizedSpecifier =
|
|
2995
|
+
const normalizedSpecifier = normalizeToFileSpecifier2(path);
|
|
2175
2996
|
console.log(`Resolving ${specifier}...`);
|
|
2176
2997
|
try {
|
|
2177
2998
|
const stats = await stat(resolvedPath);
|
|
@@ -2246,13 +3067,72 @@ async function installLocalPackage(resolved, options) {
|
|
|
2246
3067
|
};
|
|
2247
3068
|
await createAgentSymlinks([skillInfo], {
|
|
2248
3069
|
agents,
|
|
2249
|
-
projectRoot:
|
|
2250
|
-
agentConfigs: manifest?.agents
|
|
3070
|
+
projectRoot: getSymlinkRoot(),
|
|
3071
|
+
agentConfigs: manifest?.agents,
|
|
3072
|
+
global: isGlobalMode()
|
|
2251
3073
|
});
|
|
2252
3074
|
}
|
|
2253
3075
|
console.log(`Installed ${specifier} (local)`);
|
|
2254
3076
|
console.log(`Location: ${symlinkPath} -> ${resolvedPath}`);
|
|
2255
3077
|
}
|
|
3078
|
+
async function validateWellKnownPackage(specifier) {
|
|
3079
|
+
const hostname = getWellKnownHostname(specifier);
|
|
3080
|
+
console.log(`Discovering skills from ${hostname}...`);
|
|
3081
|
+
const result = await fetchWellKnownSkills(specifier);
|
|
3082
|
+
if (!result) {
|
|
3083
|
+
throw new Error(
|
|
3084
|
+
`No well-known skills found at ${specifier}
|
|
3085
|
+
Expected: ${specifier}/.well-known/skills/index.json`
|
|
3086
|
+
);
|
|
3087
|
+
}
|
|
3088
|
+
console.log(
|
|
3089
|
+
`Found ${result.skills.length} skill(s) from ${hostname}: ${result.skills.map((s) => s.name).join(", ")}`
|
|
3090
|
+
);
|
|
3091
|
+
return {
|
|
3092
|
+
type: "wellknown",
|
|
3093
|
+
specifier,
|
|
3094
|
+
hostname: result.hostname,
|
|
3095
|
+
skills: result.skills,
|
|
3096
|
+
resolvedBaseUrl: result.resolvedBaseUrl
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
async function installWellKnownPackage(resolved, options) {
|
|
3100
|
+
const { specifier, hostname, skills } = resolved;
|
|
3101
|
+
const skillsDir = getSkillsDir();
|
|
3102
|
+
for (const skill of skills) {
|
|
3103
|
+
console.log(
|
|
3104
|
+
`Installing ${getWellKnownDisplayName(hostname, skill.name)}...`
|
|
3105
|
+
);
|
|
3106
|
+
const destPath = await extractWellKnownSkill(skill, hostname, skillsDir);
|
|
3107
|
+
const integrity = calculateWellKnownIntegrity(skill);
|
|
3108
|
+
const lockfileKey = `${specifier}#${skill.name}`;
|
|
3109
|
+
const entry = {
|
|
3110
|
+
version: "well-known",
|
|
3111
|
+
resolved: skill.sourceUrl,
|
|
3112
|
+
integrity,
|
|
3113
|
+
hostname,
|
|
3114
|
+
name: skill.name,
|
|
3115
|
+
files: [...skill.files.keys()]
|
|
3116
|
+
};
|
|
3117
|
+
await addWellKnownToLockfile(lockfileKey, entry);
|
|
3118
|
+
await addWellKnownDependency(specifier, [skill.name]);
|
|
3119
|
+
const agents = options.resolvedAgents;
|
|
3120
|
+
if (agents[0] !== "none") {
|
|
3121
|
+
const manifest = await readManifest();
|
|
3122
|
+
const skillInfo = {
|
|
3123
|
+
name: skill.name,
|
|
3124
|
+
sourcePath: getWellKnownSkillPath(hostname, skill.name)
|
|
3125
|
+
};
|
|
3126
|
+
await createAgentSymlinks([skillInfo], {
|
|
3127
|
+
agents,
|
|
3128
|
+
projectRoot: process.cwd(),
|
|
3129
|
+
agentConfigs: manifest?.agents
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
console.log(`Installed ${getWellKnownDisplayName(hostname, skill.name)}`);
|
|
3133
|
+
console.log(`Location: ${destPath}`);
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
2256
3136
|
var init_add = __esm({
|
|
2257
3137
|
"src/commands/add.ts"() {
|
|
2258
3138
|
init_agents();
|
|
@@ -2261,9 +3141,10 @@ var init_add = __esm({
|
|
|
2261
3141
|
init_errors();
|
|
2262
3142
|
init_github();
|
|
2263
3143
|
init_lib();
|
|
2264
|
-
|
|
2265
|
-
|
|
3144
|
+
init_lockfile3();
|
|
3145
|
+
init_manifest3();
|
|
2266
3146
|
init_symlinks();
|
|
3147
|
+
init_wellknown();
|
|
2267
3148
|
}
|
|
2268
3149
|
});
|
|
2269
3150
|
|
|
@@ -2271,7 +3152,7 @@ var init_add = __esm({
|
|
|
2271
3152
|
init_api_client();
|
|
2272
3153
|
init_config();
|
|
2273
3154
|
init_lib();
|
|
2274
|
-
function
|
|
3155
|
+
function isLocalSpecifier2(specifier) {
|
|
2275
3156
|
return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
|
|
2276
3157
|
}
|
|
2277
3158
|
async function access(specifier, options) {
|
|
@@ -2290,8 +3171,8 @@ async function access(specifier, options) {
|
|
|
2290
3171
|
let packageName;
|
|
2291
3172
|
let packageUsername;
|
|
2292
3173
|
if (specifier) {
|
|
2293
|
-
if (
|
|
2294
|
-
const ghSpec =
|
|
3174
|
+
if (isGitHubSpecifier2(specifier)) {
|
|
3175
|
+
const ghSpec = parseGitHubSpecifier2(specifier);
|
|
2295
3176
|
if (ghSpec) {
|
|
2296
3177
|
console.error(`Error: Cannot change visibility of GitHub packages.`);
|
|
2297
3178
|
console.error(
|
|
@@ -2306,7 +3187,7 @@ async function access(specifier, options) {
|
|
|
2306
3187
|
}
|
|
2307
3188
|
process.exit(1);
|
|
2308
3189
|
}
|
|
2309
|
-
if (
|
|
3190
|
+
if (isLocalSpecifier2(specifier)) {
|
|
2310
3191
|
console.error(`Error: Cannot change visibility of local packages.`);
|
|
2311
3192
|
console.error(
|
|
2312
3193
|
` "${specifier}" is a local directory, not a registry package.`
|
|
@@ -2316,10 +3197,12 @@ async function access(specifier, options) {
|
|
|
2316
3197
|
);
|
|
2317
3198
|
process.exit(1);
|
|
2318
3199
|
}
|
|
2319
|
-
const parsed =
|
|
3200
|
+
const parsed = parseRegistrySpecifier2(specifier);
|
|
2320
3201
|
if (!parsed) {
|
|
2321
3202
|
console.error(`Error: Invalid package specifier "${specifier}".`);
|
|
2322
|
-
console.error(
|
|
3203
|
+
console.error(
|
|
3204
|
+
` Use format: @user/{username}/{name} or @org/{orgname}/{name}`
|
|
3205
|
+
);
|
|
2323
3206
|
console.error(``);
|
|
2324
3207
|
console.error(` Examples:`);
|
|
2325
3208
|
console.error(` pspm access @user/myname/my-skill --public`);
|
|
@@ -2329,21 +3212,21 @@ async function access(specifier, options) {
|
|
|
2329
3212
|
process.exit(1);
|
|
2330
3213
|
}
|
|
2331
3214
|
packageName = parsed.name;
|
|
2332
|
-
packageUsername = parsed.
|
|
3215
|
+
packageUsername = parsed.owner;
|
|
2333
3216
|
} else {
|
|
2334
3217
|
const { readFile: readFile10 } = await import('fs/promises');
|
|
2335
|
-
const { join:
|
|
3218
|
+
const { join: join18 } = await import('path');
|
|
2336
3219
|
let manifest = null;
|
|
2337
3220
|
try {
|
|
2338
3221
|
const content = await readFile10(
|
|
2339
|
-
|
|
3222
|
+
join18(process.cwd(), "pspm.json"),
|
|
2340
3223
|
"utf-8"
|
|
2341
3224
|
);
|
|
2342
3225
|
manifest = JSON.parse(content);
|
|
2343
3226
|
} catch {
|
|
2344
3227
|
try {
|
|
2345
3228
|
const content = await readFile10(
|
|
2346
|
-
|
|
3229
|
+
join18(process.cwd(), "package.json"),
|
|
2347
3230
|
"utf-8"
|
|
2348
3231
|
);
|
|
2349
3232
|
manifest = JSON.parse(content);
|
|
@@ -2385,7 +3268,7 @@ async function access(specifier, options) {
|
|
|
2385
3268
|
}
|
|
2386
3269
|
const result = response.data;
|
|
2387
3270
|
console.log(
|
|
2388
|
-
`+
|
|
3271
|
+
`+ @${result.namespace ?? "user"}/${result.username}/${result.name} is now ${result.visibility}`
|
|
2389
3272
|
);
|
|
2390
3273
|
if (visibility === "public") {
|
|
2391
3274
|
console.log("");
|
|
@@ -2402,6 +3285,209 @@ async function access(specifier, options) {
|
|
|
2402
3285
|
|
|
2403
3286
|
// src/commands/index.ts
|
|
2404
3287
|
init_add();
|
|
3288
|
+
|
|
3289
|
+
// src/commands/audit.ts
|
|
3290
|
+
init_config();
|
|
3291
|
+
init_lib();
|
|
3292
|
+
init_lockfile3();
|
|
3293
|
+
async function audit(options) {
|
|
3294
|
+
try {
|
|
3295
|
+
const lockfile = await readLockfile();
|
|
3296
|
+
if (!lockfile) {
|
|
3297
|
+
if (options.json) {
|
|
3298
|
+
console.log(
|
|
3299
|
+
JSON.stringify({
|
|
3300
|
+
ok: false,
|
|
3301
|
+
issues: [
|
|
3302
|
+
{
|
|
3303
|
+
name: "-",
|
|
3304
|
+
source: "-",
|
|
3305
|
+
severity: "error",
|
|
3306
|
+
type: "no-lockfile",
|
|
3307
|
+
message: "No lockfile found. Run 'pspm install' first."
|
|
3308
|
+
}
|
|
3309
|
+
]
|
|
3310
|
+
})
|
|
3311
|
+
);
|
|
3312
|
+
} else {
|
|
3313
|
+
console.error("No lockfile found. Run 'pspm install' to create one.");
|
|
3314
|
+
}
|
|
3315
|
+
process.exit(1);
|
|
3316
|
+
}
|
|
3317
|
+
const issues = [];
|
|
3318
|
+
const skillsDir = getSkillsDir();
|
|
3319
|
+
const projectRoot = process.cwd();
|
|
3320
|
+
if (!options.json) {
|
|
3321
|
+
console.log("Auditing installed skills...\n");
|
|
3322
|
+
}
|
|
3323
|
+
const registrySkills = await listLockfileSkills();
|
|
3324
|
+
for (const { name: fullName, entry } of registrySkills) {
|
|
3325
|
+
const match = fullName.match(/^@user\/([^/]+)\/([^/]+)$/);
|
|
3326
|
+
if (!match) continue;
|
|
3327
|
+
const [, username, skillName] = match;
|
|
3328
|
+
const destDir = join(projectRoot, skillsDir, username, skillName);
|
|
3329
|
+
const exists = await pathExists(destDir);
|
|
3330
|
+
if (!exists) {
|
|
3331
|
+
issues.push({
|
|
3332
|
+
name: fullName,
|
|
3333
|
+
source: "registry",
|
|
3334
|
+
severity: "error",
|
|
3335
|
+
type: "missing",
|
|
3336
|
+
message: `Not installed on disk. Run 'pspm install' to restore.`
|
|
3337
|
+
});
|
|
3338
|
+
continue;
|
|
3339
|
+
}
|
|
3340
|
+
if (entry.deprecated) {
|
|
3341
|
+
issues.push({
|
|
3342
|
+
name: fullName,
|
|
3343
|
+
source: "registry",
|
|
3344
|
+
severity: "warning",
|
|
3345
|
+
type: "deprecated",
|
|
3346
|
+
message: `Deprecated: ${entry.deprecated}`
|
|
3347
|
+
});
|
|
3348
|
+
}
|
|
3349
|
+
const skillMdExists = await pathExists(join(destDir, "SKILL.md"));
|
|
3350
|
+
if (!skillMdExists) {
|
|
3351
|
+
issues.push({
|
|
3352
|
+
name: fullName,
|
|
3353
|
+
source: "registry",
|
|
3354
|
+
severity: "warning",
|
|
3355
|
+
type: "integrity",
|
|
3356
|
+
message: "Missing SKILL.md in installed directory. Package may be corrupted."
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
const githubSkills = await listLockfileGitHubPackages();
|
|
3361
|
+
for (const { specifier } of githubSkills) {
|
|
3362
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
3363
|
+
if (!parsed) continue;
|
|
3364
|
+
const destDir = parsed.path ? join(
|
|
3365
|
+
projectRoot,
|
|
3366
|
+
skillsDir,
|
|
3367
|
+
"_github",
|
|
3368
|
+
parsed.owner,
|
|
3369
|
+
parsed.repo,
|
|
3370
|
+
parsed.path
|
|
3371
|
+
) : join(projectRoot, skillsDir, "_github", parsed.owner, parsed.repo);
|
|
3372
|
+
const exists = await pathExists(destDir);
|
|
3373
|
+
if (!exists) {
|
|
3374
|
+
issues.push({
|
|
3375
|
+
name: specifier,
|
|
3376
|
+
source: "github",
|
|
3377
|
+
severity: "error",
|
|
3378
|
+
type: "missing",
|
|
3379
|
+
message: `Not installed on disk. Run 'pspm install' to restore.`
|
|
3380
|
+
});
|
|
3381
|
+
continue;
|
|
3382
|
+
}
|
|
3383
|
+
const skillMdExists = await pathExists(join(destDir, "SKILL.md"));
|
|
3384
|
+
if (!skillMdExists) {
|
|
3385
|
+
issues.push({
|
|
3386
|
+
name: specifier,
|
|
3387
|
+
source: "github",
|
|
3388
|
+
severity: "warning",
|
|
3389
|
+
type: "integrity",
|
|
3390
|
+
message: "Missing SKILL.md in installed directory. Package may be corrupted."
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
const wellKnownSkills = await listLockfileWellKnownPackages();
|
|
3395
|
+
for (const { specifier, entry } of wellKnownSkills) {
|
|
3396
|
+
const wkEntry = entry;
|
|
3397
|
+
const destDir = join(
|
|
3398
|
+
projectRoot,
|
|
3399
|
+
skillsDir,
|
|
3400
|
+
"_wellknown",
|
|
3401
|
+
wkEntry.hostname,
|
|
3402
|
+
wkEntry.name
|
|
3403
|
+
);
|
|
3404
|
+
const exists = await pathExists(destDir);
|
|
3405
|
+
if (!exists) {
|
|
3406
|
+
issues.push({
|
|
3407
|
+
name: specifier,
|
|
3408
|
+
source: "well-known",
|
|
3409
|
+
severity: "error",
|
|
3410
|
+
type: "missing",
|
|
3411
|
+
message: `Not installed on disk. Run 'pspm install' to restore.`
|
|
3412
|
+
});
|
|
3413
|
+
continue;
|
|
3414
|
+
}
|
|
3415
|
+
const skillMdExists = await pathExists(join(destDir, "SKILL.md"));
|
|
3416
|
+
if (!skillMdExists) {
|
|
3417
|
+
issues.push({
|
|
3418
|
+
name: specifier,
|
|
3419
|
+
source: "well-known",
|
|
3420
|
+
severity: "warning",
|
|
3421
|
+
type: "integrity",
|
|
3422
|
+
message: "Missing SKILL.md in installed directory. Package may be corrupted."
|
|
3423
|
+
});
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
3427
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
3428
|
+
if (options.json) {
|
|
3429
|
+
console.log(
|
|
3430
|
+
JSON.stringify(
|
|
3431
|
+
{
|
|
3432
|
+
ok: errorCount === 0,
|
|
3433
|
+
totalPackages: registrySkills.length + githubSkills.length + wellKnownSkills.length,
|
|
3434
|
+
issues
|
|
3435
|
+
},
|
|
3436
|
+
null,
|
|
3437
|
+
2
|
|
3438
|
+
)
|
|
3439
|
+
);
|
|
3440
|
+
if (errorCount > 0) process.exit(1);
|
|
3441
|
+
return;
|
|
3442
|
+
}
|
|
3443
|
+
if (issues.length === 0) {
|
|
3444
|
+
const totalPackages2 = registrySkills.length + githubSkills.length + wellKnownSkills.length;
|
|
3445
|
+
console.log(`Audited ${totalPackages2} package(s). No issues found.`);
|
|
3446
|
+
return;
|
|
3447
|
+
}
|
|
3448
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
3449
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
3450
|
+
if (errors.length > 0) {
|
|
3451
|
+
console.log("Errors:");
|
|
3452
|
+
for (const issue of errors) {
|
|
3453
|
+
console.log(
|
|
3454
|
+
` [${issue.type.toUpperCase()}] ${issue.name} (${issue.source})`
|
|
3455
|
+
);
|
|
3456
|
+
console.log(` ${issue.message}`);
|
|
3457
|
+
}
|
|
3458
|
+
console.log();
|
|
3459
|
+
}
|
|
3460
|
+
if (warnings.length > 0) {
|
|
3461
|
+
console.log("Warnings:");
|
|
3462
|
+
for (const issue of warnings) {
|
|
3463
|
+
console.log(
|
|
3464
|
+
` [${issue.type.toUpperCase()}] ${issue.name} (${issue.source})`
|
|
3465
|
+
);
|
|
3466
|
+
console.log(` ${issue.message}`);
|
|
3467
|
+
}
|
|
3468
|
+
console.log();
|
|
3469
|
+
}
|
|
3470
|
+
const totalPackages = registrySkills.length + githubSkills.length + wellKnownSkills.length;
|
|
3471
|
+
console.log(
|
|
3472
|
+
`Audited ${totalPackages} package(s): ${errorCount} error(s), ${warningCount} warning(s).`
|
|
3473
|
+
);
|
|
3474
|
+
if (errorCount > 0) {
|
|
3475
|
+
process.exit(1);
|
|
3476
|
+
}
|
|
3477
|
+
} catch (error) {
|
|
3478
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
3479
|
+
console.error(`Error: ${message}`);
|
|
3480
|
+
process.exit(1);
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
async function pathExists(path) {
|
|
3484
|
+
try {
|
|
3485
|
+
await stat(path);
|
|
3486
|
+
return true;
|
|
3487
|
+
} catch {
|
|
3488
|
+
return false;
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
2405
3491
|
async function configInit(options) {
|
|
2406
3492
|
try {
|
|
2407
3493
|
const configPath = join(process.cwd(), ".pspmrc");
|
|
@@ -2471,14 +3557,19 @@ async function deprecate(specifier, message, options) {
|
|
|
2471
3557
|
try {
|
|
2472
3558
|
const apiKey = await requireApiKey();
|
|
2473
3559
|
const registryUrl = await getRegistryUrl();
|
|
2474
|
-
const parsed =
|
|
3560
|
+
const parsed = parseRegistrySpecifier2(specifier);
|
|
2475
3561
|
if (!parsed) {
|
|
2476
3562
|
console.error(
|
|
2477
|
-
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}@{version}`
|
|
3563
|
+
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}@{version} or @org/{orgname}/{name}@{version}`
|
|
2478
3564
|
);
|
|
2479
3565
|
process.exit(1);
|
|
2480
3566
|
}
|
|
2481
|
-
const {
|
|
3567
|
+
const { owner, name, versionRange } = parsed;
|
|
3568
|
+
const fullName = generateRegistryIdentifier2({
|
|
3569
|
+
namespace: parsed.namespace,
|
|
3570
|
+
owner,
|
|
3571
|
+
name
|
|
3572
|
+
});
|
|
2482
3573
|
if (!versionRange) {
|
|
2483
3574
|
console.error(
|
|
2484
3575
|
"Error: Version is required for deprecation. Use format: @user/{username}/{name}@{version}"
|
|
@@ -2487,23 +3578,15 @@ async function deprecate(specifier, message, options) {
|
|
|
2487
3578
|
}
|
|
2488
3579
|
configure2({ registryUrl, apiKey });
|
|
2489
3580
|
if (options.undo) {
|
|
2490
|
-
console.log(
|
|
2491
|
-
|
|
2492
|
-
);
|
|
2493
|
-
const response = await undeprecateSkillVersion(
|
|
2494
|
-
username,
|
|
2495
|
-
name,
|
|
2496
|
-
versionRange
|
|
2497
|
-
);
|
|
3581
|
+
console.log(`Removing deprecation from ${fullName}@${versionRange}...`);
|
|
3582
|
+
const response = await undeprecateSkillVersion(owner, name, versionRange);
|
|
2498
3583
|
if (response.status !== 200) {
|
|
2499
3584
|
console.error(
|
|
2500
3585
|
`Error: ${response.error || "Failed to remove deprecation"}`
|
|
2501
3586
|
);
|
|
2502
3587
|
process.exit(1);
|
|
2503
3588
|
}
|
|
2504
|
-
console.log(
|
|
2505
|
-
`Removed deprecation from @user/${username}/${name}@${versionRange}`
|
|
2506
|
-
);
|
|
3589
|
+
console.log(`Removed deprecation from ${fullName}@${versionRange}`);
|
|
2507
3590
|
} else {
|
|
2508
3591
|
if (!message) {
|
|
2509
3592
|
console.error(
|
|
@@ -2511,9 +3594,9 @@ async function deprecate(specifier, message, options) {
|
|
|
2511
3594
|
);
|
|
2512
3595
|
process.exit(1);
|
|
2513
3596
|
}
|
|
2514
|
-
console.log(`Deprecating
|
|
3597
|
+
console.log(`Deprecating ${fullName}@${versionRange}...`);
|
|
2515
3598
|
const response = await deprecateSkillVersion(
|
|
2516
|
-
|
|
3599
|
+
owner,
|
|
2517
3600
|
name,
|
|
2518
3601
|
versionRange,
|
|
2519
3602
|
message
|
|
@@ -2524,7 +3607,7 @@ async function deprecate(specifier, message, options) {
|
|
|
2524
3607
|
);
|
|
2525
3608
|
process.exit(1);
|
|
2526
3609
|
}
|
|
2527
|
-
console.log(`Deprecated
|
|
3610
|
+
console.log(`Deprecated ${fullName}@${versionRange}`);
|
|
2528
3611
|
console.log(`Message: ${message}`);
|
|
2529
3612
|
console.log("");
|
|
2530
3613
|
console.log(
|
|
@@ -2764,8 +3847,8 @@ init_config();
|
|
|
2764
3847
|
init_errors();
|
|
2765
3848
|
init_github();
|
|
2766
3849
|
init_lib();
|
|
2767
|
-
|
|
2768
|
-
|
|
3850
|
+
init_lockfile3();
|
|
3851
|
+
init_manifest3();
|
|
2769
3852
|
init_symlinks();
|
|
2770
3853
|
function getCacheFilePath(cacheDir, integrity) {
|
|
2771
3854
|
const match = integrity.match(/^sha256-(.+)$/);
|
|
@@ -2799,12 +3882,17 @@ async function writeToCache(cacheDir, integrity, data) {
|
|
|
2799
3882
|
}
|
|
2800
3883
|
}
|
|
2801
3884
|
async function install(specifiers, options) {
|
|
3885
|
+
if (options.global) {
|
|
3886
|
+
const { setGlobalMode: setGlobalMode2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
3887
|
+
setGlobalMode2(true);
|
|
3888
|
+
}
|
|
2802
3889
|
if (specifiers.length > 0) {
|
|
2803
3890
|
const { add: add2 } = await Promise.resolve().then(() => (init_add(), add_exports));
|
|
2804
3891
|
await add2(specifiers, {
|
|
2805
3892
|
save: true,
|
|
2806
3893
|
agent: options.agent,
|
|
2807
|
-
yes: options.yes
|
|
3894
|
+
yes: options.yes,
|
|
3895
|
+
global: options.global
|
|
2808
3896
|
});
|
|
2809
3897
|
return;
|
|
2810
3898
|
}
|
|
@@ -2845,14 +3933,14 @@ async function installFromLockfile(options) {
|
|
|
2845
3933
|
`);
|
|
2846
3934
|
configure2({ registryUrl, apiKey });
|
|
2847
3935
|
for (const { fullName, versionRange } of missingDeps) {
|
|
2848
|
-
const parsed =
|
|
3936
|
+
const parsed = parseRegistrySpecifier2(fullName);
|
|
2849
3937
|
if (!parsed) {
|
|
2850
3938
|
console.error(`Error: Invalid dependency specifier: ${fullName}`);
|
|
2851
3939
|
continue;
|
|
2852
3940
|
}
|
|
2853
|
-
const {
|
|
3941
|
+
const { owner, name } = parsed;
|
|
2854
3942
|
console.log(`Resolving ${fullName}@${versionRange}...`);
|
|
2855
|
-
const versionsResponse = await listSkillVersions(
|
|
3943
|
+
const versionsResponse = await listSkillVersions(owner, name);
|
|
2856
3944
|
if (versionsResponse.status !== 200) {
|
|
2857
3945
|
const errorMessage = extractApiErrorMessage(
|
|
2858
3946
|
versionsResponse,
|
|
@@ -2869,14 +3957,14 @@ async function installFromLockfile(options) {
|
|
|
2869
3957
|
const versionStrings = versions.map(
|
|
2870
3958
|
(v) => v.version
|
|
2871
3959
|
);
|
|
2872
|
-
const resolved =
|
|
3960
|
+
const resolved = resolveVersion2(versionRange || "*", versionStrings);
|
|
2873
3961
|
if (!resolved) {
|
|
2874
3962
|
console.error(
|
|
2875
3963
|
`Error: No version matching "${versionRange}" for ${fullName}`
|
|
2876
3964
|
);
|
|
2877
3965
|
continue;
|
|
2878
3966
|
}
|
|
2879
|
-
const versionResponse = await getSkillVersion(
|
|
3967
|
+
const versionResponse = await getSkillVersion(owner, name, resolved);
|
|
2880
3968
|
if (versionResponse.status !== 200 || !versionResponse.data) {
|
|
2881
3969
|
const errorMessage = extractApiErrorMessage(
|
|
2882
3970
|
versionResponse,
|
|
@@ -2936,7 +4024,7 @@ Resolving ${missingGitHubDeps.length} GitHub dependency(ies)...
|
|
|
2936
4024
|
`
|
|
2937
4025
|
);
|
|
2938
4026
|
for (const { specifier, ref } of missingGitHubDeps) {
|
|
2939
|
-
const parsed =
|
|
4027
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
2940
4028
|
if (!parsed) {
|
|
2941
4029
|
console.error(`Error: Invalid GitHub specifier: ${specifier}`);
|
|
2942
4030
|
continue;
|
|
@@ -2996,12 +4084,12 @@ Installing ${packageCount} registry skill(s)...
|
|
|
2996
4084
|
const installOrder = computeInstallOrder(packages);
|
|
2997
4085
|
const entries = installOrder.filter((name) => packages[name]).map((name) => [name, packages[name]]);
|
|
2998
4086
|
for (const [fullName, entry] of entries) {
|
|
2999
|
-
const
|
|
3000
|
-
if (!
|
|
4087
|
+
const parsedName = parseRegistrySpecifier2(fullName);
|
|
4088
|
+
if (!parsedName) {
|
|
3001
4089
|
console.warn(`Warning: Invalid skill name in lockfile: ${fullName}`);
|
|
3002
4090
|
continue;
|
|
3003
4091
|
}
|
|
3004
|
-
const
|
|
4092
|
+
const { namespace: ns, owner: pkgOwner, name, subname } = parsedName;
|
|
3005
4093
|
console.log(`Installing ${fullName}@${entry.version}...`);
|
|
3006
4094
|
let tarballBuffer;
|
|
3007
4095
|
let fromCache = false;
|
|
@@ -3050,7 +4138,21 @@ Installing ${packageCount} registry skill(s)...
|
|
|
3050
4138
|
}
|
|
3051
4139
|
await writeToCache(cacheDir, entry.integrity, tarballBuffer);
|
|
3052
4140
|
}
|
|
3053
|
-
const
|
|
4141
|
+
const effectiveSkillName = subname ?? name;
|
|
4142
|
+
let destDir;
|
|
4143
|
+
if (ns === "org") {
|
|
4144
|
+
destDir = join(skillsDir, "_org", pkgOwner, effectiveSkillName);
|
|
4145
|
+
} else if (ns === "github" && subname) {
|
|
4146
|
+
destDir = join(
|
|
4147
|
+
skillsDir,
|
|
4148
|
+
"_github-registry",
|
|
4149
|
+
pkgOwner,
|
|
4150
|
+
name,
|
|
4151
|
+
subname
|
|
4152
|
+
);
|
|
4153
|
+
} else {
|
|
4154
|
+
destDir = join(skillsDir, pkgOwner, effectiveSkillName);
|
|
4155
|
+
}
|
|
3054
4156
|
await rm(destDir, { recursive: true, force: true });
|
|
3055
4157
|
await mkdir(destDir, { recursive: true });
|
|
3056
4158
|
const tempFile = join(destDir, ".temp.tgz");
|
|
@@ -3068,9 +4170,10 @@ Installing ${packageCount} registry skill(s)...
|
|
|
3068
4170
|
console.log(
|
|
3069
4171
|
` Installed to ${destDir}${fromCache ? " (from cache)" : ""}`
|
|
3070
4172
|
);
|
|
4173
|
+
const pathSkillName = ns === "github" && subname ? `${name}/${subname}` : name;
|
|
3071
4174
|
installedSkills.push({
|
|
3072
|
-
name,
|
|
3073
|
-
sourcePath: getRegistrySkillPath(
|
|
4175
|
+
name: effectiveSkillName,
|
|
4176
|
+
sourcePath: getRegistrySkillPath(ns, pkgOwner, pathSkillName)
|
|
3074
4177
|
});
|
|
3075
4178
|
}
|
|
3076
4179
|
}
|
|
@@ -3081,7 +4184,7 @@ Installing ${packageCount} registry skill(s)...
|
|
|
3081
4184
|
Installing ${githubCount} GitHub skill(s)...
|
|
3082
4185
|
`);
|
|
3083
4186
|
for (const [specifier, entry] of Object.entries(githubPackages)) {
|
|
3084
|
-
const parsed =
|
|
4187
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
3085
4188
|
if (!parsed) {
|
|
3086
4189
|
console.warn(
|
|
3087
4190
|
`Warning: Invalid GitHub specifier in lockfile: ${specifier}`
|
|
@@ -3136,7 +4239,7 @@ Installing ${githubCount} GitHub skill(s)...
|
|
|
3136
4239
|
console.log(
|
|
3137
4240
|
` Installed to ${destPath}${fromCache ? " (from cache)" : ""}`
|
|
3138
4241
|
);
|
|
3139
|
-
const skillName =
|
|
4242
|
+
const skillName = getGitHubSkillName2(parsed);
|
|
3140
4243
|
installedSkills.push({
|
|
3141
4244
|
name: skillName,
|
|
3142
4245
|
sourcePath: getGitHubSkillPath(
|
|
@@ -3152,12 +4255,16 @@ Installing ${githubCount} GitHub skill(s)...
|
|
|
3152
4255
|
}
|
|
3153
4256
|
}
|
|
3154
4257
|
if (installedSkills.length > 0 && agents[0] !== "none") {
|
|
3155
|
-
|
|
3156
|
-
|
|
4258
|
+
const globalMode = isGlobalMode();
|
|
4259
|
+
console.log(
|
|
4260
|
+
`
|
|
4261
|
+
Creating symlinks for agent(s): ${agents.join(", ")}${globalMode ? " (global)" : ""}...`
|
|
4262
|
+
);
|
|
3157
4263
|
await createAgentSymlinks(installedSkills, {
|
|
3158
4264
|
agents,
|
|
3159
|
-
projectRoot: process.cwd(),
|
|
3160
|
-
agentConfigs
|
|
4265
|
+
projectRoot: globalMode ? homedir() : process.cwd(),
|
|
4266
|
+
agentConfigs,
|
|
4267
|
+
global: globalMode
|
|
3161
4268
|
});
|
|
3162
4269
|
console.log(" Symlinks created.");
|
|
3163
4270
|
}
|
|
@@ -3178,11 +4285,15 @@ All ${totalCount} skill(s) installed.`);
|
|
|
3178
4285
|
// src/commands/link.ts
|
|
3179
4286
|
init_agents();
|
|
3180
4287
|
init_lib();
|
|
3181
|
-
|
|
3182
|
-
|
|
4288
|
+
init_lockfile3();
|
|
4289
|
+
init_manifest3();
|
|
3183
4290
|
init_symlinks();
|
|
3184
4291
|
async function link(options) {
|
|
3185
4292
|
try {
|
|
4293
|
+
if (options.global) {
|
|
4294
|
+
const { setGlobalMode: setGlobalMode2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
4295
|
+
setGlobalMode2(true);
|
|
4296
|
+
}
|
|
3186
4297
|
const manifest = await readManifest();
|
|
3187
4298
|
const agentConfigs = manifest?.agents;
|
|
3188
4299
|
let agents;
|
|
@@ -3203,26 +4314,32 @@ async function link(options) {
|
|
|
3203
4314
|
const skills = [];
|
|
3204
4315
|
const registrySkills = await listLockfileSkills();
|
|
3205
4316
|
for (const { name } of registrySkills) {
|
|
3206
|
-
const parsed =
|
|
4317
|
+
const parsed = parseRegistrySpecifier2(name);
|
|
3207
4318
|
if (!parsed) {
|
|
3208
4319
|
console.warn(`Warning: Invalid skill name in lockfile: ${name}`);
|
|
3209
4320
|
continue;
|
|
3210
4321
|
}
|
|
4322
|
+
const effectiveName = parsed.subname ?? parsed.name;
|
|
4323
|
+
const pathName = parsed.namespace === "github" && parsed.subname ? `${parsed.name}/${parsed.subname}` : parsed.name;
|
|
3211
4324
|
skills.push({
|
|
3212
|
-
name:
|
|
3213
|
-
sourcePath: getRegistrySkillPath(
|
|
4325
|
+
name: effectiveName,
|
|
4326
|
+
sourcePath: getRegistrySkillPath(
|
|
4327
|
+
parsed.namespace,
|
|
4328
|
+
parsed.owner,
|
|
4329
|
+
pathName
|
|
4330
|
+
)
|
|
3214
4331
|
});
|
|
3215
4332
|
}
|
|
3216
4333
|
const githubSkills = await listLockfileGitHubPackages();
|
|
3217
4334
|
for (const { specifier } of githubSkills) {
|
|
3218
|
-
const parsed =
|
|
4335
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
3219
4336
|
if (!parsed) {
|
|
3220
4337
|
console.warn(
|
|
3221
4338
|
`Warning: Invalid GitHub specifier in lockfile: ${specifier}`
|
|
3222
4339
|
);
|
|
3223
4340
|
continue;
|
|
3224
4341
|
}
|
|
3225
|
-
const skillName =
|
|
4342
|
+
const skillName = getGitHubSkillName2(parsed);
|
|
3226
4343
|
skills.push({
|
|
3227
4344
|
name: skillName,
|
|
3228
4345
|
sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
|
|
@@ -3235,10 +4352,12 @@ async function link(options) {
|
|
|
3235
4352
|
console.log(
|
|
3236
4353
|
`Creating symlinks for ${skills.length} skill(s) to agent(s): ${agents.join(", ")}...`
|
|
3237
4354
|
);
|
|
4355
|
+
const globalMode = options.global ?? false;
|
|
3238
4356
|
await createAgentSymlinks(skills, {
|
|
3239
4357
|
agents,
|
|
3240
|
-
projectRoot: process.cwd(),
|
|
3241
|
-
agentConfigs
|
|
4358
|
+
projectRoot: globalMode ? (await import('os')).homedir() : process.cwd(),
|
|
4359
|
+
agentConfigs,
|
|
4360
|
+
global: globalMode
|
|
3242
4361
|
});
|
|
3243
4362
|
console.log("Symlinks created successfully.");
|
|
3244
4363
|
console.log("\nLinked skills:");
|
|
@@ -3255,23 +4374,33 @@ async function link(options) {
|
|
|
3255
4374
|
// src/commands/list.ts
|
|
3256
4375
|
init_agents();
|
|
3257
4376
|
init_lib();
|
|
3258
|
-
|
|
3259
|
-
|
|
4377
|
+
init_lockfile3();
|
|
4378
|
+
init_manifest3();
|
|
3260
4379
|
init_symlinks();
|
|
3261
4380
|
async function list(options) {
|
|
3262
4381
|
try {
|
|
4382
|
+
if (options.global) {
|
|
4383
|
+
const { setGlobalMode: setGlobalMode2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
4384
|
+
setGlobalMode2(true);
|
|
4385
|
+
}
|
|
3263
4386
|
const registrySkills = await listLockfileSkills();
|
|
3264
4387
|
const githubSkills = await listLockfileGitHubPackages();
|
|
4388
|
+
const wellKnownSkills = await listLockfileWellKnownPackages();
|
|
3265
4389
|
const manifest = await readManifest();
|
|
3266
4390
|
const agentConfigs = manifest?.agents;
|
|
3267
4391
|
const availableAgents = getAvailableAgents(agentConfigs);
|
|
3268
4392
|
const projectRoot = process.cwd();
|
|
3269
4393
|
const skills = [];
|
|
3270
4394
|
for (const { name: fullName, entry } of registrySkills) {
|
|
3271
|
-
const
|
|
3272
|
-
if (!
|
|
3273
|
-
const
|
|
3274
|
-
const
|
|
4395
|
+
const parsed = parseRegistrySpecifier2(fullName);
|
|
4396
|
+
if (!parsed) continue;
|
|
4397
|
+
const skillName = parsed.subname ?? parsed.name;
|
|
4398
|
+
const pathName = parsed.namespace === "github" && parsed.subname ? `${parsed.name}/${parsed.subname}` : parsed.name;
|
|
4399
|
+
const sourcePath = getRegistrySkillPath(
|
|
4400
|
+
parsed.namespace,
|
|
4401
|
+
parsed.owner,
|
|
4402
|
+
pathName
|
|
4403
|
+
);
|
|
3275
4404
|
const absolutePath = join(projectRoot, sourcePath);
|
|
3276
4405
|
let status = "installed";
|
|
3277
4406
|
try {
|
|
@@ -3296,10 +4425,10 @@ async function list(options) {
|
|
|
3296
4425
|
});
|
|
3297
4426
|
}
|
|
3298
4427
|
for (const { specifier, entry } of githubSkills) {
|
|
3299
|
-
const parsed =
|
|
4428
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
3300
4429
|
if (!parsed) continue;
|
|
3301
4430
|
const ghEntry = entry;
|
|
3302
|
-
const skillName =
|
|
4431
|
+
const skillName = getGitHubSkillName2(parsed);
|
|
3303
4432
|
const sourcePath = getGitHubSkillPath(
|
|
3304
4433
|
parsed.owner,
|
|
3305
4434
|
parsed.repo,
|
|
@@ -3330,6 +4459,34 @@ async function list(options) {
|
|
|
3330
4459
|
gitCommit: ghEntry.gitCommit
|
|
3331
4460
|
});
|
|
3332
4461
|
}
|
|
4462
|
+
for (const { specifier, entry } of wellKnownSkills) {
|
|
4463
|
+
const wkEntry = entry;
|
|
4464
|
+
const skillName = wkEntry.name;
|
|
4465
|
+
const sourcePath = getWellKnownSkillPath(wkEntry.hostname, skillName);
|
|
4466
|
+
const absolutePath = join(projectRoot, sourcePath);
|
|
4467
|
+
let status = "installed";
|
|
4468
|
+
try {
|
|
4469
|
+
await access$1(absolutePath);
|
|
4470
|
+
} catch {
|
|
4471
|
+
status = "missing";
|
|
4472
|
+
}
|
|
4473
|
+
const linkedAgents = await getLinkedAgents(
|
|
4474
|
+
skillName,
|
|
4475
|
+
availableAgents,
|
|
4476
|
+
projectRoot,
|
|
4477
|
+
agentConfigs
|
|
4478
|
+
);
|
|
4479
|
+
skills.push({
|
|
4480
|
+
name: skillName,
|
|
4481
|
+
fullName: specifier,
|
|
4482
|
+
version: "well-known",
|
|
4483
|
+
source: "well-known",
|
|
4484
|
+
sourcePath,
|
|
4485
|
+
status,
|
|
4486
|
+
linkedAgents,
|
|
4487
|
+
hostname: wkEntry.hostname
|
|
4488
|
+
});
|
|
4489
|
+
}
|
|
3333
4490
|
if (skills.length === 0) {
|
|
3334
4491
|
console.log("No skills installed.");
|
|
3335
4492
|
return;
|
|
@@ -3342,6 +4499,8 @@ async function list(options) {
|
|
|
3342
4499
|
for (const skill of skills) {
|
|
3343
4500
|
if (skill.source === "registry") {
|
|
3344
4501
|
console.log(` ${skill.fullName}@${skill.version} (registry)`);
|
|
4502
|
+
} else if (skill.source === "well-known") {
|
|
4503
|
+
console.log(` ${skill.name} (well-known: ${skill.hostname})`);
|
|
3345
4504
|
} else {
|
|
3346
4505
|
const refInfo = skill.gitRef ? `${skill.gitRef}@${skill.gitCommit?.slice(0, 7)}` : skill.version;
|
|
3347
4506
|
console.log(` ${skill.fullName} (${refInfo})`);
|
|
@@ -3360,9 +4519,13 @@ async function list(options) {
|
|
|
3360
4519
|
}
|
|
3361
4520
|
const registryCount = skills.filter((s) => s.source === "registry").length;
|
|
3362
4521
|
const githubCount = skills.filter((s) => s.source === "github").length;
|
|
4522
|
+
const wellKnownCount = skills.filter(
|
|
4523
|
+
(s) => s.source === "well-known"
|
|
4524
|
+
).length;
|
|
3363
4525
|
const parts = [];
|
|
3364
4526
|
if (registryCount > 0) parts.push(`${registryCount} registry`);
|
|
3365
4527
|
if (githubCount > 0) parts.push(`${githubCount} github`);
|
|
4528
|
+
if (wellKnownCount > 0) parts.push(`${wellKnownCount} well-known`);
|
|
3366
4529
|
console.log(`
|
|
3367
4530
|
Total: ${skills.length} skill(s) (${parts.join(", ")})`);
|
|
3368
4531
|
} catch (error) {
|
|
@@ -3579,7 +4742,7 @@ async function logout() {
|
|
|
3579
4742
|
|
|
3580
4743
|
// src/commands/migrate.ts
|
|
3581
4744
|
init_config();
|
|
3582
|
-
|
|
4745
|
+
init_lockfile3();
|
|
3583
4746
|
async function migrate(options) {
|
|
3584
4747
|
try {
|
|
3585
4748
|
const legacySkillsDir = getLegacySkillsDir();
|
|
@@ -3679,20 +4842,20 @@ async function migrate(options) {
|
|
|
3679
4842
|
process.exit(1);
|
|
3680
4843
|
}
|
|
3681
4844
|
}
|
|
3682
|
-
function
|
|
3683
|
-
const sorted = availableVersions.filter((v) =>
|
|
4845
|
+
function resolveVersion3(range, availableVersions) {
|
|
4846
|
+
const sorted = availableVersions.filter((v) => semver2.valid(v)).sort((a, b) => semver2.rcompare(a, b));
|
|
3684
4847
|
if (range === "latest") {
|
|
3685
4848
|
return sorted[0] ?? null;
|
|
3686
4849
|
}
|
|
3687
|
-
return
|
|
4850
|
+
return semver2.maxSatisfying(sorted, range);
|
|
3688
4851
|
}
|
|
3689
|
-
function
|
|
3690
|
-
return
|
|
4852
|
+
function compareVersions3(a, b) {
|
|
4853
|
+
return semver2.compare(a, b);
|
|
3691
4854
|
}
|
|
3692
|
-
function
|
|
3693
|
-
const
|
|
3694
|
-
if (
|
|
3695
|
-
return
|
|
4855
|
+
function getLatestVersion3(versions) {
|
|
4856
|
+
const valid5 = versions.filter((v) => semver2.valid(v));
|
|
4857
|
+
if (valid5.length === 0) return null;
|
|
4858
|
+
return valid5.sort((a, b) => semver2.rcompare(a, b))[0];
|
|
3696
4859
|
}
|
|
3697
4860
|
|
|
3698
4861
|
// ../../packages/server/skill-registry/src/client/outdated.ts
|
|
@@ -3725,14 +4888,14 @@ function createOutdatedChecker(config2) {
|
|
|
3725
4888
|
const versions = await fetchRegistryVersions(username, name);
|
|
3726
4889
|
const versionStrings = versions.map((v) => v.version);
|
|
3727
4890
|
const range = versionRange || "*";
|
|
3728
|
-
const wanted =
|
|
3729
|
-
const latest =
|
|
4891
|
+
const wanted = resolveVersion3(range, versionStrings);
|
|
4892
|
+
const latest = getLatestVersion3(versionStrings);
|
|
3730
4893
|
const currentVersionInfo = versions.find(
|
|
3731
4894
|
(v) => v.version === entry.version
|
|
3732
4895
|
);
|
|
3733
4896
|
const deprecated = currentVersionInfo?.deprecationMessage ?? void 0;
|
|
3734
|
-
const isOutdated = wanted !== null &&
|
|
3735
|
-
const wantedBehindLatest = wanted !== null && latest !== null &&
|
|
4897
|
+
const isOutdated = wanted !== null && compareVersions3(entry.version, wanted) < 0 || latest !== null && compareVersions3(entry.version, latest) < 0;
|
|
4898
|
+
const wantedBehindLatest = wanted !== null && latest !== null && compareVersions3(wanted, latest) < 0;
|
|
3736
4899
|
return {
|
|
3737
4900
|
name: specifier,
|
|
3738
4901
|
current: entry.version,
|
|
@@ -3865,8 +5028,8 @@ async function checkOutdated(config2, options) {
|
|
|
3865
5028
|
|
|
3866
5029
|
// src/commands/outdated.ts
|
|
3867
5030
|
init_config();
|
|
3868
|
-
|
|
3869
|
-
|
|
5031
|
+
init_lockfile3();
|
|
5032
|
+
init_manifest3();
|
|
3870
5033
|
async function outdated(packages, options) {
|
|
3871
5034
|
try {
|
|
3872
5035
|
const lockfile = await readLockfile();
|
|
@@ -4074,8 +5237,8 @@ async function publishCommand(options) {
|
|
|
4074
5237
|
dependencies: manifest.dependencies
|
|
4075
5238
|
};
|
|
4076
5239
|
if (options.bump) {
|
|
4077
|
-
const
|
|
4078
|
-
const newVersion =
|
|
5240
|
+
const semver6 = await import('semver');
|
|
5241
|
+
const newVersion = semver6.default.inc(packageJson2.version, options.bump);
|
|
4079
5242
|
if (!newVersion) {
|
|
4080
5243
|
console.error(
|
|
4081
5244
|
`Error: Failed to bump version from ${packageJson2.version}`
|
|
@@ -4204,7 +5367,7 @@ async function publishCommand(options) {
|
|
|
4204
5367
|
const visibility = result.skill.visibility;
|
|
4205
5368
|
const visibilityIcon = visibility === "public" ? "\u{1F310}" : "\u{1F512}";
|
|
4206
5369
|
console.log(
|
|
4207
|
-
`+
|
|
5370
|
+
`+ @${result.skill.namespace ?? "user"}/${result.skill.username}/${result.skill.name}@${result.version.version}`
|
|
4208
5371
|
);
|
|
4209
5372
|
console.log(`Checksum: ${result.version.checksum}`);
|
|
4210
5373
|
console.log(`Visibility: ${visibilityIcon} ${visibility}`);
|
|
@@ -4231,17 +5394,17 @@ async function publishCommand(options) {
|
|
|
4231
5394
|
init_agents();
|
|
4232
5395
|
init_config();
|
|
4233
5396
|
init_lib();
|
|
4234
|
-
|
|
4235
|
-
|
|
5397
|
+
init_lockfile3();
|
|
5398
|
+
init_manifest3();
|
|
4236
5399
|
init_symlinks();
|
|
4237
5400
|
async function remove(nameOrSpecifier) {
|
|
4238
5401
|
try {
|
|
4239
5402
|
const manifest = await readManifest();
|
|
4240
5403
|
const agentConfigs = manifest?.agents;
|
|
4241
5404
|
const agents = getAvailableAgents(agentConfigs);
|
|
4242
|
-
if (
|
|
5405
|
+
if (isGitHubSpecifier2(nameOrSpecifier)) {
|
|
4243
5406
|
await removeGitHub(nameOrSpecifier, agents, agentConfigs);
|
|
4244
|
-
} else if (nameOrSpecifier
|
|
5407
|
+
} else if (isRegistrySpecifier2(nameOrSpecifier)) {
|
|
4245
5408
|
await removeRegistry(nameOrSpecifier, agents, agentConfigs);
|
|
4246
5409
|
} else {
|
|
4247
5410
|
await removeByShortName(nameOrSpecifier, agents, agentConfigs);
|
|
@@ -4253,14 +5416,13 @@ async function remove(nameOrSpecifier) {
|
|
|
4253
5416
|
}
|
|
4254
5417
|
}
|
|
4255
5418
|
async function removeRegistry(specifier, agents, agentConfigs) {
|
|
4256
|
-
const
|
|
4257
|
-
if (!
|
|
5419
|
+
const parsed = parseRegistrySpecifier2(specifier);
|
|
5420
|
+
if (!parsed) {
|
|
4258
5421
|
console.error(`Error: Invalid skill specifier: ${specifier}`);
|
|
4259
5422
|
process.exit(1);
|
|
4260
5423
|
}
|
|
4261
|
-
const
|
|
4262
|
-
const
|
|
4263
|
-
const name = match[2];
|
|
5424
|
+
const { namespace, owner, name } = parsed;
|
|
5425
|
+
const fullName = `@${namespace}/${owner}/${name}`;
|
|
4264
5426
|
console.log(`Removing ${fullName}...`);
|
|
4265
5427
|
const removedFromLockfile = await removeFromLockfile(fullName);
|
|
4266
5428
|
const removedFromManifest = await removeDependency(fullName);
|
|
@@ -4274,7 +5436,7 @@ async function removeRegistry(specifier, agents, agentConfigs) {
|
|
|
4274
5436
|
agentConfigs
|
|
4275
5437
|
});
|
|
4276
5438
|
const skillsDir = getSkillsDir();
|
|
4277
|
-
const destDir = join(skillsDir,
|
|
5439
|
+
const destDir = namespace === "org" ? join(skillsDir, "_org", owner, name) : join(skillsDir, owner, name);
|
|
4278
5440
|
try {
|
|
4279
5441
|
await rm(destDir, { recursive: true, force: true });
|
|
4280
5442
|
} catch {
|
|
@@ -4282,7 +5444,7 @@ async function removeRegistry(specifier, agents, agentConfigs) {
|
|
|
4282
5444
|
console.log(`Removed ${fullName}`);
|
|
4283
5445
|
}
|
|
4284
5446
|
async function removeGitHub(specifier, agents, agentConfigs) {
|
|
4285
|
-
const parsed =
|
|
5447
|
+
const parsed = parseGitHubSpecifier2(specifier);
|
|
4286
5448
|
if (!parsed) {
|
|
4287
5449
|
console.error(`Error: Invalid GitHub specifier: ${specifier}`);
|
|
4288
5450
|
process.exit(1);
|
|
@@ -4295,7 +5457,7 @@ async function removeGitHub(specifier, agents, agentConfigs) {
|
|
|
4295
5457
|
console.error(`Error: ${lockfileKey} not found in lockfile or pspm.json`);
|
|
4296
5458
|
process.exit(1);
|
|
4297
5459
|
}
|
|
4298
|
-
const skillName =
|
|
5460
|
+
const skillName = getGitHubSkillName2(parsed);
|
|
4299
5461
|
await removeAgentSymlinks(skillName, {
|
|
4300
5462
|
agents,
|
|
4301
5463
|
projectRoot: process.cwd(),
|
|
@@ -4313,8 +5475,8 @@ async function removeGitHub(specifier, agents, agentConfigs) {
|
|
|
4313
5475
|
async function removeByShortName(shortName, agents, agentConfigs) {
|
|
4314
5476
|
const registrySkills = await listLockfileSkills();
|
|
4315
5477
|
const foundRegistry = registrySkills.find((s) => {
|
|
4316
|
-
const
|
|
4317
|
-
return
|
|
5478
|
+
const parsed = parseRegistrySpecifier2(s.name);
|
|
5479
|
+
return parsed && parsed.name === shortName;
|
|
4318
5480
|
});
|
|
4319
5481
|
if (foundRegistry) {
|
|
4320
5482
|
await removeRegistry(foundRegistry.name, agents, agentConfigs);
|
|
@@ -4322,9 +5484,9 @@ async function removeByShortName(shortName, agents, agentConfigs) {
|
|
|
4322
5484
|
}
|
|
4323
5485
|
const githubSkills = await listLockfileGitHubPackages();
|
|
4324
5486
|
const foundGitHub = githubSkills.find((s) => {
|
|
4325
|
-
const parsed =
|
|
5487
|
+
const parsed = parseGitHubSpecifier2(s.specifier);
|
|
4326
5488
|
if (!parsed) return false;
|
|
4327
|
-
return
|
|
5489
|
+
return getGitHubSkillName2(parsed) === shortName;
|
|
4328
5490
|
});
|
|
4329
5491
|
if (foundGitHub) {
|
|
4330
5492
|
await removeGitHub(foundGitHub.specifier, agents, agentConfigs);
|
|
@@ -4334,6 +5496,88 @@ async function removeByShortName(shortName, agents, agentConfigs) {
|
|
|
4334
5496
|
process.exit(1);
|
|
4335
5497
|
}
|
|
4336
5498
|
|
|
5499
|
+
// src/commands/search.ts
|
|
5500
|
+
init_api_client();
|
|
5501
|
+
init_config();
|
|
5502
|
+
init_generated();
|
|
5503
|
+
async function search(query, options) {
|
|
5504
|
+
try {
|
|
5505
|
+
const config2 = await resolveConfig();
|
|
5506
|
+
const apiKey = getTokenForRegistry(config2, config2.registryUrl);
|
|
5507
|
+
configure2({ registryUrl: config2.registryUrl, apiKey });
|
|
5508
|
+
const limit = options.limit ?? 20;
|
|
5509
|
+
const sort = options.sort ?? "downloads";
|
|
5510
|
+
if (!options.json) {
|
|
5511
|
+
if (query) {
|
|
5512
|
+
console.log(`Searching for "${query}"...
|
|
5513
|
+
`);
|
|
5514
|
+
} else {
|
|
5515
|
+
console.log("Browsing skills...\n");
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
const response = await explorePublicSkills({
|
|
5519
|
+
search: query,
|
|
5520
|
+
sort,
|
|
5521
|
+
limit,
|
|
5522
|
+
page: 1
|
|
5523
|
+
});
|
|
5524
|
+
if (response.status !== 200) {
|
|
5525
|
+
console.error("Error: Failed to search skills");
|
|
5526
|
+
process.exit(1);
|
|
5527
|
+
}
|
|
5528
|
+
const { skills, total } = response.data;
|
|
5529
|
+
if (skills.length === 0) {
|
|
5530
|
+
if (query) {
|
|
5531
|
+
console.log(`No skills found matching "${query}".`);
|
|
5532
|
+
} else {
|
|
5533
|
+
console.log("No skills published yet.");
|
|
5534
|
+
}
|
|
5535
|
+
return;
|
|
5536
|
+
}
|
|
5537
|
+
if (options.json) {
|
|
5538
|
+
console.log(JSON.stringify(skills, null, 2));
|
|
5539
|
+
return;
|
|
5540
|
+
}
|
|
5541
|
+
for (const skill of skills) {
|
|
5542
|
+
const name = `@${skill.namespace ?? "user"}/${skill.username}/${skill.name}`;
|
|
5543
|
+
const desc = skill.description ? ` - ${skill.description.slice(0, 80)}${skill.description.length > 80 ? "..." : ""}` : "";
|
|
5544
|
+
const downloads = skill.totalDownloads > 0 ? ` (${formatDownloads(skill.totalDownloads)} downloads)` : "";
|
|
5545
|
+
console.log(` ${name}${downloads}`);
|
|
5546
|
+
if (desc) {
|
|
5547
|
+
console.log(` ${desc.trim()}`);
|
|
5548
|
+
}
|
|
5549
|
+
}
|
|
5550
|
+
const showing = Math.min(skills.length, limit);
|
|
5551
|
+
if (total > showing) {
|
|
5552
|
+
console.log(`
|
|
5553
|
+
Showing ${showing} of ${total} results.`);
|
|
5554
|
+
} else {
|
|
5555
|
+
console.log(`
|
|
5556
|
+
${total} skill(s) found.`);
|
|
5557
|
+
}
|
|
5558
|
+
if (skills.length > 0) {
|
|
5559
|
+
const first = skills[0];
|
|
5560
|
+
console.log(
|
|
5561
|
+
`
|
|
5562
|
+
Install with: pspm add @${first.namespace ?? "user"}/${first.username}/${first.name}`
|
|
5563
|
+
);
|
|
5564
|
+
}
|
|
5565
|
+
} catch (error) {
|
|
5566
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
5567
|
+
console.error(`Error: ${message}`);
|
|
5568
|
+
process.exit(1);
|
|
5569
|
+
}
|
|
5570
|
+
}
|
|
5571
|
+
function formatDownloads(count) {
|
|
5572
|
+
if (count >= 1e6) {
|
|
5573
|
+
return `${(count / 1e6).toFixed(1)}M`;
|
|
5574
|
+
}
|
|
5575
|
+
if (count >= 1e3) {
|
|
5576
|
+
return `${(count / 1e3).toFixed(1)}k`;
|
|
5577
|
+
}
|
|
5578
|
+
return String(count);
|
|
5579
|
+
}
|
|
5580
|
+
|
|
4337
5581
|
// src/commands/unpublish.ts
|
|
4338
5582
|
init_api_client();
|
|
4339
5583
|
init_config();
|
|
@@ -4343,14 +5587,19 @@ async function unpublish(specifier, options) {
|
|
|
4343
5587
|
try {
|
|
4344
5588
|
const apiKey = await requireApiKey();
|
|
4345
5589
|
const registryUrl = await getRegistryUrl();
|
|
4346
|
-
const parsed =
|
|
5590
|
+
const parsed = parseRegistrySpecifier2(specifier);
|
|
4347
5591
|
if (!parsed) {
|
|
4348
5592
|
console.error(
|
|
4349
|
-
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}]`
|
|
5593
|
+
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}] or @org/{orgname}/{name}[@{version}]`
|
|
4350
5594
|
);
|
|
4351
5595
|
process.exit(1);
|
|
4352
5596
|
}
|
|
4353
|
-
const {
|
|
5597
|
+
const { owner, name, versionRange } = parsed;
|
|
5598
|
+
const fullName = generateRegistryIdentifier2({
|
|
5599
|
+
namespace: parsed.namespace,
|
|
5600
|
+
owner,
|
|
5601
|
+
name
|
|
5602
|
+
});
|
|
4354
5603
|
configure2({ registryUrl, apiKey });
|
|
4355
5604
|
if (versionRange) {
|
|
4356
5605
|
console.log(`Unpublishing ${specifier}...`);
|
|
@@ -4360,7 +5609,7 @@ async function unpublish(specifier, options) {
|
|
|
4360
5609
|
);
|
|
4361
5610
|
process.exit(1);
|
|
4362
5611
|
}
|
|
4363
|
-
const response = await deleteSkillVersion(
|
|
5612
|
+
const response = await deleteSkillVersion(owner, name, versionRange);
|
|
4364
5613
|
if (response.status !== 200) {
|
|
4365
5614
|
const errorMessage = extractApiErrorMessage(
|
|
4366
5615
|
response,
|
|
@@ -4369,16 +5618,16 @@ async function unpublish(specifier, options) {
|
|
|
4369
5618
|
console.error(`Error: ${errorMessage}`);
|
|
4370
5619
|
process.exit(1);
|
|
4371
5620
|
}
|
|
4372
|
-
console.log(`Unpublished
|
|
5621
|
+
console.log(`Unpublished ${fullName}@${versionRange}`);
|
|
4373
5622
|
} else {
|
|
4374
|
-
console.log(`Unpublishing all versions of
|
|
5623
|
+
console.log(`Unpublishing all versions of ${fullName}...`);
|
|
4375
5624
|
if (!options.force) {
|
|
4376
5625
|
console.error(
|
|
4377
5626
|
"Warning: This will delete ALL versions. Use --force to confirm."
|
|
4378
5627
|
);
|
|
4379
5628
|
process.exit(1);
|
|
4380
5629
|
}
|
|
4381
|
-
const response = await deleteSkill(
|
|
5630
|
+
const response = await deleteSkill(owner, name);
|
|
4382
5631
|
if (response.status !== 200) {
|
|
4383
5632
|
const errorMessage = extractApiErrorMessage(
|
|
4384
5633
|
response,
|
|
@@ -4387,7 +5636,7 @@ async function unpublish(specifier, options) {
|
|
|
4387
5636
|
console.error(`Error: ${errorMessage}`);
|
|
4388
5637
|
process.exit(1);
|
|
4389
5638
|
}
|
|
4390
|
-
console.log(`Unpublished
|
|
5639
|
+
console.log(`Unpublished ${fullName} (all versions)`);
|
|
4391
5640
|
}
|
|
4392
5641
|
} catch (error) {
|
|
4393
5642
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -4401,7 +5650,7 @@ init_api_client();
|
|
|
4401
5650
|
init_config();
|
|
4402
5651
|
init_errors();
|
|
4403
5652
|
init_lib();
|
|
4404
|
-
|
|
5653
|
+
init_lockfile3();
|
|
4405
5654
|
init_add();
|
|
4406
5655
|
async function update(options) {
|
|
4407
5656
|
try {
|
|
@@ -4417,11 +5666,13 @@ async function update(options) {
|
|
|
4417
5666
|
const updates = [];
|
|
4418
5667
|
console.log("Checking for updates...\n");
|
|
4419
5668
|
for (const { name, entry } of skills) {
|
|
4420
|
-
const
|
|
4421
|
-
if (!
|
|
4422
|
-
const [, username, skillName] = match;
|
|
5669
|
+
const parsed = parseRegistrySpecifier2(name);
|
|
5670
|
+
if (!parsed) continue;
|
|
4423
5671
|
try {
|
|
4424
|
-
const versionsResponse = await listSkillVersions(
|
|
5672
|
+
const versionsResponse = await listSkillVersions(
|
|
5673
|
+
parsed.owner,
|
|
5674
|
+
parsed.name
|
|
5675
|
+
);
|
|
4425
5676
|
if (versionsResponse.status !== 200) {
|
|
4426
5677
|
const errorMessage = extractApiErrorMessage(
|
|
4427
5678
|
versionsResponse,
|
|
@@ -4435,7 +5686,7 @@ async function update(options) {
|
|
|
4435
5686
|
const versionStrings = versions.map(
|
|
4436
5687
|
(v) => v.version
|
|
4437
5688
|
);
|
|
4438
|
-
const latest =
|
|
5689
|
+
const latest = resolveVersion2("*", versionStrings);
|
|
4439
5690
|
if (latest && latest !== entry.version) {
|
|
4440
5691
|
updates.push({
|
|
4441
5692
|
name,
|
|
@@ -4460,11 +5711,10 @@ async function update(options) {
|
|
|
4460
5711
|
return;
|
|
4461
5712
|
}
|
|
4462
5713
|
console.log("\nUpdating...\n");
|
|
4463
|
-
for (const { name, latest } of updates) {
|
|
4464
|
-
const
|
|
4465
|
-
if (!
|
|
4466
|
-
const
|
|
4467
|
-
const specifier = `@user/${username}/${skillName}@${latest}`;
|
|
5714
|
+
for (const { name: pkgName, latest } of updates) {
|
|
5715
|
+
const parsed = parseRegistrySpecifier2(pkgName);
|
|
5716
|
+
if (!parsed) continue;
|
|
5717
|
+
const specifier = `${pkgName}@${latest}`;
|
|
4468
5718
|
await add([specifier], {});
|
|
4469
5719
|
}
|
|
4470
5720
|
console.log("\nAll skills updated.");
|
|
@@ -4479,12 +5729,12 @@ async function upgrade() {
|
|
|
4479
5729
|
try {
|
|
4480
5730
|
const currentVersion = getCurrentVersion();
|
|
4481
5731
|
console.log("Checking for updates...\n");
|
|
4482
|
-
const latestVersion =
|
|
5732
|
+
const latestVersion = getLatestVersion4(packageName);
|
|
4483
5733
|
if (!latestVersion) {
|
|
4484
5734
|
console.error("Error: Could not fetch latest version from registry.");
|
|
4485
5735
|
process.exit(1);
|
|
4486
5736
|
}
|
|
4487
|
-
if (currentVersion
|
|
5737
|
+
if (semver2.valid(currentVersion) && semver2.valid(latestVersion) && !semver2.gt(latestVersion, currentVersion)) {
|
|
4488
5738
|
console.log(`Already on the latest version: ${currentVersion}`);
|
|
4489
5739
|
return;
|
|
4490
5740
|
}
|
|
@@ -4517,7 +5767,7 @@ function getCurrentVersion() {
|
|
|
4517
5767
|
return "unknown";
|
|
4518
5768
|
}
|
|
4519
5769
|
}
|
|
4520
|
-
function
|
|
5770
|
+
function getLatestVersion4(packageName) {
|
|
4521
5771
|
try {
|
|
4522
5772
|
const output = execSync(`npm view ${packageName} version`, {
|
|
4523
5773
|
encoding: "utf-8",
|
|
@@ -4569,7 +5819,7 @@ function getInstallCommand(pm, packageName, version3) {
|
|
|
4569
5819
|
}
|
|
4570
5820
|
|
|
4571
5821
|
// src/commands/version.ts
|
|
4572
|
-
|
|
5822
|
+
init_manifest3();
|
|
4573
5823
|
async function version(bump, options = {}) {
|
|
4574
5824
|
try {
|
|
4575
5825
|
const manifest = await readManifest();
|
|
@@ -4585,7 +5835,7 @@ async function version(bump, options = {}) {
|
|
|
4585
5835
|
);
|
|
4586
5836
|
process.exit(1);
|
|
4587
5837
|
}
|
|
4588
|
-
if (!
|
|
5838
|
+
if (!semver2__default.valid(manifest.version)) {
|
|
4589
5839
|
console.error(
|
|
4590
5840
|
`Error: Current version "${manifest.version}" is not valid semver.`
|
|
4591
5841
|
);
|
|
@@ -4594,7 +5844,7 @@ async function version(bump, options = {}) {
|
|
|
4594
5844
|
);
|
|
4595
5845
|
process.exit(1);
|
|
4596
5846
|
}
|
|
4597
|
-
const newVersion =
|
|
5847
|
+
const newVersion = semver2__default.inc(manifest.version, bump);
|
|
4598
5848
|
if (!newVersion) {
|
|
4599
5849
|
console.error(`Error: Failed to bump version from ${manifest.version}`);
|
|
4600
5850
|
process.exit(1);
|
|
@@ -4640,6 +5890,9 @@ async function whoami() {
|
|
|
4640
5890
|
process.exit(1);
|
|
4641
5891
|
}
|
|
4642
5892
|
}
|
|
5893
|
+
|
|
5894
|
+
// src/update-notifier.ts
|
|
5895
|
+
init_version2();
|
|
4643
5896
|
var PACKAGE_NAME = "@anytio/pspm";
|
|
4644
5897
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
4645
5898
|
var CACHE_DIR = join(homedir(), ".pspm");
|
|
@@ -4648,7 +5901,7 @@ async function checkForUpdates(currentVersion) {
|
|
|
4648
5901
|
try {
|
|
4649
5902
|
const cache = await readCache();
|
|
4650
5903
|
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
4651
|
-
if (cache.latestVersion
|
|
5904
|
+
if (isNewerVersion2(cache.latestVersion, currentVersion)) {
|
|
4652
5905
|
printUpdateWarning(currentVersion, cache.latestVersion);
|
|
4653
5906
|
}
|
|
4654
5907
|
return;
|
|
@@ -4683,7 +5936,7 @@ function fetchAndCache(currentVersion) {
|
|
|
4683
5936
|
};
|
|
4684
5937
|
writeCache(cache).catch(() => {
|
|
4685
5938
|
});
|
|
4686
|
-
if (latestVersion
|
|
5939
|
+
if (isNewerVersion2(latestVersion, currentVersion)) {
|
|
4687
5940
|
printUpdateWarning(currentVersion, latestVersion);
|
|
4688
5941
|
}
|
|
4689
5942
|
} catch {
|
|
@@ -4705,7 +5958,7 @@ var packageJson = JSON.parse(
|
|
|
4705
5958
|
);
|
|
4706
5959
|
var version2 = packageJson.version;
|
|
4707
5960
|
var program = new Command();
|
|
4708
|
-
program.name("pspm").description("
|
|
5961
|
+
program.name("pspm").description("Package manager for AI agent skills").version(version2);
|
|
4709
5962
|
var configCmd = program.command("config").description("Manage PSPM configuration");
|
|
4710
5963
|
configCmd.command("show").description("Show resolved configuration").action(async () => {
|
|
4711
5964
|
await configShow();
|
|
@@ -4745,45 +5998,64 @@ program.command("migrate").description(
|
|
|
4745
5998
|
await migrate({ dryRun: options.dryRun });
|
|
4746
5999
|
});
|
|
4747
6000
|
program.command("add <specifiers...>").description(
|
|
4748
|
-
"Add
|
|
6001
|
+
"Add skills from registry, GitHub, local paths, or well-known URLs"
|
|
4749
6002
|
).option("--save", "Save to lockfile (default)").option(
|
|
4750
6003
|
"--agent <agents>",
|
|
4751
6004
|
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
4752
|
-
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
6005
|
+
).option("-g, --global", "Install to user home directory instead of project").option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
4753
6006
|
await add(specifiers, {
|
|
4754
6007
|
save: options.save ?? true,
|
|
4755
6008
|
agent: options.agent,
|
|
4756
|
-
yes: options.yes
|
|
6009
|
+
yes: options.yes,
|
|
6010
|
+
global: options.global
|
|
4757
6011
|
});
|
|
4758
6012
|
});
|
|
4759
6013
|
program.command("remove <name>").alias("rm").description("Remove an installed skill").action(async (name) => {
|
|
4760
6014
|
await remove(name);
|
|
4761
6015
|
});
|
|
4762
|
-
program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").action(async (options) => {
|
|
4763
|
-
await list({ json: options.json });
|
|
6016
|
+
program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").option("-g, --global", "List globally installed skills").action(async (options) => {
|
|
6017
|
+
await list({ json: options.json, global: options.global });
|
|
4764
6018
|
});
|
|
4765
6019
|
program.command("install [specifiers...]").alias("i").description(
|
|
4766
6020
|
"Install skills from lockfile, or add and install specific packages"
|
|
4767
6021
|
).option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").option(
|
|
4768
6022
|
"--agent <agents>",
|
|
4769
6023
|
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
4770
|
-
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
6024
|
+
).option("-g, --global", "Install to user home directory instead of project").option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
4771
6025
|
await install(specifiers, {
|
|
4772
6026
|
frozenLockfile: options.frozenLockfile,
|
|
4773
6027
|
dir: options.dir,
|
|
4774
6028
|
agent: options.agent,
|
|
4775
|
-
yes: options.yes
|
|
6029
|
+
yes: options.yes,
|
|
6030
|
+
global: options.global
|
|
4776
6031
|
});
|
|
4777
6032
|
});
|
|
4778
6033
|
program.command("link").description("Recreate agent symlinks without reinstalling").option(
|
|
4779
6034
|
"--agent <agents>",
|
|
4780
6035
|
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
4781
|
-
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
|
|
4782
|
-
await link({
|
|
6036
|
+
).option("-g, --global", "Recreate global agent symlinks").option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
|
|
6037
|
+
await link({
|
|
6038
|
+
agent: options.agent,
|
|
6039
|
+
yes: options.yes,
|
|
6040
|
+
global: options.global
|
|
6041
|
+
});
|
|
4783
6042
|
});
|
|
4784
6043
|
program.command("update").description("Update all skills to latest compatible versions").option("--dry-run", "Show what would be updated without making changes").action(async (options) => {
|
|
4785
6044
|
await update({ dryRun: options.dryRun });
|
|
4786
6045
|
});
|
|
6046
|
+
program.command("search [query]").alias("find").description("Search and discover skills from the registry").option(
|
|
6047
|
+
"-s, --sort <sort>",
|
|
6048
|
+
"Sort by: downloads, recent, name (default: downloads)"
|
|
6049
|
+
).option("-l, --limit <n>", "Maximum results (default: 20)", Number.parseInt).option("--json", "Output as JSON").action(async (query, options) => {
|
|
6050
|
+
await search(query, {
|
|
6051
|
+
sort: options.sort,
|
|
6052
|
+
limit: options.limit,
|
|
6053
|
+
json: options.json
|
|
6054
|
+
});
|
|
6055
|
+
});
|
|
6056
|
+
program.command("audit").description("Verify integrity of installed skills and check for issues").option("--json", "Output as JSON").action(async (options) => {
|
|
6057
|
+
await audit({ json: options.json });
|
|
6058
|
+
});
|
|
4787
6059
|
program.command("outdated [packages...]").description("Check for outdated skills").option("--json", "Output as JSON").option("--all", "Include up-to-date packages").action(async (packages, options) => {
|
|
4788
6060
|
await outdated(packages, { json: options.json, all: options.all });
|
|
4789
6061
|
});
|
|
@@ -4830,6 +6102,9 @@ program.command("deprecate <specifier> [message]").description(
|
|
|
4830
6102
|
await deprecate(specifier, message, { undo: options.undo });
|
|
4831
6103
|
});
|
|
4832
6104
|
await program.parseAsync();
|
|
4833
|
-
|
|
6105
|
+
var executedCommand = program.args[0];
|
|
6106
|
+
if (executedCommand !== "upgrade") {
|
|
6107
|
+
await checkForUpdates(version2);
|
|
6108
|
+
}
|
|
4834
6109
|
//# sourceMappingURL=index.js.map
|
|
4835
6110
|
//# sourceMappingURL=index.js.map
|