@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/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 { randomBytes, createHash } from 'crypto';
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 `/@user/${username}/${name}/versions`;
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 `/@user/${username}/${name}/${version2}`;
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 (publishSkillBody, options) => {
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
- publishSkillBody
128
+ publishSkillInput
128
129
  )
129
130
  }
130
131
  );
131
132
  };
132
133
  var getDeleteSkillUrl = (name) => {
133
- return `/${name}`;
134
+ return `/api/skills/${name}`;
134
135
  };
135
- var deleteSkill = async (name, deleteSkillBody, options) => {
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 `/${name}/${version2}`;
146
+ return `/api/skills/${name}/${version2}`;
150
147
  };
151
- var deleteSkillVersion = async (name, version2, deleteSkillVersionBody, options) => {
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
- configure({ baseUrl: registryUrl, apiKey });
168
+ configure2({ registryUrl, apiKey });
169
169
  const response = await me();
170
- const user = response.data;
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/api/skills";
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
- const apiKeyMatch = content.match(/"apiKey":\s*"([^"]+)"/);
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
- const v2Config = migrateV1ToV2(parsed);
278
- await writeUserConfig(v2Config);
279
- return v2Config;
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 createDefaultV2Config();
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, JSON.stringify(config2, null, 2));
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
- return JSON.parse(content);
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 resolveConfig(globalOptions) {
313
- const userConfig = await readUserConfig();
314
- const projectConfig = await findProjectConfig();
315
- let profileName;
316
- let profileSource;
317
- if (globalOptions?.profile) {
318
- profileName = globalOptions.profile;
319
- profileSource = "cli";
320
- } else if (process.env.PSPM_PROFILE) {
321
- profileName = process.env.PSPM_PROFILE;
322
- profileSource = "env";
323
- } else if (projectConfig?.profile) {
324
- profileName = projectConfig.profile;
325
- profileSource = "project";
326
- } else if (userConfig.defaultProfile) {
327
- profileName = userConfig.defaultProfile;
328
- profileSource = "user";
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
- `[config] Profile "${profileName}" not found. Available: ${Object.keys(
338
- userConfig.profiles
339
- ).join(", ")}`
345
+ `Migrating from legacy config (profile: ${defaultProfileName})...`
340
346
  );
341
- }
342
- throw new ProfileNotFoundError(profileName);
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
- if (process.env.PSPM_DEBUG) {
345
- console.log(
346
- `[config] Using profile: ${profileName} (source: ${profileSource})`
347
- );
348
- console.log(`[config] Profile has apiKey: ${!!profile.apiKey}`);
364
+ }
365
+ async function resolveConfig() {
366
+ const newConfigPath = getConfigPath();
367
+ try {
368
+ await stat(newConfigPath);
369
+ } catch {
370
+ await migrateFromLegacyConfig();
349
371
  }
350
- let registryUrl = profile.registryUrl;
351
- let apiKey = profile.apiKey;
352
- const username = profile.username;
353
- if (projectConfig?.registryUrl) {
354
- registryUrl = projectConfig.registryUrl;
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 getProfile(profileName) {
371
- const userConfig = await readUserConfig();
372
- return userConfig.profiles[profileName] || null;
373
- }
374
- async function listProfiles() {
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
- await writeUserConfig(userConfig);
400
- return true;
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
- userConfig.defaultProfile = profileName;
408
- await writeUserConfig(userConfig);
410
+ await writeUserConfig(config2);
409
411
  }
410
- async function getDefaultProfileName() {
411
- const userConfig = await readUserConfig();
412
- return userConfig.defaultProfile;
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(globalOptions);
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(globalOptions) {
426
- const resolved = await resolveConfig(globalOptions);
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(globalOptions) {
446
- const resolved = await resolveConfig(globalOptions);
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, globalOptions) {
497
+ async function add(specifier, _options) {
526
498
  try {
527
- const apiKey = await requireApiKey(globalOptions);
528
- const registryUrl = await getRegistryUrl(globalOptions);
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
- configure({ baseUrl: registryUrl, apiKey });
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
- const versionInfo = versionResponse.data;
557
- if (!versionInfo) {
558
- console.error(`Error: Version ${resolved} not found`);
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 downloadUrl = `${registryUrl}/@user/${username}/${name}/${resolved}/download`;
562
- const tarballResponse = await fetch(downloadUrl, {
563
- headers: {
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 config2 = {};
686
- if (options.profile) {
687
- config2.profile = options.profile;
688
- }
689
- if (options.registryUrl) {
690
- config2.registryUrl = options.registryUrl;
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
- await writeFile(configPath, `${JSON.stringify(config2, null, 2)}
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(JSON.stringify(config2, null, 2));
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(options, globalOptions) {
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 profile = await getProfile(name);
817
- if (!profile) {
818
- console.error(`Error: Profile "${name}" not found.`);
819
- console.log("Run 'pspm config list' to see available profiles.");
820
- process.exit(1);
821
- }
822
- await setDefaultProfile(name);
823
- console.log(`Default profile set to "${name}".`);
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, globalOptions) {
657
+ async function install(options) {
831
658
  try {
832
- const apiKey = await requireApiKey(globalOptions);
833
- await getRegistryUrl(globalOptions);
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: createHash2 } = await import('crypto');
876
- const actualIntegrity = `sha256-${createHash2("sha256").update(tarballBuffer).digest("base64")}`;
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(globalOptions) {
1074
- const resolved = await resolveConfig(globalOptions);
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 setProfileCredentials(
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, globalOptions) {
925
+ async function directLogin(apiKey) {
1105
926
  console.log("Verifying API key...");
1106
- const resolved = await resolveConfig(globalOptions);
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 setProfileCredentials(
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, globalOptions) {
937
+ async function login(options) {
1124
938
  try {
1125
939
  if (options.apiKey) {
1126
- await directLogin(options.apiKey, globalOptions);
940
+ await directLogin(options.apiKey);
1127
941
  } else {
1128
- await browserLogin(globalOptions);
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(globalOptions) {
952
+ async function logout() {
1139
953
  try {
1140
- const resolved = await resolveConfig(globalOptions);
1141
- const loggedIn = await isLoggedIn(globalOptions);
954
+ const loggedIn = await isLoggedIn();
1142
955
  if (!loggedIn) {
1143
- console.log(`Not logged in (profile: ${resolved.profileName}).`);
956
+ console.log("Not logged in.");
1144
957
  return;
1145
958
  }
1146
- await clearProfileCredentials(resolved.profileName);
1147
- console.log(`Logged out from profile "${resolved.profileName}".`);
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
- async function publishCommand(options, globalOptions) {
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(globalOptions);
1158
- const registryUrl = await getRegistryUrl(globalOptions);
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
- configure({ baseUrl: registryUrl, apiKey });
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 errorData = response.data;
1225
- const errorMessage = errorData?.error || errorData?.message || "Publish failed";
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, globalOptions) {
1176
+ async function unpublish(specifier, options) {
1333
1177
  try {
1334
- const apiKey = await requireApiKey(globalOptions);
1335
- const registryUrl = await getRegistryUrl(globalOptions);
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
- configure({ baseUrl: registryUrl, apiKey });
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 errorData = response.data;
1356
- const errorMessage = errorData?.error || errorData?.message || "Failed to unpublish. Version may not exist.";
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 errorData = response.data;
1372
- const errorMessage = errorData?.error || errorData?.message || "Failed to unpublish. Skill may not exist.";
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, globalOptions) {
1234
+ async function update(options) {
1387
1235
  try {
1388
- const apiKey = await requireApiKey(globalOptions);
1389
- const registryUrl = await getRegistryUrl(globalOptions);
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
- configure({ baseUrl: registryUrl, apiKey });
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, {}, globalOptions);
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(globalOptions) {
1306
+ async function whoami() {
1451
1307
  try {
1452
- const resolved = await resolveConfig(globalOptions);
1453
- const apiKey = await requireApiKey(globalOptions);
1454
- const registryUrl = await getRegistryUrl(globalOptions);
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).option("-p, --profile <name>", "Use a specific profile");
1484
- function getGlobalOptions(cmd) {
1485
- let current = cmd;
1486
- while (current.parent) {
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("--profile <name>", "Profile to use for this project").option("--registry-url <url>", "Registry URL override").action(async (options) => {
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
- profile: options.profile,
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, cmd) => {
1524
- const globalOptions = getGlobalOptions(cmd);
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 (_options, cmd) => {
1528
- const globalOptions = getGlobalOptions(cmd);
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 (_options, cmd) => {
1532
- const globalOptions = getGlobalOptions(cmd);
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, cmd) => {
1536
- const globalOptions = getGlobalOptions(cmd);
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, cmd) => {
1546
- const globalOptions = getGlobalOptions(cmd);
1547
- await install(
1548
- {
1549
- frozenLockfile: options.frozenLockfile,
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, cmd) => {
1556
- const globalOptions = getGlobalOptions(cmd);
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, cmd) => {
1560
- const globalOptions = getGlobalOptions(cmd);
1561
- await publishCommand(
1562
- {
1563
- bump: options.bump,
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, cmd) => {
1570
- const globalOptions = getGlobalOptions(cmd);
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