@anytio/pspm 0.0.3 → 0.0.5
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 +86 -36
- package/dist/index.js +385 -572
- package/dist/index.js.map +1 -1
- package/package.json +67 -65
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from 'fs';
|
|
3
|
-
import { dirname, join } from 'path';
|
|
3
|
+
import { dirname, join, relative } from 'path';
|
|
4
4
|
import { fileURLToPath, URL } from 'url';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
-
import { stat, writeFile, mkdir, rm, access, readFile } from 'fs/promises';
|
|
7
|
-
import {
|
|
6
|
+
import { stat, writeFile, mkdir, rm, access, readFile, readdir, unlink } from 'fs/promises';
|
|
7
|
+
import { createHash, randomBytes } from 'crypto';
|
|
8
8
|
import * as semver from 'semver';
|
|
9
9
|
import { homedir } from 'os';
|
|
10
|
+
import * as ini from 'ini';
|
|
10
11
|
import http from 'http';
|
|
11
12
|
import open from 'open';
|
|
12
13
|
import { exec as exec$1 } from 'child_process';
|
|
@@ -38,7 +39,7 @@ function resolveVersion(range, availableVersions) {
|
|
|
38
39
|
return semver.maxSatisfying(sorted, range);
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
// ../../packages/sdk/src/fetcher.ts
|
|
42
|
+
// ../../packages/sdk/src/fetchers/cli-fetcher.ts
|
|
42
43
|
var config = null;
|
|
43
44
|
function configure(options) {
|
|
44
45
|
config = options;
|
|
@@ -76,9 +77,9 @@ async function customFetch(url, options) {
|
|
|
76
77
|
};
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
// ../../packages/sdk/src/generated/index.ts
|
|
80
|
+
// ../../packages/sdk/src/generated/fetch/index.ts
|
|
80
81
|
var getMeUrl = () => {
|
|
81
|
-
return `/me`;
|
|
82
|
+
return `/api/skills/me`;
|
|
82
83
|
};
|
|
83
84
|
var me = async (options) => {
|
|
84
85
|
return customFetch(
|
|
@@ -90,7 +91,7 @@ var me = async (options) => {
|
|
|
90
91
|
);
|
|
91
92
|
};
|
|
92
93
|
var getListSkillVersionsUrl = (username, name) => {
|
|
93
|
-
return
|
|
94
|
+
return `/api/skills/@user/${username}/${name}/versions`;
|
|
94
95
|
};
|
|
95
96
|
var listSkillVersions = async (username, name, options) => {
|
|
96
97
|
return customFetch(
|
|
@@ -102,7 +103,7 @@ var listSkillVersions = async (username, name, options) => {
|
|
|
102
103
|
);
|
|
103
104
|
};
|
|
104
105
|
var getGetSkillVersionUrl = (username, name, version2) => {
|
|
105
|
-
return
|
|
106
|
+
return `/api/skills/@user/${username}/${name}/${version2}`;
|
|
106
107
|
};
|
|
107
108
|
var getSkillVersion = async (username, name, version2, options) => {
|
|
108
109
|
return customFetch(
|
|
@@ -114,9 +115,9 @@ var getSkillVersion = async (username, name, version2, options) => {
|
|
|
114
115
|
);
|
|
115
116
|
};
|
|
116
117
|
var getPublishSkillUrl = () => {
|
|
117
|
-
return `/publish`;
|
|
118
|
+
return `/api/skills/publish`;
|
|
118
119
|
};
|
|
119
|
-
var publishSkill = async (
|
|
120
|
+
var publishSkill = async (publishSkillInput, options) => {
|
|
120
121
|
return customFetch(
|
|
121
122
|
getPublishSkillUrl(),
|
|
122
123
|
{
|
|
@@ -124,53 +125,52 @@ var publishSkill = async (publishSkillBody, options) => {
|
|
|
124
125
|
method: "POST",
|
|
125
126
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
126
127
|
body: JSON.stringify(
|
|
127
|
-
|
|
128
|
+
publishSkillInput
|
|
128
129
|
)
|
|
129
130
|
}
|
|
130
131
|
);
|
|
131
132
|
};
|
|
132
133
|
var getDeleteSkillUrl = (name) => {
|
|
133
|
-
return
|
|
134
|
+
return `/api/skills/${name}`;
|
|
134
135
|
};
|
|
135
|
-
var deleteSkill = async (name,
|
|
136
|
+
var deleteSkill = async (name, options) => {
|
|
136
137
|
return customFetch(
|
|
137
138
|
getDeleteSkillUrl(name),
|
|
138
139
|
{
|
|
139
140
|
...options,
|
|
140
|
-
method: "DELETE"
|
|
141
|
-
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
142
|
-
body: JSON.stringify(
|
|
143
|
-
deleteSkillBody
|
|
144
|
-
)
|
|
141
|
+
method: "DELETE"
|
|
145
142
|
}
|
|
146
143
|
);
|
|
147
144
|
};
|
|
148
145
|
var getDeleteSkillVersionUrl = (name, version2) => {
|
|
149
|
-
return
|
|
146
|
+
return `/api/skills/${name}/${version2}`;
|
|
150
147
|
};
|
|
151
|
-
var deleteSkillVersion = async (name, version2,
|
|
148
|
+
var deleteSkillVersion = async (name, version2, options) => {
|
|
152
149
|
return customFetch(
|
|
153
150
|
getDeleteSkillVersionUrl(name, version2),
|
|
154
151
|
{
|
|
155
152
|
...options,
|
|
156
|
-
method: "DELETE"
|
|
157
|
-
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
158
|
-
body: JSON.stringify(
|
|
159
|
-
deleteSkillVersionBody
|
|
160
|
-
)
|
|
153
|
+
method: "DELETE"
|
|
161
154
|
}
|
|
162
155
|
);
|
|
163
156
|
};
|
|
164
157
|
|
|
165
158
|
// src/api-client.ts
|
|
159
|
+
function registryUrlToBaseUrl(registryUrl) {
|
|
160
|
+
return registryUrl.replace(/\/api\/skills\/?$/, "");
|
|
161
|
+
}
|
|
162
|
+
function configure2(options) {
|
|
163
|
+
const baseUrl = registryUrlToBaseUrl(options.registryUrl);
|
|
164
|
+
configure({ baseUrl, apiKey: options.apiKey });
|
|
165
|
+
}
|
|
166
166
|
async function whoamiRequest(registryUrl, apiKey) {
|
|
167
167
|
try {
|
|
168
|
-
|
|
168
|
+
configure2({ registryUrl, apiKey });
|
|
169
169
|
const response = await me();
|
|
170
|
-
|
|
171
|
-
if (!user) {
|
|
170
|
+
if (response.status !== 200 || !response.data) {
|
|
172
171
|
return null;
|
|
173
172
|
}
|
|
173
|
+
const user = response.data;
|
|
174
174
|
return {
|
|
175
175
|
username: user.username,
|
|
176
176
|
userId: user.userId
|
|
@@ -187,14 +187,6 @@ var ConfigError = class extends Error {
|
|
|
187
187
|
this.name = "ConfigError";
|
|
188
188
|
}
|
|
189
189
|
};
|
|
190
|
-
var ProfileNotFoundError = class extends ConfigError {
|
|
191
|
-
constructor(profileName) {
|
|
192
|
-
super(
|
|
193
|
-
`Profile "${profileName}" not found. Run 'pspm config list' to see available profiles.`
|
|
194
|
-
);
|
|
195
|
-
this.name = "ProfileNotFoundError";
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
190
|
var NotLoggedInError = class extends ConfigError {
|
|
199
191
|
constructor() {
|
|
200
192
|
super(
|
|
@@ -203,10 +195,47 @@ var NotLoggedInError = class extends ConfigError {
|
|
|
203
195
|
this.name = "NotLoggedInError";
|
|
204
196
|
}
|
|
205
197
|
};
|
|
198
|
+
function extractApiErrorMessage(response, fallbackMessage) {
|
|
199
|
+
const errorData = response.data;
|
|
200
|
+
if (process.env.PSPM_DEBUG) {
|
|
201
|
+
console.log(`[debug] API response status: ${response.status}`);
|
|
202
|
+
console.log(
|
|
203
|
+
`[debug] API response data:`,
|
|
204
|
+
JSON.stringify(errorData, null, 2)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (!errorData) {
|
|
208
|
+
return `${fallbackMessage} (HTTP ${response.status})`;
|
|
209
|
+
}
|
|
210
|
+
let errorMessage = errorData.message || fallbackMessage;
|
|
211
|
+
if (errorData.code === "VALIDATION_ERROR" && errorData.details) {
|
|
212
|
+
const issues = errorData.details.issues;
|
|
213
|
+
if (issues && Array.isArray(issues)) {
|
|
214
|
+
const issueMessages = issues.map((issue) => {
|
|
215
|
+
const path = issue.path?.join(".") || "input";
|
|
216
|
+
const msg = issue.message || "invalid value";
|
|
217
|
+
return ` - ${path}: ${msg}`;
|
|
218
|
+
}).join("\n");
|
|
219
|
+
errorMessage = `Validation failed:
|
|
220
|
+
${issueMessages}`;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (errorData.code && !errorMessage.includes(errorData.code)) {
|
|
224
|
+
errorMessage = `[${errorData.code}] ${errorMessage}`;
|
|
225
|
+
}
|
|
226
|
+
if (errorData.requestId) {
|
|
227
|
+
errorMessage += `
|
|
228
|
+
(Request ID: ${errorData.requestId})`;
|
|
229
|
+
}
|
|
230
|
+
return errorMessage;
|
|
231
|
+
}
|
|
206
232
|
|
|
207
233
|
// src/config.ts
|
|
208
|
-
var DEFAULT_REGISTRY_URL = "https://pspm.dev
|
|
234
|
+
var DEFAULT_REGISTRY_URL = "https://pspm.dev";
|
|
209
235
|
function getConfigPath() {
|
|
236
|
+
return join(homedir(), ".pspmrc");
|
|
237
|
+
}
|
|
238
|
+
function getLegacyConfigPath() {
|
|
210
239
|
return join(homedir(), ".pspm", "config.json");
|
|
211
240
|
}
|
|
212
241
|
function getSkillsDir() {
|
|
@@ -215,33 +244,6 @@ function getSkillsDir() {
|
|
|
215
244
|
function getLockfilePath() {
|
|
216
245
|
return join(process.cwd(), "skill-lock.json");
|
|
217
246
|
}
|
|
218
|
-
function createDefaultV2Config() {
|
|
219
|
-
return {
|
|
220
|
-
version: 2,
|
|
221
|
-
defaultProfile: "default",
|
|
222
|
-
profiles: {
|
|
223
|
-
default: {
|
|
224
|
-
registryUrl: DEFAULT_REGISTRY_URL
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
function migrateV1ToV2(v1Config) {
|
|
230
|
-
return {
|
|
231
|
-
version: 2,
|
|
232
|
-
defaultProfile: "default",
|
|
233
|
-
profiles: {
|
|
234
|
-
default: {
|
|
235
|
-
registryUrl: v1Config.registryUrl || DEFAULT_REGISTRY_URL,
|
|
236
|
-
apiKey: v1Config.apiKey,
|
|
237
|
-
username: v1Config.username
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
function isV2Config(config2) {
|
|
243
|
-
return typeof config2 === "object" && config2 !== null && "version" in config2 && config2.version === 2;
|
|
244
|
-
}
|
|
245
247
|
async function readUserConfig() {
|
|
246
248
|
const configPath = getConfigPath();
|
|
247
249
|
if (process.env.PSPM_DEBUG) {
|
|
@@ -249,48 +251,42 @@ async function readUserConfig() {
|
|
|
249
251
|
}
|
|
250
252
|
try {
|
|
251
253
|
const content = await readFile(configPath, "utf-8");
|
|
254
|
+
const parsed = ini.parse(content);
|
|
252
255
|
if (process.env.PSPM_DEBUG) {
|
|
253
|
-
|
|
254
|
-
if (apiKeyMatch) {
|
|
255
|
-
console.log(
|
|
256
|
-
`[config] Raw apiKey from file: ${apiKeyMatch[1].substring(
|
|
257
|
-
0,
|
|
258
|
-
15
|
|
259
|
-
)}...`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
const parsed = JSON.parse(content);
|
|
264
|
-
if (process.env.PSPM_DEBUG) {
|
|
265
|
-
console.log(
|
|
266
|
-
`[config] Parsed config version: ${parsed.version}`
|
|
267
|
-
);
|
|
268
|
-
console.log(
|
|
269
|
-
`[config] Profiles found: ${Object.keys(
|
|
270
|
-
parsed.profiles || {}
|
|
271
|
-
).join(", ")}`
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
if (isV2Config(parsed)) {
|
|
275
|
-
return parsed;
|
|
256
|
+
console.log(`[config] Parsed config:`, JSON.stringify(parsed, null, 2));
|
|
276
257
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
258
|
+
return {
|
|
259
|
+
registry: parsed.registry,
|
|
260
|
+
authToken: parsed.authToken,
|
|
261
|
+
username: parsed.username
|
|
262
|
+
};
|
|
280
263
|
} catch (error) {
|
|
281
264
|
if (process.env.PSPM_DEBUG) {
|
|
282
265
|
console.log(
|
|
283
266
|
`[config] Error reading config: ${error instanceof Error ? error.message : String(error)}`
|
|
284
267
|
);
|
|
285
|
-
console.log(`[config] Falling back to default config`);
|
|
286
268
|
}
|
|
287
|
-
return
|
|
269
|
+
return {};
|
|
288
270
|
}
|
|
289
271
|
}
|
|
290
272
|
async function writeUserConfig(config2) {
|
|
291
273
|
const configPath = getConfigPath();
|
|
274
|
+
const lines = ["; PSPM Configuration", ""];
|
|
275
|
+
if (config2.registry) {
|
|
276
|
+
lines.push(`registry = ${config2.registry}`);
|
|
277
|
+
}
|
|
278
|
+
if (config2.authToken) {
|
|
279
|
+
lines.push(`authToken = ${config2.authToken}`);
|
|
280
|
+
}
|
|
281
|
+
if (config2.username) {
|
|
282
|
+
lines.push(`username = ${config2.username}`);
|
|
283
|
+
}
|
|
284
|
+
lines.push("");
|
|
292
285
|
await mkdir(dirname(configPath), { recursive: true });
|
|
293
|
-
await writeFile(configPath,
|
|
286
|
+
await writeFile(configPath, lines.join("\n"));
|
|
287
|
+
if (process.env.PSPM_DEBUG) {
|
|
288
|
+
console.log(`[config] Wrote config to: ${configPath}`);
|
|
289
|
+
}
|
|
294
290
|
}
|
|
295
291
|
async function findProjectConfig() {
|
|
296
292
|
let currentDir = process.cwd();
|
|
@@ -301,7 +297,26 @@ async function findProjectConfig() {
|
|
|
301
297
|
const stats = await stat(configPath);
|
|
302
298
|
if (stats.isFile()) {
|
|
303
299
|
const content = await readFile(configPath, "utf-8");
|
|
304
|
-
|
|
300
|
+
try {
|
|
301
|
+
const parsed = ini.parse(content);
|
|
302
|
+
if (process.env.PSPM_DEBUG) {
|
|
303
|
+
console.log(
|
|
304
|
+
`[config] Found project config at ${configPath}:`,
|
|
305
|
+
JSON.stringify(parsed, null, 2)
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
registry: parsed.registry
|
|
310
|
+
};
|
|
311
|
+
} catch {
|
|
312
|
+
try {
|
|
313
|
+
const jsonConfig = JSON.parse(content);
|
|
314
|
+
return {
|
|
315
|
+
registry: jsonConfig.registryUrl
|
|
316
|
+
};
|
|
317
|
+
} catch {
|
|
318
|
+
}
|
|
319
|
+
}
|
|
305
320
|
}
|
|
306
321
|
} catch {
|
|
307
322
|
}
|
|
@@ -309,49 +324,61 @@ async function findProjectConfig() {
|
|
|
309
324
|
}
|
|
310
325
|
return null;
|
|
311
326
|
}
|
|
312
|
-
async function
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
} else {
|
|
330
|
-
profileName = "default";
|
|
331
|
-
profileSource = "default";
|
|
332
|
-
}
|
|
333
|
-
const profile = userConfig.profiles[profileName];
|
|
334
|
-
if (!profile) {
|
|
335
|
-
if (process.env.PSPM_DEBUG) {
|
|
327
|
+
async function migrateFromLegacyConfig() {
|
|
328
|
+
const legacyPath = getLegacyConfigPath();
|
|
329
|
+
try {
|
|
330
|
+
const content = await readFile(legacyPath, "utf-8");
|
|
331
|
+
const parsed = JSON.parse(content);
|
|
332
|
+
let config2 = {};
|
|
333
|
+
if (parsed.version === 2 && parsed.profiles) {
|
|
334
|
+
const v2Config = parsed;
|
|
335
|
+
const defaultProfileName = v2Config.defaultProfile || "default";
|
|
336
|
+
const profile = v2Config.profiles[defaultProfileName];
|
|
337
|
+
if (profile) {
|
|
338
|
+
config2 = {
|
|
339
|
+
registry: profile.registryUrl !== DEFAULT_REGISTRY_URL ? profile.registryUrl : void 0,
|
|
340
|
+
authToken: profile.apiKey,
|
|
341
|
+
username: profile.username
|
|
342
|
+
};
|
|
343
|
+
}
|
|
336
344
|
console.log(
|
|
337
|
-
`
|
|
338
|
-
userConfig.profiles
|
|
339
|
-
).join(", ")}`
|
|
345
|
+
`Migrating from legacy config (profile: ${defaultProfileName})...`
|
|
340
346
|
);
|
|
341
|
-
}
|
|
342
|
-
|
|
347
|
+
} else {
|
|
348
|
+
const v1Config = parsed;
|
|
349
|
+
config2 = {
|
|
350
|
+
registry: v1Config.registryUrl !== DEFAULT_REGISTRY_URL ? v1Config.registryUrl : void 0,
|
|
351
|
+
authToken: v1Config.apiKey,
|
|
352
|
+
username: v1Config.username
|
|
353
|
+
};
|
|
354
|
+
console.log("Migrating from legacy config...");
|
|
355
|
+
}
|
|
356
|
+
await writeUserConfig(config2);
|
|
357
|
+
console.log(`Created new config at: ${getConfigPath()}`);
|
|
358
|
+
await unlink(legacyPath);
|
|
359
|
+
console.log(`Removed legacy config: ${legacyPath}`);
|
|
360
|
+
return config2;
|
|
361
|
+
} catch {
|
|
362
|
+
return null;
|
|
343
363
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
364
|
+
}
|
|
365
|
+
async function resolveConfig() {
|
|
366
|
+
const newConfigPath = getConfigPath();
|
|
367
|
+
try {
|
|
368
|
+
await stat(newConfigPath);
|
|
369
|
+
} catch {
|
|
370
|
+
await migrateFromLegacyConfig();
|
|
349
371
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
372
|
+
const userConfig = await readUserConfig();
|
|
373
|
+
const projectConfig = await findProjectConfig();
|
|
374
|
+
let registryUrl = DEFAULT_REGISTRY_URL;
|
|
375
|
+
let apiKey = userConfig.authToken;
|
|
376
|
+
const username = userConfig.username;
|
|
377
|
+
if (userConfig.registry) {
|
|
378
|
+
registryUrl = userConfig.registry;
|
|
379
|
+
}
|
|
380
|
+
if (projectConfig?.registry) {
|
|
381
|
+
registryUrl = projectConfig.registry;
|
|
355
382
|
}
|
|
356
383
|
if (process.env.PSPM_REGISTRY_URL) {
|
|
357
384
|
registryUrl = process.env.PSPM_REGISTRY_URL;
|
|
@@ -359,117 +386,62 @@ async function resolveConfig(globalOptions) {
|
|
|
359
386
|
if (process.env.PSPM_API_KEY) {
|
|
360
387
|
apiKey = process.env.PSPM_API_KEY;
|
|
361
388
|
}
|
|
389
|
+
if (process.env.PSPM_DEBUG) {
|
|
390
|
+
console.log(`[config] Resolved config:`);
|
|
391
|
+
console.log(`[config] registryUrl: ${registryUrl}`);
|
|
392
|
+
console.log(`[config] apiKey: ${apiKey ? "***" : "(not set)"}`);
|
|
393
|
+
console.log(`[config] username: ${username || "(not set)"}`);
|
|
394
|
+
}
|
|
362
395
|
return {
|
|
363
|
-
profileName,
|
|
364
|
-
profileSource,
|
|
365
396
|
registryUrl,
|
|
366
397
|
apiKey,
|
|
367
398
|
username
|
|
368
399
|
};
|
|
369
400
|
}
|
|
370
|
-
async function
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const userConfig = await readUserConfig();
|
|
376
|
-
return Object.keys(userConfig.profiles);
|
|
377
|
-
}
|
|
378
|
-
async function setProfile(profileName, config2) {
|
|
379
|
-
const userConfig = await readUserConfig();
|
|
380
|
-
const existing = userConfig.profiles[profileName] || {
|
|
381
|
-
registryUrl: DEFAULT_REGISTRY_URL
|
|
382
|
-
};
|
|
383
|
-
userConfig.profiles[profileName] = {
|
|
384
|
-
...existing,
|
|
385
|
-
...config2
|
|
386
|
-
};
|
|
387
|
-
await writeUserConfig(userConfig);
|
|
388
|
-
}
|
|
389
|
-
async function deleteProfile(profileName) {
|
|
390
|
-
const userConfig = await readUserConfig();
|
|
391
|
-
if (!userConfig.profiles[profileName]) {
|
|
392
|
-
return false;
|
|
393
|
-
}
|
|
394
|
-
delete userConfig.profiles[profileName];
|
|
395
|
-
if (userConfig.defaultProfile === profileName) {
|
|
396
|
-
const remainingProfiles = Object.keys(userConfig.profiles);
|
|
397
|
-
userConfig.defaultProfile = remainingProfiles[0] || "default";
|
|
401
|
+
async function setCredentials(authToken, username, registry) {
|
|
402
|
+
const config2 = await readUserConfig();
|
|
403
|
+
config2.authToken = authToken;
|
|
404
|
+
if (username) {
|
|
405
|
+
config2.username = username;
|
|
398
406
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
async function setDefaultProfile(profileName) {
|
|
403
|
-
const userConfig = await readUserConfig();
|
|
404
|
-
if (!userConfig.profiles[profileName]) {
|
|
405
|
-
throw new ProfileNotFoundError(profileName);
|
|
407
|
+
if (registry && registry !== DEFAULT_REGISTRY_URL) {
|
|
408
|
+
config2.registry = registry;
|
|
406
409
|
}
|
|
407
|
-
|
|
408
|
-
await writeUserConfig(userConfig);
|
|
410
|
+
await writeUserConfig(config2);
|
|
409
411
|
}
|
|
410
|
-
async function
|
|
411
|
-
const
|
|
412
|
-
|
|
412
|
+
async function clearCredentials() {
|
|
413
|
+
const config2 = await readUserConfig();
|
|
414
|
+
delete config2.authToken;
|
|
415
|
+
delete config2.username;
|
|
416
|
+
await writeUserConfig(config2);
|
|
413
417
|
}
|
|
414
|
-
({
|
|
415
|
-
registryUrl: process.env.PSPM_REGISTRY_URL || DEFAULT_REGISTRY_URL
|
|
416
|
-
});
|
|
417
|
-
async function isLoggedIn(globalOptions) {
|
|
418
|
+
async function isLoggedIn() {
|
|
418
419
|
try {
|
|
419
|
-
const resolved = await resolveConfig(
|
|
420
|
+
const resolved = await resolveConfig();
|
|
420
421
|
return !!resolved.apiKey;
|
|
421
422
|
} catch {
|
|
422
423
|
return false;
|
|
423
424
|
}
|
|
424
425
|
}
|
|
425
|
-
async function requireApiKey(
|
|
426
|
-
const resolved = await resolveConfig(
|
|
426
|
+
async function requireApiKey() {
|
|
427
|
+
const resolved = await resolveConfig();
|
|
427
428
|
if (!resolved.apiKey) {
|
|
428
429
|
if (process.env.PSPM_DEBUG) {
|
|
429
|
-
console.log(
|
|
430
|
-
`[config] requireApiKey: No API key found for profile "${resolved.profileName}"`
|
|
431
|
-
);
|
|
430
|
+
console.log(`[config] requireApiKey: No API key found`);
|
|
432
431
|
}
|
|
433
432
|
throw new NotLoggedInError();
|
|
434
433
|
}
|
|
435
434
|
if (process.env.PSPM_DEBUG) {
|
|
436
435
|
console.log(
|
|
437
|
-
`[config] requireApiKey: Got API key (${resolved.apiKey.substring(
|
|
438
|
-
0,
|
|
439
|
-
10
|
|
440
|
-
)}...)`
|
|
436
|
+
`[config] requireApiKey: Got API key (${resolved.apiKey.substring(0, 10)}...)`
|
|
441
437
|
);
|
|
442
438
|
}
|
|
443
439
|
return resolved.apiKey;
|
|
444
440
|
}
|
|
445
|
-
async function getRegistryUrl(
|
|
446
|
-
const resolved = await resolveConfig(
|
|
441
|
+
async function getRegistryUrl() {
|
|
442
|
+
const resolved = await resolveConfig();
|
|
447
443
|
return resolved.registryUrl;
|
|
448
444
|
}
|
|
449
|
-
async function clearProfileCredentials(profileName) {
|
|
450
|
-
const userConfig = await readUserConfig();
|
|
451
|
-
if (userConfig.profiles[profileName]) {
|
|
452
|
-
userConfig.profiles[profileName].apiKey = void 0;
|
|
453
|
-
userConfig.profiles[profileName].username = void 0;
|
|
454
|
-
await writeUserConfig(userConfig);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
async function setProfileCredentials(profileName, apiKey, username, registryUrl) {
|
|
458
|
-
const userConfig = await readUserConfig();
|
|
459
|
-
if (!userConfig.profiles[profileName]) {
|
|
460
|
-
userConfig.profiles[profileName] = {
|
|
461
|
-
registryUrl: registryUrl || DEFAULT_REGISTRY_URL
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
userConfig.profiles[profileName].apiKey = apiKey;
|
|
465
|
-
if (username) {
|
|
466
|
-
userConfig.profiles[profileName].username = username;
|
|
467
|
-
}
|
|
468
|
-
if (registryUrl) {
|
|
469
|
-
userConfig.profiles[profileName].registryUrl = registryUrl;
|
|
470
|
-
}
|
|
471
|
-
await writeUserConfig(userConfig);
|
|
472
|
-
}
|
|
473
445
|
async function readLockfile() {
|
|
474
446
|
const lockfilePath = getLockfilePath();
|
|
475
447
|
try {
|
|
@@ -522,10 +494,10 @@ async function listLockfileSkills() {
|
|
|
522
494
|
}
|
|
523
495
|
|
|
524
496
|
// src/commands/add.ts
|
|
525
|
-
async function add(specifier, _options
|
|
497
|
+
async function add(specifier, _options) {
|
|
526
498
|
try {
|
|
527
|
-
const apiKey = await requireApiKey(
|
|
528
|
-
const registryUrl = await getRegistryUrl(
|
|
499
|
+
const apiKey = await requireApiKey();
|
|
500
|
+
const registryUrl = await getRegistryUrl();
|
|
529
501
|
const parsed = parseSkillSpecifier(specifier);
|
|
530
502
|
if (!parsed) {
|
|
531
503
|
console.error(
|
|
@@ -534,9 +506,17 @@ async function add(specifier, _options, globalOptions) {
|
|
|
534
506
|
process.exit(1);
|
|
535
507
|
}
|
|
536
508
|
const { username, name, versionRange } = parsed;
|
|
537
|
-
|
|
509
|
+
configure2({ registryUrl, apiKey });
|
|
538
510
|
console.log(`Resolving ${specifier}...`);
|
|
539
511
|
const versionsResponse = await listSkillVersions(username, name);
|
|
512
|
+
if (versionsResponse.status !== 200) {
|
|
513
|
+
const errorMessage = extractApiErrorMessage(
|
|
514
|
+
versionsResponse,
|
|
515
|
+
`Skill @user/${username}/${name} not found`
|
|
516
|
+
);
|
|
517
|
+
console.error(`Error: ${errorMessage}`);
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
540
520
|
const versions = versionsResponse.data;
|
|
541
521
|
if (versions.length === 0) {
|
|
542
522
|
console.error(`Error: Skill @user/${username}/${name} not found`);
|
|
@@ -553,14 +533,18 @@ async function add(specifier, _options, globalOptions) {
|
|
|
553
533
|
}
|
|
554
534
|
console.log(`Installing @user/${username}/${name}@${resolved}...`);
|
|
555
535
|
const versionResponse = await getSkillVersion(username, name, resolved);
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
536
|
+
if (versionResponse.status !== 200 || !versionResponse.data) {
|
|
537
|
+
const errorMessage = extractApiErrorMessage(
|
|
538
|
+
versionResponse,
|
|
539
|
+
`Version ${resolved} not found`
|
|
540
|
+
);
|
|
541
|
+
console.error(`Error: ${errorMessage}`);
|
|
559
542
|
process.exit(1);
|
|
560
543
|
}
|
|
561
|
-
const
|
|
562
|
-
const
|
|
563
|
-
|
|
544
|
+
const versionInfo = versionResponse.data;
|
|
545
|
+
const isPresignedUrl = versionInfo.downloadUrl.includes(".r2.cloudflarestorage.com") || versionInfo.downloadUrl.includes("X-Amz-Signature");
|
|
546
|
+
const tarballResponse = await fetch(versionInfo.downloadUrl, {
|
|
547
|
+
headers: isPresignedUrl ? {} : {
|
|
564
548
|
Authorization: `Bearer ${apiKey}`
|
|
565
549
|
},
|
|
566
550
|
redirect: "follow"
|
|
@@ -611,68 +595,6 @@ async function add(specifier, _options, globalOptions) {
|
|
|
611
595
|
process.exit(1);
|
|
612
596
|
}
|
|
613
597
|
}
|
|
614
|
-
|
|
615
|
-
// src/commands/config/add.ts
|
|
616
|
-
async function configAdd(name, options) {
|
|
617
|
-
try {
|
|
618
|
-
const existing = await getProfile(name);
|
|
619
|
-
if (existing) {
|
|
620
|
-
console.error(`Error: Profile "${name}" already exists.`);
|
|
621
|
-
console.log("Use 'pspm config set' to modify it.");
|
|
622
|
-
process.exit(1);
|
|
623
|
-
}
|
|
624
|
-
await setProfile(name, {
|
|
625
|
-
registryUrl: options.registryUrl || "https://pspm.dev/api/skills"
|
|
626
|
-
});
|
|
627
|
-
console.log(`Created profile "${name}".`);
|
|
628
|
-
if (options.registryUrl) {
|
|
629
|
-
console.log(` Registry URL: ${options.registryUrl}`);
|
|
630
|
-
}
|
|
631
|
-
console.log("");
|
|
632
|
-
console.log(
|
|
633
|
-
`To set credentials, run: pspm login --api-key <key> --profile ${name}`
|
|
634
|
-
);
|
|
635
|
-
console.log(`To make this the default, run: pspm config use ${name}`);
|
|
636
|
-
} catch (error) {
|
|
637
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
638
|
-
console.error(`Error: ${message}`);
|
|
639
|
-
process.exit(1);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// src/commands/config/delete.ts
|
|
644
|
-
async function configDelete(name) {
|
|
645
|
-
try {
|
|
646
|
-
const profiles = await listProfiles();
|
|
647
|
-
const defaultProfile = await getDefaultProfileName();
|
|
648
|
-
if (!profiles.includes(name)) {
|
|
649
|
-
console.error(`Error: Profile "${name}" not found.`);
|
|
650
|
-
console.log("Run 'pspm config list' to see available profiles.");
|
|
651
|
-
process.exit(1);
|
|
652
|
-
}
|
|
653
|
-
if (profiles.length === 1) {
|
|
654
|
-
console.error("Error: Cannot delete the last profile.");
|
|
655
|
-
console.log("Create another profile first, then delete this one.");
|
|
656
|
-
process.exit(1);
|
|
657
|
-
}
|
|
658
|
-
const wasDefault = name === defaultProfile;
|
|
659
|
-
const success = await deleteProfile(name);
|
|
660
|
-
if (success) {
|
|
661
|
-
console.log(`Deleted profile "${name}".`);
|
|
662
|
-
if (wasDefault) {
|
|
663
|
-
const newDefault = await getDefaultProfileName();
|
|
664
|
-
console.log(`Default profile is now "${newDefault}".`);
|
|
665
|
-
}
|
|
666
|
-
} else {
|
|
667
|
-
console.error(`Error: Failed to delete profile "${name}".`);
|
|
668
|
-
process.exit(1);
|
|
669
|
-
}
|
|
670
|
-
} catch (error) {
|
|
671
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
672
|
-
console.error(`Error: ${message}`);
|
|
673
|
-
process.exit(1);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
598
|
async function configInit(options) {
|
|
677
599
|
try {
|
|
678
600
|
const configPath = join(process.cwd(), ".pspmrc");
|
|
@@ -682,23 +604,19 @@ async function configInit(options) {
|
|
|
682
604
|
process.exit(1);
|
|
683
605
|
} catch {
|
|
684
606
|
}
|
|
685
|
-
const
|
|
686
|
-
if (options.
|
|
687
|
-
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
if (Object.keys(config2).length === 0) {
|
|
693
|
-
config2.profile = "development";
|
|
607
|
+
const lines = ["; Project-specific PSPM configuration", ""];
|
|
608
|
+
if (options.registry) {
|
|
609
|
+
lines.push(`registry = ${options.registry}`);
|
|
610
|
+
} else {
|
|
611
|
+
lines.push("; Uncomment to use a custom registry:");
|
|
612
|
+
lines.push("; registry = https://custom-registry.example.com");
|
|
694
613
|
}
|
|
695
|
-
|
|
696
|
-
|
|
614
|
+
lines.push("");
|
|
615
|
+
await writeFile(configPath, lines.join("\n"));
|
|
697
616
|
console.log("Created .pspmrc");
|
|
698
617
|
console.log("");
|
|
699
618
|
console.log("Contents:");
|
|
700
|
-
console.log(
|
|
701
|
-
console.log("");
|
|
619
|
+
console.log(lines.join("\n"));
|
|
702
620
|
console.log("Note: .pspmrc should be committed to version control.");
|
|
703
621
|
console.log("API keys should NOT be stored here - use pspm login instead.");
|
|
704
622
|
} catch (error) {
|
|
@@ -708,129 +626,38 @@ async function configInit(options) {
|
|
|
708
626
|
}
|
|
709
627
|
}
|
|
710
628
|
|
|
711
|
-
// src/commands/config/list.ts
|
|
712
|
-
async function configList() {
|
|
713
|
-
try {
|
|
714
|
-
const profiles = await listProfiles();
|
|
715
|
-
const defaultProfile = await getDefaultProfileName();
|
|
716
|
-
if (profiles.length === 0) {
|
|
717
|
-
console.log("No profiles configured.");
|
|
718
|
-
console.log("Run 'pspm config add <name>' to create one.");
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
console.log("Profiles:\n");
|
|
722
|
-
for (const name of profiles) {
|
|
723
|
-
const marker = name === defaultProfile ? " (default)" : "";
|
|
724
|
-
console.log(` ${name}${marker}`);
|
|
725
|
-
}
|
|
726
|
-
console.log("");
|
|
727
|
-
} catch (error) {
|
|
728
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
729
|
-
console.error(`Error: ${message}`);
|
|
730
|
-
process.exit(1);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// src/commands/config/set.ts
|
|
735
|
-
var VALID_KEYS = ["registryUrl", "apiKey", "username"];
|
|
736
|
-
async function configSet(profile, key, value) {
|
|
737
|
-
try {
|
|
738
|
-
if (!VALID_KEYS.includes(key)) {
|
|
739
|
-
console.error(`Error: Invalid key "${key}".`);
|
|
740
|
-
console.log(`Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
741
|
-
process.exit(1);
|
|
742
|
-
}
|
|
743
|
-
const existing = await getProfile(profile);
|
|
744
|
-
if (!existing) {
|
|
745
|
-
console.error(`Error: Profile "${profile}" not found.`);
|
|
746
|
-
console.log("Run 'pspm config add' to create it first.");
|
|
747
|
-
process.exit(1);
|
|
748
|
-
}
|
|
749
|
-
await setProfile(profile, { [key]: value });
|
|
750
|
-
console.log(`Updated ${key} for profile "${profile}".`);
|
|
751
|
-
} catch (error) {
|
|
752
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
753
|
-
console.error(`Error: ${message}`);
|
|
754
|
-
process.exit(1);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
629
|
// src/commands/config/show.ts
|
|
759
|
-
async function configShow(
|
|
760
|
-
try {
|
|
761
|
-
if (options.name) {
|
|
762
|
-
const profile = await getProfile(options.name);
|
|
763
|
-
if (!profile) {
|
|
764
|
-
console.error(`Error: Profile "${options.name}" not found.`);
|
|
765
|
-
console.log("Run 'pspm config list' to see available profiles.");
|
|
766
|
-
process.exit(1);
|
|
767
|
-
}
|
|
768
|
-
const defaultProfile = await getDefaultProfileName();
|
|
769
|
-
const isDefault = options.name === defaultProfile;
|
|
770
|
-
console.log(`Profile: ${options.name}${isDefault ? " (default)" : ""}
|
|
771
|
-
`);
|
|
772
|
-
console.log(` Registry URL: ${profile.registryUrl}`);
|
|
773
|
-
console.log(` API Key: ${profile.apiKey ? "***" : "(not set)"}`);
|
|
774
|
-
console.log(` Username: ${profile.username || "(not set)"}`);
|
|
775
|
-
} else {
|
|
776
|
-
const resolved = await resolveConfig(globalOptions);
|
|
777
|
-
const projectConfig = await findProjectConfig();
|
|
778
|
-
const configPath = getConfigPath();
|
|
779
|
-
console.log("Resolved Configuration:\n");
|
|
780
|
-
console.log(` Active Profile: ${resolved.profileName}`);
|
|
781
|
-
console.log(` Profile Source: ${formatSource(resolved.profileSource)}`);
|
|
782
|
-
console.log(` Registry URL: ${resolved.registryUrl}`);
|
|
783
|
-
console.log(` API Key: ${resolved.apiKey ? "***" : "(not set)"}`);
|
|
784
|
-
console.log(` Username: ${resolved.username || "(not set)"}`);
|
|
785
|
-
console.log("");
|
|
786
|
-
console.log("Config Locations:");
|
|
787
|
-
console.log(` User config: ${configPath}`);
|
|
788
|
-
console.log(` Project config: ${projectConfig ? ".pspmrc" : "(none)"}`);
|
|
789
|
-
}
|
|
790
|
-
} catch (error) {
|
|
791
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
792
|
-
console.error(`Error: ${message}`);
|
|
793
|
-
process.exit(1);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
function formatSource(source) {
|
|
797
|
-
switch (source) {
|
|
798
|
-
case "cli":
|
|
799
|
-
return "--profile flag";
|
|
800
|
-
case "env":
|
|
801
|
-
return "PSPM_PROFILE env var";
|
|
802
|
-
case "project":
|
|
803
|
-
return ".pspmrc file";
|
|
804
|
-
case "user":
|
|
805
|
-
return "user config default";
|
|
806
|
-
case "default":
|
|
807
|
-
return "fallback default";
|
|
808
|
-
default:
|
|
809
|
-
return source;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// src/commands/config/use.ts
|
|
814
|
-
async function configUse(name) {
|
|
630
|
+
async function configShow() {
|
|
815
631
|
try {
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
console.log(
|
|
632
|
+
const resolved = await resolveConfig();
|
|
633
|
+
const projectConfig = await findProjectConfig();
|
|
634
|
+
const configPath = getConfigPath();
|
|
635
|
+
console.log("Resolved Configuration:\n");
|
|
636
|
+
console.log(` Registry URL: ${resolved.registryUrl}`);
|
|
637
|
+
console.log(` API Key: ${resolved.apiKey ? "***" : "(not set)"}`);
|
|
638
|
+
console.log(` Username: ${resolved.username || "(not set)"}`);
|
|
639
|
+
console.log("");
|
|
640
|
+
console.log("Config Locations:");
|
|
641
|
+
console.log(` User config: ${configPath}`);
|
|
642
|
+
console.log(` Project config: ${projectConfig ? ".pspmrc" : "(none)"}`);
|
|
643
|
+
console.log("");
|
|
644
|
+
console.log("Environment Variables:");
|
|
645
|
+
console.log(
|
|
646
|
+
` PSPM_REGISTRY_URL: ${process.env.PSPM_REGISTRY_URL || "(not set)"}`
|
|
647
|
+
);
|
|
648
|
+
console.log(
|
|
649
|
+
` PSPM_API_KEY: ${process.env.PSPM_API_KEY ? "***" : "(not set)"}`
|
|
650
|
+
);
|
|
824
651
|
} catch (error) {
|
|
825
652
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
826
653
|
console.error(`Error: ${message}`);
|
|
827
654
|
process.exit(1);
|
|
828
655
|
}
|
|
829
656
|
}
|
|
830
|
-
async function install(options
|
|
657
|
+
async function install(options) {
|
|
831
658
|
try {
|
|
832
|
-
const apiKey = await requireApiKey(
|
|
833
|
-
await getRegistryUrl(
|
|
659
|
+
const apiKey = await requireApiKey();
|
|
660
|
+
await getRegistryUrl();
|
|
834
661
|
const skillsDir = options.dir || getSkillsDir();
|
|
835
662
|
const lockfile = await readLockfile();
|
|
836
663
|
if (!lockfile) {
|
|
@@ -859,8 +686,9 @@ async function install(options, globalOptions) {
|
|
|
859
686
|
}
|
|
860
687
|
const [, username, name] = match;
|
|
861
688
|
console.log(`Installing ${fullName}@${entry.version}...`);
|
|
689
|
+
const isPresignedUrl = entry.resolved.includes(".r2.cloudflarestorage.com") || entry.resolved.includes("X-Amz-Signature");
|
|
862
690
|
const response = await fetch(entry.resolved, {
|
|
863
|
-
headers: {
|
|
691
|
+
headers: isPresignedUrl ? {} : {
|
|
864
692
|
Authorization: `Bearer ${apiKey}`
|
|
865
693
|
},
|
|
866
694
|
redirect: "follow"
|
|
@@ -872,8 +700,8 @@ async function install(options, globalOptions) {
|
|
|
872
700
|
continue;
|
|
873
701
|
}
|
|
874
702
|
const tarballBuffer = Buffer.from(await response.arrayBuffer());
|
|
875
|
-
const { createHash:
|
|
876
|
-
const actualIntegrity = `sha256-${
|
|
703
|
+
const { createHash: createHash3 } = await import('crypto');
|
|
704
|
+
const actualIntegrity = `sha256-${createHash3("sha256").update(tarballBuffer).digest("base64")}`;
|
|
877
705
|
if (actualIntegrity !== entry.integrity) {
|
|
878
706
|
console.error(` Error: Checksum verification failed for ${fullName}`);
|
|
879
707
|
if (options.frozenLockfile) {
|
|
@@ -1070,9 +898,8 @@ function startCallbackServer(expectedState) {
|
|
|
1070
898
|
);
|
|
1071
899
|
});
|
|
1072
900
|
}
|
|
1073
|
-
async function browserLogin(
|
|
1074
|
-
const
|
|
1075
|
-
const registryUrl = await getRegistryUrl(globalOptions);
|
|
901
|
+
async function browserLogin() {
|
|
902
|
+
const registryUrl = await getRegistryUrl();
|
|
1076
903
|
const webAppUrl = getWebAppUrl(registryUrl);
|
|
1077
904
|
const state = randomBytes(32).toString("base64url");
|
|
1078
905
|
console.log("Starting browser-based login...");
|
|
@@ -1091,41 +918,28 @@ async function browserLogin(globalOptions) {
|
|
|
1091
918
|
cleanup();
|
|
1092
919
|
console.log("Received token, exchanging for API key...");
|
|
1093
920
|
const { apiKey, username } = await exchangeCliToken2(registryUrl, token);
|
|
1094
|
-
await
|
|
1095
|
-
resolved.profileName,
|
|
1096
|
-
apiKey,
|
|
1097
|
-
username,
|
|
1098
|
-
registryUrl
|
|
1099
|
-
);
|
|
921
|
+
await setCredentials(apiKey, username, registryUrl);
|
|
1100
922
|
console.log(`Logged in as ${username}`);
|
|
1101
|
-
console.log(`Profile: ${resolved.profileName}`);
|
|
1102
923
|
console.log(`Registry: ${registryUrl}`);
|
|
1103
924
|
}
|
|
1104
|
-
async function directLogin(apiKey
|
|
925
|
+
async function directLogin(apiKey) {
|
|
1105
926
|
console.log("Verifying API key...");
|
|
1106
|
-
const
|
|
1107
|
-
const registryUrl = await getRegistryUrl(globalOptions);
|
|
927
|
+
const registryUrl = await getRegistryUrl();
|
|
1108
928
|
const user = await whoamiRequest(registryUrl, apiKey);
|
|
1109
929
|
if (!user) {
|
|
1110
930
|
console.error("Error: Invalid API key or not authenticated");
|
|
1111
931
|
process.exit(1);
|
|
1112
932
|
}
|
|
1113
|
-
await
|
|
1114
|
-
resolved.profileName,
|
|
1115
|
-
apiKey,
|
|
1116
|
-
user.username,
|
|
1117
|
-
registryUrl
|
|
1118
|
-
);
|
|
933
|
+
await setCredentials(apiKey, user.username, registryUrl);
|
|
1119
934
|
console.log(`Logged in as ${user.username}`);
|
|
1120
|
-
console.log(`Profile: ${resolved.profileName}`);
|
|
1121
935
|
console.log(`Registry: ${registryUrl}`);
|
|
1122
936
|
}
|
|
1123
|
-
async function login(options
|
|
937
|
+
async function login(options) {
|
|
1124
938
|
try {
|
|
1125
939
|
if (options.apiKey) {
|
|
1126
|
-
await directLogin(options.apiKey
|
|
940
|
+
await directLogin(options.apiKey);
|
|
1127
941
|
} else {
|
|
1128
|
-
await browserLogin(
|
|
942
|
+
await browserLogin();
|
|
1129
943
|
}
|
|
1130
944
|
} catch (error) {
|
|
1131
945
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -1135,16 +949,15 @@ async function login(options, globalOptions) {
|
|
|
1135
949
|
}
|
|
1136
950
|
|
|
1137
951
|
// src/commands/logout.ts
|
|
1138
|
-
async function logout(
|
|
952
|
+
async function logout() {
|
|
1139
953
|
try {
|
|
1140
|
-
const
|
|
1141
|
-
const loggedIn = await isLoggedIn(globalOptions);
|
|
954
|
+
const loggedIn = await isLoggedIn();
|
|
1142
955
|
if (!loggedIn) {
|
|
1143
|
-
console.log(
|
|
956
|
+
console.log("Not logged in.");
|
|
1144
957
|
return;
|
|
1145
958
|
}
|
|
1146
|
-
await
|
|
1147
|
-
console.log(
|
|
959
|
+
await clearCredentials();
|
|
960
|
+
console.log("Logged out successfully.");
|
|
1148
961
|
} catch (error) {
|
|
1149
962
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1150
963
|
console.error(`Error: ${message}`);
|
|
@@ -1152,10 +965,37 @@ async function logout(globalOptions) {
|
|
|
1152
965
|
}
|
|
1153
966
|
}
|
|
1154
967
|
var exec = promisify(exec$1);
|
|
1155
|
-
|
|
968
|
+
function formatBytes(bytes) {
|
|
969
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
970
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}kB`;
|
|
971
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
972
|
+
}
|
|
973
|
+
async function getFilesWithSizes(dir, baseDir) {
|
|
974
|
+
const results = [];
|
|
975
|
+
try {
|
|
976
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
977
|
+
for (const entry of entries) {
|
|
978
|
+
const fullPath = join(dir, entry.name);
|
|
979
|
+
const relativePath = relative(baseDir, fullPath);
|
|
980
|
+
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
if (entry.isDirectory()) {
|
|
984
|
+
const subFiles = await getFilesWithSizes(fullPath, baseDir);
|
|
985
|
+
results.push(...subFiles);
|
|
986
|
+
} else {
|
|
987
|
+
const fileStat = await stat(fullPath);
|
|
988
|
+
results.push({ path: relativePath, size: fileStat.size });
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
} catch {
|
|
992
|
+
}
|
|
993
|
+
return results;
|
|
994
|
+
}
|
|
995
|
+
async function publishCommand(options) {
|
|
1156
996
|
try {
|
|
1157
|
-
const apiKey = await requireApiKey(
|
|
1158
|
-
const registryUrl = await getRegistryUrl(
|
|
997
|
+
const apiKey = await requireApiKey();
|
|
998
|
+
const registryUrl = await getRegistryUrl();
|
|
1159
999
|
const packageJsonPath = join(process.cwd(), "package.json");
|
|
1160
1000
|
let packageJson2;
|
|
1161
1001
|
try {
|
|
@@ -1185,8 +1025,6 @@ async function publishCommand(options, globalOptions) {
|
|
|
1185
1025
|
packageJson2.version = newVersion;
|
|
1186
1026
|
console.log(`Bumped version to ${newVersion}`);
|
|
1187
1027
|
}
|
|
1188
|
-
console.log(`Registry: ${registryUrl}`);
|
|
1189
|
-
console.log(`Publishing ${packageJson2.name}@${packageJson2.version}...`);
|
|
1190
1028
|
const safeName = packageJson2.name.replace(/[@/]/g, "-").replace(/^-+/, "");
|
|
1191
1029
|
const tarballName = `${safeName}-${packageJson2.version}.tgz`;
|
|
1192
1030
|
const tempDir = join(process.cwd(), ".pspm-publish");
|
|
@@ -1209,26 +1047,60 @@ async function publishCommand(options, globalOptions) {
|
|
|
1209
1047
|
}
|
|
1210
1048
|
}
|
|
1211
1049
|
await exec(`cp package.json "${tempDir}/package/"`);
|
|
1050
|
+
const packageDir = join(tempDir, "package");
|
|
1051
|
+
const tarballContents = await getFilesWithSizes(packageDir, packageDir);
|
|
1052
|
+
const unpackedSize = tarballContents.reduce((acc, f) => acc + f.size, 0);
|
|
1212
1053
|
const tarballPath = join(tempDir, tarballName);
|
|
1213
1054
|
await exec(
|
|
1214
1055
|
`tar -czf "${tarballPath}" -C "${tempDir}" --exclude='node_modules' --exclude='.git' package`
|
|
1215
1056
|
);
|
|
1216
1057
|
const tarballBuffer = await readFile(tarballPath);
|
|
1217
1058
|
const tarballBase64 = tarballBuffer.toString("base64");
|
|
1218
|
-
|
|
1059
|
+
const tarballSize = tarballBuffer.length;
|
|
1060
|
+
const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
|
|
1061
|
+
const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
|
|
1062
|
+
const integrity = `sha512-${integrityHash}`;
|
|
1063
|
+
console.log("");
|
|
1064
|
+
console.log(`pspm notice`);
|
|
1065
|
+
console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
|
|
1066
|
+
console.log(`pspm notice Tarball Contents`);
|
|
1067
|
+
tarballContents.sort((a, b) => b.size - a.size);
|
|
1068
|
+
for (const file of tarballContents) {
|
|
1069
|
+
console.log(
|
|
1070
|
+
`pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
console.log(`pspm notice Tarball Details`);
|
|
1074
|
+
console.log(`pspm notice name: ${packageJson2.name}`);
|
|
1075
|
+
console.log(`pspm notice version: ${packageJson2.version}`);
|
|
1076
|
+
console.log(`pspm notice filename: ${tarballName}`);
|
|
1077
|
+
console.log(`pspm notice package size: ${formatBytes(tarballSize)}`);
|
|
1078
|
+
console.log(`pspm notice unpacked size: ${formatBytes(unpackedSize)}`);
|
|
1079
|
+
console.log(`pspm notice shasum: ${shasum}`);
|
|
1080
|
+
console.log(
|
|
1081
|
+
`pspm notice integrity: ${integrity.substring(0, 50)}...`
|
|
1082
|
+
);
|
|
1083
|
+
console.log(`pspm notice total files: ${tarballContents.length}`);
|
|
1084
|
+
console.log(`pspm notice`);
|
|
1085
|
+
console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
|
|
1086
|
+
configure2({ registryUrl, apiKey });
|
|
1219
1087
|
const response = await publishSkill({
|
|
1220
1088
|
manifest: packageJson2,
|
|
1221
1089
|
tarballBase64
|
|
1222
1090
|
});
|
|
1223
1091
|
if (response.status !== 200) {
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1092
|
+
const errorMessage = extractApiErrorMessage(response, "Publish failed");
|
|
1093
|
+
if (errorMessage.includes("must be greater than") || errorMessage.includes("already exists")) {
|
|
1094
|
+
console.error(`pspm error code E403`);
|
|
1095
|
+
console.error(
|
|
1096
|
+
`pspm error 403 403 Forbidden - You cannot publish over the previously published versions: ${packageJson2.version}.`
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1226
1099
|
throw new Error(errorMessage);
|
|
1227
1100
|
}
|
|
1228
1101
|
const result = response.data;
|
|
1229
1102
|
console.log(
|
|
1230
|
-
`
|
|
1231
|
-
Published @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
|
|
1103
|
+
`+ @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
|
|
1232
1104
|
);
|
|
1233
1105
|
console.log(`Checksum: ${result.version.checksum}`);
|
|
1234
1106
|
} finally {
|
|
@@ -1238,37 +1110,9 @@ Published @user/${result.skill.username}/${result.skill.name}@${result.version.v
|
|
|
1238
1110
|
} catch (error) {
|
|
1239
1111
|
if (error instanceof Error) {
|
|
1240
1112
|
console.error(`Error: ${error.message}`);
|
|
1241
|
-
const anyError = error;
|
|
1242
|
-
if (anyError.cause?.response) {
|
|
1243
|
-
try {
|
|
1244
|
-
const text = await anyError.cause.response.text();
|
|
1245
|
-
console.error(`Response body: ${text}`);
|
|
1246
|
-
} catch {
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
if (anyError.cause?.body) {
|
|
1250
|
-
console.error(
|
|
1251
|
-
`Cause body: ${JSON.stringify(anyError.cause.body, null, 2)}`
|
|
1252
|
-
);
|
|
1253
|
-
}
|
|
1254
|
-
if (anyError.body) {
|
|
1255
|
-
console.error(`Error body: ${JSON.stringify(anyError.body, null, 2)}`);
|
|
1256
|
-
}
|
|
1257
|
-
if (anyError.data) {
|
|
1258
|
-
console.error(`Error data: ${JSON.stringify(anyError.data, null, 2)}`);
|
|
1259
|
-
}
|
|
1260
|
-
if (process.env.PSPM_DEBUG) {
|
|
1261
|
-
console.error("\nFull error details:");
|
|
1262
|
-
console.error(error);
|
|
1263
|
-
if (error.stack) {
|
|
1264
|
-
console.error("\nStack trace:");
|
|
1265
|
-
console.error(error.stack);
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
1113
|
} else {
|
|
1269
1114
|
console.error(`Error: ${String(error)}`);
|
|
1270
1115
|
}
|
|
1271
|
-
console.error("\nTip: Set PSPM_DEBUG=1 for more detailed error output");
|
|
1272
1116
|
process.exit(1);
|
|
1273
1117
|
}
|
|
1274
1118
|
}
|
|
@@ -1329,10 +1173,10 @@ async function remove(nameOrSpecifier) {
|
|
|
1329
1173
|
}
|
|
1330
1174
|
|
|
1331
1175
|
// src/commands/unpublish.ts
|
|
1332
|
-
async function unpublish(specifier, options
|
|
1176
|
+
async function unpublish(specifier, options) {
|
|
1333
1177
|
try {
|
|
1334
|
-
const apiKey = await requireApiKey(
|
|
1335
|
-
const registryUrl = await getRegistryUrl(
|
|
1178
|
+
const apiKey = await requireApiKey();
|
|
1179
|
+
const registryUrl = await getRegistryUrl();
|
|
1336
1180
|
const parsed = parseSkillSpecifier(specifier);
|
|
1337
1181
|
if (!parsed) {
|
|
1338
1182
|
console.error(
|
|
@@ -1341,7 +1185,7 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1341
1185
|
process.exit(1);
|
|
1342
1186
|
}
|
|
1343
1187
|
const { username, name, versionRange } = parsed;
|
|
1344
|
-
|
|
1188
|
+
configure2({ registryUrl, apiKey });
|
|
1345
1189
|
if (versionRange) {
|
|
1346
1190
|
console.log(`Unpublishing ${specifier}...`);
|
|
1347
1191
|
if (!options.force) {
|
|
@@ -1352,8 +1196,10 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1352
1196
|
}
|
|
1353
1197
|
const response = await deleteSkillVersion(name, versionRange);
|
|
1354
1198
|
if (response.status !== 200) {
|
|
1355
|
-
const
|
|
1356
|
-
|
|
1199
|
+
const errorMessage = extractApiErrorMessage(
|
|
1200
|
+
response,
|
|
1201
|
+
"Failed to unpublish. Version may not exist."
|
|
1202
|
+
);
|
|
1357
1203
|
console.error(`Error: ${errorMessage}`);
|
|
1358
1204
|
process.exit(1);
|
|
1359
1205
|
}
|
|
@@ -1368,8 +1214,10 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1368
1214
|
}
|
|
1369
1215
|
const response = await deleteSkill(name);
|
|
1370
1216
|
if (response.status !== 200) {
|
|
1371
|
-
const
|
|
1372
|
-
|
|
1217
|
+
const errorMessage = extractApiErrorMessage(
|
|
1218
|
+
response,
|
|
1219
|
+
"Failed to unpublish. Skill may not exist."
|
|
1220
|
+
);
|
|
1373
1221
|
console.error(`Error: ${errorMessage}`);
|
|
1374
1222
|
process.exit(1);
|
|
1375
1223
|
}
|
|
@@ -1383,16 +1231,16 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1383
1231
|
}
|
|
1384
1232
|
|
|
1385
1233
|
// src/commands/update.ts
|
|
1386
|
-
async function update(options
|
|
1234
|
+
async function update(options) {
|
|
1387
1235
|
try {
|
|
1388
|
-
const apiKey = await requireApiKey(
|
|
1389
|
-
const registryUrl = await getRegistryUrl(
|
|
1236
|
+
const apiKey = await requireApiKey();
|
|
1237
|
+
const registryUrl = await getRegistryUrl();
|
|
1390
1238
|
const skills = await listLockfileSkills();
|
|
1391
1239
|
if (skills.length === 0) {
|
|
1392
1240
|
console.log("No skills installed.");
|
|
1393
1241
|
return;
|
|
1394
1242
|
}
|
|
1395
|
-
|
|
1243
|
+
configure2({ registryUrl, apiKey });
|
|
1396
1244
|
const updates = [];
|
|
1397
1245
|
console.log("Checking for updates...\n");
|
|
1398
1246
|
for (const { name, entry } of skills) {
|
|
@@ -1401,6 +1249,14 @@ async function update(options, globalOptions) {
|
|
|
1401
1249
|
const [, username, skillName] = match;
|
|
1402
1250
|
try {
|
|
1403
1251
|
const versionsResponse = await listSkillVersions(username, skillName);
|
|
1252
|
+
if (versionsResponse.status !== 200) {
|
|
1253
|
+
const errorMessage = extractApiErrorMessage(
|
|
1254
|
+
versionsResponse,
|
|
1255
|
+
"Failed to fetch versions"
|
|
1256
|
+
);
|
|
1257
|
+
console.warn(` Warning: ${name}: ${errorMessage}`);
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1404
1260
|
const versions = versionsResponse.data;
|
|
1405
1261
|
if (versions.length === 0) continue;
|
|
1406
1262
|
const versionStrings = versions.map(
|
|
@@ -1436,7 +1292,7 @@ async function update(options, globalOptions) {
|
|
|
1436
1292
|
if (!match) continue;
|
|
1437
1293
|
const [, username, skillName] = match;
|
|
1438
1294
|
const specifier = `@user/${username}/${skillName}@${latest}`;
|
|
1439
|
-
await add(specifier, {}
|
|
1295
|
+
await add(specifier, {});
|
|
1440
1296
|
}
|
|
1441
1297
|
console.log("\nAll skills updated.");
|
|
1442
1298
|
} catch (error) {
|
|
@@ -1447,21 +1303,19 @@ async function update(options, globalOptions) {
|
|
|
1447
1303
|
}
|
|
1448
1304
|
|
|
1449
1305
|
// src/commands/whoami.ts
|
|
1450
|
-
async function whoami(
|
|
1306
|
+
async function whoami() {
|
|
1451
1307
|
try {
|
|
1452
|
-
const resolved = await resolveConfig(
|
|
1453
|
-
const apiKey = await requireApiKey(
|
|
1454
|
-
const registryUrl = await getRegistryUrl(
|
|
1308
|
+
const resolved = await resolveConfig();
|
|
1309
|
+
const apiKey = await requireApiKey();
|
|
1310
|
+
const registryUrl = await getRegistryUrl();
|
|
1455
1311
|
const user = await whoamiRequest(registryUrl, apiKey);
|
|
1456
1312
|
if (user) {
|
|
1457
1313
|
console.log(`Username: ${user.username}`);
|
|
1458
1314
|
console.log(`User ID: ${user.userId}`);
|
|
1459
1315
|
console.log(`Registry: ${registryUrl}`);
|
|
1460
|
-
console.log(`Profile: ${resolved.profileName}`);
|
|
1461
1316
|
} else if (resolved.username) {
|
|
1462
1317
|
console.log(`Username: ${resolved.username} (cached)`);
|
|
1463
1318
|
console.log(`Registry: ${registryUrl}`);
|
|
1464
|
-
console.log(`Profile: ${resolved.profileName}`);
|
|
1465
1319
|
} else {
|
|
1466
1320
|
console.error("Could not determine current user.");
|
|
1467
1321
|
process.exit(1);
|
|
@@ -1480,61 +1334,30 @@ var packageJson = JSON.parse(
|
|
|
1480
1334
|
);
|
|
1481
1335
|
var version = packageJson.version;
|
|
1482
1336
|
var program = new Command();
|
|
1483
|
-
program.name("pspm").description("Prompt Skill Package Manager for AnyT").version(version)
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
current = current.parent;
|
|
1488
|
-
}
|
|
1489
|
-
const opts = current.opts();
|
|
1490
|
-
return {
|
|
1491
|
-
profile: opts.profile
|
|
1492
|
-
};
|
|
1493
|
-
}
|
|
1494
|
-
var configCmd = program.command("config").description("Manage PSPM configuration and profiles");
|
|
1495
|
-
configCmd.command("list").description("List all profiles").action(async () => {
|
|
1496
|
-
await configList();
|
|
1497
|
-
});
|
|
1498
|
-
configCmd.command("show [name]").description("Show resolved config or a specific profile").action(async (name, _options, cmd) => {
|
|
1499
|
-
const globalOptions = getGlobalOptions(cmd);
|
|
1500
|
-
await configShow({ name }, globalOptions);
|
|
1501
|
-
});
|
|
1502
|
-
configCmd.command("add <name>").description("Create a new profile").option("--registry-url <url>", "Registry URL for the profile").action(async (name, options) => {
|
|
1503
|
-
await configAdd(name, { registryUrl: options.registryUrl });
|
|
1504
|
-
});
|
|
1505
|
-
configCmd.command("use <name>").description("Set the default profile").action(async (name) => {
|
|
1506
|
-
await configUse(name);
|
|
1507
|
-
});
|
|
1508
|
-
configCmd.command("set <profile> <key> <value>").description("Set a profile field (registryUrl, apiKey, username)").action(async (profile, key, value) => {
|
|
1509
|
-
await configSet(profile, key, value);
|
|
1510
|
-
});
|
|
1511
|
-
configCmd.command("delete <name>").description("Delete a profile").action(async (name) => {
|
|
1512
|
-
await configDelete(name);
|
|
1337
|
+
program.name("pspm").description("Prompt Skill Package Manager for AnyT").version(version);
|
|
1338
|
+
var configCmd = program.command("config").description("Manage PSPM configuration");
|
|
1339
|
+
configCmd.command("show").description("Show resolved configuration").action(async () => {
|
|
1340
|
+
await configShow();
|
|
1513
1341
|
});
|
|
1514
|
-
configCmd.command("init").description("Create a .pspmrc file in the current directory").option("--
|
|
1342
|
+
configCmd.command("init").description("Create a .pspmrc file in the current directory").option("--registry <url>", "Registry URL override").action(async (options) => {
|
|
1515
1343
|
await configInit({
|
|
1516
|
-
|
|
1517
|
-
registryUrl: options.registryUrl
|
|
1344
|
+
registry: options.registry
|
|
1518
1345
|
});
|
|
1519
1346
|
});
|
|
1520
1347
|
program.command("login").description("Log in via browser or with an API key").option(
|
|
1521
1348
|
"--api-key <key>",
|
|
1522
1349
|
"API key for direct authentication (skips browser)"
|
|
1523
|
-
).action(async (options
|
|
1524
|
-
|
|
1525
|
-
await login({ apiKey: options.apiKey }, globalOptions);
|
|
1350
|
+
).action(async (options) => {
|
|
1351
|
+
await login({ apiKey: options.apiKey });
|
|
1526
1352
|
});
|
|
1527
|
-
program.command("logout").description("Log out and clear stored credentials").action(async (
|
|
1528
|
-
|
|
1529
|
-
await logout(globalOptions);
|
|
1353
|
+
program.command("logout").description("Log out and clear stored credentials").action(async () => {
|
|
1354
|
+
await logout();
|
|
1530
1355
|
});
|
|
1531
|
-
program.command("whoami").description("Show current user information").action(async (
|
|
1532
|
-
|
|
1533
|
-
await whoami(globalOptions);
|
|
1356
|
+
program.command("whoami").description("Show current user information").action(async () => {
|
|
1357
|
+
await whoami();
|
|
1534
1358
|
});
|
|
1535
|
-
program.command("add <specifier>").description("Add a skill (e.g., @user/bsheng/vite_slides@^2.0.0)").option("--save", "Save to lockfile (default)").action(async (specifier, options
|
|
1536
|
-
|
|
1537
|
-
await add(specifier, { save: options.save ?? true }, globalOptions);
|
|
1359
|
+
program.command("add <specifier>").description("Add a skill (e.g., @user/bsheng/vite_slides@^2.0.0)").option("--save", "Save to lockfile (default)").action(async (specifier, options) => {
|
|
1360
|
+
await add(specifier, { save: options.save ?? true });
|
|
1538
1361
|
});
|
|
1539
1362
|
program.command("remove <name>").alias("rm").description("Remove an installed skill").action(async (name) => {
|
|
1540
1363
|
await remove(name);
|
|
@@ -1542,33 +1365,23 @@ program.command("remove <name>").alias("rm").description("Remove an installed sk
|
|
|
1542
1365
|
program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").action(async (options) => {
|
|
1543
1366
|
await list({ json: options.json });
|
|
1544
1367
|
});
|
|
1545
|
-
program.command("install").alias("i").description("Install all skills from lockfile").option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").action(async (options
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
dir: options.dir
|
|
1551
|
-
},
|
|
1552
|
-
globalOptions
|
|
1553
|
-
);
|
|
1368
|
+
program.command("install").alias("i").description("Install all skills from lockfile").option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").action(async (options) => {
|
|
1369
|
+
await install({
|
|
1370
|
+
frozenLockfile: options.frozenLockfile,
|
|
1371
|
+
dir: options.dir
|
|
1372
|
+
});
|
|
1554
1373
|
});
|
|
1555
|
-
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
|
|
1556
|
-
|
|
1557
|
-
await update({ dryRun: options.dryRun }, globalOptions);
|
|
1374
|
+
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) => {
|
|
1375
|
+
await update({ dryRun: options.dryRun });
|
|
1558
1376
|
});
|
|
1559
|
-
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").action(async (options
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
tag: options.tag
|
|
1565
|
-
},
|
|
1566
|
-
globalOptions
|
|
1567
|
-
);
|
|
1377
|
+
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").action(async (options) => {
|
|
1378
|
+
await publishCommand({
|
|
1379
|
+
bump: options.bump,
|
|
1380
|
+
tag: options.tag
|
|
1381
|
+
});
|
|
1568
1382
|
});
|
|
1569
|
-
program.command("unpublish <specifier>").description("Remove a published skill version").option("--force", "Confirm destructive action").action(async (specifier, options
|
|
1570
|
-
|
|
1571
|
-
await unpublish(specifier, { force: options.force }, globalOptions);
|
|
1383
|
+
program.command("unpublish <specifier>").description("Remove a published skill version").option("--force", "Confirm destructive action").action(async (specifier, options) => {
|
|
1384
|
+
await unpublish(specifier, { force: options.force });
|
|
1572
1385
|
});
|
|
1573
1386
|
program.parse();
|
|
1574
1387
|
//# sourceMappingURL=index.js.map
|