@anytio/pspm 0.1.0 → 0.1.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/README.md +10 -3
- package/dist/index.js +725 -467
- package/dist/index.js.map +1 -1
- package/package.json +67 -67
package/dist/index.js
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from 'fs';
|
|
3
|
-
import { dirname, join, basename, relative } from 'path';
|
|
4
|
-
import { fileURLToPath, URL as URL$1 } from 'url';
|
|
5
|
-
import { Command } from 'commander';
|
|
6
2
|
import { createHash, randomBytes } from 'crypto';
|
|
7
3
|
import * as semver from 'semver';
|
|
8
|
-
import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, lstat,
|
|
4
|
+
import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, lstat, unlink, cp, readlink, symlink } from 'fs/promises';
|
|
9
5
|
import { homedir } from 'os';
|
|
6
|
+
import { dirname, join, basename, relative } from 'path';
|
|
10
7
|
import * as ini from 'ini';
|
|
11
8
|
import { checkbox } from '@inquirer/prompts';
|
|
9
|
+
import { readFileSync } from 'fs';
|
|
10
|
+
import { fileURLToPath, URL as URL$1 } from 'url';
|
|
11
|
+
import { Command } from 'commander';
|
|
12
12
|
import { createInterface } from 'readline';
|
|
13
13
|
import http from 'http';
|
|
14
14
|
import open from 'open';
|
|
15
15
|
import { exec as exec$1 } from 'child_process';
|
|
16
16
|
import { promisify } from 'util';
|
|
17
17
|
|
|
18
|
+
var __defProp = Object.defineProperty;
|
|
19
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
20
|
+
var __esm = (fn, res) => function __init() {
|
|
21
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
22
|
+
};
|
|
23
|
+
var __export = (target, all) => {
|
|
24
|
+
for (var name in all)
|
|
25
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
|
+
};
|
|
18
27
|
function calculateIntegrity(data) {
|
|
19
28
|
const hash = createHash("sha256").update(data).digest("base64");
|
|
20
29
|
return `sha256-${hash}`;
|
|
21
30
|
}
|
|
31
|
+
var init_integrity = __esm({
|
|
32
|
+
"../../packages/shared/pspm-types/src/integrity.ts"() {
|
|
33
|
+
}
|
|
34
|
+
});
|
|
22
35
|
|
|
23
36
|
// ../../packages/shared/pspm-types/src/manifest.ts
|
|
24
|
-
var DEFAULT_SKILL_FILES = [
|
|
25
|
-
"SKILL.md",
|
|
26
|
-
"runtime",
|
|
27
|
-
"scripts",
|
|
28
|
-
"data"
|
|
29
|
-
];
|
|
30
|
-
var PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
|
|
31
37
|
function validateManifest(manifest) {
|
|
32
38
|
if (!manifest.name) {
|
|
33
39
|
return { valid: false, error: "Manifest must have a 'name' field" };
|
|
@@ -49,9 +55,20 @@ function validateManifest(manifest) {
|
|
|
49
55
|
}
|
|
50
56
|
return { valid: true };
|
|
51
57
|
}
|
|
58
|
+
var DEFAULT_SKILL_FILES, PSPM_SCHEMA_URL;
|
|
59
|
+
var init_manifest = __esm({
|
|
60
|
+
"../../packages/shared/pspm-types/src/manifest.ts"() {
|
|
61
|
+
DEFAULT_SKILL_FILES = [
|
|
62
|
+
"SKILL.md",
|
|
63
|
+
"runtime",
|
|
64
|
+
"scripts",
|
|
65
|
+
"data"
|
|
66
|
+
];
|
|
67
|
+
PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
|
|
68
|
+
}
|
|
69
|
+
});
|
|
52
70
|
|
|
53
71
|
// ../../packages/shared/pspm-types/src/specifier.ts
|
|
54
|
-
var SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
|
|
55
72
|
function parseSkillSpecifier(specifier) {
|
|
56
73
|
const match = specifier.match(SPECIFIER_PATTERN);
|
|
57
74
|
if (!match) {
|
|
@@ -63,7 +80,6 @@ function parseSkillSpecifier(specifier) {
|
|
|
63
80
|
versionRange: match[3]
|
|
64
81
|
};
|
|
65
82
|
}
|
|
66
|
-
var GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
|
|
67
83
|
function parseGitHubSpecifier(specifier) {
|
|
68
84
|
const match = specifier.match(GITHUB_SPECIFIER_PATTERN);
|
|
69
85
|
if (!match) {
|
|
@@ -98,6 +114,13 @@ function getGitHubSkillName(spec) {
|
|
|
98
114
|
function isGitHubSpecifier(specifier) {
|
|
99
115
|
return specifier.startsWith("github:");
|
|
100
116
|
}
|
|
117
|
+
var SPECIFIER_PATTERN, GITHUB_SPECIFIER_PATTERN;
|
|
118
|
+
var init_specifier = __esm({
|
|
119
|
+
"../../packages/shared/pspm-types/src/specifier.ts"() {
|
|
120
|
+
SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
|
|
121
|
+
GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
101
124
|
function resolveVersion(range, availableVersions) {
|
|
102
125
|
const sorted = availableVersions.filter((v) => semver.valid(v)).sort((a, b) => semver.rcompare(a, b));
|
|
103
126
|
if (!range || range === "latest" || range === "*") {
|
|
@@ -105,9 +128,22 @@ function resolveVersion(range, availableVersions) {
|
|
|
105
128
|
}
|
|
106
129
|
return semver.maxSatisfying(sorted, range);
|
|
107
130
|
}
|
|
131
|
+
var init_version = __esm({
|
|
132
|
+
"../../packages/shared/pspm-types/src/version.ts"() {
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// ../../packages/shared/pspm-types/src/index.ts
|
|
137
|
+
var init_src = __esm({
|
|
138
|
+
"../../packages/shared/pspm-types/src/index.ts"() {
|
|
139
|
+
init_integrity();
|
|
140
|
+
init_manifest();
|
|
141
|
+
init_specifier();
|
|
142
|
+
init_version();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
108
145
|
|
|
109
146
|
// ../../packages/sdk/src/fetchers/cli-fetcher.ts
|
|
110
|
-
var config = null;
|
|
111
147
|
function configure(options) {
|
|
112
148
|
config = options;
|
|
113
149
|
}
|
|
@@ -146,84 +182,104 @@ async function customFetch(url, options) {
|
|
|
146
182
|
headers: response.headers
|
|
147
183
|
};
|
|
148
184
|
}
|
|
185
|
+
var config;
|
|
186
|
+
var init_cli_fetcher = __esm({
|
|
187
|
+
"../../packages/sdk/src/fetchers/cli-fetcher.ts"() {
|
|
188
|
+
config = null;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
149
191
|
|
|
150
192
|
// ../../packages/sdk/src/generated/fetch/index.ts
|
|
151
|
-
var getMeUrl
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
193
|
+
var getMeUrl, me, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getPublishSkillUrl, publishSkill, getDeleteSkillUrl, deleteSkill, getDeleteSkillVersionUrl, deleteSkillVersion;
|
|
194
|
+
var init_fetch = __esm({
|
|
195
|
+
"../../packages/sdk/src/generated/fetch/index.ts"() {
|
|
196
|
+
init_cli_fetcher();
|
|
197
|
+
getMeUrl = () => {
|
|
198
|
+
return `/api/skills/me`;
|
|
199
|
+
};
|
|
200
|
+
me = async (options) => {
|
|
201
|
+
return customFetch(
|
|
202
|
+
getMeUrl(),
|
|
203
|
+
{
|
|
204
|
+
...options,
|
|
205
|
+
method: "GET"
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
};
|
|
209
|
+
getListSkillVersionsUrl = (username, name) => {
|
|
210
|
+
return `/api/skills/@user/${username}/${name}/versions`;
|
|
211
|
+
};
|
|
212
|
+
listSkillVersions = async (username, name, options) => {
|
|
213
|
+
return customFetch(
|
|
214
|
+
getListSkillVersionsUrl(username, name),
|
|
215
|
+
{
|
|
216
|
+
...options,
|
|
217
|
+
method: "GET"
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
getGetSkillVersionUrl = (username, name, version2) => {
|
|
222
|
+
return `/api/skills/@user/${username}/${name}/${version2}`;
|
|
223
|
+
};
|
|
224
|
+
getSkillVersion = async (username, name, version2, options) => {
|
|
225
|
+
return customFetch(
|
|
226
|
+
getGetSkillVersionUrl(username, name, version2),
|
|
227
|
+
{
|
|
228
|
+
...options,
|
|
229
|
+
method: "GET"
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
getPublishSkillUrl = () => {
|
|
234
|
+
return `/api/skills/publish`;
|
|
235
|
+
};
|
|
236
|
+
publishSkill = async (publishSkillInput, options) => {
|
|
237
|
+
return customFetch(
|
|
238
|
+
getPublishSkillUrl(),
|
|
239
|
+
{
|
|
240
|
+
...options,
|
|
241
|
+
method: "POST",
|
|
242
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
243
|
+
body: JSON.stringify(
|
|
244
|
+
publishSkillInput
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
};
|
|
249
|
+
getDeleteSkillUrl = (name) => {
|
|
250
|
+
return `/api/skills/${name}`;
|
|
251
|
+
};
|
|
252
|
+
deleteSkill = async (name, options) => {
|
|
253
|
+
return customFetch(
|
|
254
|
+
getDeleteSkillUrl(name),
|
|
255
|
+
{
|
|
256
|
+
...options,
|
|
257
|
+
method: "DELETE"
|
|
258
|
+
}
|
|
259
|
+
);
|
|
260
|
+
};
|
|
261
|
+
getDeleteSkillVersionUrl = (name, version2) => {
|
|
262
|
+
return `/api/skills/${name}/${version2}`;
|
|
263
|
+
};
|
|
264
|
+
deleteSkillVersion = async (name, version2, options) => {
|
|
265
|
+
return customFetch(
|
|
266
|
+
getDeleteSkillVersionUrl(name, version2),
|
|
267
|
+
{
|
|
268
|
+
...options,
|
|
269
|
+
method: "DELETE"
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ../../packages/sdk/src/index.ts
|
|
277
|
+
var init_src2 = __esm({
|
|
278
|
+
"../../packages/sdk/src/index.ts"() {
|
|
279
|
+
init_cli_fetcher();
|
|
280
|
+
init_fetch();
|
|
281
|
+
}
|
|
282
|
+
});
|
|
227
283
|
|
|
228
284
|
// src/api-client.ts
|
|
229
285
|
function registryUrlToBaseUrl(registryUrl) {
|
|
@@ -345,22 +401,13 @@ async function changeSkillAccess(skillName, input) {
|
|
|
345
401
|
};
|
|
346
402
|
}
|
|
347
403
|
}
|
|
404
|
+
var init_api_client = __esm({
|
|
405
|
+
"src/api-client.ts"() {
|
|
406
|
+
init_src2();
|
|
407
|
+
}
|
|
408
|
+
});
|
|
348
409
|
|
|
349
410
|
// src/errors.ts
|
|
350
|
-
var ConfigError = class extends Error {
|
|
351
|
-
constructor(message) {
|
|
352
|
-
super(message);
|
|
353
|
-
this.name = "ConfigError";
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
var NotLoggedInError = class extends ConfigError {
|
|
357
|
-
constructor() {
|
|
358
|
-
super(
|
|
359
|
-
"Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var."
|
|
360
|
-
);
|
|
361
|
-
this.name = "NotLoggedInError";
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
411
|
function extractApiErrorMessage(response, fallbackMessage) {
|
|
365
412
|
const errorData = response.data;
|
|
366
413
|
if (process.env.PSPM_DEBUG) {
|
|
@@ -395,9 +442,25 @@ ${issueMessages}`;
|
|
|
395
442
|
}
|
|
396
443
|
return errorMessage;
|
|
397
444
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
445
|
+
var ConfigError, NotLoggedInError;
|
|
446
|
+
var init_errors = __esm({
|
|
447
|
+
"src/errors.ts"() {
|
|
448
|
+
ConfigError = class extends Error {
|
|
449
|
+
constructor(message) {
|
|
450
|
+
super(message);
|
|
451
|
+
this.name = "ConfigError";
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
NotLoggedInError = class extends ConfigError {
|
|
455
|
+
constructor() {
|
|
456
|
+
super(
|
|
457
|
+
"Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var."
|
|
458
|
+
);
|
|
459
|
+
this.name = "NotLoggedInError";
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
});
|
|
401
464
|
function getConfigPath() {
|
|
402
465
|
return join(homedir(), ".pspmrc");
|
|
403
466
|
}
|
|
@@ -667,131 +730,13 @@ async function getRegistryUrl() {
|
|
|
667
730
|
const resolved = await resolveConfig();
|
|
668
731
|
return resolved.registryUrl;
|
|
669
732
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const registryUrl = await getRegistryUrl();
|
|
676
|
-
if (options.public && options.private) {
|
|
677
|
-
console.error("Error: Cannot specify both --public and --private");
|
|
678
|
-
process.exit(1);
|
|
679
|
-
}
|
|
680
|
-
if (!options.public && !options.private) {
|
|
681
|
-
console.error("Error: Must specify either --public or --private");
|
|
682
|
-
process.exit(1);
|
|
683
|
-
}
|
|
684
|
-
const visibility = options.public ? "public" : "private";
|
|
685
|
-
let packageName;
|
|
686
|
-
if (specifier) {
|
|
687
|
-
const parsed = parseSkillSpecifier(specifier);
|
|
688
|
-
if (!parsed) {
|
|
689
|
-
console.error(
|
|
690
|
-
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
|
|
691
|
-
);
|
|
692
|
-
process.exit(1);
|
|
693
|
-
}
|
|
694
|
-
packageName = parsed.name;
|
|
695
|
-
} else {
|
|
696
|
-
const { readFile: readFile7 } = await import('fs/promises');
|
|
697
|
-
const { join: join13 } = await import('path');
|
|
698
|
-
let manifest = null;
|
|
699
|
-
try {
|
|
700
|
-
const content = await readFile7(
|
|
701
|
-
join13(process.cwd(), "pspm.json"),
|
|
702
|
-
"utf-8"
|
|
703
|
-
);
|
|
704
|
-
manifest = JSON.parse(content);
|
|
705
|
-
} catch {
|
|
706
|
-
try {
|
|
707
|
-
const content = await readFile7(
|
|
708
|
-
join13(process.cwd(), "package.json"),
|
|
709
|
-
"utf-8"
|
|
710
|
-
);
|
|
711
|
-
manifest = JSON.parse(content);
|
|
712
|
-
} catch {
|
|
713
|
-
console.error(
|
|
714
|
-
"Error: No pspm.json or package.json found in current directory"
|
|
715
|
-
);
|
|
716
|
-
console.error(
|
|
717
|
-
"Either run this command in a package directory or specify a package name"
|
|
718
|
-
);
|
|
719
|
-
process.exit(1);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
if (!manifest?.name) {
|
|
723
|
-
console.error("Error: Package manifest is missing 'name' field");
|
|
724
|
-
process.exit(1);
|
|
725
|
-
}
|
|
726
|
-
packageName = manifest.name;
|
|
727
|
-
}
|
|
728
|
-
configure2({ registryUrl, apiKey });
|
|
729
|
-
console.log(`Setting ${packageName} to ${visibility}...`);
|
|
730
|
-
const response = await changeSkillAccess(packageName, { visibility });
|
|
731
|
-
if (response.status !== 200 || !response.data) {
|
|
732
|
-
const errorMessage = response.error ?? "Failed to change visibility";
|
|
733
|
-
console.error(`Error: ${errorMessage}`);
|
|
734
|
-
process.exit(1);
|
|
735
|
-
}
|
|
736
|
-
const result = response.data;
|
|
737
|
-
console.log(
|
|
738
|
-
`+ @user/${result.username}/${result.name} is now ${result.visibility}`
|
|
739
|
-
);
|
|
740
|
-
if (visibility === "public") {
|
|
741
|
-
console.log("");
|
|
742
|
-
console.log(
|
|
743
|
-
"Note: This action is irreversible. Public packages cannot be made private."
|
|
744
|
-
);
|
|
745
|
-
}
|
|
746
|
-
} catch (error) {
|
|
747
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
748
|
-
console.error(`Error: ${message}`);
|
|
749
|
-
process.exit(1);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
var AGENT_INFO = {
|
|
753
|
-
"claude-code": {
|
|
754
|
-
displayName: "Claude Code",
|
|
755
|
-
skillsDir: ".claude/skills"
|
|
756
|
-
},
|
|
757
|
-
codex: {
|
|
758
|
-
displayName: "Codex",
|
|
759
|
-
skillsDir: ".codex/skills"
|
|
760
|
-
},
|
|
761
|
-
cursor: {
|
|
762
|
-
displayName: "Cursor",
|
|
763
|
-
skillsDir: ".cursor/skills"
|
|
764
|
-
},
|
|
765
|
-
gemini: {
|
|
766
|
-
displayName: "Gemini CLI",
|
|
767
|
-
skillsDir: ".gemini/skills"
|
|
768
|
-
},
|
|
769
|
-
kiro: {
|
|
770
|
-
displayName: "Kiro CLI",
|
|
771
|
-
skillsDir: ".kiro/skills"
|
|
772
|
-
},
|
|
773
|
-
opencode: {
|
|
774
|
-
displayName: "OpenCode",
|
|
775
|
-
skillsDir: ".opencode/skills"
|
|
733
|
+
var DEFAULT_REGISTRY_URL;
|
|
734
|
+
var init_config = __esm({
|
|
735
|
+
"src/config.ts"() {
|
|
736
|
+
init_errors();
|
|
737
|
+
DEFAULT_REGISTRY_URL = "https://pspm.dev";
|
|
776
738
|
}
|
|
777
|
-
};
|
|
778
|
-
var DEFAULT_AGENT_CONFIGS = {
|
|
779
|
-
"claude-code": { skillsDir: AGENT_INFO["claude-code"].skillsDir },
|
|
780
|
-
codex: { skillsDir: AGENT_INFO.codex.skillsDir },
|
|
781
|
-
cursor: { skillsDir: AGENT_INFO.cursor.skillsDir },
|
|
782
|
-
gemini: { skillsDir: AGENT_INFO.gemini.skillsDir },
|
|
783
|
-
kiro: { skillsDir: AGENT_INFO.kiro.skillsDir },
|
|
784
|
-
opencode: { skillsDir: AGENT_INFO.opencode.skillsDir }
|
|
785
|
-
};
|
|
786
|
-
var DEFAULT_AGENT = "claude-code";
|
|
787
|
-
var ALL_AGENTS = [
|
|
788
|
-
"claude-code",
|
|
789
|
-
"codex",
|
|
790
|
-
"cursor",
|
|
791
|
-
"gemini",
|
|
792
|
-
"kiro",
|
|
793
|
-
"opencode"
|
|
794
|
-
];
|
|
739
|
+
});
|
|
795
740
|
function resolveAgentConfig(name, overrides) {
|
|
796
741
|
if (overrides?.[name]) {
|
|
797
742
|
return overrides[name];
|
|
@@ -803,7 +748,7 @@ function resolveAgentConfig(name, overrides) {
|
|
|
803
748
|
}
|
|
804
749
|
function parseAgentArg(agentArg) {
|
|
805
750
|
if (!agentArg) {
|
|
806
|
-
return [
|
|
751
|
+
return [...DEFAULT_AGENTS];
|
|
807
752
|
}
|
|
808
753
|
if (agentArg === "none") {
|
|
809
754
|
return ["none"];
|
|
@@ -831,35 +776,54 @@ async function promptForAgents() {
|
|
|
831
776
|
}
|
|
832
777
|
return selected;
|
|
833
778
|
}
|
|
834
|
-
var
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
779
|
+
var AGENT_INFO, DEFAULT_AGENT_CONFIGS, ALL_AGENTS, DEFAULT_AGENTS;
|
|
780
|
+
var init_agents = __esm({
|
|
781
|
+
"src/agents.ts"() {
|
|
782
|
+
AGENT_INFO = {
|
|
783
|
+
"claude-code": {
|
|
784
|
+
displayName: "Claude Code",
|
|
785
|
+
skillsDir: ".claude/skills"
|
|
786
|
+
},
|
|
787
|
+
codex: {
|
|
788
|
+
displayName: "Codex",
|
|
789
|
+
skillsDir: ".codex/skills"
|
|
790
|
+
},
|
|
791
|
+
cursor: {
|
|
792
|
+
displayName: "Cursor",
|
|
793
|
+
skillsDir: ".cursor/skills"
|
|
794
|
+
},
|
|
795
|
+
gemini: {
|
|
796
|
+
displayName: "Gemini CLI",
|
|
797
|
+
skillsDir: ".gemini/skills"
|
|
798
|
+
},
|
|
799
|
+
kiro: {
|
|
800
|
+
displayName: "Kiro CLI",
|
|
801
|
+
skillsDir: ".kiro/skills"
|
|
802
|
+
},
|
|
803
|
+
opencode: {
|
|
804
|
+
displayName: "OpenCode",
|
|
805
|
+
skillsDir: ".opencode/skills"
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
DEFAULT_AGENT_CONFIGS = {
|
|
809
|
+
"claude-code": { skillsDir: AGENT_INFO["claude-code"].skillsDir },
|
|
810
|
+
codex: { skillsDir: AGENT_INFO.codex.skillsDir },
|
|
811
|
+
cursor: { skillsDir: AGENT_INFO.cursor.skillsDir },
|
|
812
|
+
gemini: { skillsDir: AGENT_INFO.gemini.skillsDir },
|
|
813
|
+
kiro: { skillsDir: AGENT_INFO.kiro.skillsDir },
|
|
814
|
+
opencode: { skillsDir: AGENT_INFO.opencode.skillsDir }
|
|
815
|
+
};
|
|
816
|
+
ALL_AGENTS = [
|
|
817
|
+
"claude-code",
|
|
818
|
+
"codex",
|
|
819
|
+
"cursor",
|
|
820
|
+
"gemini",
|
|
821
|
+
"kiro",
|
|
822
|
+
"opencode"
|
|
823
|
+
];
|
|
824
|
+
DEFAULT_AGENTS = ALL_AGENTS;
|
|
861
825
|
}
|
|
862
|
-
};
|
|
826
|
+
});
|
|
863
827
|
function getGitHubHeaders() {
|
|
864
828
|
const headers = {
|
|
865
829
|
Accept: "application/vnd.github+json",
|
|
@@ -986,6 +950,41 @@ function getGitHubDisplayName(spec, commit) {
|
|
|
986
950
|
}
|
|
987
951
|
return name;
|
|
988
952
|
}
|
|
953
|
+
var GitHubRateLimitError, GitHubNotFoundError, GitHubPathNotFoundError;
|
|
954
|
+
var init_github = __esm({
|
|
955
|
+
"src/github.ts"() {
|
|
956
|
+
init_src();
|
|
957
|
+
GitHubRateLimitError = class extends Error {
|
|
958
|
+
constructor() {
|
|
959
|
+
super(
|
|
960
|
+
"GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable for higher limits."
|
|
961
|
+
);
|
|
962
|
+
this.name = "GitHubRateLimitError";
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
GitHubNotFoundError = class extends Error {
|
|
966
|
+
constructor(spec) {
|
|
967
|
+
const path = spec.path ? `/${spec.path}` : "";
|
|
968
|
+
const ref = spec.ref ? `@${spec.ref}` : "";
|
|
969
|
+
super(
|
|
970
|
+
`GitHub repository not found: ${spec.owner}/${spec.repo}${path}${ref}`
|
|
971
|
+
);
|
|
972
|
+
this.name = "GitHubNotFoundError";
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
GitHubPathNotFoundError = class extends Error {
|
|
976
|
+
constructor(spec, availablePaths) {
|
|
977
|
+
const pathInfo = availablePaths?.length ? `
|
|
978
|
+
Available paths in repository root:
|
|
979
|
+
${availablePaths.join("\n ")}` : "";
|
|
980
|
+
super(
|
|
981
|
+
`Path "${spec.path}" not found in ${spec.owner}/${spec.repo}${pathInfo}`
|
|
982
|
+
);
|
|
983
|
+
this.name = "GitHubPathNotFoundError";
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
});
|
|
989
988
|
async function hasLegacyLockfile() {
|
|
990
989
|
try {
|
|
991
990
|
await stat(getLegacyLockfilePath());
|
|
@@ -1143,6 +1142,11 @@ async function listLockfileGitHubPackages() {
|
|
|
1143
1142
|
entry
|
|
1144
1143
|
}));
|
|
1145
1144
|
}
|
|
1145
|
+
var init_lockfile = __esm({
|
|
1146
|
+
"src/lockfile.ts"() {
|
|
1147
|
+
init_config();
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1146
1150
|
function getManifestPath() {
|
|
1147
1151
|
return join(process.cwd(), "pspm.json");
|
|
1148
1152
|
}
|
|
@@ -1214,6 +1218,10 @@ async function removeGitHubDependency(specifier) {
|
|
|
1214
1218
|
await writeManifest(manifest);
|
|
1215
1219
|
return true;
|
|
1216
1220
|
}
|
|
1221
|
+
var init_manifest2 = __esm({
|
|
1222
|
+
"src/manifest.ts"() {
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1217
1225
|
async function createAgentSymlinks(skills, options) {
|
|
1218
1226
|
const { agents, projectRoot, agentConfigs } = options;
|
|
1219
1227
|
if (agents.length === 1 && agents[0] === "none") {
|
|
@@ -1305,9 +1313,47 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
|
|
|
1305
1313
|
}
|
|
1306
1314
|
return linkedAgents;
|
|
1307
1315
|
}
|
|
1316
|
+
var init_symlinks = __esm({
|
|
1317
|
+
"src/symlinks.ts"() {
|
|
1318
|
+
init_agents();
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1308
1321
|
|
|
1309
1322
|
// src/commands/add.ts
|
|
1310
|
-
|
|
1323
|
+
var add_exports = {};
|
|
1324
|
+
__export(add_exports, {
|
|
1325
|
+
add: () => add
|
|
1326
|
+
});
|
|
1327
|
+
async function add(specifiers, options) {
|
|
1328
|
+
console.log("Resolving packages...\n");
|
|
1329
|
+
const resolvedPackages = [];
|
|
1330
|
+
const validationErrors = [];
|
|
1331
|
+
for (const specifier of specifiers) {
|
|
1332
|
+
try {
|
|
1333
|
+
if (isGitHubSpecifier(specifier)) {
|
|
1334
|
+
const resolved = await validateGitHubPackage(specifier);
|
|
1335
|
+
resolvedPackages.push(resolved);
|
|
1336
|
+
} else {
|
|
1337
|
+
const resolved = await validateRegistryPackage(specifier);
|
|
1338
|
+
resolvedPackages.push(resolved);
|
|
1339
|
+
}
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1342
|
+
validationErrors.push({ specifier, error: message });
|
|
1343
|
+
console.error(`Failed to resolve ${specifier}: ${message}
|
|
1344
|
+
`);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
if (resolvedPackages.length === 0) {
|
|
1348
|
+
console.error("No packages could be resolved.");
|
|
1349
|
+
process.exit(1);
|
|
1350
|
+
}
|
|
1351
|
+
if (validationErrors.length > 0) {
|
|
1352
|
+
console.log(
|
|
1353
|
+
`Resolved ${resolvedPackages.length} of ${specifiers.length} packages.
|
|
1354
|
+
`
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
1311
1357
|
let agents;
|
|
1312
1358
|
const manifest = await readManifest();
|
|
1313
1359
|
if (options.agent) {
|
|
@@ -1319,211 +1365,343 @@ async function add(specifier, options) {
|
|
|
1319
1365
|
} else {
|
|
1320
1366
|
console.log("No pspm.json found. Let's set up your project.\n");
|
|
1321
1367
|
agents = await promptForAgents();
|
|
1368
|
+
console.log();
|
|
1322
1369
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1370
|
+
const results = [];
|
|
1371
|
+
for (const resolved of resolvedPackages) {
|
|
1372
|
+
try {
|
|
1373
|
+
if (resolved.type === "github") {
|
|
1374
|
+
await installGitHubPackage(resolved, {
|
|
1375
|
+
...options,
|
|
1376
|
+
resolvedAgents: agents
|
|
1377
|
+
});
|
|
1378
|
+
} else {
|
|
1379
|
+
await installRegistryPackage(resolved, {
|
|
1380
|
+
...options,
|
|
1381
|
+
resolvedAgents: agents
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
results.push({ specifier: resolved.specifier, success: true });
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1387
|
+
results.push({
|
|
1388
|
+
specifier: resolved.specifier,
|
|
1389
|
+
success: false,
|
|
1390
|
+
error: message
|
|
1391
|
+
});
|
|
1392
|
+
console.error(`Failed to install ${resolved.specifier}: ${message}
|
|
1393
|
+
`);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
if (specifiers.length > 1) {
|
|
1397
|
+
const succeeded = results.filter((r) => r.success).length;
|
|
1398
|
+
const failed = results.filter((r) => !r.success).length + validationErrors.length;
|
|
1399
|
+
console.log(`
|
|
1400
|
+
Summary: ${succeeded} added, ${failed} failed`);
|
|
1401
|
+
if (failed > 0) {
|
|
1402
|
+
process.exit(1);
|
|
1403
|
+
}
|
|
1327
1404
|
}
|
|
1328
1405
|
}
|
|
1329
|
-
async function
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1406
|
+
async function validateRegistryPackage(specifier) {
|
|
1407
|
+
const config2 = await resolveConfig();
|
|
1408
|
+
const registryUrl = config2.registryUrl;
|
|
1409
|
+
const apiKey = getTokenForRegistry(config2, registryUrl);
|
|
1410
|
+
const parsed = parseSkillSpecifier(specifier);
|
|
1411
|
+
if (!parsed) {
|
|
1412
|
+
throw new Error(
|
|
1413
|
+
`Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}]`
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
const { username, name, versionRange } = parsed;
|
|
1417
|
+
configure2({ registryUrl, apiKey: apiKey ?? "" });
|
|
1418
|
+
console.log(`Resolving ${specifier}...`);
|
|
1419
|
+
const versionsResponse = await listSkillVersions(username, name);
|
|
1420
|
+
if (versionsResponse.status !== 200) {
|
|
1421
|
+
if (versionsResponse.status === 401) {
|
|
1422
|
+
if (!apiKey) {
|
|
1423
|
+
throw new Error(
|
|
1424
|
+
`Package @user/${username}/${name} requires authentication. Please run 'pspm login' to authenticate`
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
throw new Error(
|
|
1428
|
+
`Access denied to @user/${username}/${name}. You may not have permission to access this private package.`
|
|
1338
1429
|
);
|
|
1430
|
+
}
|
|
1431
|
+
const errorMessage = extractApiErrorMessage(
|
|
1432
|
+
versionsResponse,
|
|
1433
|
+
`Skill @user/${username}/${name} not found`
|
|
1434
|
+
);
|
|
1435
|
+
throw new Error(errorMessage);
|
|
1436
|
+
}
|
|
1437
|
+
const versions = versionsResponse.data;
|
|
1438
|
+
if (versions.length === 0) {
|
|
1439
|
+
throw new Error(`Skill @user/${username}/${name} not found`);
|
|
1440
|
+
}
|
|
1441
|
+
const versionStrings = versions.map((v) => v.version);
|
|
1442
|
+
const resolvedVersion = resolveVersion(versionRange || "*", versionStrings);
|
|
1443
|
+
if (!resolvedVersion) {
|
|
1444
|
+
throw new Error(
|
|
1445
|
+
`No version matching "${versionRange || "latest"}" found for @user/${username}/${name}. Available versions: ${versionStrings.join(", ")}`
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
const versionResponse = await getSkillVersion(
|
|
1449
|
+
username,
|
|
1450
|
+
name,
|
|
1451
|
+
resolvedVersion
|
|
1452
|
+
);
|
|
1453
|
+
if (versionResponse.status !== 200 || !versionResponse.data) {
|
|
1454
|
+
const errorMessage = extractApiErrorMessage(
|
|
1455
|
+
versionResponse,
|
|
1456
|
+
`Version ${resolvedVersion} not found`
|
|
1457
|
+
);
|
|
1458
|
+
throw new Error(errorMessage);
|
|
1459
|
+
}
|
|
1460
|
+
console.log(`Resolved @user/${username}/${name}@${resolvedVersion}`);
|
|
1461
|
+
return {
|
|
1462
|
+
type: "registry",
|
|
1463
|
+
specifier,
|
|
1464
|
+
username,
|
|
1465
|
+
name,
|
|
1466
|
+
versionRange,
|
|
1467
|
+
resolvedVersion,
|
|
1468
|
+
versionInfo: {
|
|
1469
|
+
downloadUrl: versionResponse.data.downloadUrl,
|
|
1470
|
+
checksum: versionResponse.data.checksum
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
async function validateGitHubPackage(specifier) {
|
|
1475
|
+
const parsed = parseGitHubSpecifier(specifier);
|
|
1476
|
+
if (!parsed) {
|
|
1477
|
+
throw new Error(
|
|
1478
|
+
`Invalid GitHub specifier "${specifier}". Use format: github:{owner}/{repo}[/{path}][@{ref}]`
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
const ref = parsed.ref || "HEAD";
|
|
1482
|
+
console.log(`Resolving ${getGitHubDisplayName(parsed)}...`);
|
|
1483
|
+
const result = await downloadGitHubPackage(parsed);
|
|
1484
|
+
console.log(`Resolved ${specifier} (${ref}@${result.commit.slice(0, 7)})`);
|
|
1485
|
+
return {
|
|
1486
|
+
type: "github",
|
|
1487
|
+
specifier,
|
|
1488
|
+
parsed,
|
|
1489
|
+
ref,
|
|
1490
|
+
downloadResult: result
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
async function installRegistryPackage(resolved, options) {
|
|
1494
|
+
const { username, name, versionRange, resolvedVersion, versionInfo } = resolved;
|
|
1495
|
+
console.log(`Installing @user/${username}/${name}@${resolvedVersion}...`);
|
|
1496
|
+
const config2 = await resolveConfig();
|
|
1497
|
+
const apiKey = getTokenForRegistry(config2, config2.registryUrl);
|
|
1498
|
+
const isPresignedUrl = versionInfo.downloadUrl.includes(".r2.cloudflarestorage.com") || versionInfo.downloadUrl.includes("X-Amz-Signature");
|
|
1499
|
+
const downloadHeaders = {};
|
|
1500
|
+
if (!isPresignedUrl && apiKey) {
|
|
1501
|
+
downloadHeaders.Authorization = `Bearer ${apiKey}`;
|
|
1502
|
+
}
|
|
1503
|
+
const tarballResponse = await fetch(versionInfo.downloadUrl, {
|
|
1504
|
+
headers: downloadHeaders,
|
|
1505
|
+
redirect: "follow"
|
|
1506
|
+
});
|
|
1507
|
+
if (!tarballResponse.ok) {
|
|
1508
|
+
throw new Error(`Failed to download tarball (${tarballResponse.status})`);
|
|
1509
|
+
}
|
|
1510
|
+
const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
|
|
1511
|
+
const integrity = calculateIntegrity(tarballBuffer);
|
|
1512
|
+
const expectedIntegrity = `sha256-${Buffer.from(versionInfo.checksum, "hex").toString("base64")}`;
|
|
1513
|
+
if (integrity !== expectedIntegrity) {
|
|
1514
|
+
throw new Error("Checksum verification failed");
|
|
1515
|
+
}
|
|
1516
|
+
const skillsDir = getSkillsDir();
|
|
1517
|
+
const destDir = join(skillsDir, username, name);
|
|
1518
|
+
await mkdir(destDir, { recursive: true });
|
|
1519
|
+
const { writeFile: writeFile8 } = await import('fs/promises');
|
|
1520
|
+
const tempFile = join(destDir, ".temp.tgz");
|
|
1521
|
+
await writeFile8(tempFile, tarballBuffer);
|
|
1522
|
+
const { exec: exec2 } = await import('child_process');
|
|
1523
|
+
const { promisify: promisify2 } = await import('util');
|
|
1524
|
+
const execAsync = promisify2(exec2);
|
|
1525
|
+
try {
|
|
1526
|
+
await rm(destDir, { recursive: true, force: true });
|
|
1527
|
+
await mkdir(destDir, { recursive: true });
|
|
1528
|
+
await writeFile8(tempFile, tarballBuffer);
|
|
1529
|
+
await execAsync(
|
|
1530
|
+
`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
|
|
1531
|
+
);
|
|
1532
|
+
} finally {
|
|
1533
|
+
await rm(tempFile, { force: true });
|
|
1534
|
+
}
|
|
1535
|
+
const fullName = `@user/${username}/${name}`;
|
|
1536
|
+
await addToLockfile(fullName, {
|
|
1537
|
+
version: resolvedVersion,
|
|
1538
|
+
resolved: versionInfo.downloadUrl,
|
|
1539
|
+
integrity
|
|
1540
|
+
});
|
|
1541
|
+
const dependencyRange = versionRange || `^${resolvedVersion}`;
|
|
1542
|
+
await addDependency(fullName, dependencyRange);
|
|
1543
|
+
const agents = options.resolvedAgents;
|
|
1544
|
+
if (agents[0] !== "none") {
|
|
1545
|
+
const skillManifest = await readManifest();
|
|
1546
|
+
const skillInfo = {
|
|
1547
|
+
name,
|
|
1548
|
+
sourcePath: getRegistrySkillPath(username, name)
|
|
1549
|
+
};
|
|
1550
|
+
await createAgentSymlinks([skillInfo], {
|
|
1551
|
+
agents,
|
|
1552
|
+
projectRoot: process.cwd(),
|
|
1553
|
+
agentConfigs: skillManifest?.agents
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
console.log(`Installed @user/${username}/${name}@${resolvedVersion}`);
|
|
1557
|
+
console.log(`Location: ${destDir}`);
|
|
1558
|
+
}
|
|
1559
|
+
async function installGitHubPackage(resolved, options) {
|
|
1560
|
+
const { specifier, parsed, ref, downloadResult } = resolved;
|
|
1561
|
+
console.log(
|
|
1562
|
+
`Installing ${specifier} (${ref}@${downloadResult.commit.slice(0, 7)})...`
|
|
1563
|
+
);
|
|
1564
|
+
const skillsDir = getSkillsDir();
|
|
1565
|
+
const destPath = await extractGitHubPackage(
|
|
1566
|
+
parsed,
|
|
1567
|
+
downloadResult.buffer,
|
|
1568
|
+
skillsDir
|
|
1569
|
+
);
|
|
1570
|
+
const lockfileSpecifier = formatGitHubSpecifier({
|
|
1571
|
+
owner: parsed.owner,
|
|
1572
|
+
repo: parsed.repo,
|
|
1573
|
+
path: parsed.path
|
|
1574
|
+
// Don't include ref in the specifier key, it's stored in gitRef
|
|
1575
|
+
});
|
|
1576
|
+
const entry = {
|
|
1577
|
+
version: downloadResult.commit.slice(0, 7),
|
|
1578
|
+
resolved: `https://github.com/${parsed.owner}/${parsed.repo}`,
|
|
1579
|
+
integrity: downloadResult.integrity,
|
|
1580
|
+
gitCommit: downloadResult.commit,
|
|
1581
|
+
gitRef: ref
|
|
1582
|
+
};
|
|
1583
|
+
await addGitHubToLockfile(lockfileSpecifier, entry);
|
|
1584
|
+
await addGitHubDependency(lockfileSpecifier, ref);
|
|
1585
|
+
const agents = options.resolvedAgents;
|
|
1586
|
+
if (agents[0] !== "none") {
|
|
1587
|
+
const manifest = await readManifest();
|
|
1588
|
+
const skillName = getGitHubSkillName(parsed);
|
|
1589
|
+
const skillInfo = {
|
|
1590
|
+
name: skillName,
|
|
1591
|
+
sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
|
|
1592
|
+
};
|
|
1593
|
+
await createAgentSymlinks([skillInfo], {
|
|
1594
|
+
agents,
|
|
1595
|
+
projectRoot: process.cwd(),
|
|
1596
|
+
agentConfigs: manifest?.agents
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
console.log(
|
|
1600
|
+
`Installed ${specifier} (${ref}@${downloadResult.commit.slice(0, 7)})`
|
|
1601
|
+
);
|
|
1602
|
+
console.log(`Location: ${destPath}`);
|
|
1603
|
+
}
|
|
1604
|
+
var init_add = __esm({
|
|
1605
|
+
"src/commands/add.ts"() {
|
|
1606
|
+
init_src();
|
|
1607
|
+
init_agents();
|
|
1608
|
+
init_api_client();
|
|
1609
|
+
init_config();
|
|
1610
|
+
init_errors();
|
|
1611
|
+
init_github();
|
|
1612
|
+
init_lockfile();
|
|
1613
|
+
init_manifest2();
|
|
1614
|
+
init_symlinks();
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
|
|
1618
|
+
// src/commands/access.ts
|
|
1619
|
+
init_src();
|
|
1620
|
+
init_api_client();
|
|
1621
|
+
init_config();
|
|
1622
|
+
async function access(specifier, options) {
|
|
1623
|
+
try {
|
|
1624
|
+
const apiKey = await requireApiKey();
|
|
1625
|
+
const registryUrl = await getRegistryUrl();
|
|
1626
|
+
if (options.public && options.private) {
|
|
1627
|
+
console.error("Error: Cannot specify both --public and --private");
|
|
1339
1628
|
process.exit(1);
|
|
1340
1629
|
}
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1630
|
+
if (!options.public && !options.private) {
|
|
1631
|
+
console.error("Error: Must specify either --public or --private");
|
|
1632
|
+
process.exit(1);
|
|
1633
|
+
}
|
|
1634
|
+
const visibility = options.public ? "public" : "private";
|
|
1635
|
+
let packageName;
|
|
1636
|
+
if (specifier) {
|
|
1637
|
+
const parsed = parseSkillSpecifier(specifier);
|
|
1638
|
+
if (!parsed) {
|
|
1639
|
+
console.error(
|
|
1640
|
+
`Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
|
|
1641
|
+
);
|
|
1642
|
+
process.exit(1);
|
|
1643
|
+
}
|
|
1644
|
+
packageName = parsed.name;
|
|
1645
|
+
} else {
|
|
1646
|
+
const { readFile: readFile7 } = await import('fs/promises');
|
|
1647
|
+
const { join: join13 } = await import('path');
|
|
1648
|
+
let manifest = null;
|
|
1649
|
+
try {
|
|
1650
|
+
const content = await readFile7(
|
|
1651
|
+
join13(process.cwd(), "pspm.json"),
|
|
1652
|
+
"utf-8"
|
|
1653
|
+
);
|
|
1654
|
+
manifest = JSON.parse(content);
|
|
1655
|
+
} catch {
|
|
1656
|
+
try {
|
|
1657
|
+
const content = await readFile7(
|
|
1658
|
+
join13(process.cwd(), "package.json"),
|
|
1659
|
+
"utf-8"
|
|
1660
|
+
);
|
|
1661
|
+
manifest = JSON.parse(content);
|
|
1662
|
+
} catch {
|
|
1348
1663
|
console.error(
|
|
1349
|
-
|
|
1664
|
+
"Error: No pspm.json or package.json found in current directory"
|
|
1350
1665
|
);
|
|
1351
|
-
console.error("Please run 'pspm login' to authenticate");
|
|
1352
|
-
} else {
|
|
1353
1666
|
console.error(
|
|
1354
|
-
|
|
1667
|
+
"Either run this command in a package directory or specify a package name"
|
|
1355
1668
|
);
|
|
1669
|
+
process.exit(1);
|
|
1356
1670
|
}
|
|
1671
|
+
}
|
|
1672
|
+
if (!manifest?.name) {
|
|
1673
|
+
console.error("Error: Package manifest is missing 'name' field");
|
|
1357
1674
|
process.exit(1);
|
|
1358
1675
|
}
|
|
1359
|
-
|
|
1360
|
-
versionsResponse,
|
|
1361
|
-
`Skill @user/${username}/${name} not found`
|
|
1362
|
-
);
|
|
1363
|
-
console.error(`Error: ${errorMessage}`);
|
|
1364
|
-
process.exit(1);
|
|
1365
|
-
}
|
|
1366
|
-
const versions = versionsResponse.data;
|
|
1367
|
-
if (versions.length === 0) {
|
|
1368
|
-
console.error(`Error: Skill @user/${username}/${name} not found`);
|
|
1369
|
-
process.exit(1);
|
|
1370
|
-
}
|
|
1371
|
-
const versionStrings = versions.map((v) => v.version);
|
|
1372
|
-
const resolved = resolveVersion(versionRange || "*", versionStrings);
|
|
1373
|
-
if (!resolved) {
|
|
1374
|
-
console.error(
|
|
1375
|
-
`Error: No version matching "${versionRange || "latest"}" found for @user/${username}/${name}`
|
|
1376
|
-
);
|
|
1377
|
-
console.error(`Available versions: ${versionStrings.join(", ")}`);
|
|
1378
|
-
process.exit(1);
|
|
1676
|
+
packageName = manifest.name;
|
|
1379
1677
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
`Version ${resolved} not found`
|
|
1386
|
-
);
|
|
1678
|
+
configure2({ registryUrl, apiKey });
|
|
1679
|
+
console.log(`Setting ${packageName} to ${visibility}...`);
|
|
1680
|
+
const response = await changeSkillAccess(packageName, { visibility });
|
|
1681
|
+
if (response.status !== 200 || !response.data) {
|
|
1682
|
+
const errorMessage = response.error ?? "Failed to change visibility";
|
|
1387
1683
|
console.error(`Error: ${errorMessage}`);
|
|
1388
1684
|
process.exit(1);
|
|
1389
1685
|
}
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
redirect: "follow"
|
|
1399
|
-
});
|
|
1400
|
-
if (!tarballResponse.ok) {
|
|
1401
|
-
console.error(
|
|
1402
|
-
`Error: Failed to download tarball (${tarballResponse.status})`
|
|
1403
|
-
);
|
|
1404
|
-
process.exit(1);
|
|
1405
|
-
}
|
|
1406
|
-
const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
|
|
1407
|
-
const integrity = calculateIntegrity(tarballBuffer);
|
|
1408
|
-
const expectedIntegrity = `sha256-${Buffer.from(versionInfo.checksum, "hex").toString("base64")}`;
|
|
1409
|
-
if (integrity !== expectedIntegrity) {
|
|
1410
|
-
console.error("Error: Checksum verification failed");
|
|
1411
|
-
process.exit(1);
|
|
1412
|
-
}
|
|
1413
|
-
const skillsDir = getSkillsDir();
|
|
1414
|
-
const destDir = join(skillsDir, username, name);
|
|
1415
|
-
await mkdir(destDir, { recursive: true });
|
|
1416
|
-
const { writeFile: writeFile8 } = await import('fs/promises');
|
|
1417
|
-
const tempFile = join(destDir, ".temp.tgz");
|
|
1418
|
-
await writeFile8(tempFile, tarballBuffer);
|
|
1419
|
-
const { exec: exec2 } = await import('child_process');
|
|
1420
|
-
const { promisify: promisify2 } = await import('util');
|
|
1421
|
-
const execAsync = promisify2(exec2);
|
|
1422
|
-
try {
|
|
1423
|
-
await rm(destDir, { recursive: true, force: true });
|
|
1424
|
-
await mkdir(destDir, { recursive: true });
|
|
1425
|
-
await writeFile8(tempFile, tarballBuffer);
|
|
1426
|
-
await execAsync(
|
|
1427
|
-
`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
|
|
1686
|
+
const result = response.data;
|
|
1687
|
+
console.log(
|
|
1688
|
+
`+ @user/${result.username}/${result.name} is now ${result.visibility}`
|
|
1689
|
+
);
|
|
1690
|
+
if (visibility === "public") {
|
|
1691
|
+
console.log("");
|
|
1692
|
+
console.log(
|
|
1693
|
+
"Note: This action is irreversible. Public packages cannot be made private."
|
|
1428
1694
|
);
|
|
1429
|
-
} finally {
|
|
1430
|
-
await rm(tempFile, { force: true });
|
|
1431
|
-
}
|
|
1432
|
-
const fullName = `@user/${username}/${name}`;
|
|
1433
|
-
await addToLockfile(fullName, {
|
|
1434
|
-
version: resolved,
|
|
1435
|
-
resolved: versionInfo.downloadUrl,
|
|
1436
|
-
integrity
|
|
1437
|
-
});
|
|
1438
|
-
const dependencyRange = versionRange || `^${resolved}`;
|
|
1439
|
-
await addDependency(fullName, dependencyRange);
|
|
1440
|
-
const agents = options.resolvedAgents;
|
|
1441
|
-
if (agents[0] !== "none") {
|
|
1442
|
-
const skillManifest = await readManifest();
|
|
1443
|
-
const skillInfo = {
|
|
1444
|
-
name,
|
|
1445
|
-
sourcePath: getRegistrySkillPath(username, name)
|
|
1446
|
-
};
|
|
1447
|
-
await createAgentSymlinks([skillInfo], {
|
|
1448
|
-
agents,
|
|
1449
|
-
projectRoot: process.cwd(),
|
|
1450
|
-
agentConfigs: skillManifest?.agents
|
|
1451
|
-
});
|
|
1452
1695
|
}
|
|
1453
|
-
console.log(`Installed @user/${username}/${name}@${resolved}`);
|
|
1454
|
-
console.log(`Location: ${destDir}`);
|
|
1455
1696
|
} catch (error) {
|
|
1456
1697
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1457
1698
|
console.error(`Error: ${message}`);
|
|
1458
1699
|
process.exit(1);
|
|
1459
1700
|
}
|
|
1460
1701
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
if (!parsed) {
|
|
1465
|
-
console.error(
|
|
1466
|
-
`Error: Invalid GitHub specifier "${specifier}". Use format: github:{owner}/{repo}[/{path}][@{ref}]`
|
|
1467
|
-
);
|
|
1468
|
-
process.exit(1);
|
|
1469
|
-
}
|
|
1470
|
-
const ref = parsed.ref || "HEAD";
|
|
1471
|
-
console.log(`Resolving ${getGitHubDisplayName(parsed)}...`);
|
|
1472
|
-
const result = await downloadGitHubPackage(parsed);
|
|
1473
|
-
console.log(
|
|
1474
|
-
`Installing ${specifier} (${ref}@${result.commit.slice(0, 7)})...`
|
|
1475
|
-
);
|
|
1476
|
-
const skillsDir = getSkillsDir();
|
|
1477
|
-
const destPath = await extractGitHubPackage(
|
|
1478
|
-
parsed,
|
|
1479
|
-
result.buffer,
|
|
1480
|
-
skillsDir
|
|
1481
|
-
);
|
|
1482
|
-
const lockfileSpecifier = formatGitHubSpecifier({
|
|
1483
|
-
owner: parsed.owner,
|
|
1484
|
-
repo: parsed.repo,
|
|
1485
|
-
path: parsed.path
|
|
1486
|
-
// Don't include ref in the specifier key, it's stored in gitRef
|
|
1487
|
-
});
|
|
1488
|
-
const entry = {
|
|
1489
|
-
version: result.commit.slice(0, 7),
|
|
1490
|
-
resolved: `https://github.com/${parsed.owner}/${parsed.repo}`,
|
|
1491
|
-
integrity: result.integrity,
|
|
1492
|
-
gitCommit: result.commit,
|
|
1493
|
-
gitRef: ref
|
|
1494
|
-
};
|
|
1495
|
-
await addGitHubToLockfile(lockfileSpecifier, entry);
|
|
1496
|
-
await addGitHubDependency(lockfileSpecifier, ref);
|
|
1497
|
-
const agents = options.resolvedAgents;
|
|
1498
|
-
if (agents[0] !== "none") {
|
|
1499
|
-
const manifest = await readManifest();
|
|
1500
|
-
const skillName = getGitHubSkillName(parsed);
|
|
1501
|
-
const skillInfo = {
|
|
1502
|
-
name: skillName,
|
|
1503
|
-
sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
|
|
1504
|
-
};
|
|
1505
|
-
await createAgentSymlinks([skillInfo], {
|
|
1506
|
-
agents,
|
|
1507
|
-
projectRoot: process.cwd(),
|
|
1508
|
-
agentConfigs: manifest?.agents
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
console.log(`Installed ${specifier} (${ref}@${result.commit.slice(0, 7)})`);
|
|
1512
|
-
console.log(`Location: ${destPath}`);
|
|
1513
|
-
} catch (error) {
|
|
1514
|
-
if (error instanceof GitHubRateLimitError) {
|
|
1515
|
-
console.error(`Error: ${error.message}`);
|
|
1516
|
-
} else if (error instanceof GitHubPathNotFoundError) {
|
|
1517
|
-
console.error(`Error: ${error.message}`);
|
|
1518
|
-
} else if (error instanceof GitHubNotFoundError) {
|
|
1519
|
-
console.error(`Error: ${error.message}`);
|
|
1520
|
-
} else {
|
|
1521
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1522
|
-
console.error(`Error: ${message}`);
|
|
1523
|
-
}
|
|
1524
|
-
process.exit(1);
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1702
|
+
|
|
1703
|
+
// src/commands/index.ts
|
|
1704
|
+
init_add();
|
|
1527
1705
|
async function configInit(options) {
|
|
1528
1706
|
try {
|
|
1529
1707
|
const configPath = join(process.cwd(), ".pspmrc");
|
|
@@ -1556,6 +1734,7 @@ async function configInit(options) {
|
|
|
1556
1734
|
}
|
|
1557
1735
|
|
|
1558
1736
|
// src/commands/config/show.ts
|
|
1737
|
+
init_config();
|
|
1559
1738
|
async function configShow() {
|
|
1560
1739
|
try {
|
|
1561
1740
|
const resolved = await resolveConfig();
|
|
@@ -1585,6 +1764,9 @@ async function configShow() {
|
|
|
1585
1764
|
}
|
|
1586
1765
|
|
|
1587
1766
|
// src/commands/deprecate.ts
|
|
1767
|
+
init_src();
|
|
1768
|
+
init_api_client();
|
|
1769
|
+
init_config();
|
|
1588
1770
|
async function deprecate(specifier, message, options) {
|
|
1589
1771
|
try {
|
|
1590
1772
|
const apiKey = await requireApiKey();
|
|
@@ -1647,6 +1829,9 @@ async function deprecate(specifier, message, options) {
|
|
|
1647
1829
|
process.exit(1);
|
|
1648
1830
|
}
|
|
1649
1831
|
}
|
|
1832
|
+
|
|
1833
|
+
// src/commands/init.ts
|
|
1834
|
+
init_src();
|
|
1650
1835
|
function prompt(rl, question, defaultValue) {
|
|
1651
1836
|
return new Promise((resolve) => {
|
|
1652
1837
|
const displayDefault = defaultValue ? ` (${defaultValue})` : "";
|
|
@@ -1862,6 +2047,17 @@ async function init(options) {
|
|
|
1862
2047
|
process.exit(1);
|
|
1863
2048
|
}
|
|
1864
2049
|
}
|
|
2050
|
+
|
|
2051
|
+
// src/commands/install.ts
|
|
2052
|
+
init_src();
|
|
2053
|
+
init_agents();
|
|
2054
|
+
init_api_client();
|
|
2055
|
+
init_config();
|
|
2056
|
+
init_errors();
|
|
2057
|
+
init_github();
|
|
2058
|
+
init_lockfile();
|
|
2059
|
+
init_manifest2();
|
|
2060
|
+
init_symlinks();
|
|
1865
2061
|
function getCacheFilePath(cacheDir, integrity) {
|
|
1866
2062
|
const match = integrity.match(/^sha256-(.+)$/);
|
|
1867
2063
|
if (!match) {
|
|
@@ -1893,26 +2089,25 @@ async function writeToCache(cacheDir, integrity, data) {
|
|
|
1893
2089
|
} catch {
|
|
1894
2090
|
}
|
|
1895
2091
|
}
|
|
1896
|
-
async function install(options) {
|
|
2092
|
+
async function install(specifiers, options) {
|
|
2093
|
+
if (specifiers.length > 0) {
|
|
2094
|
+
const { add: add2 } = await Promise.resolve().then(() => (init_add(), add_exports));
|
|
2095
|
+
await add2(specifiers, {
|
|
2096
|
+
save: true,
|
|
2097
|
+
agent: options.agent,
|
|
2098
|
+
yes: options.yes
|
|
2099
|
+
});
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
await installFromLockfile(options);
|
|
2103
|
+
}
|
|
2104
|
+
async function installFromLockfile(options) {
|
|
1897
2105
|
try {
|
|
1898
2106
|
const config2 = await resolveConfig();
|
|
1899
2107
|
const registryUrl = config2.registryUrl;
|
|
1900
2108
|
const apiKey = getTokenForRegistry(config2, registryUrl);
|
|
1901
2109
|
const skillsDir = options.dir || getSkillsDir();
|
|
1902
2110
|
const cacheDir = getCacheDir();
|
|
1903
|
-
const manifest = await readManifest();
|
|
1904
|
-
const agentConfigs = manifest?.agents;
|
|
1905
|
-
let agents;
|
|
1906
|
-
if (options.agent) {
|
|
1907
|
-
agents = parseAgentArg(options.agent);
|
|
1908
|
-
} else if (manifest) {
|
|
1909
|
-
agents = parseAgentArg(void 0);
|
|
1910
|
-
} else if (options.yes) {
|
|
1911
|
-
agents = parseAgentArg(void 0);
|
|
1912
|
-
} else {
|
|
1913
|
-
console.log("No pspm.json found. Let's set up your project.\n");
|
|
1914
|
-
agents = await promptForAgents();
|
|
1915
|
-
}
|
|
1916
2111
|
await migrateLockfileIfNeeded();
|
|
1917
2112
|
let lockfile = await readLockfile();
|
|
1918
2113
|
const manifestDeps = await getDependencies();
|
|
@@ -2069,6 +2264,20 @@ Resolving ${missingGitHubDeps.length} GitHub dependency(ies)...
|
|
|
2069
2264
|
}
|
|
2070
2265
|
lockfile = await readLockfile();
|
|
2071
2266
|
}
|
|
2267
|
+
const manifest = await readManifest();
|
|
2268
|
+
const agentConfigs = manifest?.agents;
|
|
2269
|
+
let agents;
|
|
2270
|
+
if (options.agent) {
|
|
2271
|
+
agents = parseAgentArg(options.agent);
|
|
2272
|
+
} else if (manifest) {
|
|
2273
|
+
agents = parseAgentArg(void 0);
|
|
2274
|
+
} else if (options.yes) {
|
|
2275
|
+
agents = parseAgentArg(void 0);
|
|
2276
|
+
} else {
|
|
2277
|
+
console.log("\nNo pspm.json found. Let's set up your project.\n");
|
|
2278
|
+
agents = await promptForAgents();
|
|
2279
|
+
console.log();
|
|
2280
|
+
}
|
|
2072
2281
|
const packages = lockfile?.packages ?? lockfile?.skills ?? {};
|
|
2073
2282
|
const packageCount = Object.keys(packages).length;
|
|
2074
2283
|
if (packageCount > 0) {
|
|
@@ -2257,6 +2466,11 @@ All ${totalCount} skill(s) installed.`);
|
|
|
2257
2466
|
}
|
|
2258
2467
|
|
|
2259
2468
|
// src/commands/link.ts
|
|
2469
|
+
init_src();
|
|
2470
|
+
init_agents();
|
|
2471
|
+
init_lockfile();
|
|
2472
|
+
init_manifest2();
|
|
2473
|
+
init_symlinks();
|
|
2260
2474
|
async function link(options) {
|
|
2261
2475
|
try {
|
|
2262
2476
|
const manifest = await readManifest();
|
|
@@ -2327,6 +2541,13 @@ async function link(options) {
|
|
|
2327
2541
|
process.exit(1);
|
|
2328
2542
|
}
|
|
2329
2543
|
}
|
|
2544
|
+
|
|
2545
|
+
// src/commands/list.ts
|
|
2546
|
+
init_src();
|
|
2547
|
+
init_agents();
|
|
2548
|
+
init_lockfile();
|
|
2549
|
+
init_manifest2();
|
|
2550
|
+
init_symlinks();
|
|
2330
2551
|
async function list(options) {
|
|
2331
2552
|
try {
|
|
2332
2553
|
const registrySkills = await listLockfileSkills();
|
|
@@ -2440,6 +2661,10 @@ Total: ${skills.length} skill(s) (${parts.join(", ")})`);
|
|
|
2440
2661
|
process.exit(1);
|
|
2441
2662
|
}
|
|
2442
2663
|
}
|
|
2664
|
+
|
|
2665
|
+
// src/commands/login.ts
|
|
2666
|
+
init_api_client();
|
|
2667
|
+
init_config();
|
|
2443
2668
|
var DEFAULT_WEB_APP_URL = "https://pspm.dev";
|
|
2444
2669
|
function getWebAppUrl(registryUrl) {
|
|
2445
2670
|
if (process.env.PSPM_WEB_URL) {
|
|
@@ -2617,6 +2842,7 @@ async function login(options) {
|
|
|
2617
2842
|
}
|
|
2618
2843
|
|
|
2619
2844
|
// src/commands/logout.ts
|
|
2845
|
+
init_config();
|
|
2620
2846
|
async function logout() {
|
|
2621
2847
|
try {
|
|
2622
2848
|
const loggedIn = await isLoggedIn();
|
|
@@ -2632,6 +2858,10 @@ async function logout() {
|
|
|
2632
2858
|
process.exit(1);
|
|
2633
2859
|
}
|
|
2634
2860
|
}
|
|
2861
|
+
|
|
2862
|
+
// src/commands/migrate.ts
|
|
2863
|
+
init_config();
|
|
2864
|
+
init_lockfile();
|
|
2635
2865
|
async function migrate(options) {
|
|
2636
2866
|
try {
|
|
2637
2867
|
const legacySkillsDir = getLegacySkillsDir();
|
|
@@ -2731,6 +2961,12 @@ async function migrate(options) {
|
|
|
2731
2961
|
process.exit(1);
|
|
2732
2962
|
}
|
|
2733
2963
|
}
|
|
2964
|
+
|
|
2965
|
+
// src/commands/publish.ts
|
|
2966
|
+
init_src();
|
|
2967
|
+
init_api_client();
|
|
2968
|
+
init_config();
|
|
2969
|
+
init_errors();
|
|
2734
2970
|
var exec = promisify(exec$1);
|
|
2735
2971
|
async function detectManifest() {
|
|
2736
2972
|
const cwd = process.cwd();
|
|
@@ -2936,6 +3172,14 @@ Setting visibility to ${options.access}...`);
|
|
|
2936
3172
|
process.exit(1);
|
|
2937
3173
|
}
|
|
2938
3174
|
}
|
|
3175
|
+
|
|
3176
|
+
// src/commands/remove.ts
|
|
3177
|
+
init_src();
|
|
3178
|
+
init_agents();
|
|
3179
|
+
init_config();
|
|
3180
|
+
init_lockfile();
|
|
3181
|
+
init_manifest2();
|
|
3182
|
+
init_symlinks();
|
|
2939
3183
|
async function remove(nameOrSpecifier) {
|
|
2940
3184
|
try {
|
|
2941
3185
|
const manifest = await readManifest();
|
|
@@ -3037,6 +3281,10 @@ async function removeByShortName(shortName, agents, agentConfigs) {
|
|
|
3037
3281
|
}
|
|
3038
3282
|
|
|
3039
3283
|
// src/commands/unpublish.ts
|
|
3284
|
+
init_src();
|
|
3285
|
+
init_api_client();
|
|
3286
|
+
init_config();
|
|
3287
|
+
init_errors();
|
|
3040
3288
|
async function unpublish(specifier, options) {
|
|
3041
3289
|
try {
|
|
3042
3290
|
const apiKey = await requireApiKey();
|
|
@@ -3095,6 +3343,12 @@ async function unpublish(specifier, options) {
|
|
|
3095
3343
|
}
|
|
3096
3344
|
|
|
3097
3345
|
// src/commands/update.ts
|
|
3346
|
+
init_src();
|
|
3347
|
+
init_api_client();
|
|
3348
|
+
init_config();
|
|
3349
|
+
init_errors();
|
|
3350
|
+
init_lockfile();
|
|
3351
|
+
init_add();
|
|
3098
3352
|
async function update(options) {
|
|
3099
3353
|
try {
|
|
3100
3354
|
const apiKey = await requireApiKey();
|
|
@@ -3156,7 +3410,7 @@ async function update(options) {
|
|
|
3156
3410
|
if (!match) continue;
|
|
3157
3411
|
const [, username, skillName] = match;
|
|
3158
3412
|
const specifier = `@user/${username}/${skillName}@${latest}`;
|
|
3159
|
-
await add(specifier, {});
|
|
3413
|
+
await add([specifier], {});
|
|
3160
3414
|
}
|
|
3161
3415
|
console.log("\nAll skills updated.");
|
|
3162
3416
|
} catch (error) {
|
|
@@ -3167,6 +3421,8 @@ async function update(options) {
|
|
|
3167
3421
|
}
|
|
3168
3422
|
|
|
3169
3423
|
// src/commands/whoami.ts
|
|
3424
|
+
init_api_client();
|
|
3425
|
+
init_config();
|
|
3170
3426
|
async function whoami() {
|
|
3171
3427
|
try {
|
|
3172
3428
|
const resolved = await resolveConfig();
|
|
@@ -3234,13 +3490,13 @@ program.command("migrate").description(
|
|
|
3234
3490
|
).option("--dry-run", "Show what would be migrated without making changes").action(async (options) => {
|
|
3235
3491
|
await migrate({ dryRun: options.dryRun });
|
|
3236
3492
|
});
|
|
3237
|
-
program.command("add <
|
|
3238
|
-
"Add
|
|
3493
|
+
program.command("add <specifiers...>").description(
|
|
3494
|
+
"Add one or more skills (e.g., @user/bsheng/vite_slides@^2.0.0 or github:owner/repo/path@ref)"
|
|
3239
3495
|
).option("--save", "Save to lockfile (default)").option(
|
|
3240
3496
|
"--agent <agents>",
|
|
3241
|
-
'Comma-separated agents for symlinks (default:
|
|
3242
|
-
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (
|
|
3243
|
-
await add(
|
|
3497
|
+
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
3498
|
+
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
3499
|
+
await add(specifiers, {
|
|
3244
3500
|
save: options.save ?? true,
|
|
3245
3501
|
agent: options.agent,
|
|
3246
3502
|
yes: options.yes
|
|
@@ -3252,11 +3508,13 @@ program.command("remove <name>").alias("rm").description("Remove an installed sk
|
|
|
3252
3508
|
program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").action(async (options) => {
|
|
3253
3509
|
await list({ json: options.json });
|
|
3254
3510
|
});
|
|
3255
|
-
program.command("install").alias("i").description(
|
|
3511
|
+
program.command("install [specifiers...]").alias("i").description(
|
|
3512
|
+
"Install skills from lockfile, or add and install specific packages"
|
|
3513
|
+
).option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").option(
|
|
3256
3514
|
"--agent <agents>",
|
|
3257
|
-
'Comma-separated agents for symlinks (default:
|
|
3258
|
-
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
|
|
3259
|
-
await install({
|
|
3515
|
+
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
3516
|
+
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
|
|
3517
|
+
await install(specifiers, {
|
|
3260
3518
|
frozenLockfile: options.frozenLockfile,
|
|
3261
3519
|
dir: options.dir,
|
|
3262
3520
|
agent: options.agent,
|
|
@@ -3265,7 +3523,7 @@ program.command("install").alias("i").description("Install all skills from lockf
|
|
|
3265
3523
|
});
|
|
3266
3524
|
program.command("link").description("Recreate agent symlinks without reinstalling").option(
|
|
3267
3525
|
"--agent <agents>",
|
|
3268
|
-
'Comma-separated agents for symlinks (default:
|
|
3526
|
+
'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
|
|
3269
3527
|
).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
|
|
3270
3528
|
await link({ agent: options.agent, yes: options.yes });
|
|
3271
3529
|
});
|