@anytio/pspm 0.3.2 → 0.4.1
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 +81 -13
- package/CLI_GUIDE.md +76 -20
- package/README.md +42 -14
- package/dist/index.js +546 -605
- package/dist/index.js.map +1 -1
- package/package.json +16 -17
package/dist/index.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, symlink, lstat, unlink, cp, readlink } from 'fs/promises';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { dirname, join, basename, resolve, relative } from 'path';
|
|
5
|
+
import * as ini from 'ini';
|
|
6
|
+
import ignore from 'ignore';
|
|
7
|
+
import { createHash, randomBytes } from 'crypto';
|
|
8
|
+
import * as semver from 'semver';
|
|
9
|
+
import semver__default from 'semver';
|
|
10
|
+
import { checkbox } from '@inquirer/prompts';
|
|
11
|
+
import { readFileSync } from 'fs';
|
|
12
|
+
import { fileURLToPath, URL as URL$1 } from 'url';
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { createInterface } from 'readline';
|
|
15
|
+
import http from 'http';
|
|
16
|
+
import open from 'open';
|
|
17
|
+
import { exec as exec$1 } from 'child_process';
|
|
18
|
+
import { promisify } from 'util';
|
|
19
|
+
|
|
2
20
|
var __defProp = Object.defineProperty;
|
|
3
21
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
22
|
var __esm = (fn, res) => function __init() {
|
|
@@ -51,7 +69,6 @@ async function customFetch(url, options) {
|
|
|
51
69
|
var config;
|
|
52
70
|
var init_fetcher = __esm({
|
|
53
71
|
"src/sdk/fetcher.ts"() {
|
|
54
|
-
"use strict";
|
|
55
72
|
config = null;
|
|
56
73
|
}
|
|
57
74
|
});
|
|
@@ -60,7 +77,6 @@ var init_fetcher = __esm({
|
|
|
60
77
|
var getMeUrl, me, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getPublishSkillUrl, publishSkill, getDeleteSkillUrl, deleteSkill, getDeleteSkillVersionUrl, deleteSkillVersion;
|
|
61
78
|
var init_generated = __esm({
|
|
62
79
|
"src/sdk/generated/index.ts"() {
|
|
63
|
-
"use strict";
|
|
64
80
|
init_fetcher();
|
|
65
81
|
getMeUrl = () => {
|
|
66
82
|
return `/api/skills/me`;
|
|
@@ -86,12 +102,12 @@ var init_generated = __esm({
|
|
|
86
102
|
}
|
|
87
103
|
);
|
|
88
104
|
};
|
|
89
|
-
getGetSkillVersionUrl = (username, name,
|
|
90
|
-
return `/api/skills/@user/${username}/${name}/${
|
|
105
|
+
getGetSkillVersionUrl = (username, name, version3) => {
|
|
106
|
+
return `/api/skills/@user/${username}/${name}/${version3}`;
|
|
91
107
|
};
|
|
92
|
-
getSkillVersion = async (username, name,
|
|
108
|
+
getSkillVersion = async (username, name, version3, options) => {
|
|
93
109
|
return customFetch(
|
|
94
|
-
getGetSkillVersionUrl(username, name,
|
|
110
|
+
getGetSkillVersionUrl(username, name, version3),
|
|
95
111
|
{
|
|
96
112
|
...options,
|
|
97
113
|
method: "GET"
|
|
@@ -126,12 +142,12 @@ var init_generated = __esm({
|
|
|
126
142
|
}
|
|
127
143
|
);
|
|
128
144
|
};
|
|
129
|
-
getDeleteSkillVersionUrl = (name,
|
|
130
|
-
return `/api/skills/${name}/${
|
|
145
|
+
getDeleteSkillVersionUrl = (name, version3) => {
|
|
146
|
+
return `/api/skills/${name}/${version3}`;
|
|
131
147
|
};
|
|
132
|
-
deleteSkillVersion = async (name,
|
|
148
|
+
deleteSkillVersion = async (name, version3, options) => {
|
|
133
149
|
return customFetch(
|
|
134
|
-
getDeleteSkillVersionUrl(name,
|
|
150
|
+
getDeleteSkillVersionUrl(name, version3),
|
|
135
151
|
{
|
|
136
152
|
...options,
|
|
137
153
|
method: "DELETE"
|
|
@@ -165,14 +181,14 @@ async function whoamiRequest(registryUrl, apiKey) {
|
|
|
165
181
|
return null;
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
|
-
async function deprecateSkillVersion(skillName,
|
|
184
|
+
async function deprecateSkillVersion(skillName, version3, message) {
|
|
169
185
|
const config2 = getConfig();
|
|
170
186
|
if (!config2) {
|
|
171
187
|
return { status: 401, error: "SDK not configured" };
|
|
172
188
|
}
|
|
173
189
|
try {
|
|
174
190
|
const response = await fetch(
|
|
175
|
-
`${config2.baseUrl}/api/skills/${skillName}/${
|
|
191
|
+
`${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
|
|
176
192
|
{
|
|
177
193
|
method: "POST",
|
|
178
194
|
headers: {
|
|
@@ -195,14 +211,14 @@ async function deprecateSkillVersion(skillName, version2, message) {
|
|
|
195
211
|
};
|
|
196
212
|
}
|
|
197
213
|
}
|
|
198
|
-
async function undeprecateSkillVersion(skillName,
|
|
214
|
+
async function undeprecateSkillVersion(skillName, version3) {
|
|
199
215
|
const config2 = getConfig();
|
|
200
216
|
if (!config2) {
|
|
201
217
|
return { status: 401, error: "SDK not configured" };
|
|
202
218
|
}
|
|
203
219
|
try {
|
|
204
220
|
const response = await fetch(
|
|
205
|
-
`${config2.baseUrl}/api/skills/${skillName}/${
|
|
221
|
+
`${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
|
|
206
222
|
{
|
|
207
223
|
method: "DELETE",
|
|
208
224
|
headers: {
|
|
@@ -263,13 +279,27 @@ async function changeSkillAccess(skillName, input) {
|
|
|
263
279
|
}
|
|
264
280
|
var init_api_client = __esm({
|
|
265
281
|
"src/api-client.ts"() {
|
|
266
|
-
"use strict";
|
|
267
282
|
init_fetcher();
|
|
268
283
|
init_generated();
|
|
269
284
|
}
|
|
270
285
|
});
|
|
271
286
|
|
|
272
287
|
// src/errors.ts
|
|
288
|
+
function getHttpStatusDescription(status) {
|
|
289
|
+
const descriptions = {
|
|
290
|
+
400: "Bad Request - The request was malformed",
|
|
291
|
+
401: "Unauthorized - Please run 'pspm login' first",
|
|
292
|
+
403: "Forbidden - You don't have permission for this action",
|
|
293
|
+
404: "Not Found - The endpoint or resource doesn't exist",
|
|
294
|
+
409: "Conflict - The resource already exists or there's a version conflict",
|
|
295
|
+
422: "Validation Error - The request data is invalid",
|
|
296
|
+
429: "Too Many Requests - Please slow down and try again",
|
|
297
|
+
500: "Internal Server Error - Something went wrong on the server",
|
|
298
|
+
502: "Bad Gateway - The server is temporarily unavailable",
|
|
299
|
+
503: "Service Unavailable - The server is temporarily unavailable"
|
|
300
|
+
};
|
|
301
|
+
return descriptions[status] || `HTTP Error ${status}`;
|
|
302
|
+
}
|
|
273
303
|
function extractApiErrorMessage(response, fallbackMessage) {
|
|
274
304
|
const errorData = response.data;
|
|
275
305
|
if (process.env.PSPM_DEBUG) {
|
|
@@ -279,8 +309,20 @@ function extractApiErrorMessage(response, fallbackMessage) {
|
|
|
279
309
|
JSON.stringify(errorData, null, 2)
|
|
280
310
|
);
|
|
281
311
|
}
|
|
282
|
-
if (
|
|
283
|
-
|
|
312
|
+
if (typeof errorData === "string") {
|
|
313
|
+
if (response.status === 404) {
|
|
314
|
+
return `${fallbackMessage}: ${getHttpStatusDescription(404)}
|
|
315
|
+
The registry endpoint may be unavailable or misconfigured.`;
|
|
316
|
+
}
|
|
317
|
+
return `${fallbackMessage}: ${errorData} (HTTP ${response.status})`;
|
|
318
|
+
}
|
|
319
|
+
if (!errorData || typeof errorData !== "object") {
|
|
320
|
+
const statusDesc = getHttpStatusDescription(response.status);
|
|
321
|
+
if (response.status === 404) {
|
|
322
|
+
return `${fallbackMessage}: ${statusDesc}
|
|
323
|
+
Check that the registry URL is correct in your config.`;
|
|
324
|
+
}
|
|
325
|
+
return `${fallbackMessage}: ${statusDesc}`;
|
|
284
326
|
}
|
|
285
327
|
let errorMessage = errorData.message || fallbackMessage;
|
|
286
328
|
if (errorData.code === "VALIDATION_ERROR" && errorData.details) {
|
|
@@ -298,6 +340,9 @@ ${issueMessages}`;
|
|
|
298
340
|
if (errorData.code && !errorMessage.includes(errorData.code)) {
|
|
299
341
|
errorMessage = `[${errorData.code}] ${errorMessage}`;
|
|
300
342
|
}
|
|
343
|
+
if (response.status >= 400) {
|
|
344
|
+
errorMessage += ` (HTTP ${response.status})`;
|
|
345
|
+
}
|
|
301
346
|
if (errorData.requestId) {
|
|
302
347
|
errorMessage += `
|
|
303
348
|
(Request ID: ${errorData.requestId})`;
|
|
@@ -307,7 +352,6 @@ ${issueMessages}`;
|
|
|
307
352
|
var ConfigError, NotLoggedInError;
|
|
308
353
|
var init_errors = __esm({
|
|
309
354
|
"src/errors.ts"() {
|
|
310
|
-
"use strict";
|
|
311
355
|
ConfigError = class extends Error {
|
|
312
356
|
constructor(message) {
|
|
313
357
|
super(message);
|
|
@@ -324,12 +368,6 @@ var init_errors = __esm({
|
|
|
324
368
|
};
|
|
325
369
|
}
|
|
326
370
|
});
|
|
327
|
-
|
|
328
|
-
// src/config.ts
|
|
329
|
-
import { mkdir, readFile, stat, unlink, writeFile } from "fs/promises";
|
|
330
|
-
import { homedir } from "os";
|
|
331
|
-
import { dirname, join } from "path";
|
|
332
|
-
import * as ini from "ini";
|
|
333
371
|
function getConfigPath() {
|
|
334
372
|
return join(homedir(), ".pspmrc");
|
|
335
373
|
}
|
|
@@ -602,106 +640,63 @@ async function getRegistryUrl() {
|
|
|
602
640
|
var DEFAULT_REGISTRY_URL;
|
|
603
641
|
var init_config = __esm({
|
|
604
642
|
"src/config.ts"() {
|
|
605
|
-
"use strict";
|
|
606
643
|
init_errors();
|
|
607
|
-
DEFAULT_REGISTRY_URL = "https://pspm.dev";
|
|
644
|
+
DEFAULT_REGISTRY_URL = "https://registry.pspm.dev";
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
async function loadIgnorePatterns(cwd = process.cwd()) {
|
|
648
|
+
const ig = ignore();
|
|
649
|
+
ig.add(ALWAYS_IGNORED);
|
|
650
|
+
const pspmIgnorePath = join(cwd, ".pspmignore");
|
|
651
|
+
try {
|
|
652
|
+
const content = await readFile(pspmIgnorePath, "utf-8");
|
|
653
|
+
const patterns = parseIgnorePatterns(content);
|
|
654
|
+
ig.add(patterns);
|
|
655
|
+
return { ig, source: ".pspmignore", patterns };
|
|
656
|
+
} catch {
|
|
657
|
+
}
|
|
658
|
+
const gitIgnorePath = join(cwd, ".gitignore");
|
|
659
|
+
try {
|
|
660
|
+
const content = await readFile(gitIgnorePath, "utf-8");
|
|
661
|
+
const patterns = parseIgnorePatterns(content);
|
|
662
|
+
ig.add(patterns);
|
|
663
|
+
return { ig, source: ".gitignore", patterns };
|
|
664
|
+
} catch {
|
|
665
|
+
}
|
|
666
|
+
return { ig, source: null, patterns: [] };
|
|
667
|
+
}
|
|
668
|
+
function getExcludeArgsForRsync(patterns) {
|
|
669
|
+
const allPatterns = [.../* @__PURE__ */ new Set([...ALWAYS_IGNORED, ...patterns])];
|
|
670
|
+
return allPatterns.map((p) => `--exclude='${p}'`).join(" ");
|
|
671
|
+
}
|
|
672
|
+
function parseIgnorePatterns(content) {
|
|
673
|
+
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
674
|
+
}
|
|
675
|
+
var ALWAYS_IGNORED;
|
|
676
|
+
var init_ignore = __esm({
|
|
677
|
+
"src/lib/ignore.ts"() {
|
|
678
|
+
ALWAYS_IGNORED = [
|
|
679
|
+
"node_modules",
|
|
680
|
+
".git",
|
|
681
|
+
".pspm-publish"
|
|
682
|
+
// temp directory used during publish
|
|
683
|
+
];
|
|
608
684
|
}
|
|
609
685
|
});
|
|
610
|
-
|
|
611
|
-
// src/lib/integrity.ts
|
|
612
|
-
import { createHash } from "crypto";
|
|
613
686
|
function calculateIntegrity(data) {
|
|
614
687
|
const hash = createHash("sha256").update(data).digest("base64");
|
|
615
688
|
return `sha256-${hash}`;
|
|
616
689
|
}
|
|
617
690
|
var init_integrity = __esm({
|
|
618
691
|
"src/lib/integrity.ts"() {
|
|
619
|
-
"use strict";
|
|
620
692
|
}
|
|
621
693
|
});
|
|
622
694
|
|
|
623
|
-
// src/lib/
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
}
|
|
629
|
-
function isBareLocalPath(specifier) {
|
|
630
|
-
return specifier.startsWith("./") || specifier.startsWith("../");
|
|
631
|
-
}
|
|
632
|
-
function parseLocalSpecifier(specifier) {
|
|
633
|
-
const match = specifier.match(LOCAL_SPECIFIER_PATTERN);
|
|
634
|
-
if (!match) {
|
|
635
|
-
return null;
|
|
636
|
-
}
|
|
637
|
-
const path = match[1];
|
|
638
|
-
if (!path || path.trim() === "") {
|
|
639
|
-
return null;
|
|
640
|
-
}
|
|
641
|
-
return {
|
|
642
|
-
path,
|
|
643
|
-
isAbsolute: isAbsolute(path)
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
function getLocalSkillName(spec) {
|
|
647
|
-
const normalizedPath = spec.path.replace(/\/+$/, "");
|
|
648
|
-
const segments = normalizedPath.split("/").filter(Boolean);
|
|
649
|
-
return segments[segments.length - 1] || spec.path;
|
|
650
|
-
}
|
|
651
|
-
function normalizeToFileSpecifier(path) {
|
|
652
|
-
if (isLocalSpecifier(path)) {
|
|
653
|
-
return path;
|
|
654
|
-
}
|
|
655
|
-
return `file:${path}`;
|
|
656
|
-
}
|
|
657
|
-
function resolveLocalPath(spec, basePath = process.cwd()) {
|
|
658
|
-
if (spec.isAbsolute) {
|
|
659
|
-
return resolve(spec.path);
|
|
660
|
-
}
|
|
661
|
-
return resolve(basePath, spec.path);
|
|
662
|
-
}
|
|
663
|
-
async function validateLocalSkill(absolutePath) {
|
|
664
|
-
try {
|
|
665
|
-
const stats = await stat2(absolutePath);
|
|
666
|
-
if (!stats.isDirectory()) {
|
|
667
|
-
return { valid: false, error: `Not a directory: ${absolutePath}` };
|
|
668
|
-
}
|
|
669
|
-
} catch {
|
|
670
|
-
return { valid: false, error: `Directory not found: ${absolutePath}` };
|
|
671
|
-
}
|
|
672
|
-
const manifestPath = join2(absolutePath, "pspm.json");
|
|
673
|
-
try {
|
|
674
|
-
await access(manifestPath);
|
|
675
|
-
} catch {
|
|
676
|
-
return {
|
|
677
|
-
valid: false,
|
|
678
|
-
error: `No pspm.json found in ${absolutePath}`
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
try {
|
|
682
|
-
const { readFile: readFile7 } = await import("fs/promises");
|
|
683
|
-
const content = await readFile7(manifestPath, "utf-8");
|
|
684
|
-
const manifest = JSON.parse(content);
|
|
685
|
-
if (!manifest.name) {
|
|
686
|
-
return {
|
|
687
|
-
valid: false,
|
|
688
|
-
error: `Manifest in ${absolutePath} is missing 'name' field`
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
return { valid: true, manifest };
|
|
692
|
-
} catch (error) {
|
|
693
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
694
|
-
return {
|
|
695
|
-
valid: false,
|
|
696
|
-
error: `Failed to read manifest in ${absolutePath}: ${message}`
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
var LOCAL_SPECIFIER_PATTERN;
|
|
701
|
-
var init_local = __esm({
|
|
702
|
-
"src/lib/local.ts"() {
|
|
703
|
-
"use strict";
|
|
704
|
-
LOCAL_SPECIFIER_PATTERN = /^file:(.+)$/;
|
|
695
|
+
// src/lib/lockfile.ts
|
|
696
|
+
var PSPM_LOCKFILE_SCHEMA_URL;
|
|
697
|
+
var init_lockfile = __esm({
|
|
698
|
+
"src/lib/lockfile.ts"() {
|
|
699
|
+
PSPM_LOCKFILE_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm-lock.json";
|
|
705
700
|
}
|
|
706
701
|
});
|
|
707
702
|
|
|
@@ -730,7 +725,6 @@ function validateManifest(manifest) {
|
|
|
730
725
|
var DEFAULT_SKILL_FILES, PSPM_SCHEMA_URL;
|
|
731
726
|
var init_manifest = __esm({
|
|
732
727
|
"src/lib/manifest.ts"() {
|
|
733
|
-
"use strict";
|
|
734
728
|
DEFAULT_SKILL_FILES = [
|
|
735
729
|
"SKILL.md",
|
|
736
730
|
"runtime",
|
|
@@ -740,9 +734,6 @@ var init_manifest = __esm({
|
|
|
740
734
|
PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
|
|
741
735
|
}
|
|
742
736
|
});
|
|
743
|
-
|
|
744
|
-
// src/lib/version.ts
|
|
745
|
-
import * as semver from "semver";
|
|
746
737
|
function resolveVersion(range, availableVersions) {
|
|
747
738
|
const sorted = availableVersions.filter((v) => semver.valid(v)).sort((a, b) => semver.rcompare(a, b));
|
|
748
739
|
if (!range || range === "latest" || range === "*") {
|
|
@@ -756,19 +747,18 @@ function findHighestSatisfying(ranges, availableVersions) {
|
|
|
756
747
|
const normalizedRanges = ranges.map(
|
|
757
748
|
(r) => !r || r === "latest" || r === "*" ? "*" : r
|
|
758
749
|
);
|
|
759
|
-
for (const
|
|
750
|
+
for (const version3 of sorted) {
|
|
760
751
|
const satisfiesAll = normalizedRanges.every(
|
|
761
|
-
(range) => semver.satisfies(
|
|
752
|
+
(range) => semver.satisfies(version3, range)
|
|
762
753
|
);
|
|
763
754
|
if (satisfiesAll) {
|
|
764
|
-
return
|
|
755
|
+
return version3;
|
|
765
756
|
}
|
|
766
757
|
}
|
|
767
758
|
return null;
|
|
768
759
|
}
|
|
769
760
|
var init_version = __esm({
|
|
770
761
|
"src/lib/version.ts"() {
|
|
771
|
-
"use strict";
|
|
772
762
|
}
|
|
773
763
|
});
|
|
774
764
|
|
|
@@ -1077,7 +1067,6 @@ function printResolutionErrors(errors, conflicts = []) {
|
|
|
1077
1067
|
var MAX_DEPENDENCY_DEPTH;
|
|
1078
1068
|
var init_resolver = __esm({
|
|
1079
1069
|
"src/lib/resolver.ts"() {
|
|
1080
|
-
"use strict";
|
|
1081
1070
|
init_api_client();
|
|
1082
1071
|
init_version();
|
|
1083
1072
|
MAX_DEPENDENCY_DEPTH = 5;
|
|
@@ -1090,9 +1079,14 @@ function parseSkillSpecifier(specifier) {
|
|
|
1090
1079
|
if (!match) {
|
|
1091
1080
|
return null;
|
|
1092
1081
|
}
|
|
1082
|
+
const username = match[1];
|
|
1083
|
+
const name = match[2];
|
|
1084
|
+
if (!username || !name) {
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1093
1087
|
return {
|
|
1094
|
-
username
|
|
1095
|
-
name
|
|
1088
|
+
username,
|
|
1089
|
+
name,
|
|
1096
1090
|
versionRange: match[3]
|
|
1097
1091
|
};
|
|
1098
1092
|
}
|
|
@@ -1102,6 +1096,9 @@ function parseGitHubSpecifier(specifier) {
|
|
|
1102
1096
|
return null;
|
|
1103
1097
|
}
|
|
1104
1098
|
const [, owner, repo, pathWithSlash, ref] = match;
|
|
1099
|
+
if (!owner || !repo) {
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1105
1102
|
return {
|
|
1106
1103
|
owner,
|
|
1107
1104
|
repo,
|
|
@@ -1123,7 +1120,10 @@ function formatGitHubSpecifier(spec) {
|
|
|
1123
1120
|
function getGitHubSkillName(spec) {
|
|
1124
1121
|
if (spec.path) {
|
|
1125
1122
|
const segments = spec.path.split("/").filter(Boolean);
|
|
1126
|
-
|
|
1123
|
+
const lastSegment = segments[segments.length - 1];
|
|
1124
|
+
if (lastSegment) {
|
|
1125
|
+
return lastSegment;
|
|
1126
|
+
}
|
|
1127
1127
|
}
|
|
1128
1128
|
return spec.repo;
|
|
1129
1129
|
}
|
|
@@ -1133,7 +1133,6 @@ function isGitHubSpecifier(specifier) {
|
|
|
1133
1133
|
var SPECIFIER_PATTERN, GITHUB_SPECIFIER_PATTERN;
|
|
1134
1134
|
var init_specifier = __esm({
|
|
1135
1135
|
"src/lib/specifier.ts"() {
|
|
1136
|
-
"use strict";
|
|
1137
1136
|
SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
|
|
1138
1137
|
GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
|
|
1139
1138
|
}
|
|
@@ -1142,18 +1141,15 @@ var init_specifier = __esm({
|
|
|
1142
1141
|
// src/lib/index.ts
|
|
1143
1142
|
var init_lib = __esm({
|
|
1144
1143
|
"src/lib/index.ts"() {
|
|
1145
|
-
|
|
1144
|
+
init_ignore();
|
|
1146
1145
|
init_integrity();
|
|
1147
|
-
|
|
1146
|
+
init_lockfile();
|
|
1148
1147
|
init_manifest();
|
|
1149
1148
|
init_resolver();
|
|
1150
1149
|
init_specifier();
|
|
1151
1150
|
init_version();
|
|
1152
1151
|
}
|
|
1153
1152
|
});
|
|
1154
|
-
|
|
1155
|
-
// src/agents.ts
|
|
1156
|
-
import { checkbox } from "@inquirer/prompts";
|
|
1157
1153
|
function resolveAgentConfig(name, overrides) {
|
|
1158
1154
|
if (overrides?.[name]) {
|
|
1159
1155
|
return overrides[name];
|
|
@@ -1196,7 +1192,6 @@ async function promptForAgents() {
|
|
|
1196
1192
|
var AGENT_INFO, DEFAULT_AGENT_CONFIGS, ALL_AGENTS;
|
|
1197
1193
|
var init_agents = __esm({
|
|
1198
1194
|
"src/agents.ts"() {
|
|
1199
|
-
"use strict";
|
|
1200
1195
|
AGENT_INFO = {
|
|
1201
1196
|
"claude-code": {
|
|
1202
1197
|
displayName: "Claude Code",
|
|
@@ -1241,10 +1236,6 @@ var init_agents = __esm({
|
|
|
1241
1236
|
];
|
|
1242
1237
|
}
|
|
1243
1238
|
});
|
|
1244
|
-
|
|
1245
|
-
// src/github.ts
|
|
1246
|
-
import { cp, lstat, mkdir as mkdir2, readdir, rm, writeFile as writeFile2 } from "fs/promises";
|
|
1247
|
-
import { join as join3 } from "path";
|
|
1248
1239
|
function getGitHubHeaders() {
|
|
1249
1240
|
const headers = {
|
|
1250
1241
|
Accept: "application/vnd.github+json",
|
|
@@ -1320,14 +1311,14 @@ async function downloadGitHubPackage(spec) {
|
|
|
1320
1311
|
return { buffer, commit, integrity };
|
|
1321
1312
|
}
|
|
1322
1313
|
async function extractGitHubPackage(spec, buffer, skillsDir) {
|
|
1323
|
-
const destPath = spec.path ?
|
|
1324
|
-
const tempDir =
|
|
1325
|
-
await
|
|
1326
|
-
const tempFile =
|
|
1314
|
+
const destPath = spec.path ? join(skillsDir, "_github", spec.owner, spec.repo, spec.path) : join(skillsDir, "_github", spec.owner, spec.repo);
|
|
1315
|
+
const tempDir = join(skillsDir, "_github", ".temp", `${Date.now()}`);
|
|
1316
|
+
await mkdir(tempDir, { recursive: true });
|
|
1317
|
+
const tempFile = join(tempDir, "archive.tgz");
|
|
1327
1318
|
try {
|
|
1328
|
-
await
|
|
1329
|
-
const { exec: exec2 } = await import(
|
|
1330
|
-
const { promisify: promisify2 } = await import(
|
|
1319
|
+
await writeFile(tempFile, buffer);
|
|
1320
|
+
const { exec: exec2 } = await import('child_process');
|
|
1321
|
+
const { promisify: promisify2 } = await import('util');
|
|
1331
1322
|
const execAsync = promisify2(exec2);
|
|
1332
1323
|
await execAsync(`tar -xzf "${tempFile}" -C "${tempDir}"`);
|
|
1333
1324
|
const entries = await readdir(tempDir);
|
|
@@ -1337,15 +1328,15 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
|
|
|
1337
1328
|
if (!extractedDir) {
|
|
1338
1329
|
throw new Error("Failed to find extracted directory in tarball");
|
|
1339
1330
|
}
|
|
1340
|
-
const sourcePath =
|
|
1341
|
-
const copySource = spec.path ?
|
|
1331
|
+
const sourcePath = join(tempDir, extractedDir);
|
|
1332
|
+
const copySource = spec.path ? join(sourcePath, spec.path) : sourcePath;
|
|
1342
1333
|
if (spec.path) {
|
|
1343
1334
|
const pathExists = await lstat(copySource).catch(() => null);
|
|
1344
1335
|
if (!pathExists) {
|
|
1345
1336
|
const rootEntries = await readdir(sourcePath);
|
|
1346
1337
|
const dirs = [];
|
|
1347
1338
|
for (const entry of rootEntries) {
|
|
1348
|
-
const stat8 = await lstat(
|
|
1339
|
+
const stat8 = await lstat(join(sourcePath, entry)).catch(() => null);
|
|
1349
1340
|
if (stat8?.isDirectory() && !entry.startsWith(".")) {
|
|
1350
1341
|
dirs.push(entry);
|
|
1351
1342
|
}
|
|
@@ -1354,7 +1345,7 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
|
|
|
1354
1345
|
}
|
|
1355
1346
|
}
|
|
1356
1347
|
await rm(destPath, { recursive: true, force: true });
|
|
1357
|
-
await
|
|
1348
|
+
await mkdir(destPath, { recursive: true });
|
|
1358
1349
|
await cp(copySource, destPath, { recursive: true });
|
|
1359
1350
|
return spec.path ? `.pspm/skills/_github/${spec.owner}/${spec.repo}/${spec.path}` : `.pspm/skills/_github/${spec.owner}/${spec.repo}`;
|
|
1360
1351
|
} finally {
|
|
@@ -1368,15 +1359,13 @@ function getGitHubDisplayName(spec, commit) {
|
|
|
1368
1359
|
}
|
|
1369
1360
|
if (spec.ref || commit) {
|
|
1370
1361
|
const ref = spec.ref || "HEAD";
|
|
1371
|
-
|
|
1372
|
-
name += ` (${ref}${shortCommit ? `@${shortCommit}` : ""})`;
|
|
1362
|
+
name += ` (${ref}${""})`;
|
|
1373
1363
|
}
|
|
1374
1364
|
return name;
|
|
1375
1365
|
}
|
|
1376
1366
|
var GitHubRateLimitError, GitHubNotFoundError, GitHubPathNotFoundError;
|
|
1377
1367
|
var init_github = __esm({
|
|
1378
1368
|
"src/github.ts"() {
|
|
1379
|
-
"use strict";
|
|
1380
1369
|
init_lib();
|
|
1381
1370
|
GitHubRateLimitError = class extends Error {
|
|
1382
1371
|
constructor() {
|
|
@@ -1409,13 +1398,9 @@ Available paths in repository root:
|
|
|
1409
1398
|
};
|
|
1410
1399
|
}
|
|
1411
1400
|
});
|
|
1412
|
-
|
|
1413
|
-
// src/lockfile.ts
|
|
1414
|
-
import { mkdir as mkdir3, readFile as readFile2, stat as stat3, writeFile as writeFile3 } from "fs/promises";
|
|
1415
|
-
import { dirname as dirname2 } from "path";
|
|
1416
1401
|
async function hasLegacyLockfile() {
|
|
1417
1402
|
try {
|
|
1418
|
-
await
|
|
1403
|
+
await stat(getLegacyLockfilePath());
|
|
1419
1404
|
return true;
|
|
1420
1405
|
} catch {
|
|
1421
1406
|
return false;
|
|
@@ -1425,24 +1410,24 @@ async function migrateLockfileIfNeeded() {
|
|
|
1425
1410
|
const legacyPath = getLegacyLockfilePath();
|
|
1426
1411
|
const newPath = getLockfilePath();
|
|
1427
1412
|
try {
|
|
1428
|
-
await
|
|
1413
|
+
await stat(legacyPath);
|
|
1429
1414
|
} catch {
|
|
1430
1415
|
return false;
|
|
1431
1416
|
}
|
|
1432
1417
|
try {
|
|
1433
|
-
await
|
|
1418
|
+
await stat(newPath);
|
|
1434
1419
|
return false;
|
|
1435
1420
|
} catch {
|
|
1436
1421
|
}
|
|
1437
1422
|
try {
|
|
1438
|
-
const content = await
|
|
1423
|
+
const content = await readFile(legacyPath, "utf-8");
|
|
1439
1424
|
const oldLockfile = JSON.parse(content);
|
|
1440
1425
|
const newLockfile = {
|
|
1441
1426
|
lockfileVersion: 2,
|
|
1442
1427
|
registryUrl: oldLockfile.registryUrl,
|
|
1443
1428
|
packages: oldLockfile.skills ?? {}
|
|
1444
1429
|
};
|
|
1445
|
-
await
|
|
1430
|
+
await writeFile(newPath, `${JSON.stringify(newLockfile, null, 2)}
|
|
1446
1431
|
`);
|
|
1447
1432
|
console.log("Migrated lockfile: skill-lock.json \u2192 pspm-lock.json");
|
|
1448
1433
|
return true;
|
|
@@ -1453,7 +1438,7 @@ async function migrateLockfileIfNeeded() {
|
|
|
1453
1438
|
async function readLockfile() {
|
|
1454
1439
|
const lockfilePath = getLockfilePath();
|
|
1455
1440
|
try {
|
|
1456
|
-
const content = await
|
|
1441
|
+
const content = await readFile(lockfilePath, "utf-8");
|
|
1457
1442
|
const lockfile = JSON.parse(content);
|
|
1458
1443
|
if (lockfile.lockfileVersion === 1 && lockfile.skills && !lockfile.packages) {
|
|
1459
1444
|
return {
|
|
@@ -1466,7 +1451,7 @@ async function readLockfile() {
|
|
|
1466
1451
|
} catch {
|
|
1467
1452
|
if (await hasLegacyLockfile()) {
|
|
1468
1453
|
try {
|
|
1469
|
-
const content = await
|
|
1454
|
+
const content = await readFile(getLegacyLockfilePath(), "utf-8");
|
|
1470
1455
|
const legacyLockfile = JSON.parse(content);
|
|
1471
1456
|
return {
|
|
1472
1457
|
lockfileVersion: 2,
|
|
@@ -1482,30 +1467,25 @@ async function readLockfile() {
|
|
|
1482
1467
|
}
|
|
1483
1468
|
async function writeLockfile(lockfile) {
|
|
1484
1469
|
const lockfilePath = getLockfilePath();
|
|
1485
|
-
await
|
|
1470
|
+
await mkdir(dirname(lockfilePath), { recursive: true });
|
|
1486
1471
|
const packages = lockfile.packages ?? lockfile.skills ?? {};
|
|
1487
1472
|
const hasDependencies = Object.values(packages).some(
|
|
1488
1473
|
(pkg) => pkg.dependencies && Object.keys(pkg.dependencies).length > 0
|
|
1489
1474
|
);
|
|
1490
|
-
const
|
|
1491
|
-
let version2 = 3;
|
|
1492
|
-
if (hasLocalPackages) {
|
|
1493
|
-
version2 = 5;
|
|
1494
|
-
} else if (hasDependencies) {
|
|
1495
|
-
version2 = 4;
|
|
1496
|
-
}
|
|
1475
|
+
const version3 = hasDependencies ? 4 : 3;
|
|
1497
1476
|
const normalized = {
|
|
1498
|
-
|
|
1477
|
+
$schema: PSPM_LOCKFILE_SCHEMA_URL,
|
|
1478
|
+
lockfileVersion: version3,
|
|
1499
1479
|
registryUrl: lockfile.registryUrl,
|
|
1500
1480
|
packages
|
|
1501
1481
|
};
|
|
1502
1482
|
if (lockfile.githubPackages && Object.keys(lockfile.githubPackages).length > 0) {
|
|
1503
1483
|
normalized.githubPackages = lockfile.githubPackages;
|
|
1504
1484
|
}
|
|
1505
|
-
if (
|
|
1485
|
+
if (lockfile.localPackages && Object.keys(lockfile.localPackages).length > 0) {
|
|
1506
1486
|
normalized.localPackages = lockfile.localPackages;
|
|
1507
1487
|
}
|
|
1508
|
-
await
|
|
1488
|
+
await writeFile(lockfilePath, `${JSON.stringify(normalized, null, 2)}
|
|
1509
1489
|
`);
|
|
1510
1490
|
}
|
|
1511
1491
|
async function createEmptyLockfile() {
|
|
@@ -1609,41 +1589,18 @@ async function addLocalToLockfile(specifier, entry) {
|
|
|
1609
1589
|
lockfile.localPackages[specifier] = entry;
|
|
1610
1590
|
await writeLockfile(lockfile);
|
|
1611
1591
|
}
|
|
1612
|
-
|
|
1613
|
-
const lockfile = await readLockfile();
|
|
1614
|
-
if (!lockfile?.localPackages?.[specifier]) {
|
|
1615
|
-
return false;
|
|
1616
|
-
}
|
|
1617
|
-
delete lockfile.localPackages[specifier];
|
|
1618
|
-
await writeLockfile(lockfile);
|
|
1619
|
-
return true;
|
|
1620
|
-
}
|
|
1621
|
-
async function listLockfileLocalPackages() {
|
|
1622
|
-
const lockfile = await readLockfile();
|
|
1623
|
-
if (!lockfile?.localPackages) {
|
|
1624
|
-
return [];
|
|
1625
|
-
}
|
|
1626
|
-
return Object.entries(lockfile.localPackages).map(([specifier, entry]) => ({
|
|
1627
|
-
specifier,
|
|
1628
|
-
entry
|
|
1629
|
-
}));
|
|
1630
|
-
}
|
|
1631
|
-
var init_lockfile = __esm({
|
|
1592
|
+
var init_lockfile2 = __esm({
|
|
1632
1593
|
"src/lockfile.ts"() {
|
|
1633
|
-
"use strict";
|
|
1634
1594
|
init_config();
|
|
1595
|
+
init_lib();
|
|
1635
1596
|
}
|
|
1636
1597
|
});
|
|
1637
|
-
|
|
1638
|
-
// src/manifest.ts
|
|
1639
|
-
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
1640
|
-
import { join as join4 } from "path";
|
|
1641
1598
|
function getManifestPath() {
|
|
1642
|
-
return
|
|
1599
|
+
return join(process.cwd(), "pspm.json");
|
|
1643
1600
|
}
|
|
1644
1601
|
async function readManifest() {
|
|
1645
1602
|
try {
|
|
1646
|
-
const content = await
|
|
1603
|
+
const content = await readFile(getManifestPath(), "utf-8");
|
|
1647
1604
|
return JSON.parse(content);
|
|
1648
1605
|
} catch {
|
|
1649
1606
|
return null;
|
|
@@ -1651,7 +1608,7 @@ async function readManifest() {
|
|
|
1651
1608
|
}
|
|
1652
1609
|
async function writeManifest(manifest) {
|
|
1653
1610
|
const content = JSON.stringify(manifest, null, 2);
|
|
1654
|
-
await
|
|
1611
|
+
await writeFile(getManifestPath(), `${content}
|
|
1655
1612
|
`);
|
|
1656
1613
|
}
|
|
1657
1614
|
async function createMinimalManifest() {
|
|
@@ -1709,36 +1666,18 @@ async function removeGitHubDependency(specifier) {
|
|
|
1709
1666
|
await writeManifest(manifest);
|
|
1710
1667
|
return true;
|
|
1711
1668
|
}
|
|
1712
|
-
async function
|
|
1713
|
-
const manifest = await readManifest();
|
|
1714
|
-
return manifest?.localDependencies ?? {};
|
|
1715
|
-
}
|
|
1716
|
-
async function addLocalDependency(specifier, version2 = "*") {
|
|
1669
|
+
async function addLocalDependency(specifier, version3 = "*") {
|
|
1717
1670
|
const manifest = await ensureManifest();
|
|
1718
1671
|
if (!manifest.localDependencies) {
|
|
1719
1672
|
manifest.localDependencies = {};
|
|
1720
1673
|
}
|
|
1721
|
-
manifest.localDependencies[specifier] =
|
|
1674
|
+
manifest.localDependencies[specifier] = version3;
|
|
1722
1675
|
await writeManifest(manifest);
|
|
1723
1676
|
}
|
|
1724
|
-
async function removeLocalDependency(specifier) {
|
|
1725
|
-
const manifest = await readManifest();
|
|
1726
|
-
if (!manifest?.localDependencies?.[specifier]) {
|
|
1727
|
-
return false;
|
|
1728
|
-
}
|
|
1729
|
-
delete manifest.localDependencies[specifier];
|
|
1730
|
-
await writeManifest(manifest);
|
|
1731
|
-
return true;
|
|
1732
|
-
}
|
|
1733
1677
|
var init_manifest2 = __esm({
|
|
1734
1678
|
"src/manifest.ts"() {
|
|
1735
|
-
"use strict";
|
|
1736
1679
|
}
|
|
1737
1680
|
});
|
|
1738
|
-
|
|
1739
|
-
// src/symlinks.ts
|
|
1740
|
-
import { lstat as lstat2, mkdir as mkdir4, readlink, rm as rm2, symlink } from "fs/promises";
|
|
1741
|
-
import { dirname as dirname3, join as join5, relative } from "path";
|
|
1742
1681
|
async function createAgentSymlinks(skills, options) {
|
|
1743
1682
|
const { agents, projectRoot, agentConfigs } = options;
|
|
1744
1683
|
if (agents.length === 1 && agents[0] === "none") {
|
|
@@ -1750,26 +1689,26 @@ async function createAgentSymlinks(skills, options) {
|
|
|
1750
1689
|
console.warn(`Warning: Unknown agent "${agentName}", skipping symlinks`);
|
|
1751
1690
|
continue;
|
|
1752
1691
|
}
|
|
1753
|
-
const agentSkillsDir =
|
|
1754
|
-
await
|
|
1692
|
+
const agentSkillsDir = join(projectRoot, config2.skillsDir);
|
|
1693
|
+
await mkdir(agentSkillsDir, { recursive: true });
|
|
1755
1694
|
for (const skill of skills) {
|
|
1756
|
-
const symlinkPath =
|
|
1757
|
-
const targetPath =
|
|
1758
|
-
const relativeTarget = relative(
|
|
1695
|
+
const symlinkPath = join(agentSkillsDir, skill.name);
|
|
1696
|
+
const targetPath = join(projectRoot, skill.sourcePath);
|
|
1697
|
+
const relativeTarget = relative(dirname(symlinkPath), targetPath);
|
|
1759
1698
|
await createSymlink(symlinkPath, relativeTarget, skill.name);
|
|
1760
1699
|
}
|
|
1761
1700
|
}
|
|
1762
1701
|
}
|
|
1763
1702
|
async function createSymlink(symlinkPath, target, skillName) {
|
|
1764
1703
|
try {
|
|
1765
|
-
const stats = await
|
|
1704
|
+
const stats = await lstat(symlinkPath).catch(() => null);
|
|
1766
1705
|
if (stats) {
|
|
1767
1706
|
if (stats.isSymbolicLink()) {
|
|
1768
1707
|
const existingTarget = await readlink(symlinkPath);
|
|
1769
1708
|
if (existingTarget === target) {
|
|
1770
1709
|
return;
|
|
1771
1710
|
}
|
|
1772
|
-
await
|
|
1711
|
+
await rm(symlinkPath);
|
|
1773
1712
|
} else {
|
|
1774
1713
|
console.warn(
|
|
1775
1714
|
`Warning: File exists at symlink path for "${skillName}", skipping: ${symlinkPath}`
|
|
@@ -1795,11 +1734,11 @@ async function removeAgentSymlinks(skillName, options) {
|
|
|
1795
1734
|
if (!config2) {
|
|
1796
1735
|
continue;
|
|
1797
1736
|
}
|
|
1798
|
-
const symlinkPath =
|
|
1737
|
+
const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
|
|
1799
1738
|
try {
|
|
1800
|
-
const stats = await
|
|
1739
|
+
const stats = await lstat(symlinkPath).catch(() => null);
|
|
1801
1740
|
if (stats?.isSymbolicLink()) {
|
|
1802
|
-
await
|
|
1741
|
+
await rm(symlinkPath);
|
|
1803
1742
|
}
|
|
1804
1743
|
} catch {
|
|
1805
1744
|
}
|
|
@@ -1822,9 +1761,9 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
|
|
|
1822
1761
|
for (const agentName of agents) {
|
|
1823
1762
|
const config2 = resolveAgentConfig(agentName, agentConfigs);
|
|
1824
1763
|
if (!config2) continue;
|
|
1825
|
-
const symlinkPath =
|
|
1764
|
+
const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
|
|
1826
1765
|
try {
|
|
1827
|
-
const stats = await
|
|
1766
|
+
const stats = await lstat(symlinkPath);
|
|
1828
1767
|
if (stats.isSymbolicLink()) {
|
|
1829
1768
|
linkedAgents.push(agentName);
|
|
1830
1769
|
}
|
|
@@ -1835,7 +1774,6 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
|
|
|
1835
1774
|
}
|
|
1836
1775
|
var init_symlinks = __esm({
|
|
1837
1776
|
"src/symlinks.ts"() {
|
|
1838
|
-
"use strict";
|
|
1839
1777
|
init_agents();
|
|
1840
1778
|
}
|
|
1841
1779
|
});
|
|
@@ -1845,18 +1783,28 @@ var add_exports = {};
|
|
|
1845
1783
|
__export(add_exports, {
|
|
1846
1784
|
add: () => add
|
|
1847
1785
|
});
|
|
1848
|
-
|
|
1849
|
-
|
|
1786
|
+
function isLocalSpecifier2(specifier) {
|
|
1787
|
+
return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
|
|
1788
|
+
}
|
|
1789
|
+
function parseLocalPath(specifier) {
|
|
1790
|
+
if (specifier.startsWith("file:")) {
|
|
1791
|
+
return specifier.slice(5);
|
|
1792
|
+
}
|
|
1793
|
+
return specifier;
|
|
1794
|
+
}
|
|
1795
|
+
function normalizeToFileSpecifier(path) {
|
|
1796
|
+
if (path.startsWith("file:")) {
|
|
1797
|
+
return path;
|
|
1798
|
+
}
|
|
1799
|
+
return `file:${path}`;
|
|
1800
|
+
}
|
|
1850
1801
|
async function add(specifiers, options) {
|
|
1851
1802
|
console.log("Resolving packages...\n");
|
|
1852
1803
|
const resolvedPackages = [];
|
|
1853
1804
|
const validationErrors = [];
|
|
1854
|
-
for (
|
|
1805
|
+
for (const specifier of specifiers) {
|
|
1855
1806
|
try {
|
|
1856
|
-
if (
|
|
1857
|
-
specifier = normalizeToFileSpecifier(specifier);
|
|
1858
|
-
}
|
|
1859
|
-
if (isLocalSpecifier(specifier)) {
|
|
1807
|
+
if (isLocalSpecifier2(specifier)) {
|
|
1860
1808
|
const resolved = await validateLocalPackage(specifier);
|
|
1861
1809
|
resolvedPackages.push(resolved);
|
|
1862
1810
|
} else if (isGitHubSpecifier(specifier)) {
|
|
@@ -2036,23 +1984,23 @@ async function installFromNode(node, options) {
|
|
|
2036
1984
|
throw new Error("Checksum verification failed");
|
|
2037
1985
|
}
|
|
2038
1986
|
const skillsDir = getSkillsDir();
|
|
2039
|
-
const destDir =
|
|
2040
|
-
await
|
|
2041
|
-
const { writeFile: writeFile8 } = await import(
|
|
2042
|
-
const tempFile =
|
|
1987
|
+
const destDir = join(skillsDir, username, name);
|
|
1988
|
+
await mkdir(destDir, { recursive: true });
|
|
1989
|
+
const { writeFile: writeFile8 } = await import('fs/promises');
|
|
1990
|
+
const tempFile = join(destDir, ".temp.tgz");
|
|
2043
1991
|
await writeFile8(tempFile, tarballBuffer);
|
|
2044
|
-
const { exec: exec2 } = await import(
|
|
2045
|
-
const { promisify: promisify2 } = await import(
|
|
1992
|
+
const { exec: exec2 } = await import('child_process');
|
|
1993
|
+
const { promisify: promisify2 } = await import('util');
|
|
2046
1994
|
const execAsync = promisify2(exec2);
|
|
2047
1995
|
try {
|
|
2048
|
-
await
|
|
2049
|
-
await
|
|
1996
|
+
await rm(destDir, { recursive: true, force: true });
|
|
1997
|
+
await mkdir(destDir, { recursive: true });
|
|
2050
1998
|
await writeFile8(tempFile, tarballBuffer);
|
|
2051
1999
|
await execAsync(
|
|
2052
2000
|
`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
|
|
2053
2001
|
);
|
|
2054
2002
|
} finally {
|
|
2055
|
-
await
|
|
2003
|
+
await rm(tempFile, { force: true });
|
|
2056
2004
|
}
|
|
2057
2005
|
const resolvedDeps = {};
|
|
2058
2006
|
for (const [depName, _range] of Object.entries(node.dependencies)) {
|
|
@@ -2221,50 +2169,74 @@ async function installGitHubPackage(resolved, options) {
|
|
|
2221
2169
|
console.log(`Location: ${destPath}`);
|
|
2222
2170
|
}
|
|
2223
2171
|
async function validateLocalPackage(specifier) {
|
|
2224
|
-
const
|
|
2225
|
-
|
|
2172
|
+
const path = parseLocalPath(specifier);
|
|
2173
|
+
const resolvedPath = resolve(process.cwd(), path);
|
|
2174
|
+
const normalizedSpecifier = normalizeToFileSpecifier(path);
|
|
2175
|
+
console.log(`Resolving ${specifier}...`);
|
|
2176
|
+
try {
|
|
2177
|
+
const stats = await stat(resolvedPath);
|
|
2178
|
+
if (!stats.isDirectory()) {
|
|
2179
|
+
throw new Error(`Path is not a directory: ${resolvedPath}`);
|
|
2180
|
+
}
|
|
2181
|
+
} catch (error) {
|
|
2182
|
+
if (error.code === "ENOENT") {
|
|
2183
|
+
throw new Error(
|
|
2184
|
+
`Directory not found: ${resolvedPath}
|
|
2185
|
+
Check that the path exists and is accessible.`
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2188
|
+
throw error;
|
|
2189
|
+
}
|
|
2190
|
+
let hasSkillMd = false;
|
|
2191
|
+
let hasPspmJson = false;
|
|
2192
|
+
try {
|
|
2193
|
+
await stat(join(resolvedPath, "SKILL.md"));
|
|
2194
|
+
hasSkillMd = true;
|
|
2195
|
+
} catch {
|
|
2196
|
+
}
|
|
2197
|
+
try {
|
|
2198
|
+
await stat(join(resolvedPath, "pspm.json"));
|
|
2199
|
+
hasPspmJson = true;
|
|
2200
|
+
} catch {
|
|
2201
|
+
}
|
|
2202
|
+
if (!hasSkillMd && !hasPspmJson) {
|
|
2226
2203
|
throw new Error(
|
|
2227
|
-
`
|
|
2204
|
+
`Not a valid skill directory: ${resolvedPath}
|
|
2205
|
+
Missing both SKILL.md and pspm.json. At least one is required.`
|
|
2228
2206
|
);
|
|
2229
2207
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
const validation = await validateLocalSkill(resolvedPath);
|
|
2233
|
-
if (!validation.valid) {
|
|
2234
|
-
throw new Error(validation.error);
|
|
2235
|
-
}
|
|
2236
|
-
const name = validation.manifest?.name || getLocalSkillName(parsed);
|
|
2237
|
-
console.log(`Resolved ${specifier} -> ${name} (local)`);
|
|
2208
|
+
const name = basename(resolvedPath);
|
|
2209
|
+
console.log(`Resolved ${specifier} -> ${resolvedPath}`);
|
|
2238
2210
|
return {
|
|
2239
2211
|
type: "local",
|
|
2240
2212
|
specifier,
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
resolvedPath
|
|
2213
|
+
normalizedSpecifier,
|
|
2214
|
+
path,
|
|
2215
|
+
resolvedPath,
|
|
2216
|
+
name
|
|
2244
2217
|
};
|
|
2245
2218
|
}
|
|
2246
2219
|
async function installLocalPackage(resolved, options) {
|
|
2247
|
-
const { specifier,
|
|
2248
|
-
console.log(`Installing ${specifier}
|
|
2220
|
+
const { specifier, normalizedSpecifier, path, resolvedPath, name } = resolved;
|
|
2221
|
+
console.log(`Installing ${specifier}...`);
|
|
2249
2222
|
const skillsDir = getSkillsDir();
|
|
2250
|
-
const
|
|
2251
|
-
await
|
|
2252
|
-
const symlinkPath =
|
|
2223
|
+
const localSkillsDir = join(skillsDir, "_local");
|
|
2224
|
+
await mkdir(localSkillsDir, { recursive: true });
|
|
2225
|
+
const symlinkPath = join(localSkillsDir, name);
|
|
2226
|
+
const relativeTarget = relative(dirname(symlinkPath), resolvedPath);
|
|
2253
2227
|
try {
|
|
2254
|
-
await
|
|
2228
|
+
await rm(symlinkPath, { force: true });
|
|
2255
2229
|
} catch {
|
|
2256
2230
|
}
|
|
2257
|
-
|
|
2258
|
-
const relativeTarget = relativePath(dirname4(symlinkPath), resolvedPath);
|
|
2259
|
-
await symlink2(relativeTarget, symlinkPath);
|
|
2231
|
+
await symlink(relativeTarget, symlinkPath);
|
|
2260
2232
|
const entry = {
|
|
2261
2233
|
version: "local",
|
|
2262
|
-
path
|
|
2234
|
+
path,
|
|
2263
2235
|
resolvedPath,
|
|
2264
2236
|
name
|
|
2265
2237
|
};
|
|
2266
|
-
await addLocalToLockfile(
|
|
2267
|
-
await addLocalDependency(
|
|
2238
|
+
await addLocalToLockfile(normalizedSpecifier, entry);
|
|
2239
|
+
await addLocalDependency(normalizedSpecifier);
|
|
2268
2240
|
const agents = options.resolvedAgents;
|
|
2269
2241
|
if (agents[0] !== "none") {
|
|
2270
2242
|
const manifest = await readManifest();
|
|
@@ -2283,30 +2255,26 @@ async function installLocalPackage(resolved, options) {
|
|
|
2283
2255
|
}
|
|
2284
2256
|
var init_add = __esm({
|
|
2285
2257
|
"src/commands/add.ts"() {
|
|
2286
|
-
"use strict";
|
|
2287
2258
|
init_agents();
|
|
2288
2259
|
init_api_client();
|
|
2289
2260
|
init_config();
|
|
2290
2261
|
init_errors();
|
|
2291
2262
|
init_github();
|
|
2292
2263
|
init_lib();
|
|
2293
|
-
|
|
2264
|
+
init_lockfile2();
|
|
2294
2265
|
init_manifest2();
|
|
2295
2266
|
init_symlinks();
|
|
2296
2267
|
}
|
|
2297
2268
|
});
|
|
2298
2269
|
|
|
2299
|
-
// src/index.ts
|
|
2300
|
-
import { readFileSync } from "fs";
|
|
2301
|
-
import { dirname as dirname6, join as join13 } from "path";
|
|
2302
|
-
import { fileURLToPath } from "url";
|
|
2303
|
-
import { Command } from "commander";
|
|
2304
|
-
|
|
2305
2270
|
// src/commands/access.ts
|
|
2306
2271
|
init_api_client();
|
|
2307
2272
|
init_config();
|
|
2308
2273
|
init_lib();
|
|
2309
|
-
|
|
2274
|
+
function isLocalSpecifier(specifier) {
|
|
2275
|
+
return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
|
|
2276
|
+
}
|
|
2277
|
+
async function access(specifier, options) {
|
|
2310
2278
|
try {
|
|
2311
2279
|
const apiKey = await requireApiKey();
|
|
2312
2280
|
const registryUrl = await getRegistryUrl();
|
|
@@ -2321,27 +2289,58 @@ async function access2(specifier, options) {
|
|
|
2321
2289
|
const visibility = options.public ? "public" : "private";
|
|
2322
2290
|
let packageName;
|
|
2323
2291
|
if (specifier) {
|
|
2292
|
+
if (isGitHubSpecifier(specifier)) {
|
|
2293
|
+
const ghSpec = parseGitHubSpecifier(specifier);
|
|
2294
|
+
if (ghSpec) {
|
|
2295
|
+
console.error(`Error: Cannot change visibility of GitHub packages.`);
|
|
2296
|
+
console.error(
|
|
2297
|
+
` "${specifier}" is hosted on GitHub, not the PSPM registry.`
|
|
2298
|
+
);
|
|
2299
|
+
console.error(
|
|
2300
|
+
` Visibility can only be changed for packages published to the registry.`
|
|
2301
|
+
);
|
|
2302
|
+
} else {
|
|
2303
|
+
console.error(`Error: Invalid GitHub specifier "${specifier}".`);
|
|
2304
|
+
console.error(` Use format: github:{owner}/{repo}[/{path}][@{ref}]`);
|
|
2305
|
+
}
|
|
2306
|
+
process.exit(1);
|
|
2307
|
+
}
|
|
2308
|
+
if (isLocalSpecifier(specifier)) {
|
|
2309
|
+
console.error(`Error: Cannot change visibility of local packages.`);
|
|
2310
|
+
console.error(
|
|
2311
|
+
` "${specifier}" is a local directory, not a registry package.`
|
|
2312
|
+
);
|
|
2313
|
+
console.error(
|
|
2314
|
+
` Visibility can only be changed for packages published to the registry.`
|
|
2315
|
+
);
|
|
2316
|
+
process.exit(1);
|
|
2317
|
+
}
|
|
2324
2318
|
const parsed = parseSkillSpecifier(specifier);
|
|
2325
2319
|
if (!parsed) {
|
|
2320
|
+
console.error(`Error: Invalid package specifier "${specifier}".`);
|
|
2321
|
+
console.error(` Use format: @user/{username}/{name}`);
|
|
2322
|
+
console.error(``);
|
|
2323
|
+
console.error(` Examples:`);
|
|
2324
|
+
console.error(` pspm access @user/myname/my-skill --public`);
|
|
2326
2325
|
console.error(
|
|
2327
|
-
`
|
|
2326
|
+
` pspm access --public (uses current directory's pspm.json)`
|
|
2328
2327
|
);
|
|
2329
2328
|
process.exit(1);
|
|
2330
2329
|
}
|
|
2331
2330
|
packageName = parsed.name;
|
|
2332
2331
|
} else {
|
|
2333
|
-
const { readFile:
|
|
2334
|
-
const { join: join14 } = await import(
|
|
2332
|
+
const { readFile: readFile8 } = await import('fs/promises');
|
|
2333
|
+
const { join: join14 } = await import('path');
|
|
2335
2334
|
let manifest = null;
|
|
2336
2335
|
try {
|
|
2337
|
-
const content = await
|
|
2336
|
+
const content = await readFile8(
|
|
2338
2337
|
join14(process.cwd(), "pspm.json"),
|
|
2339
2338
|
"utf-8"
|
|
2340
2339
|
);
|
|
2341
2340
|
manifest = JSON.parse(content);
|
|
2342
2341
|
} catch {
|
|
2343
2342
|
try {
|
|
2344
|
-
const content = await
|
|
2343
|
+
const content = await readFile8(
|
|
2345
2344
|
join14(process.cwd(), "package.json"),
|
|
2346
2345
|
"utf-8"
|
|
2347
2346
|
);
|
|
@@ -2389,15 +2388,11 @@ async function access2(specifier, options) {
|
|
|
2389
2388
|
|
|
2390
2389
|
// src/commands/index.ts
|
|
2391
2390
|
init_add();
|
|
2392
|
-
|
|
2393
|
-
// src/commands/config/init.ts
|
|
2394
|
-
import { stat as stat4, writeFile as writeFile5 } from "fs/promises";
|
|
2395
|
-
import { join as join7 } from "path";
|
|
2396
2391
|
async function configInit(options) {
|
|
2397
2392
|
try {
|
|
2398
|
-
const configPath =
|
|
2393
|
+
const configPath = join(process.cwd(), ".pspmrc");
|
|
2399
2394
|
try {
|
|
2400
|
-
await
|
|
2395
|
+
await stat(configPath);
|
|
2401
2396
|
console.error("Error: .pspmrc already exists in this directory.");
|
|
2402
2397
|
process.exit(1);
|
|
2403
2398
|
} catch {
|
|
@@ -2410,7 +2405,7 @@ async function configInit(options) {
|
|
|
2410
2405
|
lines.push("; registry = https://custom-registry.example.com");
|
|
2411
2406
|
}
|
|
2412
2407
|
lines.push("");
|
|
2413
|
-
await
|
|
2408
|
+
await writeFile(configPath, lines.join("\n"));
|
|
2414
2409
|
console.log("Created .pspmrc");
|
|
2415
2410
|
console.log("");
|
|
2416
2411
|
console.log("Contents:");
|
|
@@ -2523,9 +2518,6 @@ async function deprecate(specifier, message, options) {
|
|
|
2523
2518
|
|
|
2524
2519
|
// src/commands/init.ts
|
|
2525
2520
|
init_lib();
|
|
2526
|
-
import { readFile as readFile4, stat as stat5, writeFile as writeFile6 } from "fs/promises";
|
|
2527
|
-
import { basename, join as join8 } from "path";
|
|
2528
|
-
import { createInterface } from "readline";
|
|
2529
2521
|
function prompt(rl, question, defaultValue) {
|
|
2530
2522
|
return new Promise((resolve2) => {
|
|
2531
2523
|
const displayDefault = defaultValue ? ` (${defaultValue})` : "";
|
|
@@ -2536,8 +2528,8 @@ function prompt(rl, question, defaultValue) {
|
|
|
2536
2528
|
}
|
|
2537
2529
|
async function readExistingPackageJson() {
|
|
2538
2530
|
try {
|
|
2539
|
-
const content = await
|
|
2540
|
-
|
|
2531
|
+
const content = await readFile(
|
|
2532
|
+
join(process.cwd(), "package.json"),
|
|
2541
2533
|
"utf-8"
|
|
2542
2534
|
);
|
|
2543
2535
|
const pkg = JSON.parse(content);
|
|
@@ -2554,8 +2546,8 @@ async function readExistingPackageJson() {
|
|
|
2554
2546
|
}
|
|
2555
2547
|
async function getGitAuthor() {
|
|
2556
2548
|
try {
|
|
2557
|
-
const { exec: exec2 } = await import(
|
|
2558
|
-
const { promisify: promisify2 } = await import(
|
|
2549
|
+
const { exec: exec2 } = await import('child_process');
|
|
2550
|
+
const { promisify: promisify2 } = await import('util');
|
|
2559
2551
|
const execAsync = promisify2(exec2);
|
|
2560
2552
|
const [nameResult, emailResult] = await Promise.all([
|
|
2561
2553
|
execAsync("git config user.name").catch(() => ({ stdout: "" })),
|
|
@@ -2581,15 +2573,15 @@ function sanitizeName(name) {
|
|
|
2581
2573
|
function isValidName(name) {
|
|
2582
2574
|
return /^[a-z][a-z0-9_-]*$/.test(name);
|
|
2583
2575
|
}
|
|
2584
|
-
function isValidVersion(
|
|
2585
|
-
return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(
|
|
2576
|
+
function isValidVersion(version3) {
|
|
2577
|
+
return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version3);
|
|
2586
2578
|
}
|
|
2587
2579
|
async function init(options) {
|
|
2588
2580
|
try {
|
|
2589
|
-
const pspmJsonPath =
|
|
2581
|
+
const pspmJsonPath = join(process.cwd(), "pspm.json");
|
|
2590
2582
|
let exists = false;
|
|
2591
2583
|
try {
|
|
2592
|
-
await
|
|
2584
|
+
await stat(pspmJsonPath);
|
|
2593
2585
|
exists = true;
|
|
2594
2586
|
} catch {
|
|
2595
2587
|
}
|
|
@@ -2654,10 +2646,10 @@ async function init(options) {
|
|
|
2654
2646
|
);
|
|
2655
2647
|
name = await prompt(rl, "skill name:", sanitizeName(name));
|
|
2656
2648
|
}
|
|
2657
|
-
let
|
|
2658
|
-
while (!isValidVersion(
|
|
2649
|
+
let version3 = await prompt(rl, "version:", defaultVersion);
|
|
2650
|
+
while (!isValidVersion(version3)) {
|
|
2659
2651
|
console.log(" Version must be valid semver (e.g., 1.0.0)");
|
|
2660
|
-
|
|
2652
|
+
version3 = await prompt(rl, "version:", "0.1.0");
|
|
2661
2653
|
}
|
|
2662
2654
|
const description = await prompt(
|
|
2663
2655
|
rl,
|
|
@@ -2677,7 +2669,7 @@ async function init(options) {
|
|
|
2677
2669
|
manifest = {
|
|
2678
2670
|
$schema: PSPM_SCHEMA_URL,
|
|
2679
2671
|
name,
|
|
2680
|
-
version:
|
|
2672
|
+
version: version3,
|
|
2681
2673
|
description: description || void 0,
|
|
2682
2674
|
author: author || void 0,
|
|
2683
2675
|
license,
|
|
@@ -2714,17 +2706,17 @@ async function init(options) {
|
|
|
2714
2706
|
input: process.stdin,
|
|
2715
2707
|
output: process.stdout
|
|
2716
2708
|
});
|
|
2717
|
-
const
|
|
2709
|
+
const confirm2 = await prompt(rl, "Is this OK?", "yes");
|
|
2718
2710
|
rl.close();
|
|
2719
|
-
if (
|
|
2711
|
+
if (confirm2.toLowerCase() !== "yes" && confirm2.toLowerCase() !== "y") {
|
|
2720
2712
|
console.log("Aborted.");
|
|
2721
2713
|
process.exit(0);
|
|
2722
2714
|
}
|
|
2723
2715
|
}
|
|
2724
|
-
await
|
|
2716
|
+
await writeFile(pspmJsonPath, `${content}
|
|
2725
2717
|
`);
|
|
2726
2718
|
try {
|
|
2727
|
-
await
|
|
2719
|
+
await stat(join(process.cwd(), "SKILL.md"));
|
|
2728
2720
|
} catch {
|
|
2729
2721
|
console.log(
|
|
2730
2722
|
"Note: Create a SKILL.md file with your skill's prompt content."
|
|
@@ -2749,19 +2741,9 @@ init_config();
|
|
|
2749
2741
|
init_errors();
|
|
2750
2742
|
init_github();
|
|
2751
2743
|
init_lib();
|
|
2752
|
-
|
|
2744
|
+
init_lockfile2();
|
|
2753
2745
|
init_manifest2();
|
|
2754
2746
|
init_symlinks();
|
|
2755
|
-
import { createHash as createHash2 } from "crypto";
|
|
2756
|
-
import {
|
|
2757
|
-
lstat as lstat3,
|
|
2758
|
-
mkdir as mkdir6,
|
|
2759
|
-
readFile as readFile5,
|
|
2760
|
-
rm as rm4,
|
|
2761
|
-
symlink as symlink3,
|
|
2762
|
-
writeFile as writeFile7
|
|
2763
|
-
} from "fs/promises";
|
|
2764
|
-
import { dirname as dirname5, join as join9, relative as relative2 } from "path";
|
|
2765
2747
|
function getCacheFilePath(cacheDir, integrity) {
|
|
2766
2748
|
const match = integrity.match(/^sha256-(.+)$/);
|
|
2767
2749
|
if (!match) {
|
|
@@ -2769,15 +2751,15 @@ function getCacheFilePath(cacheDir, integrity) {
|
|
|
2769
2751
|
}
|
|
2770
2752
|
const base64Hash = match[1];
|
|
2771
2753
|
const hexHash = Buffer.from(base64Hash, "base64").toString("hex");
|
|
2772
|
-
return
|
|
2754
|
+
return join(cacheDir, `sha256-${hexHash}.tgz`);
|
|
2773
2755
|
}
|
|
2774
2756
|
async function readFromCache(cacheDir, integrity) {
|
|
2775
2757
|
try {
|
|
2776
2758
|
const cachePath = getCacheFilePath(cacheDir, integrity);
|
|
2777
|
-
const data = await
|
|
2778
|
-
const actualIntegrity = `sha256-${
|
|
2759
|
+
const data = await readFile(cachePath);
|
|
2760
|
+
const actualIntegrity = `sha256-${createHash("sha256").update(data).digest("base64")}`;
|
|
2779
2761
|
if (actualIntegrity !== integrity) {
|
|
2780
|
-
await
|
|
2762
|
+
await rm(cachePath, { force: true });
|
|
2781
2763
|
return null;
|
|
2782
2764
|
}
|
|
2783
2765
|
return data;
|
|
@@ -2787,9 +2769,9 @@ async function readFromCache(cacheDir, integrity) {
|
|
|
2787
2769
|
}
|
|
2788
2770
|
async function writeToCache(cacheDir, integrity, data) {
|
|
2789
2771
|
try {
|
|
2790
|
-
await
|
|
2772
|
+
await mkdir(cacheDir, { recursive: true });
|
|
2791
2773
|
const cachePath = getCacheFilePath(cacheDir, integrity);
|
|
2792
|
-
await
|
|
2774
|
+
await writeFile(cachePath, data);
|
|
2793
2775
|
} catch {
|
|
2794
2776
|
}
|
|
2795
2777
|
}
|
|
@@ -2816,10 +2798,8 @@ async function installFromLockfile(options) {
|
|
|
2816
2798
|
let lockfile = await readLockfile();
|
|
2817
2799
|
const manifestDeps = await getDependencies();
|
|
2818
2800
|
const manifestGitHubDeps = await getGitHubDependencies();
|
|
2819
|
-
const manifestLocalDeps = await getLocalDependencies();
|
|
2820
2801
|
const lockfilePackages = lockfile?.packages ?? lockfile?.skills ?? {};
|
|
2821
2802
|
const lockfileGitHubPackages = lockfile?.githubPackages ?? {};
|
|
2822
|
-
const lockfileLocalPackages = lockfile?.localPackages ?? {};
|
|
2823
2803
|
const installedSkills = [];
|
|
2824
2804
|
const missingDeps = [];
|
|
2825
2805
|
for (const [fullName, versionRange] of Object.entries(manifestDeps)) {
|
|
@@ -2970,53 +2950,6 @@ Resolving ${missingGitHubDeps.length} GitHub dependency(ies)...
|
|
|
2970
2950
|
}
|
|
2971
2951
|
lockfile = await readLockfile();
|
|
2972
2952
|
}
|
|
2973
|
-
const missingLocalDeps = [];
|
|
2974
|
-
for (const [specifier] of Object.entries(manifestLocalDeps)) {
|
|
2975
|
-
if (!lockfileLocalPackages[specifier]) {
|
|
2976
|
-
missingLocalDeps.push({ specifier });
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
|
-
if (missingLocalDeps.length > 0) {
|
|
2980
|
-
if (options.frozenLockfile) {
|
|
2981
|
-
console.error(
|
|
2982
|
-
"Error: Local dependencies in pspm.json are not in lockfile. Cannot install with --frozen-lockfile"
|
|
2983
|
-
);
|
|
2984
|
-
console.error("Missing local dependencies:");
|
|
2985
|
-
for (const dep of missingLocalDeps) {
|
|
2986
|
-
console.error(` - ${dep.specifier}`);
|
|
2987
|
-
}
|
|
2988
|
-
process.exit(1);
|
|
2989
|
-
}
|
|
2990
|
-
console.log(
|
|
2991
|
-
`
|
|
2992
|
-
Resolving ${missingLocalDeps.length} local dependency(ies)...
|
|
2993
|
-
`
|
|
2994
|
-
);
|
|
2995
|
-
for (const { specifier } of missingLocalDeps) {
|
|
2996
|
-
const parsed = parseLocalSpecifier(specifier);
|
|
2997
|
-
if (!parsed) {
|
|
2998
|
-
console.error(`Error: Invalid local specifier: ${specifier}`);
|
|
2999
|
-
continue;
|
|
3000
|
-
}
|
|
3001
|
-
console.log(`Resolving ${specifier}...`);
|
|
3002
|
-
const resolvedPath = resolveLocalPath(parsed);
|
|
3003
|
-
const validation = await validateLocalSkill(resolvedPath);
|
|
3004
|
-
if (!validation.valid) {
|
|
3005
|
-
console.error(`Error: ${validation.error}`);
|
|
3006
|
-
continue;
|
|
3007
|
-
}
|
|
3008
|
-
const name = validation.manifest?.name || parsed.path.split("/").pop() || "unknown";
|
|
3009
|
-
const entry = {
|
|
3010
|
-
version: "local",
|
|
3011
|
-
path: parsed.path,
|
|
3012
|
-
resolvedPath,
|
|
3013
|
-
name
|
|
3014
|
-
};
|
|
3015
|
-
await addLocalToLockfile(specifier, entry);
|
|
3016
|
-
console.log(` Resolved ${specifier} -> ${name} (local)`);
|
|
3017
|
-
}
|
|
3018
|
-
lockfile = await readLockfile();
|
|
3019
|
-
}
|
|
3020
2953
|
const manifest = await readManifest();
|
|
3021
2954
|
const agentConfigs = manifest?.agents;
|
|
3022
2955
|
let agents;
|
|
@@ -3082,7 +3015,7 @@ Installing ${packageCount} registry skill(s)...
|
|
|
3082
3015
|
continue;
|
|
3083
3016
|
}
|
|
3084
3017
|
tarballBuffer = Buffer.from(await response.arrayBuffer());
|
|
3085
|
-
const actualIntegrity = `sha256-${
|
|
3018
|
+
const actualIntegrity = `sha256-${createHash("sha256").update(tarballBuffer).digest("base64")}`;
|
|
3086
3019
|
if (actualIntegrity !== entry.integrity) {
|
|
3087
3020
|
console.error(
|
|
3088
3021
|
` Error: Checksum verification failed for ${fullName}`
|
|
@@ -3094,20 +3027,20 @@ Installing ${packageCount} registry skill(s)...
|
|
|
3094
3027
|
}
|
|
3095
3028
|
await writeToCache(cacheDir, entry.integrity, tarballBuffer);
|
|
3096
3029
|
}
|
|
3097
|
-
const destDir =
|
|
3098
|
-
await
|
|
3099
|
-
await
|
|
3100
|
-
const tempFile =
|
|
3101
|
-
await
|
|
3102
|
-
const { exec: exec2 } = await import(
|
|
3103
|
-
const { promisify: promisify2 } = await import(
|
|
3030
|
+
const destDir = join(skillsDir, username, name);
|
|
3031
|
+
await rm(destDir, { recursive: true, force: true });
|
|
3032
|
+
await mkdir(destDir, { recursive: true });
|
|
3033
|
+
const tempFile = join(destDir, ".temp.tgz");
|
|
3034
|
+
await writeFile(tempFile, tarballBuffer);
|
|
3035
|
+
const { exec: exec2 } = await import('child_process');
|
|
3036
|
+
const { promisify: promisify2 } = await import('util');
|
|
3104
3037
|
const execAsync = promisify2(exec2);
|
|
3105
3038
|
try {
|
|
3106
3039
|
await execAsync(
|
|
3107
3040
|
`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
|
|
3108
3041
|
);
|
|
3109
3042
|
} finally {
|
|
3110
|
-
await
|
|
3043
|
+
await rm(tempFile, { force: true });
|
|
3111
3044
|
}
|
|
3112
3045
|
console.log(
|
|
3113
3046
|
` Installed to ${destDir}${fromCache ? " (from cache)" : ""}`
|
|
@@ -3195,52 +3128,6 @@ Installing ${githubCount} GitHub skill(s)...
|
|
|
3195
3128
|
}
|
|
3196
3129
|
}
|
|
3197
3130
|
}
|
|
3198
|
-
const localPackages = lockfile?.localPackages ?? {};
|
|
3199
|
-
const localCount = Object.keys(localPackages).length;
|
|
3200
|
-
if (localCount > 0) {
|
|
3201
|
-
console.log(`
|
|
3202
|
-
Installing ${localCount} local skill(s)...
|
|
3203
|
-
`);
|
|
3204
|
-
for (const [specifier, entry] of Object.entries(localPackages)) {
|
|
3205
|
-
const localEntry = entry;
|
|
3206
|
-
console.log(`Installing ${specifier} (local symlink)...`);
|
|
3207
|
-
const validation = await validateLocalSkill(localEntry.resolvedPath);
|
|
3208
|
-
if (!validation.valid) {
|
|
3209
|
-
console.error(` Error: ${validation.error}`);
|
|
3210
|
-
console.error(
|
|
3211
|
-
` Hint: The local skill at ${localEntry.resolvedPath} may have been moved or deleted.`
|
|
3212
|
-
);
|
|
3213
|
-
continue;
|
|
3214
|
-
}
|
|
3215
|
-
const localDir = join9(skillsDir, "_local");
|
|
3216
|
-
await mkdir6(localDir, { recursive: true });
|
|
3217
|
-
const symlinkPath = join9(localDir, localEntry.name);
|
|
3218
|
-
try {
|
|
3219
|
-
const stats = await lstat3(symlinkPath);
|
|
3220
|
-
if (stats.isSymbolicLink()) {
|
|
3221
|
-
await rm4(symlinkPath);
|
|
3222
|
-
}
|
|
3223
|
-
} catch {
|
|
3224
|
-
}
|
|
3225
|
-
const relativeTarget = relative2(
|
|
3226
|
-
dirname5(symlinkPath),
|
|
3227
|
-
localEntry.resolvedPath
|
|
3228
|
-
);
|
|
3229
|
-
try {
|
|
3230
|
-
await symlink3(relativeTarget, symlinkPath);
|
|
3231
|
-
console.log(
|
|
3232
|
-
` Installed to ${symlinkPath} -> ${localEntry.resolvedPath}`
|
|
3233
|
-
);
|
|
3234
|
-
installedSkills.push({
|
|
3235
|
-
name: localEntry.name,
|
|
3236
|
-
sourcePath: getLocalSkillPath(localEntry.name)
|
|
3237
|
-
});
|
|
3238
|
-
} catch (error) {
|
|
3239
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3240
|
-
console.error(` Error creating symlink: ${message}`);
|
|
3241
|
-
}
|
|
3242
|
-
}
|
|
3243
|
-
}
|
|
3244
3131
|
if (installedSkills.length > 0 && agents[0] !== "none") {
|
|
3245
3132
|
console.log(`
|
|
3246
3133
|
Creating symlinks for agent(s): ${agents.join(", ")}...`);
|
|
@@ -3251,7 +3138,7 @@ Creating symlinks for agent(s): ${agents.join(", ")}...`);
|
|
|
3251
3138
|
});
|
|
3252
3139
|
console.log(" Symlinks created.");
|
|
3253
3140
|
}
|
|
3254
|
-
const totalCount = packageCount + githubCount
|
|
3141
|
+
const totalCount = packageCount + githubCount;
|
|
3255
3142
|
if (totalCount === 0) {
|
|
3256
3143
|
console.log("No skills to install.");
|
|
3257
3144
|
} else {
|
|
@@ -3268,7 +3155,7 @@ All ${totalCount} skill(s) installed.`);
|
|
|
3268
3155
|
// src/commands/link.ts
|
|
3269
3156
|
init_agents();
|
|
3270
3157
|
init_lib();
|
|
3271
|
-
|
|
3158
|
+
init_lockfile2();
|
|
3272
3159
|
init_manifest2();
|
|
3273
3160
|
init_symlinks();
|
|
3274
3161
|
async function link(options) {
|
|
@@ -3345,11 +3232,9 @@ async function link(options) {
|
|
|
3345
3232
|
// src/commands/list.ts
|
|
3346
3233
|
init_agents();
|
|
3347
3234
|
init_lib();
|
|
3348
|
-
|
|
3235
|
+
init_lockfile2();
|
|
3349
3236
|
init_manifest2();
|
|
3350
3237
|
init_symlinks();
|
|
3351
|
-
import { access as access3 } from "fs/promises";
|
|
3352
|
-
import { join as join10 } from "path";
|
|
3353
3238
|
async function list(options) {
|
|
3354
3239
|
try {
|
|
3355
3240
|
const registrySkills = await listLockfileSkills();
|
|
@@ -3364,10 +3249,10 @@ async function list(options) {
|
|
|
3364
3249
|
if (!match) continue;
|
|
3365
3250
|
const [, username, skillName] = match;
|
|
3366
3251
|
const sourcePath = getRegistrySkillPath(username, skillName);
|
|
3367
|
-
const absolutePath =
|
|
3252
|
+
const absolutePath = join(projectRoot, sourcePath);
|
|
3368
3253
|
let status = "installed";
|
|
3369
3254
|
try {
|
|
3370
|
-
await
|
|
3255
|
+
await access$1(absolutePath);
|
|
3371
3256
|
} catch {
|
|
3372
3257
|
status = "missing";
|
|
3373
3258
|
}
|
|
@@ -3397,10 +3282,10 @@ async function list(options) {
|
|
|
3397
3282
|
parsed.repo,
|
|
3398
3283
|
parsed.path
|
|
3399
3284
|
);
|
|
3400
|
-
const absolutePath =
|
|
3285
|
+
const absolutePath = join(projectRoot, sourcePath);
|
|
3401
3286
|
let status = "installed";
|
|
3402
3287
|
try {
|
|
3403
|
-
await
|
|
3288
|
+
await access$1(absolutePath);
|
|
3404
3289
|
} catch {
|
|
3405
3290
|
status = "missing";
|
|
3406
3291
|
}
|
|
@@ -3422,35 +3307,6 @@ async function list(options) {
|
|
|
3422
3307
|
gitCommit: ghEntry.gitCommit
|
|
3423
3308
|
});
|
|
3424
3309
|
}
|
|
3425
|
-
const localSkills = await listLockfileLocalPackages();
|
|
3426
|
-
for (const { specifier, entry } of localSkills) {
|
|
3427
|
-
const localEntry = entry;
|
|
3428
|
-
const skillName = localEntry.name;
|
|
3429
|
-
const sourcePath = getLocalSkillPath(skillName);
|
|
3430
|
-
const absolutePath = join10(projectRoot, sourcePath);
|
|
3431
|
-
let status = "installed";
|
|
3432
|
-
try {
|
|
3433
|
-
await access3(absolutePath);
|
|
3434
|
-
} catch {
|
|
3435
|
-
status = "missing";
|
|
3436
|
-
}
|
|
3437
|
-
const linkedAgents = await getLinkedAgents(
|
|
3438
|
-
skillName,
|
|
3439
|
-
availableAgents,
|
|
3440
|
-
projectRoot,
|
|
3441
|
-
agentConfigs
|
|
3442
|
-
);
|
|
3443
|
-
skills.push({
|
|
3444
|
-
name: skillName,
|
|
3445
|
-
fullName: specifier,
|
|
3446
|
-
version: "local",
|
|
3447
|
-
source: "local",
|
|
3448
|
-
sourcePath,
|
|
3449
|
-
status,
|
|
3450
|
-
linkedAgents,
|
|
3451
|
-
localPath: localEntry.resolvedPath
|
|
3452
|
-
});
|
|
3453
|
-
}
|
|
3454
3310
|
if (skills.length === 0) {
|
|
3455
3311
|
console.log("No skills installed.");
|
|
3456
3312
|
return;
|
|
@@ -3463,14 +3319,9 @@ async function list(options) {
|
|
|
3463
3319
|
for (const skill of skills) {
|
|
3464
3320
|
if (skill.source === "registry") {
|
|
3465
3321
|
console.log(` ${skill.fullName}@${skill.version} (registry)`);
|
|
3466
|
-
} else
|
|
3322
|
+
} else {
|
|
3467
3323
|
const refInfo = skill.gitRef ? `${skill.gitRef}@${skill.gitCommit?.slice(0, 7)}` : skill.version;
|
|
3468
3324
|
console.log(` ${skill.fullName} (${refInfo})`);
|
|
3469
|
-
} else {
|
|
3470
|
-
console.log(` ${skill.fullName} [local]`);
|
|
3471
|
-
if (skill.localPath) {
|
|
3472
|
-
console.log(` Path: ${skill.localPath}`);
|
|
3473
|
-
}
|
|
3474
3325
|
}
|
|
3475
3326
|
if (skill.status === "missing") {
|
|
3476
3327
|
console.log(` Status: MISSING (run 'pspm install' to restore)`);
|
|
@@ -3486,11 +3337,9 @@ async function list(options) {
|
|
|
3486
3337
|
}
|
|
3487
3338
|
const registryCount = skills.filter((s) => s.source === "registry").length;
|
|
3488
3339
|
const githubCount = skills.filter((s) => s.source === "github").length;
|
|
3489
|
-
const localCount = skills.filter((s) => s.source === "local").length;
|
|
3490
3340
|
const parts = [];
|
|
3491
3341
|
if (registryCount > 0) parts.push(`${registryCount} registry`);
|
|
3492
3342
|
if (githubCount > 0) parts.push(`${githubCount} github`);
|
|
3493
|
-
if (localCount > 0) parts.push(`${localCount} local`);
|
|
3494
3343
|
console.log(`
|
|
3495
3344
|
Total: ${skills.length} skill(s) (${parts.join(", ")})`);
|
|
3496
3345
|
} catch (error) {
|
|
@@ -3503,26 +3352,30 @@ Total: ${skills.length} skill(s) (${parts.join(", ")})`);
|
|
|
3503
3352
|
// src/commands/login.ts
|
|
3504
3353
|
init_api_client();
|
|
3505
3354
|
init_config();
|
|
3506
|
-
import { randomBytes } from "crypto";
|
|
3507
|
-
import http from "http";
|
|
3508
|
-
import { URL as URL2 } from "url";
|
|
3509
|
-
import open from "open";
|
|
3510
3355
|
var DEFAULT_WEB_APP_URL = "https://pspm.dev";
|
|
3511
3356
|
function getWebAppUrl(registryUrl) {
|
|
3512
3357
|
if (process.env.PSPM_WEB_URL) {
|
|
3513
3358
|
return process.env.PSPM_WEB_URL.replace(/\/$/, "");
|
|
3514
3359
|
}
|
|
3515
3360
|
try {
|
|
3516
|
-
const url = new
|
|
3517
|
-
|
|
3361
|
+
const url = new URL$1(registryUrl);
|
|
3362
|
+
let host = url.host;
|
|
3363
|
+
if (host.startsWith("registry.")) {
|
|
3364
|
+
host = host.slice("registry.".length);
|
|
3365
|
+
}
|
|
3366
|
+
return `${url.protocol}//${host}`;
|
|
3518
3367
|
} catch {
|
|
3519
3368
|
return DEFAULT_WEB_APP_URL;
|
|
3520
3369
|
}
|
|
3521
3370
|
}
|
|
3522
3371
|
function getServerUrl(registryUrl) {
|
|
3523
3372
|
try {
|
|
3524
|
-
const url = new
|
|
3525
|
-
|
|
3373
|
+
const url = new URL$1(registryUrl);
|
|
3374
|
+
let host = url.host;
|
|
3375
|
+
if (host.startsWith("registry.")) {
|
|
3376
|
+
host = host.slice("registry.".length);
|
|
3377
|
+
}
|
|
3378
|
+
return `${url.protocol}//${host}`;
|
|
3526
3379
|
} catch {
|
|
3527
3380
|
return DEFAULT_WEB_APP_URL;
|
|
3528
3381
|
}
|
|
@@ -3553,7 +3406,7 @@ function startCallbackServer(expectedState) {
|
|
|
3553
3406
|
rejectToken = reject;
|
|
3554
3407
|
});
|
|
3555
3408
|
const server = http.createServer((req, res) => {
|
|
3556
|
-
const url = new
|
|
3409
|
+
const url = new URL$1(req.url || "/", "http://localhost");
|
|
3557
3410
|
if (url.pathname === "/callback") {
|
|
3558
3411
|
const token = url.searchParams.get("token");
|
|
3559
3412
|
const state = url.searchParams.get("state");
|
|
@@ -3703,8 +3556,7 @@ async function logout() {
|
|
|
3703
3556
|
|
|
3704
3557
|
// src/commands/migrate.ts
|
|
3705
3558
|
init_config();
|
|
3706
|
-
|
|
3707
|
-
import { mkdir as mkdir7, readdir as readdir2, rename, rm as rm5, stat as stat6 } from "fs/promises";
|
|
3559
|
+
init_lockfile2();
|
|
3708
3560
|
async function migrate(options) {
|
|
3709
3561
|
try {
|
|
3710
3562
|
const legacySkillsDir = getLegacySkillsDir();
|
|
@@ -3715,9 +3567,9 @@ async function migrate(options) {
|
|
|
3715
3567
|
let migrationNeeded = false;
|
|
3716
3568
|
const actions = [];
|
|
3717
3569
|
try {
|
|
3718
|
-
const legacyStats = await
|
|
3570
|
+
const legacyStats = await stat(legacySkillsDir);
|
|
3719
3571
|
if (legacyStats.isDirectory()) {
|
|
3720
|
-
const contents = await
|
|
3572
|
+
const contents = await readdir(legacySkillsDir);
|
|
3721
3573
|
if (contents.length > 0) {
|
|
3722
3574
|
migrationNeeded = true;
|
|
3723
3575
|
actions.push("Move .skills/ \u2192 .pspm/skills/");
|
|
@@ -3726,9 +3578,9 @@ async function migrate(options) {
|
|
|
3726
3578
|
} catch {
|
|
3727
3579
|
}
|
|
3728
3580
|
try {
|
|
3729
|
-
await
|
|
3581
|
+
await stat(legacyLockfilePath);
|
|
3730
3582
|
try {
|
|
3731
|
-
await
|
|
3583
|
+
await stat(newLockfilePath);
|
|
3732
3584
|
actions.push(
|
|
3733
3585
|
"Note: Both skill-lock.json and pspm-lock.json exist. Manual merge may be needed."
|
|
3734
3586
|
);
|
|
@@ -3760,21 +3612,21 @@ async function migrate(options) {
|
|
|
3760
3612
|
console.log(" \u2713 Migrated skill-lock.json \u2192 pspm-lock.json");
|
|
3761
3613
|
}
|
|
3762
3614
|
try {
|
|
3763
|
-
const legacyStats = await
|
|
3615
|
+
const legacyStats = await stat(legacySkillsDir);
|
|
3764
3616
|
if (legacyStats.isDirectory()) {
|
|
3765
|
-
const contents = await
|
|
3617
|
+
const contents = await readdir(legacySkillsDir);
|
|
3766
3618
|
if (contents.length > 0) {
|
|
3767
|
-
await
|
|
3619
|
+
await mkdir(pspmDir, { recursive: true });
|
|
3768
3620
|
try {
|
|
3769
|
-
const newStats = await
|
|
3621
|
+
const newStats = await stat(newSkillsDir);
|
|
3770
3622
|
if (newStats.isDirectory()) {
|
|
3771
|
-
const newContents = await
|
|
3623
|
+
const newContents = await readdir(newSkillsDir);
|
|
3772
3624
|
if (newContents.length > 0) {
|
|
3773
3625
|
console.log(
|
|
3774
3626
|
" ! Both .skills/ and .pspm/skills/ have content. Manual merge required."
|
|
3775
3627
|
);
|
|
3776
3628
|
} else {
|
|
3777
|
-
await
|
|
3629
|
+
await rm(newSkillsDir, { recursive: true, force: true });
|
|
3778
3630
|
await rename(legacySkillsDir, newSkillsDir);
|
|
3779
3631
|
console.log(" \u2713 Moved .skills/ \u2192 .pspm/skills/");
|
|
3780
3632
|
}
|
|
@@ -3810,24 +3662,32 @@ init_api_client();
|
|
|
3810
3662
|
init_config();
|
|
3811
3663
|
init_errors();
|
|
3812
3664
|
init_lib();
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3665
|
+
var exec = promisify(exec$1);
|
|
3666
|
+
function confirm(question) {
|
|
3667
|
+
return new Promise((resolve2) => {
|
|
3668
|
+
const rl = createInterface({
|
|
3669
|
+
input: process.stdin,
|
|
3670
|
+
output: process.stdout
|
|
3671
|
+
});
|
|
3672
|
+
rl.question(`${question} (y/N) `, (answer) => {
|
|
3673
|
+
rl.close();
|
|
3674
|
+
const normalized = answer.trim().toLowerCase();
|
|
3675
|
+
resolve2(normalized === "y" || normalized === "yes");
|
|
3676
|
+
});
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3819
3679
|
async function detectManifest() {
|
|
3820
3680
|
const cwd = process.cwd();
|
|
3821
|
-
const pspmJsonPath =
|
|
3681
|
+
const pspmJsonPath = join(cwd, "pspm.json");
|
|
3822
3682
|
try {
|
|
3823
|
-
const content = await
|
|
3683
|
+
const content = await readFile(pspmJsonPath, "utf-8");
|
|
3824
3684
|
const manifest = JSON.parse(content);
|
|
3825
3685
|
return { type: "pspm.json", manifest, path: pspmJsonPath };
|
|
3826
3686
|
} catch {
|
|
3827
3687
|
}
|
|
3828
|
-
const packageJsonPath =
|
|
3688
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
3829
3689
|
try {
|
|
3830
|
-
const content = await
|
|
3690
|
+
const content = await readFile(packageJsonPath, "utf-8");
|
|
3831
3691
|
const packageJson2 = JSON.parse(content);
|
|
3832
3692
|
const manifest = {
|
|
3833
3693
|
name: packageJson2.name,
|
|
@@ -3835,7 +3695,8 @@ async function detectManifest() {
|
|
|
3835
3695
|
description: packageJson2.description,
|
|
3836
3696
|
author: typeof packageJson2.author === "string" ? packageJson2.author : packageJson2.author?.name,
|
|
3837
3697
|
license: packageJson2.license,
|
|
3838
|
-
files: packageJson2.files
|
|
3698
|
+
files: packageJson2.files,
|
|
3699
|
+
dependencies: packageJson2.dependencies
|
|
3839
3700
|
};
|
|
3840
3701
|
return { type: "package.json", manifest, path: packageJsonPath };
|
|
3841
3702
|
} catch {
|
|
@@ -3847,21 +3708,31 @@ function formatBytes(bytes) {
|
|
|
3847
3708
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}kB`;
|
|
3848
3709
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
3849
3710
|
}
|
|
3850
|
-
async function getFilesWithSizes(dir, baseDir) {
|
|
3711
|
+
async function getFilesWithSizes(dir, baseDir, ignoreResult) {
|
|
3851
3712
|
const results = [];
|
|
3852
3713
|
try {
|
|
3853
|
-
const entries = await
|
|
3714
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
3854
3715
|
for (const entry of entries) {
|
|
3855
|
-
const fullPath =
|
|
3856
|
-
const relativePath =
|
|
3857
|
-
if (
|
|
3716
|
+
const fullPath = join(dir, entry.name);
|
|
3717
|
+
const relativePath = relative(baseDir, fullPath);
|
|
3718
|
+
if (ALWAYS_IGNORED.includes(entry.name)) {
|
|
3858
3719
|
continue;
|
|
3859
3720
|
}
|
|
3721
|
+
if (ignoreResult?.ig) {
|
|
3722
|
+
const pathToCheck = entry.isDirectory() ? `${relativePath}/` : relativePath;
|
|
3723
|
+
if (ignoreResult.ig.ignores(pathToCheck)) {
|
|
3724
|
+
continue;
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3860
3727
|
if (entry.isDirectory()) {
|
|
3861
|
-
const subFiles = await getFilesWithSizes(
|
|
3728
|
+
const subFiles = await getFilesWithSizes(
|
|
3729
|
+
fullPath,
|
|
3730
|
+
baseDir,
|
|
3731
|
+
ignoreResult
|
|
3732
|
+
);
|
|
3862
3733
|
results.push(...subFiles);
|
|
3863
3734
|
} else {
|
|
3864
|
-
const fileStat = await
|
|
3735
|
+
const fileStat = await stat(fullPath);
|
|
3865
3736
|
results.push({ path: relativePath, size: fileStat.size });
|
|
3866
3737
|
}
|
|
3867
3738
|
}
|
|
@@ -3887,15 +3758,40 @@ async function publishCommand(options) {
|
|
|
3887
3758
|
console.error(`Error: ${validation.error}`);
|
|
3888
3759
|
process.exit(1);
|
|
3889
3760
|
}
|
|
3761
|
+
const skillMdPath = join(process.cwd(), "SKILL.md");
|
|
3762
|
+
try {
|
|
3763
|
+
await stat(skillMdPath);
|
|
3764
|
+
} catch {
|
|
3765
|
+
console.error(
|
|
3766
|
+
"Error: SKILL.md is required. Create a SKILL.md file with your skill's documentation before publishing."
|
|
3767
|
+
);
|
|
3768
|
+
process.exit(1);
|
|
3769
|
+
}
|
|
3770
|
+
if (options.access === "public") {
|
|
3771
|
+
console.log("");
|
|
3772
|
+
console.log("\u26A0\uFE0F Warning: You are about to publish this skill as PUBLIC.");
|
|
3773
|
+
console.log(
|
|
3774
|
+
" Once a skill is public, it CANNOT be made private again."
|
|
3775
|
+
);
|
|
3776
|
+
console.log(" This action is irreversible.");
|
|
3777
|
+
console.log("");
|
|
3778
|
+
const confirmed = await confirm("Do you want to continue?");
|
|
3779
|
+
if (!confirmed) {
|
|
3780
|
+
console.log("Publish cancelled.");
|
|
3781
|
+
process.exit(0);
|
|
3782
|
+
}
|
|
3783
|
+
console.log("");
|
|
3784
|
+
}
|
|
3890
3785
|
const packageJson2 = {
|
|
3891
3786
|
name: manifest.name,
|
|
3892
3787
|
version: manifest.version,
|
|
3893
3788
|
description: manifest.description,
|
|
3894
|
-
files: manifest.files
|
|
3789
|
+
files: manifest.files,
|
|
3790
|
+
dependencies: manifest.dependencies
|
|
3895
3791
|
};
|
|
3896
3792
|
if (options.bump) {
|
|
3897
|
-
const
|
|
3898
|
-
const newVersion =
|
|
3793
|
+
const semver3 = await import('semver');
|
|
3794
|
+
const newVersion = semver3.default.inc(packageJson2.version, options.bump);
|
|
3899
3795
|
if (!newVersion) {
|
|
3900
3796
|
console.error(
|
|
3901
3797
|
`Error: Failed to bump version from ${packageJson2.version}`
|
|
@@ -3905,9 +3801,16 @@ async function publishCommand(options) {
|
|
|
3905
3801
|
packageJson2.version = newVersion;
|
|
3906
3802
|
console.log(`Bumped version to ${newVersion}`);
|
|
3907
3803
|
}
|
|
3804
|
+
const ignoreResult = await loadIgnorePatterns();
|
|
3805
|
+
if (ignoreResult.source) {
|
|
3806
|
+
console.log(
|
|
3807
|
+
`pspm notice Using ${ignoreResult.source} for ignore patterns`
|
|
3808
|
+
);
|
|
3809
|
+
}
|
|
3810
|
+
const excludeArgs = getExcludeArgsForRsync(ignoreResult.patterns);
|
|
3908
3811
|
const safeName = packageJson2.name.replace(/[@/]/g, "-").replace(/^-+/, "");
|
|
3909
3812
|
const tarballName = `${safeName}-${packageJson2.version}.tgz`;
|
|
3910
|
-
const tempDir =
|
|
3813
|
+
const tempDir = join(process.cwd(), ".pspm-publish");
|
|
3911
3814
|
try {
|
|
3912
3815
|
await exec(`rm -rf "${tempDir}" && mkdir -p "${tempDir}"`);
|
|
3913
3816
|
const files = packageJson2.files || [...DEFAULT_SKILL_FILES];
|
|
@@ -3915,7 +3818,7 @@ async function publishCommand(options) {
|
|
|
3915
3818
|
for (const file of files) {
|
|
3916
3819
|
try {
|
|
3917
3820
|
await exec(
|
|
3918
|
-
`rsync -a
|
|
3821
|
+
`rsync -a ${excludeArgs} "${file}" "${tempDir}/package/" 2>/dev/null || true`
|
|
3919
3822
|
);
|
|
3920
3823
|
} catch {
|
|
3921
3824
|
}
|
|
@@ -3923,7 +3826,7 @@ async function publishCommand(options) {
|
|
|
3923
3826
|
if (detection.type === "pspm.json") {
|
|
3924
3827
|
await exec(`cp pspm.json "${tempDir}/package/"`);
|
|
3925
3828
|
try {
|
|
3926
|
-
await
|
|
3829
|
+
await stat(join(process.cwd(), "package.json"));
|
|
3927
3830
|
await exec(
|
|
3928
3831
|
`cp package.json "${tempDir}/package/" 2>/dev/null || true`
|
|
3929
3832
|
);
|
|
@@ -3932,30 +3835,51 @@ async function publishCommand(options) {
|
|
|
3932
3835
|
} else {
|
|
3933
3836
|
await exec(`cp package.json "${tempDir}/package/"`);
|
|
3934
3837
|
}
|
|
3935
|
-
const packageDir =
|
|
3936
|
-
const tarballContents = await getFilesWithSizes(
|
|
3838
|
+
const packageDir = join(tempDir, "package");
|
|
3839
|
+
const tarballContents = await getFilesWithSizes(
|
|
3840
|
+
packageDir,
|
|
3841
|
+
packageDir,
|
|
3842
|
+
ignoreResult
|
|
3843
|
+
);
|
|
3937
3844
|
const unpackedSize = tarballContents.reduce((acc, f) => acc + f.size, 0);
|
|
3938
|
-
const tarballPath =
|
|
3845
|
+
const tarballPath = join(tempDir, tarballName);
|
|
3939
3846
|
await exec(
|
|
3940
|
-
`tar -czf "${tarballPath}" -C "${tempDir}"
|
|
3847
|
+
`tar -czf "${tarballPath}" -C "${tempDir}" ${excludeArgs} package`
|
|
3941
3848
|
);
|
|
3942
|
-
const tarballBuffer = await
|
|
3849
|
+
const tarballBuffer = await readFile(tarballPath);
|
|
3943
3850
|
const tarballBase64 = tarballBuffer.toString("base64");
|
|
3944
3851
|
const tarballSize = tarballBuffer.length;
|
|
3945
|
-
const shasum =
|
|
3946
|
-
const integrityHash =
|
|
3852
|
+
const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
|
|
3853
|
+
const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
|
|
3947
3854
|
const integrity = `sha512-${integrityHash}`;
|
|
3855
|
+
const MAX_TARBALL_SIZE = 10 * 1024 * 1024;
|
|
3856
|
+
if (tarballSize > MAX_TARBALL_SIZE) {
|
|
3857
|
+
console.error("");
|
|
3858
|
+
console.error(
|
|
3859
|
+
`Error: Package size ${formatBytes(tarballSize)} exceeds the maximum allowed size of ${formatBytes(MAX_TARBALL_SIZE)}.`
|
|
3860
|
+
);
|
|
3861
|
+
console.error("");
|
|
3862
|
+
console.error("To reduce the package size:");
|
|
3863
|
+
console.error(
|
|
3864
|
+
' - Add a "files" field in your manifest to include only necessary files'
|
|
3865
|
+
);
|
|
3866
|
+
console.error(" - Add patterns to .pspmignore to exclude large files");
|
|
3867
|
+
console.error(
|
|
3868
|
+
" - Remove build artifacts, tests, and documentation from the package"
|
|
3869
|
+
);
|
|
3870
|
+
process.exit(1);
|
|
3871
|
+
}
|
|
3948
3872
|
console.log("");
|
|
3949
3873
|
console.log("pspm notice");
|
|
3950
3874
|
console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
|
|
3951
|
-
console.log("pspm notice Tarball Contents");
|
|
3875
|
+
console.log("pspm notice === Tarball Contents ===");
|
|
3952
3876
|
tarballContents.sort((a, b) => b.size - a.size);
|
|
3953
3877
|
for (const file of tarballContents) {
|
|
3954
3878
|
console.log(
|
|
3955
3879
|
`pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
|
|
3956
3880
|
);
|
|
3957
3881
|
}
|
|
3958
|
-
console.log("pspm notice Tarball Details");
|
|
3882
|
+
console.log("pspm notice === Tarball Details ===");
|
|
3959
3883
|
console.log(`pspm notice name: ${packageJson2.name}`);
|
|
3960
3884
|
console.log(`pspm notice version: ${packageJson2.version}`);
|
|
3961
3885
|
console.log(`pspm notice filename: ${tarballName}`);
|
|
@@ -3967,11 +3891,20 @@ async function publishCommand(options) {
|
|
|
3967
3891
|
);
|
|
3968
3892
|
console.log(`pspm notice total files: ${tarballContents.length}`);
|
|
3969
3893
|
console.log("pspm notice");
|
|
3894
|
+
const confirmed = await confirm(
|
|
3895
|
+
`Publish ${packageJson2.name}@${packageJson2.version} to ${registryUrl}?`
|
|
3896
|
+
);
|
|
3897
|
+
if (!confirmed) {
|
|
3898
|
+
console.log("Publish cancelled.");
|
|
3899
|
+
process.exit(0);
|
|
3900
|
+
}
|
|
3901
|
+
console.log("");
|
|
3970
3902
|
console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
|
|
3971
3903
|
configure2({ registryUrl, apiKey });
|
|
3972
3904
|
const response = await publishSkill({
|
|
3973
3905
|
manifest: packageJson2,
|
|
3974
|
-
tarballBase64
|
|
3906
|
+
tarballBase64,
|
|
3907
|
+
visibility: options.access
|
|
3975
3908
|
});
|
|
3976
3909
|
if (response.status !== 200) {
|
|
3977
3910
|
const errorMessage = extractApiErrorMessage(response, "Publish failed");
|
|
@@ -3984,28 +3917,17 @@ async function publishCommand(options) {
|
|
|
3984
3917
|
throw new Error(errorMessage);
|
|
3985
3918
|
}
|
|
3986
3919
|
const result = response.data;
|
|
3920
|
+
const visibility = result.skill.visibility;
|
|
3921
|
+
const visibilityIcon = visibility === "public" ? "\u{1F310}" : "\u{1F512}";
|
|
3987
3922
|
console.log(
|
|
3988
3923
|
`+ @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
|
|
3989
3924
|
);
|
|
3990
3925
|
console.log(`Checksum: ${result.version.checksum}`);
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
});
|
|
3997
|
-
if (accessResponse.status !== 200 || !accessResponse.data) {
|
|
3998
|
-
console.warn(
|
|
3999
|
-
`Warning: Failed to set visibility: ${accessResponse.error ?? "Unknown error"}`
|
|
4000
|
-
);
|
|
4001
|
-
} else {
|
|
4002
|
-
console.log(`Package is now ${accessResponse.data.visibility}`);
|
|
4003
|
-
if (options.access === "public") {
|
|
4004
|
-
console.log(
|
|
4005
|
-
"Note: This action is irreversible. Public packages cannot be made private."
|
|
4006
|
-
);
|
|
4007
|
-
}
|
|
4008
|
-
}
|
|
3926
|
+
console.log(`Visibility: ${visibilityIcon} ${visibility}`);
|
|
3927
|
+
if (visibility === "public") {
|
|
3928
|
+
console.log(
|
|
3929
|
+
"Note: Public packages cannot be made private. This is irreversible."
|
|
3930
|
+
);
|
|
4009
3931
|
}
|
|
4010
3932
|
} finally {
|
|
4011
3933
|
await exec(`rm -rf "${tempDir}"`).catch(() => {
|
|
@@ -4025,19 +3947,15 @@ Setting visibility to ${options.access}...`);
|
|
|
4025
3947
|
init_agents();
|
|
4026
3948
|
init_config();
|
|
4027
3949
|
init_lib();
|
|
4028
|
-
|
|
3950
|
+
init_lockfile2();
|
|
4029
3951
|
init_manifest2();
|
|
4030
3952
|
init_symlinks();
|
|
4031
|
-
import { rm as rm6 } from "fs/promises";
|
|
4032
|
-
import { join as join12 } from "path";
|
|
4033
3953
|
async function remove(nameOrSpecifier) {
|
|
4034
3954
|
try {
|
|
4035
3955
|
const manifest = await readManifest();
|
|
4036
3956
|
const agentConfigs = manifest?.agents;
|
|
4037
3957
|
const agents = getAvailableAgents(agentConfigs);
|
|
4038
|
-
if (
|
|
4039
|
-
await removeLocal(nameOrSpecifier, agents, agentConfigs);
|
|
4040
|
-
} else if (isGitHubSpecifier(nameOrSpecifier)) {
|
|
3958
|
+
if (isGitHubSpecifier(nameOrSpecifier)) {
|
|
4041
3959
|
await removeGitHub(nameOrSpecifier, agents, agentConfigs);
|
|
4042
3960
|
} else if (nameOrSpecifier.startsWith("@user/")) {
|
|
4043
3961
|
await removeRegistry(nameOrSpecifier, agents, agentConfigs);
|
|
@@ -4072,9 +3990,9 @@ async function removeRegistry(specifier, agents, agentConfigs) {
|
|
|
4072
3990
|
agentConfigs
|
|
4073
3991
|
});
|
|
4074
3992
|
const skillsDir = getSkillsDir();
|
|
4075
|
-
const destDir =
|
|
3993
|
+
const destDir = join(skillsDir, username, name);
|
|
4076
3994
|
try {
|
|
4077
|
-
await
|
|
3995
|
+
await rm(destDir, { recursive: true, force: true });
|
|
4078
3996
|
} catch {
|
|
4079
3997
|
}
|
|
4080
3998
|
console.log(`Removed ${fullName}`);
|
|
@@ -4101,42 +4019,13 @@ async function removeGitHub(specifier, agents, agentConfigs) {
|
|
|
4101
4019
|
});
|
|
4102
4020
|
const skillsDir = getSkillsDir();
|
|
4103
4021
|
const destPath = getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path);
|
|
4104
|
-
const destDir =
|
|
4022
|
+
const destDir = join(skillsDir, "..", destPath);
|
|
4105
4023
|
try {
|
|
4106
|
-
await
|
|
4024
|
+
await rm(destDir, { recursive: true, force: true });
|
|
4107
4025
|
} catch {
|
|
4108
4026
|
}
|
|
4109
4027
|
console.log(`Removed ${lockfileKey}`);
|
|
4110
4028
|
}
|
|
4111
|
-
async function removeLocal(specifier, agents, agentConfigs) {
|
|
4112
|
-
const parsed = parseLocalSpecifier(specifier);
|
|
4113
|
-
if (!parsed) {
|
|
4114
|
-
console.error(`Error: Invalid local specifier: ${specifier}`);
|
|
4115
|
-
process.exit(1);
|
|
4116
|
-
}
|
|
4117
|
-
console.log(`Removing ${specifier}...`);
|
|
4118
|
-
const removedFromLockfile = await removeLocalFromLockfile(specifier);
|
|
4119
|
-
const removedFromManifest = await removeLocalDependency(specifier);
|
|
4120
|
-
if (!removedFromLockfile && !removedFromManifest) {
|
|
4121
|
-
console.error(`Error: ${specifier} not found in lockfile or pspm.json`);
|
|
4122
|
-
process.exit(1);
|
|
4123
|
-
}
|
|
4124
|
-
const localSkills = await listLockfileLocalPackages();
|
|
4125
|
-
const foundLocal = localSkills.find((s) => s.specifier === specifier);
|
|
4126
|
-
const skillName = foundLocal?.entry.name || parsed.path.split("/").filter(Boolean).pop() || "unknown";
|
|
4127
|
-
await removeAgentSymlinks(skillName, {
|
|
4128
|
-
agents,
|
|
4129
|
-
projectRoot: process.cwd(),
|
|
4130
|
-
agentConfigs
|
|
4131
|
-
});
|
|
4132
|
-
const skillsDir = getSkillsDir();
|
|
4133
|
-
const symlinkPath = join12(skillsDir, "_local", skillName);
|
|
4134
|
-
try {
|
|
4135
|
-
await rm6(symlinkPath, { force: true });
|
|
4136
|
-
} catch {
|
|
4137
|
-
}
|
|
4138
|
-
console.log(`Removed ${specifier}`);
|
|
4139
|
-
}
|
|
4140
4029
|
async function removeByShortName(shortName, agents, agentConfigs) {
|
|
4141
4030
|
const registrySkills = await listLockfileSkills();
|
|
4142
4031
|
const foundRegistry = registrySkills.find((s) => {
|
|
@@ -4157,12 +4046,6 @@ async function removeByShortName(shortName, agents, agentConfigs) {
|
|
|
4157
4046
|
await removeGitHub(foundGitHub.specifier, agents, agentConfigs);
|
|
4158
4047
|
return;
|
|
4159
4048
|
}
|
|
4160
|
-
const localSkills = await listLockfileLocalPackages();
|
|
4161
|
-
const foundLocal = localSkills.find((s) => s.entry.name === shortName);
|
|
4162
|
-
if (foundLocal) {
|
|
4163
|
-
await removeLocal(foundLocal.specifier, agents, agentConfigs);
|
|
4164
|
-
return;
|
|
4165
|
-
}
|
|
4166
4049
|
console.error(`Error: Skill "${shortName}" not found in lockfile`);
|
|
4167
4050
|
process.exit(1);
|
|
4168
4051
|
}
|
|
@@ -4234,7 +4117,7 @@ init_api_client();
|
|
|
4234
4117
|
init_config();
|
|
4235
4118
|
init_errors();
|
|
4236
4119
|
init_lib();
|
|
4237
|
-
|
|
4120
|
+
init_lockfile2();
|
|
4238
4121
|
init_add();
|
|
4239
4122
|
async function update(options) {
|
|
4240
4123
|
try {
|
|
@@ -4307,6 +4190,52 @@ async function update(options) {
|
|
|
4307
4190
|
}
|
|
4308
4191
|
}
|
|
4309
4192
|
|
|
4193
|
+
// src/commands/version.ts
|
|
4194
|
+
init_manifest2();
|
|
4195
|
+
async function version(bump, options = {}) {
|
|
4196
|
+
try {
|
|
4197
|
+
const manifest = await readManifest();
|
|
4198
|
+
if (!manifest) {
|
|
4199
|
+
console.error("Error: No pspm.json found in current directory.");
|
|
4200
|
+
console.error("Run 'pspm init' to create one.");
|
|
4201
|
+
process.exit(1);
|
|
4202
|
+
}
|
|
4203
|
+
if (!manifest.version) {
|
|
4204
|
+
console.error("Error: pspm.json does not have a version field.");
|
|
4205
|
+
console.error(
|
|
4206
|
+
'Add a version field (e.g., "version": "0.1.0") to your pspm.json.'
|
|
4207
|
+
);
|
|
4208
|
+
process.exit(1);
|
|
4209
|
+
}
|
|
4210
|
+
if (!semver__default.valid(manifest.version)) {
|
|
4211
|
+
console.error(
|
|
4212
|
+
`Error: Current version "${manifest.version}" is not valid semver.`
|
|
4213
|
+
);
|
|
4214
|
+
console.error(
|
|
4215
|
+
'Fix the version in pspm.json to be valid semver (e.g., "1.0.0").'
|
|
4216
|
+
);
|
|
4217
|
+
process.exit(1);
|
|
4218
|
+
}
|
|
4219
|
+
const newVersion = semver__default.inc(manifest.version, bump);
|
|
4220
|
+
if (!newVersion) {
|
|
4221
|
+
console.error(`Error: Failed to bump version from ${manifest.version}`);
|
|
4222
|
+
process.exit(1);
|
|
4223
|
+
}
|
|
4224
|
+
if (options.dryRun) {
|
|
4225
|
+
console.log(`Would bump version: ${manifest.version} \u2192 ${newVersion}`);
|
|
4226
|
+
return;
|
|
4227
|
+
}
|
|
4228
|
+
manifest.version = newVersion;
|
|
4229
|
+
await writeManifest(manifest);
|
|
4230
|
+
console.log(`v${newVersion}`);
|
|
4231
|
+
console.log(`Updated ${getManifestPath()}`);
|
|
4232
|
+
} catch (error) {
|
|
4233
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
4234
|
+
console.error(`Error: ${message}`);
|
|
4235
|
+
process.exit(1);
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4310
4239
|
// src/commands/whoami.ts
|
|
4311
4240
|
init_api_client();
|
|
4312
4241
|
init_config();
|
|
@@ -4335,13 +4264,13 @@ async function whoami() {
|
|
|
4335
4264
|
}
|
|
4336
4265
|
|
|
4337
4266
|
// src/index.ts
|
|
4338
|
-
var __dirname =
|
|
4267
|
+
var __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
4339
4268
|
var packageJson = JSON.parse(
|
|
4340
|
-
readFileSync(
|
|
4269
|
+
readFileSync(join(__dirname$1, "..", "package.json"), "utf-8")
|
|
4341
4270
|
);
|
|
4342
|
-
var
|
|
4271
|
+
var version2 = packageJson.version;
|
|
4343
4272
|
var program = new Command();
|
|
4344
|
-
program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(
|
|
4273
|
+
program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version2);
|
|
4345
4274
|
var configCmd = program.command("config").description("Manage PSPM configuration");
|
|
4346
4275
|
configCmd.command("show").description("Show resolved configuration").action(async () => {
|
|
4347
4276
|
await configShow();
|
|
@@ -4417,6 +4346,17 @@ program.command("link").description("Recreate agent symlinks without reinstallin
|
|
|
4417
4346
|
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) => {
|
|
4418
4347
|
await update({ dryRun: options.dryRun });
|
|
4419
4348
|
});
|
|
4349
|
+
program.command("version <bump>").description("Bump package version (major, minor, patch)").option("--dry-run", "Show what would be changed without writing").action(async (bump, options) => {
|
|
4350
|
+
const validBumps = ["major", "minor", "patch"];
|
|
4351
|
+
if (!validBumps.includes(bump)) {
|
|
4352
|
+
console.error(`Error: Invalid version bump "${bump}".`);
|
|
4353
|
+
console.error("Must be one of: major, minor, patch");
|
|
4354
|
+
process.exit(1);
|
|
4355
|
+
}
|
|
4356
|
+
await version(bump, {
|
|
4357
|
+
dryRun: options.dryRun
|
|
4358
|
+
});
|
|
4359
|
+
});
|
|
4420
4360
|
program.command("publish").description("Publish current directory as a skill").option("--bump <level>", "Bump version (major, minor, patch)").option("--tag <tag>", "Tag for the release").option("--access <level>", "Set package visibility (public or private)").action(async (options) => {
|
|
4421
4361
|
await publishCommand({
|
|
4422
4362
|
bump: options.bump,
|
|
@@ -4430,7 +4370,7 @@ program.command("unpublish <specifier>").description(
|
|
|
4430
4370
|
await unpublish(specifier, { force: options.force });
|
|
4431
4371
|
});
|
|
4432
4372
|
program.command("access [specifier]").description("Change package visibility (public/private)").option("--public", "Make the package public (irreversible)").option("--private", "Make the package private (only for private packages)").action(async (specifier, options) => {
|
|
4433
|
-
await
|
|
4373
|
+
await access(specifier, {
|
|
4434
4374
|
public: options.public,
|
|
4435
4375
|
private: options.private
|
|
4436
4376
|
});
|
|
@@ -4441,4 +4381,5 @@ program.command("deprecate <specifier> [message]").description(
|
|
|
4441
4381
|
await deprecate(specifier, message, { undo: options.undo });
|
|
4442
4382
|
});
|
|
4443
4383
|
program.parse();
|
|
4384
|
+
//# sourceMappingURL=index.js.map
|
|
4444
4385
|
//# sourceMappingURL=index.js.map
|