@anytio/pspm 0.0.2 → 0.0.4

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/client.ts
42
+ // ../../packages/sdk/src/fetchers/cli-fetcher.ts
42
43
  var config = null;
43
44
  function configure(options) {
44
45
  config = options;
@@ -49,18 +50,10 @@ function getConfig() {
49
50
  }
50
51
  return config;
51
52
  }
52
- var SDKError = class extends Error {
53
- constructor(message, status, body) {
54
- super(message);
55
- this.status = status;
56
- this.body = body;
57
- this.name = "SDKError";
58
- }
59
- };
60
- async function apiFetch(path, options = {}) {
53
+ async function customFetch(url, options) {
61
54
  const { baseUrl, apiKey } = getConfig();
62
- const url = `${baseUrl}${path}`;
63
- const response = await fetch(url, {
55
+ const fullUrl = `${baseUrl}${url}`;
56
+ const response = await fetch(fullUrl, {
64
57
  ...options,
65
58
  headers: {
66
59
  ...options.headers,
@@ -68,67 +61,116 @@ async function apiFetch(path, options = {}) {
68
61
  "Content-Type": "application/json"
69
62
  }
70
63
  });
71
- if (!response.ok) {
72
- const errorText = await response.text();
73
- let errorMessage = `API error: ${response.status}`;
64
+ const text = await response.text();
65
+ let data = null;
66
+ if (text) {
74
67
  try {
75
- const errorJson = JSON.parse(errorText);
76
- if (errorJson.message) {
77
- errorMessage = errorJson.message;
78
- } else if (errorJson.error) {
79
- errorMessage = errorJson.error;
80
- }
68
+ data = JSON.parse(text);
81
69
  } catch {
82
- if (errorText) {
83
- errorMessage = errorText;
84
- }
70
+ data = text;
85
71
  }
86
- throw new SDKError(errorMessage, response.status, errorText);
87
72
  }
88
- const text = await response.text();
89
- if (!text) {
90
- return null;
91
- }
92
- return JSON.parse(text);
93
- }
94
- async function me() {
95
- return apiFetch("/me", { method: "GET" });
73
+ return {
74
+ data,
75
+ status: response.status,
76
+ headers: response.headers
77
+ };
96
78
  }
97
- async function listVersions(params) {
98
- return apiFetch(
99
- `/@user/${params.username}/${params.name}/versions`,
100
- { method: "GET" }
79
+
80
+ // ../../packages/sdk/src/generated/fetch/index.ts
81
+ var getMeUrl = () => {
82
+ return `/api/skills/me`;
83
+ };
84
+ var me = async (options) => {
85
+ return customFetch(
86
+ getMeUrl(),
87
+ {
88
+ ...options,
89
+ method: "GET"
90
+ }
101
91
  );
102
- }
103
- async function getVersion(params) {
104
- return apiFetch(
105
- `/@user/${params.username}/${params.name}/${params.version}`,
106
- { method: "GET" }
92
+ };
93
+ var getListSkillVersionsUrl = (username, name) => {
94
+ return `/api/skills/@user/${username}/${name}/versions`;
95
+ };
96
+ var listSkillVersions = async (username, name, options) => {
97
+ return customFetch(
98
+ getListSkillVersionsUrl(username, name),
99
+ {
100
+ ...options,
101
+ method: "GET"
102
+ }
107
103
  );
108
- }
109
- async function publish(body) {
110
- return apiFetch("/publish", {
111
- method: "POST",
112
- body: JSON.stringify(body)
113
- });
114
- }
115
- async function deleteSkill(params) {
116
- return apiFetch(`/${params.name}`, { method: "DELETE" });
117
- }
118
- async function deleteVersion(params) {
119
- return apiFetch(`/${params.name}/${params.version}`, {
120
- method: "DELETE"
121
- });
122
- }
104
+ };
105
+ var getGetSkillVersionUrl = (username, name, version2) => {
106
+ return `/api/skills/@user/${username}/${name}/${version2}`;
107
+ };
108
+ var getSkillVersion = async (username, name, version2, options) => {
109
+ return customFetch(
110
+ getGetSkillVersionUrl(username, name, version2),
111
+ {
112
+ ...options,
113
+ method: "GET"
114
+ }
115
+ );
116
+ };
117
+ var getPublishSkillUrl = () => {
118
+ return `/api/skills/publish`;
119
+ };
120
+ var publishSkill = async (publishSkillInput, options) => {
121
+ return customFetch(
122
+ getPublishSkillUrl(),
123
+ {
124
+ ...options,
125
+ method: "POST",
126
+ headers: { "Content-Type": "application/json", ...options?.headers },
127
+ body: JSON.stringify(
128
+ publishSkillInput
129
+ )
130
+ }
131
+ );
132
+ };
133
+ var getDeleteSkillUrl = (name) => {
134
+ return `/api/skills/${name}`;
135
+ };
136
+ var deleteSkill = async (name, options) => {
137
+ return customFetch(
138
+ getDeleteSkillUrl(name),
139
+ {
140
+ ...options,
141
+ method: "DELETE"
142
+ }
143
+ );
144
+ };
145
+ var getDeleteSkillVersionUrl = (name, version2) => {
146
+ return `/api/skills/${name}/${version2}`;
147
+ };
148
+ var deleteSkillVersion = async (name, version2, options) => {
149
+ return customFetch(
150
+ getDeleteSkillVersionUrl(name, version2),
151
+ {
152
+ ...options,
153
+ method: "DELETE"
154
+ }
155
+ );
156
+ };
123
157
 
124
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
+ }
125
166
  async function whoamiRequest(registryUrl, apiKey) {
126
167
  try {
127
- configure({ baseUrl: `${registryUrl}/rpc`, apiKey });
128
- const user = await me();
129
- if (!user) {
168
+ configure2({ registryUrl, apiKey });
169
+ const response = await me();
170
+ if (response.status !== 200 || !response.data) {
130
171
  return null;
131
172
  }
173
+ const user = response.data;
132
174
  return {
133
175
  username: user.username,
134
176
  userId: user.userId
@@ -145,14 +187,6 @@ var ConfigError = class extends Error {
145
187
  this.name = "ConfigError";
146
188
  }
147
189
  };
148
- var ProfileNotFoundError = class extends ConfigError {
149
- constructor(profileName) {
150
- super(
151
- `Profile "${profileName}" not found. Run 'pspm config list' to see available profiles.`
152
- );
153
- this.name = "ProfileNotFoundError";
154
- }
155
- };
156
190
  var NotLoggedInError = class extends ConfigError {
157
191
  constructor() {
158
192
  super(
@@ -161,10 +195,47 @@ var NotLoggedInError = class extends ConfigError {
161
195
  this.name = "NotLoggedInError";
162
196
  }
163
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
+ }
164
232
 
165
233
  // src/config.ts
166
- var DEFAULT_REGISTRY_URL = "https://pspm.dev/api/skills";
234
+ var DEFAULT_REGISTRY_URL = "https://pspm.dev";
167
235
  function getConfigPath() {
236
+ return join(homedir(), ".pspmrc");
237
+ }
238
+ function getLegacyConfigPath() {
168
239
  return join(homedir(), ".pspm", "config.json");
169
240
  }
170
241
  function getSkillsDir() {
@@ -173,33 +244,6 @@ function getSkillsDir() {
173
244
  function getLockfilePath() {
174
245
  return join(process.cwd(), "skill-lock.json");
175
246
  }
176
- function createDefaultV2Config() {
177
- return {
178
- version: 2,
179
- defaultProfile: "default",
180
- profiles: {
181
- default: {
182
- registryUrl: DEFAULT_REGISTRY_URL
183
- }
184
- }
185
- };
186
- }
187
- function migrateV1ToV2(v1Config) {
188
- return {
189
- version: 2,
190
- defaultProfile: "default",
191
- profiles: {
192
- default: {
193
- registryUrl: v1Config.registryUrl || DEFAULT_REGISTRY_URL,
194
- apiKey: v1Config.apiKey,
195
- username: v1Config.username
196
- }
197
- }
198
- };
199
- }
200
- function isV2Config(config2) {
201
- return typeof config2 === "object" && config2 !== null && "version" in config2 && config2.version === 2;
202
- }
203
247
  async function readUserConfig() {
204
248
  const configPath = getConfigPath();
205
249
  if (process.env.PSPM_DEBUG) {
@@ -207,48 +251,42 @@ async function readUserConfig() {
207
251
  }
208
252
  try {
209
253
  const content = await readFile(configPath, "utf-8");
254
+ const parsed = ini.parse(content);
210
255
  if (process.env.PSPM_DEBUG) {
211
- const apiKeyMatch = content.match(/"apiKey":\s*"([^"]+)"/);
212
- if (apiKeyMatch) {
213
- console.log(
214
- `[config] Raw apiKey from file: ${apiKeyMatch[1].substring(
215
- 0,
216
- 15
217
- )}...`
218
- );
219
- }
256
+ console.log(`[config] Parsed config:`, JSON.stringify(parsed, null, 2));
220
257
  }
221
- const parsed = JSON.parse(content);
222
- if (process.env.PSPM_DEBUG) {
223
- console.log(
224
- `[config] Parsed config version: ${parsed.version}`
225
- );
226
- console.log(
227
- `[config] Profiles found: ${Object.keys(
228
- parsed.profiles || {}
229
- ).join(", ")}`
230
- );
231
- }
232
- if (isV2Config(parsed)) {
233
- return parsed;
234
- }
235
- const v2Config = migrateV1ToV2(parsed);
236
- await writeUserConfig(v2Config);
237
- return v2Config;
258
+ return {
259
+ registry: parsed.registry,
260
+ authToken: parsed.authToken,
261
+ username: parsed.username
262
+ };
238
263
  } catch (error) {
239
264
  if (process.env.PSPM_DEBUG) {
240
265
  console.log(
241
266
  `[config] Error reading config: ${error instanceof Error ? error.message : String(error)}`
242
267
  );
243
- console.log(`[config] Falling back to default config`);
244
268
  }
245
- return createDefaultV2Config();
269
+ return {};
246
270
  }
247
271
  }
248
272
  async function writeUserConfig(config2) {
249
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("");
250
285
  await mkdir(dirname(configPath), { recursive: true });
251
- 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
+ }
252
290
  }
253
291
  async function findProjectConfig() {
254
292
  let currentDir = process.cwd();
@@ -259,7 +297,26 @@ async function findProjectConfig() {
259
297
  const stats = await stat(configPath);
260
298
  if (stats.isFile()) {
261
299
  const content = await readFile(configPath, "utf-8");
262
- 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
+ }
263
320
  }
264
321
  } catch {
265
322
  }
@@ -267,49 +324,61 @@ async function findProjectConfig() {
267
324
  }
268
325
  return null;
269
326
  }
270
- async function resolveConfig(globalOptions) {
271
- const userConfig = await readUserConfig();
272
- const projectConfig = await findProjectConfig();
273
- let profileName;
274
- let profileSource;
275
- if (globalOptions?.profile) {
276
- profileName = globalOptions.profile;
277
- profileSource = "cli";
278
- } else if (process.env.PSPM_PROFILE) {
279
- profileName = process.env.PSPM_PROFILE;
280
- profileSource = "env";
281
- } else if (projectConfig?.profile) {
282
- profileName = projectConfig.profile;
283
- profileSource = "project";
284
- } else if (userConfig.defaultProfile) {
285
- profileName = userConfig.defaultProfile;
286
- profileSource = "user";
287
- } else {
288
- profileName = "default";
289
- profileSource = "default";
290
- }
291
- const profile = userConfig.profiles[profileName];
292
- if (!profile) {
293
- 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
+ }
294
344
  console.log(
295
- `[config] Profile "${profileName}" not found. Available: ${Object.keys(
296
- userConfig.profiles
297
- ).join(", ")}`
345
+ `Migrating from legacy config (profile: ${defaultProfileName})...`
298
346
  );
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...");
299
355
  }
300
- throw new ProfileNotFoundError(profileName);
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;
301
363
  }
302
- if (process.env.PSPM_DEBUG) {
303
- console.log(
304
- `[config] Using profile: ${profileName} (source: ${profileSource})`
305
- );
306
- 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();
371
+ }
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;
307
379
  }
308
- let registryUrl = profile.registryUrl;
309
- let apiKey = profile.apiKey;
310
- const username = profile.username;
311
- if (projectConfig?.registryUrl) {
312
- registryUrl = projectConfig.registryUrl;
380
+ if (projectConfig?.registry) {
381
+ registryUrl = projectConfig.registry;
313
382
  }
314
383
  if (process.env.PSPM_REGISTRY_URL) {
315
384
  registryUrl = process.env.PSPM_REGISTRY_URL;
@@ -317,117 +386,62 @@ async function resolveConfig(globalOptions) {
317
386
  if (process.env.PSPM_API_KEY) {
318
387
  apiKey = process.env.PSPM_API_KEY;
319
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
+ }
320
395
  return {
321
- profileName,
322
- profileSource,
323
396
  registryUrl,
324
397
  apiKey,
325
398
  username
326
399
  };
327
400
  }
328
- async function getProfile(profileName) {
329
- const userConfig = await readUserConfig();
330
- return userConfig.profiles[profileName] || null;
331
- }
332
- async function listProfiles() {
333
- const userConfig = await readUserConfig();
334
- return Object.keys(userConfig.profiles);
335
- }
336
- async function setProfile(profileName, config2) {
337
- const userConfig = await readUserConfig();
338
- const existing = userConfig.profiles[profileName] || {
339
- registryUrl: DEFAULT_REGISTRY_URL
340
- };
341
- userConfig.profiles[profileName] = {
342
- ...existing,
343
- ...config2
344
- };
345
- await writeUserConfig(userConfig);
346
- }
347
- async function deleteProfile(profileName) {
348
- const userConfig = await readUserConfig();
349
- if (!userConfig.profiles[profileName]) {
350
- return false;
401
+ async function setCredentials(authToken, username, registry) {
402
+ const config2 = await readUserConfig();
403
+ config2.authToken = authToken;
404
+ if (username) {
405
+ config2.username = username;
351
406
  }
352
- delete userConfig.profiles[profileName];
353
- if (userConfig.defaultProfile === profileName) {
354
- const remainingProfiles = Object.keys(userConfig.profiles);
355
- userConfig.defaultProfile = remainingProfiles[0] || "default";
407
+ if (registry && registry !== DEFAULT_REGISTRY_URL) {
408
+ config2.registry = registry;
356
409
  }
357
- await writeUserConfig(userConfig);
358
- return true;
410
+ await writeUserConfig(config2);
359
411
  }
360
- async function setDefaultProfile(profileName) {
361
- const userConfig = await readUserConfig();
362
- if (!userConfig.profiles[profileName]) {
363
- throw new ProfileNotFoundError(profileName);
364
- }
365
- userConfig.defaultProfile = profileName;
366
- await writeUserConfig(userConfig);
412
+ async function clearCredentials() {
413
+ const config2 = await readUserConfig();
414
+ delete config2.authToken;
415
+ delete config2.username;
416
+ await writeUserConfig(config2);
367
417
  }
368
- async function getDefaultProfileName() {
369
- const userConfig = await readUserConfig();
370
- return userConfig.defaultProfile;
371
- }
372
- ({
373
- registryUrl: process.env.PSPM_REGISTRY_URL || DEFAULT_REGISTRY_URL
374
- });
375
- async function isLoggedIn(globalOptions) {
418
+ async function isLoggedIn() {
376
419
  try {
377
- const resolved = await resolveConfig(globalOptions);
420
+ const resolved = await resolveConfig();
378
421
  return !!resolved.apiKey;
379
422
  } catch {
380
423
  return false;
381
424
  }
382
425
  }
383
- async function requireApiKey(globalOptions) {
384
- const resolved = await resolveConfig(globalOptions);
426
+ async function requireApiKey() {
427
+ const resolved = await resolveConfig();
385
428
  if (!resolved.apiKey) {
386
429
  if (process.env.PSPM_DEBUG) {
387
- console.log(
388
- `[config] requireApiKey: No API key found for profile "${resolved.profileName}"`
389
- );
430
+ console.log(`[config] requireApiKey: No API key found`);
390
431
  }
391
432
  throw new NotLoggedInError();
392
433
  }
393
434
  if (process.env.PSPM_DEBUG) {
394
435
  console.log(
395
- `[config] requireApiKey: Got API key (${resolved.apiKey.substring(
396
- 0,
397
- 10
398
- )}...)`
436
+ `[config] requireApiKey: Got API key (${resolved.apiKey.substring(0, 10)}...)`
399
437
  );
400
438
  }
401
439
  return resolved.apiKey;
402
440
  }
403
- async function getRegistryUrl(globalOptions) {
404
- const resolved = await resolveConfig(globalOptions);
441
+ async function getRegistryUrl() {
442
+ const resolved = await resolveConfig();
405
443
  return resolved.registryUrl;
406
444
  }
407
- async function clearProfileCredentials(profileName) {
408
- const userConfig = await readUserConfig();
409
- if (userConfig.profiles[profileName]) {
410
- userConfig.profiles[profileName].apiKey = void 0;
411
- userConfig.profiles[profileName].username = void 0;
412
- await writeUserConfig(userConfig);
413
- }
414
- }
415
- async function setProfileCredentials(profileName, apiKey, username, registryUrl) {
416
- const userConfig = await readUserConfig();
417
- if (!userConfig.profiles[profileName]) {
418
- userConfig.profiles[profileName] = {
419
- registryUrl: registryUrl || DEFAULT_REGISTRY_URL
420
- };
421
- }
422
- userConfig.profiles[profileName].apiKey = apiKey;
423
- if (username) {
424
- userConfig.profiles[profileName].username = username;
425
- }
426
- if (registryUrl) {
427
- userConfig.profiles[profileName].registryUrl = registryUrl;
428
- }
429
- await writeUserConfig(userConfig);
430
- }
431
445
  async function readLockfile() {
432
446
  const lockfilePath = getLockfilePath();
433
447
  try {
@@ -480,10 +494,10 @@ async function listLockfileSkills() {
480
494
  }
481
495
 
482
496
  // src/commands/add.ts
483
- async function add(specifier, _options, globalOptions) {
497
+ async function add(specifier, _options) {
484
498
  try {
485
- const apiKey = await requireApiKey(globalOptions);
486
- const registryUrl = await getRegistryUrl(globalOptions);
499
+ const apiKey = await requireApiKey();
500
+ const registryUrl = await getRegistryUrl();
487
501
  const parsed = parseSkillSpecifier(specifier);
488
502
  if (!parsed) {
489
503
  console.error(
@@ -492,9 +506,18 @@ async function add(specifier, _options, globalOptions) {
492
506
  process.exit(1);
493
507
  }
494
508
  const { username, name, versionRange } = parsed;
495
- configure({ baseUrl: `${registryUrl}/rpc`, apiKey });
509
+ configure2({ registryUrl, apiKey });
496
510
  console.log(`Resolving ${specifier}...`);
497
- const versions = await listVersions({ username, name });
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
+ }
520
+ const versions = versionsResponse.data;
498
521
  if (versions.length === 0) {
499
522
  console.error(`Error: Skill @user/${username}/${name} not found`);
500
523
  process.exit(1);
@@ -509,15 +532,16 @@ async function add(specifier, _options, globalOptions) {
509
532
  process.exit(1);
510
533
  }
511
534
  console.log(`Installing @user/${username}/${name}@${resolved}...`);
512
- const versionInfo = await getVersion({
513
- username,
514
- name,
515
- version: resolved
516
- });
517
- if (!versionInfo) {
518
- console.error(`Error: Version ${resolved} not found`);
535
+ const versionResponse = await getSkillVersion(username, name, resolved);
536
+ if (versionResponse.status !== 200 || !versionResponse.data) {
537
+ const errorMessage = extractApiErrorMessage(
538
+ versionResponse,
539
+ `Version ${resolved} not found`
540
+ );
541
+ console.error(`Error: ${errorMessage}`);
519
542
  process.exit(1);
520
543
  }
544
+ const versionInfo = versionResponse.data;
521
545
  const downloadUrl = `${registryUrl}/@user/${username}/${name}/${resolved}/download`;
522
546
  const tarballResponse = await fetch(downloadUrl, {
523
547
  headers: {
@@ -571,68 +595,6 @@ async function add(specifier, _options, globalOptions) {
571
595
  process.exit(1);
572
596
  }
573
597
  }
574
-
575
- // src/commands/config/add.ts
576
- async function configAdd(name, options) {
577
- try {
578
- const existing = await getProfile(name);
579
- if (existing) {
580
- console.error(`Error: Profile "${name}" already exists.`);
581
- console.log("Use 'pspm config set' to modify it.");
582
- process.exit(1);
583
- }
584
- await setProfile(name, {
585
- registryUrl: options.registryUrl || "https://pspm.dev/api/skills"
586
- });
587
- console.log(`Created profile "${name}".`);
588
- if (options.registryUrl) {
589
- console.log(` Registry URL: ${options.registryUrl}`);
590
- }
591
- console.log("");
592
- console.log(
593
- `To set credentials, run: pspm login --api-key <key> --profile ${name}`
594
- );
595
- console.log(`To make this the default, run: pspm config use ${name}`);
596
- } catch (error) {
597
- const message = error instanceof Error ? error.message : "Unknown error";
598
- console.error(`Error: ${message}`);
599
- process.exit(1);
600
- }
601
- }
602
-
603
- // src/commands/config/delete.ts
604
- async function configDelete(name) {
605
- try {
606
- const profiles = await listProfiles();
607
- const defaultProfile = await getDefaultProfileName();
608
- if (!profiles.includes(name)) {
609
- console.error(`Error: Profile "${name}" not found.`);
610
- console.log("Run 'pspm config list' to see available profiles.");
611
- process.exit(1);
612
- }
613
- if (profiles.length === 1) {
614
- console.error("Error: Cannot delete the last profile.");
615
- console.log("Create another profile first, then delete this one.");
616
- process.exit(1);
617
- }
618
- const wasDefault = name === defaultProfile;
619
- const success = await deleteProfile(name);
620
- if (success) {
621
- console.log(`Deleted profile "${name}".`);
622
- if (wasDefault) {
623
- const newDefault = await getDefaultProfileName();
624
- console.log(`Default profile is now "${newDefault}".`);
625
- }
626
- } else {
627
- console.error(`Error: Failed to delete profile "${name}".`);
628
- process.exit(1);
629
- }
630
- } catch (error) {
631
- const message = error instanceof Error ? error.message : "Unknown error";
632
- console.error(`Error: ${message}`);
633
- process.exit(1);
634
- }
635
- }
636
598
  async function configInit(options) {
637
599
  try {
638
600
  const configPath = join(process.cwd(), ".pspmrc");
@@ -642,23 +604,19 @@ async function configInit(options) {
642
604
  process.exit(1);
643
605
  } catch {
644
606
  }
645
- const config2 = {};
646
- if (options.profile) {
647
- config2.profile = options.profile;
648
- }
649
- if (options.registryUrl) {
650
- config2.registryUrl = options.registryUrl;
651
- }
652
- if (Object.keys(config2).length === 0) {
653
- 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");
654
613
  }
655
- await writeFile(configPath, `${JSON.stringify(config2, null, 2)}
656
- `);
614
+ lines.push("");
615
+ await writeFile(configPath, lines.join("\n"));
657
616
  console.log("Created .pspmrc");
658
617
  console.log("");
659
618
  console.log("Contents:");
660
- console.log(JSON.stringify(config2, null, 2));
661
- console.log("");
619
+ console.log(lines.join("\n"));
662
620
  console.log("Note: .pspmrc should be committed to version control.");
663
621
  console.log("API keys should NOT be stored here - use pspm login instead.");
664
622
  } catch (error) {
@@ -668,129 +626,38 @@ async function configInit(options) {
668
626
  }
669
627
  }
670
628
 
671
- // src/commands/config/list.ts
672
- async function configList() {
673
- try {
674
- const profiles = await listProfiles();
675
- const defaultProfile = await getDefaultProfileName();
676
- if (profiles.length === 0) {
677
- console.log("No profiles configured.");
678
- console.log("Run 'pspm config add <name>' to create one.");
679
- return;
680
- }
681
- console.log("Profiles:\n");
682
- for (const name of profiles) {
683
- const marker = name === defaultProfile ? " (default)" : "";
684
- console.log(` ${name}${marker}`);
685
- }
686
- console.log("");
687
- } catch (error) {
688
- const message = error instanceof Error ? error.message : "Unknown error";
689
- console.error(`Error: ${message}`);
690
- process.exit(1);
691
- }
692
- }
693
-
694
- // src/commands/config/set.ts
695
- var VALID_KEYS = ["registryUrl", "apiKey", "username"];
696
- async function configSet(profile, key, value) {
697
- try {
698
- if (!VALID_KEYS.includes(key)) {
699
- console.error(`Error: Invalid key "${key}".`);
700
- console.log(`Valid keys: ${VALID_KEYS.join(", ")}`);
701
- process.exit(1);
702
- }
703
- const existing = await getProfile(profile);
704
- if (!existing) {
705
- console.error(`Error: Profile "${profile}" not found.`);
706
- console.log("Run 'pspm config add' to create it first.");
707
- process.exit(1);
708
- }
709
- await setProfile(profile, { [key]: value });
710
- console.log(`Updated ${key} for profile "${profile}".`);
711
- } catch (error) {
712
- const message = error instanceof Error ? error.message : "Unknown error";
713
- console.error(`Error: ${message}`);
714
- process.exit(1);
715
- }
716
- }
717
-
718
629
  // src/commands/config/show.ts
719
- async function configShow(options, globalOptions) {
720
- try {
721
- if (options.name) {
722
- const profile = await getProfile(options.name);
723
- if (!profile) {
724
- console.error(`Error: Profile "${options.name}" not found.`);
725
- console.log("Run 'pspm config list' to see available profiles.");
726
- process.exit(1);
727
- }
728
- const defaultProfile = await getDefaultProfileName();
729
- const isDefault = options.name === defaultProfile;
730
- console.log(`Profile: ${options.name}${isDefault ? " (default)" : ""}
731
- `);
732
- console.log(` Registry URL: ${profile.registryUrl}`);
733
- console.log(` API Key: ${profile.apiKey ? "***" : "(not set)"}`);
734
- console.log(` Username: ${profile.username || "(not set)"}`);
735
- } else {
736
- const resolved = await resolveConfig(globalOptions);
737
- const projectConfig = await findProjectConfig();
738
- const configPath = getConfigPath();
739
- console.log("Resolved Configuration:\n");
740
- console.log(` Active Profile: ${resolved.profileName}`);
741
- console.log(` Profile Source: ${formatSource(resolved.profileSource)}`);
742
- console.log(` Registry URL: ${resolved.registryUrl}`);
743
- console.log(` API Key: ${resolved.apiKey ? "***" : "(not set)"}`);
744
- console.log(` Username: ${resolved.username || "(not set)"}`);
745
- console.log("");
746
- console.log("Config Locations:");
747
- console.log(` User config: ${configPath}`);
748
- console.log(` Project config: ${projectConfig ? ".pspmrc" : "(none)"}`);
749
- }
750
- } catch (error) {
751
- const message = error instanceof Error ? error.message : "Unknown error";
752
- console.error(`Error: ${message}`);
753
- process.exit(1);
754
- }
755
- }
756
- function formatSource(source) {
757
- switch (source) {
758
- case "cli":
759
- return "--profile flag";
760
- case "env":
761
- return "PSPM_PROFILE env var";
762
- case "project":
763
- return ".pspmrc file";
764
- case "user":
765
- return "user config default";
766
- case "default":
767
- return "fallback default";
768
- default:
769
- return source;
770
- }
771
- }
772
-
773
- // src/commands/config/use.ts
774
- async function configUse(name) {
630
+ async function configShow() {
775
631
  try {
776
- const profile = await getProfile(name);
777
- if (!profile) {
778
- console.error(`Error: Profile "${name}" not found.`);
779
- console.log("Run 'pspm config list' to see available profiles.");
780
- process.exit(1);
781
- }
782
- await setDefaultProfile(name);
783
- 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
+ );
784
651
  } catch (error) {
785
652
  const message = error instanceof Error ? error.message : "Unknown error";
786
653
  console.error(`Error: ${message}`);
787
654
  process.exit(1);
788
655
  }
789
656
  }
790
- async function install(options, globalOptions) {
657
+ async function install(options) {
791
658
  try {
792
- const apiKey = await requireApiKey(globalOptions);
793
- await getRegistryUrl(globalOptions);
659
+ const apiKey = await requireApiKey();
660
+ await getRegistryUrl();
794
661
  const skillsDir = options.dir || getSkillsDir();
795
662
  const lockfile = await readLockfile();
796
663
  if (!lockfile) {
@@ -832,8 +699,8 @@ async function install(options, globalOptions) {
832
699
  continue;
833
700
  }
834
701
  const tarballBuffer = Buffer.from(await response.arrayBuffer());
835
- const { createHash: createHash2 } = await import('crypto');
836
- const actualIntegrity = `sha256-${createHash2("sha256").update(tarballBuffer).digest("base64")}`;
702
+ const { createHash: createHash3 } = await import('crypto');
703
+ const actualIntegrity = `sha256-${createHash3("sha256").update(tarballBuffer).digest("base64")}`;
837
704
  if (actualIntegrity !== entry.integrity) {
838
705
  console.error(` Error: Checksum verification failed for ${fullName}`);
839
706
  if (options.frozenLockfile) {
@@ -924,9 +791,9 @@ function getServerUrl(registryUrl) {
924
791
  return DEFAULT_WEB_APP_URL;
925
792
  }
926
793
  }
927
- async function exchangeCliToken(registryUrl, token) {
794
+ async function exchangeCliToken2(registryUrl, token) {
928
795
  const serverUrl = getServerUrl(registryUrl);
929
- const rpcUrl = `${serverUrl}/api/api-keys/rpc/exchangeCliToken`;
796
+ const rpcUrl = `${serverUrl}/api/api-keys/cli-token-exchange`;
930
797
  const response = await fetch(rpcUrl, {
931
798
  method: "POST",
932
799
  headers: {
@@ -1030,9 +897,8 @@ function startCallbackServer(expectedState) {
1030
897
  );
1031
898
  });
1032
899
  }
1033
- async function browserLogin(globalOptions) {
1034
- const resolved = await resolveConfig(globalOptions);
1035
- const registryUrl = await getRegistryUrl(globalOptions);
900
+ async function browserLogin() {
901
+ const registryUrl = await getRegistryUrl();
1036
902
  const webAppUrl = getWebAppUrl(registryUrl);
1037
903
  const state = randomBytes(32).toString("base64url");
1038
904
  console.log("Starting browser-based login...");
@@ -1050,42 +916,29 @@ async function browserLogin(globalOptions) {
1050
916
  const token = await tokenPromise;
1051
917
  cleanup();
1052
918
  console.log("Received token, exchanging for API key...");
1053
- const { apiKey, username } = await exchangeCliToken(registryUrl, token);
1054
- await setProfileCredentials(
1055
- resolved.profileName,
1056
- apiKey,
1057
- username,
1058
- registryUrl
1059
- );
919
+ const { apiKey, username } = await exchangeCliToken2(registryUrl, token);
920
+ await setCredentials(apiKey, username, registryUrl);
1060
921
  console.log(`Logged in as ${username}`);
1061
- console.log(`Profile: ${resolved.profileName}`);
1062
922
  console.log(`Registry: ${registryUrl}`);
1063
923
  }
1064
- async function directLogin(apiKey, globalOptions) {
924
+ async function directLogin(apiKey) {
1065
925
  console.log("Verifying API key...");
1066
- const resolved = await resolveConfig(globalOptions);
1067
- const registryUrl = await getRegistryUrl(globalOptions);
926
+ const registryUrl = await getRegistryUrl();
1068
927
  const user = await whoamiRequest(registryUrl, apiKey);
1069
928
  if (!user) {
1070
929
  console.error("Error: Invalid API key or not authenticated");
1071
930
  process.exit(1);
1072
931
  }
1073
- await setProfileCredentials(
1074
- resolved.profileName,
1075
- apiKey,
1076
- user.username,
1077
- registryUrl
1078
- );
932
+ await setCredentials(apiKey, user.username, registryUrl);
1079
933
  console.log(`Logged in as ${user.username}`);
1080
- console.log(`Profile: ${resolved.profileName}`);
1081
934
  console.log(`Registry: ${registryUrl}`);
1082
935
  }
1083
- async function login(options, globalOptions) {
936
+ async function login(options) {
1084
937
  try {
1085
938
  if (options.apiKey) {
1086
- await directLogin(options.apiKey, globalOptions);
939
+ await directLogin(options.apiKey);
1087
940
  } else {
1088
- await browserLogin(globalOptions);
941
+ await browserLogin();
1089
942
  }
1090
943
  } catch (error) {
1091
944
  const message = error instanceof Error ? error.message : "Unknown error";
@@ -1095,16 +948,15 @@ async function login(options, globalOptions) {
1095
948
  }
1096
949
 
1097
950
  // src/commands/logout.ts
1098
- async function logout(globalOptions) {
951
+ async function logout() {
1099
952
  try {
1100
- const resolved = await resolveConfig(globalOptions);
1101
- const loggedIn = await isLoggedIn(globalOptions);
953
+ const loggedIn = await isLoggedIn();
1102
954
  if (!loggedIn) {
1103
- console.log(`Not logged in (profile: ${resolved.profileName}).`);
955
+ console.log("Not logged in.");
1104
956
  return;
1105
957
  }
1106
- await clearProfileCredentials(resolved.profileName);
1107
- console.log(`Logged out from profile "${resolved.profileName}".`);
958
+ await clearCredentials();
959
+ console.log("Logged out successfully.");
1108
960
  } catch (error) {
1109
961
  const message = error instanceof Error ? error.message : "Unknown error";
1110
962
  console.error(`Error: ${message}`);
@@ -1112,10 +964,37 @@ async function logout(globalOptions) {
1112
964
  }
1113
965
  }
1114
966
  var exec = promisify(exec$1);
1115
- async function publishCommand(options, globalOptions) {
967
+ function formatBytes(bytes) {
968
+ if (bytes < 1024) return `${bytes}B`;
969
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}kB`;
970
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
971
+ }
972
+ async function getFilesWithSizes(dir, baseDir) {
973
+ const results = [];
1116
974
  try {
1117
- const apiKey = await requireApiKey(globalOptions);
1118
- const registryUrl = await getRegistryUrl(globalOptions);
975
+ const entries = await readdir(dir, { withFileTypes: true });
976
+ for (const entry of entries) {
977
+ const fullPath = join(dir, entry.name);
978
+ const relativePath = relative(baseDir, fullPath);
979
+ if (entry.name === "node_modules" || entry.name === ".git") {
980
+ continue;
981
+ }
982
+ if (entry.isDirectory()) {
983
+ const subFiles = await getFilesWithSizes(fullPath, baseDir);
984
+ results.push(...subFiles);
985
+ } else {
986
+ const fileStat = await stat(fullPath);
987
+ results.push({ path: relativePath, size: fileStat.size });
988
+ }
989
+ }
990
+ } catch {
991
+ }
992
+ return results;
993
+ }
994
+ async function publishCommand(options) {
995
+ try {
996
+ const apiKey = await requireApiKey();
997
+ const registryUrl = await getRegistryUrl();
1119
998
  const packageJsonPath = join(process.cwd(), "package.json");
1120
999
  let packageJson2;
1121
1000
  try {
@@ -1145,8 +1024,6 @@ async function publishCommand(options, globalOptions) {
1145
1024
  packageJson2.version = newVersion;
1146
1025
  console.log(`Bumped version to ${newVersion}`);
1147
1026
  }
1148
- console.log(`Registry: ${registryUrl}`);
1149
- console.log(`Publishing ${packageJson2.name}@${packageJson2.version}...`);
1150
1027
  const safeName = packageJson2.name.replace(/[@/]/g, "-").replace(/^-+/, "");
1151
1028
  const tarballName = `${safeName}-${packageJson2.version}.tgz`;
1152
1029
  const tempDir = join(process.cwd(), ".pspm-publish");
@@ -1169,20 +1046,60 @@ async function publishCommand(options, globalOptions) {
1169
1046
  }
1170
1047
  }
1171
1048
  await exec(`cp package.json "${tempDir}/package/"`);
1049
+ const packageDir = join(tempDir, "package");
1050
+ const tarballContents = await getFilesWithSizes(packageDir, packageDir);
1051
+ const unpackedSize = tarballContents.reduce((acc, f) => acc + f.size, 0);
1172
1052
  const tarballPath = join(tempDir, tarballName);
1173
1053
  await exec(
1174
1054
  `tar -czf "${tarballPath}" -C "${tempDir}" --exclude='node_modules' --exclude='.git' package`
1175
1055
  );
1176
1056
  const tarballBuffer = await readFile(tarballPath);
1177
1057
  const tarballBase64 = tarballBuffer.toString("base64");
1178
- configure({ baseUrl: `${registryUrl}/rpc`, apiKey });
1179
- const result = await publish({
1058
+ const tarballSize = tarballBuffer.length;
1059
+ const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
1060
+ const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
1061
+ const integrity = `sha512-${integrityHash}`;
1062
+ console.log("");
1063
+ console.log(`pspm notice`);
1064
+ console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
1065
+ console.log(`pspm notice Tarball Contents`);
1066
+ tarballContents.sort((a, b) => b.size - a.size);
1067
+ for (const file of tarballContents) {
1068
+ console.log(
1069
+ `pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
1070
+ );
1071
+ }
1072
+ console.log(`pspm notice Tarball Details`);
1073
+ console.log(`pspm notice name: ${packageJson2.name}`);
1074
+ console.log(`pspm notice version: ${packageJson2.version}`);
1075
+ console.log(`pspm notice filename: ${tarballName}`);
1076
+ console.log(`pspm notice package size: ${formatBytes(tarballSize)}`);
1077
+ console.log(`pspm notice unpacked size: ${formatBytes(unpackedSize)}`);
1078
+ console.log(`pspm notice shasum: ${shasum}`);
1079
+ console.log(
1080
+ `pspm notice integrity: ${integrity.substring(0, 50)}...`
1081
+ );
1082
+ console.log(`pspm notice total files: ${tarballContents.length}`);
1083
+ console.log(`pspm notice`);
1084
+ console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
1085
+ configure2({ registryUrl, apiKey });
1086
+ const response = await publishSkill({
1180
1087
  manifest: packageJson2,
1181
1088
  tarballBase64
1182
1089
  });
1090
+ if (response.status !== 200) {
1091
+ const errorMessage = extractApiErrorMessage(response, "Publish failed");
1092
+ if (errorMessage.includes("must be greater than") || errorMessage.includes("already exists")) {
1093
+ console.error(`pspm error code E403`);
1094
+ console.error(
1095
+ `pspm error 403 403 Forbidden - You cannot publish over the previously published versions: ${packageJson2.version}.`
1096
+ );
1097
+ }
1098
+ throw new Error(errorMessage);
1099
+ }
1100
+ const result = response.data;
1183
1101
  console.log(
1184
- `
1185
- Published @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
1102
+ `+ @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
1186
1103
  );
1187
1104
  console.log(`Checksum: ${result.version.checksum}`);
1188
1105
  } finally {
@@ -1192,37 +1109,9 @@ Published @user/${result.skill.username}/${result.skill.name}@${result.version.v
1192
1109
  } catch (error) {
1193
1110
  if (error instanceof Error) {
1194
1111
  console.error(`Error: ${error.message}`);
1195
- const anyError = error;
1196
- if (anyError.cause?.response) {
1197
- try {
1198
- const text = await anyError.cause.response.text();
1199
- console.error(`Response body: ${text}`);
1200
- } catch {
1201
- }
1202
- }
1203
- if (anyError.cause?.body) {
1204
- console.error(
1205
- `Cause body: ${JSON.stringify(anyError.cause.body, null, 2)}`
1206
- );
1207
- }
1208
- if (anyError.body) {
1209
- console.error(`Error body: ${JSON.stringify(anyError.body, null, 2)}`);
1210
- }
1211
- if (anyError.data) {
1212
- console.error(`Error data: ${JSON.stringify(anyError.data, null, 2)}`);
1213
- }
1214
- if (process.env.PSPM_DEBUG) {
1215
- console.error("\nFull error details:");
1216
- console.error(error);
1217
- if (error.stack) {
1218
- console.error("\nStack trace:");
1219
- console.error(error.stack);
1220
- }
1221
- }
1222
1112
  } else {
1223
1113
  console.error(`Error: ${String(error)}`);
1224
1114
  }
1225
- console.error("\nTip: Set PSPM_DEBUG=1 for more detailed error output");
1226
1115
  process.exit(1);
1227
1116
  }
1228
1117
  }
@@ -1283,10 +1172,10 @@ async function remove(nameOrSpecifier) {
1283
1172
  }
1284
1173
 
1285
1174
  // src/commands/unpublish.ts
1286
- async function unpublish(specifier, options, globalOptions) {
1175
+ async function unpublish(specifier, options) {
1287
1176
  try {
1288
- const apiKey = await requireApiKey(globalOptions);
1289
- const registryUrl = await getRegistryUrl(globalOptions);
1177
+ const apiKey = await requireApiKey();
1178
+ const registryUrl = await getRegistryUrl();
1290
1179
  const parsed = parseSkillSpecifier(specifier);
1291
1180
  if (!parsed) {
1292
1181
  console.error(
@@ -1295,7 +1184,7 @@ async function unpublish(specifier, options, globalOptions) {
1295
1184
  process.exit(1);
1296
1185
  }
1297
1186
  const { username, name, versionRange } = parsed;
1298
- configure({ baseUrl: `${registryUrl}/rpc`, apiKey });
1187
+ configure2({ registryUrl, apiKey });
1299
1188
  if (versionRange) {
1300
1189
  console.log(`Unpublishing ${specifier}...`);
1301
1190
  if (!options.force) {
@@ -1304,16 +1193,16 @@ async function unpublish(specifier, options, globalOptions) {
1304
1193
  );
1305
1194
  process.exit(1);
1306
1195
  }
1307
- const result = await deleteVersion({
1308
- name,
1309
- version: versionRange
1310
- });
1311
- if (result.success) {
1312
- console.log(`Unpublished @user/${username}/${name}@${versionRange}`);
1313
- } else {
1314
- console.error(`Error: Failed to unpublish. Version may not exist.`);
1196
+ const response = await deleteSkillVersion(name, versionRange);
1197
+ if (response.status !== 200) {
1198
+ const errorMessage = extractApiErrorMessage(
1199
+ response,
1200
+ "Failed to unpublish. Version may not exist."
1201
+ );
1202
+ console.error(`Error: ${errorMessage}`);
1315
1203
  process.exit(1);
1316
1204
  }
1205
+ console.log(`Unpublished @user/${username}/${name}@${versionRange}`);
1317
1206
  } else {
1318
1207
  console.log(`Unpublishing all versions of @user/${username}/${name}...`);
1319
1208
  if (!options.force) {
@@ -1322,13 +1211,16 @@ async function unpublish(specifier, options, globalOptions) {
1322
1211
  );
1323
1212
  process.exit(1);
1324
1213
  }
1325
- const result = await deleteSkill({ name });
1326
- if (result.success) {
1327
- console.log(`Unpublished @user/${username}/${name} (all versions)`);
1328
- } else {
1329
- console.error(`Error: Failed to unpublish. Skill may not exist.`);
1214
+ const response = await deleteSkill(name);
1215
+ if (response.status !== 200) {
1216
+ const errorMessage = extractApiErrorMessage(
1217
+ response,
1218
+ "Failed to unpublish. Skill may not exist."
1219
+ );
1220
+ console.error(`Error: ${errorMessage}`);
1330
1221
  process.exit(1);
1331
1222
  }
1223
+ console.log(`Unpublished @user/${username}/${name} (all versions)`);
1332
1224
  }
1333
1225
  } catch (error) {
1334
1226
  const message = error instanceof Error ? error.message : "Unknown error";
@@ -1338,16 +1230,16 @@ async function unpublish(specifier, options, globalOptions) {
1338
1230
  }
1339
1231
 
1340
1232
  // src/commands/update.ts
1341
- async function update(options, globalOptions) {
1233
+ async function update(options) {
1342
1234
  try {
1343
- const apiKey = await requireApiKey(globalOptions);
1344
- const registryUrl = await getRegistryUrl(globalOptions);
1235
+ const apiKey = await requireApiKey();
1236
+ const registryUrl = await getRegistryUrl();
1345
1237
  const skills = await listLockfileSkills();
1346
1238
  if (skills.length === 0) {
1347
1239
  console.log("No skills installed.");
1348
1240
  return;
1349
1241
  }
1350
- configure({ baseUrl: `${registryUrl}/rpc`, apiKey });
1242
+ configure2({ registryUrl, apiKey });
1351
1243
  const updates = [];
1352
1244
  console.log("Checking for updates...\n");
1353
1245
  for (const { name, entry } of skills) {
@@ -1355,10 +1247,16 @@ async function update(options, globalOptions) {
1355
1247
  if (!match) continue;
1356
1248
  const [, username, skillName] = match;
1357
1249
  try {
1358
- const versions = await listVersions({
1359
- username,
1360
- name: skillName
1361
- });
1250
+ const versionsResponse = await listSkillVersions(username, skillName);
1251
+ if (versionsResponse.status !== 200) {
1252
+ const errorMessage = extractApiErrorMessage(
1253
+ versionsResponse,
1254
+ "Failed to fetch versions"
1255
+ );
1256
+ console.warn(` Warning: ${name}: ${errorMessage}`);
1257
+ continue;
1258
+ }
1259
+ const versions = versionsResponse.data;
1362
1260
  if (versions.length === 0) continue;
1363
1261
  const versionStrings = versions.map(
1364
1262
  (v) => v.version
@@ -1393,7 +1291,7 @@ async function update(options, globalOptions) {
1393
1291
  if (!match) continue;
1394
1292
  const [, username, skillName] = match;
1395
1293
  const specifier = `@user/${username}/${skillName}@${latest}`;
1396
- await add(specifier, {}, globalOptions);
1294
+ await add(specifier, {});
1397
1295
  }
1398
1296
  console.log("\nAll skills updated.");
1399
1297
  } catch (error) {
@@ -1404,21 +1302,19 @@ async function update(options, globalOptions) {
1404
1302
  }
1405
1303
 
1406
1304
  // src/commands/whoami.ts
1407
- async function whoami(globalOptions) {
1305
+ async function whoami() {
1408
1306
  try {
1409
- const resolved = await resolveConfig(globalOptions);
1410
- const apiKey = await requireApiKey(globalOptions);
1411
- const registryUrl = await getRegistryUrl(globalOptions);
1307
+ const resolved = await resolveConfig();
1308
+ const apiKey = await requireApiKey();
1309
+ const registryUrl = await getRegistryUrl();
1412
1310
  const user = await whoamiRequest(registryUrl, apiKey);
1413
1311
  if (user) {
1414
1312
  console.log(`Username: ${user.username}`);
1415
1313
  console.log(`User ID: ${user.userId}`);
1416
1314
  console.log(`Registry: ${registryUrl}`);
1417
- console.log(`Profile: ${resolved.profileName}`);
1418
1315
  } else if (resolved.username) {
1419
1316
  console.log(`Username: ${resolved.username} (cached)`);
1420
1317
  console.log(`Registry: ${registryUrl}`);
1421
- console.log(`Profile: ${resolved.profileName}`);
1422
1318
  } else {
1423
1319
  console.error("Could not determine current user.");
1424
1320
  process.exit(1);
@@ -1437,61 +1333,30 @@ var packageJson = JSON.parse(
1437
1333
  );
1438
1334
  var version = packageJson.version;
1439
1335
  var program = new Command();
1440
- program.name("pspm").description("Prompt Skill Package Manager for AnyT").version(version).option("-p, --profile <name>", "Use a specific profile");
1441
- function getGlobalOptions(cmd) {
1442
- let current = cmd;
1443
- while (current.parent) {
1444
- current = current.parent;
1445
- }
1446
- const opts = current.opts();
1447
- return {
1448
- profile: opts.profile
1449
- };
1450
- }
1451
- var configCmd = program.command("config").description("Manage PSPM configuration and profiles");
1452
- configCmd.command("list").description("List all profiles").action(async () => {
1453
- await configList();
1454
- });
1455
- configCmd.command("show [name]").description("Show resolved config or a specific profile").action(async (name, _options, cmd) => {
1456
- const globalOptions = getGlobalOptions(cmd);
1457
- await configShow({ name }, globalOptions);
1458
- });
1459
- configCmd.command("add <name>").description("Create a new profile").option("--registry-url <url>", "Registry URL for the profile").action(async (name, options) => {
1460
- await configAdd(name, { registryUrl: options.registryUrl });
1461
- });
1462
- configCmd.command("use <name>").description("Set the default profile").action(async (name) => {
1463
- await configUse(name);
1464
- });
1465
- configCmd.command("set <profile> <key> <value>").description("Set a profile field (registryUrl, apiKey, username)").action(async (profile, key, value) => {
1466
- await configSet(profile, key, value);
1336
+ program.name("pspm").description("Prompt Skill Package Manager for AnyT").version(version);
1337
+ var configCmd = program.command("config").description("Manage PSPM configuration");
1338
+ configCmd.command("show").description("Show resolved configuration").action(async () => {
1339
+ await configShow();
1467
1340
  });
1468
- configCmd.command("delete <name>").description("Delete a profile").action(async (name) => {
1469
- await configDelete(name);
1470
- });
1471
- 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) => {
1341
+ configCmd.command("init").description("Create a .pspmrc file in the current directory").option("--registry <url>", "Registry URL override").action(async (options) => {
1472
1342
  await configInit({
1473
- profile: options.profile,
1474
- registryUrl: options.registryUrl
1343
+ registry: options.registry
1475
1344
  });
1476
1345
  });
1477
1346
  program.command("login").description("Log in via browser or with an API key").option(
1478
1347
  "--api-key <key>",
1479
1348
  "API key for direct authentication (skips browser)"
1480
- ).action(async (options, cmd) => {
1481
- const globalOptions = getGlobalOptions(cmd);
1482
- await login({ apiKey: options.apiKey }, globalOptions);
1349
+ ).action(async (options) => {
1350
+ await login({ apiKey: options.apiKey });
1483
1351
  });
1484
- program.command("logout").description("Log out and clear stored credentials").action(async (_options, cmd) => {
1485
- const globalOptions = getGlobalOptions(cmd);
1486
- await logout(globalOptions);
1352
+ program.command("logout").description("Log out and clear stored credentials").action(async () => {
1353
+ await logout();
1487
1354
  });
1488
- program.command("whoami").description("Show current user information").action(async (_options, cmd) => {
1489
- const globalOptions = getGlobalOptions(cmd);
1490
- await whoami(globalOptions);
1355
+ program.command("whoami").description("Show current user information").action(async () => {
1356
+ await whoami();
1491
1357
  });
1492
- 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) => {
1493
- const globalOptions = getGlobalOptions(cmd);
1494
- await add(specifier, { save: options.save ?? true }, globalOptions);
1358
+ 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) => {
1359
+ await add(specifier, { save: options.save ?? true });
1495
1360
  });
1496
1361
  program.command("remove <name>").alias("rm").description("Remove an installed skill").action(async (name) => {
1497
1362
  await remove(name);
@@ -1499,33 +1364,23 @@ program.command("remove <name>").alias("rm").description("Remove an installed sk
1499
1364
  program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").action(async (options) => {
1500
1365
  await list({ json: options.json });
1501
1366
  });
1502
- 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) => {
1503
- const globalOptions = getGlobalOptions(cmd);
1504
- await install(
1505
- {
1506
- frozenLockfile: options.frozenLockfile,
1507
- dir: options.dir
1508
- },
1509
- globalOptions
1510
- );
1367
+ 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) => {
1368
+ await install({
1369
+ frozenLockfile: options.frozenLockfile,
1370
+ dir: options.dir
1371
+ });
1511
1372
  });
1512
- 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) => {
1513
- const globalOptions = getGlobalOptions(cmd);
1514
- await update({ dryRun: options.dryRun }, globalOptions);
1373
+ 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) => {
1374
+ await update({ dryRun: options.dryRun });
1515
1375
  });
1516
- 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) => {
1517
- const globalOptions = getGlobalOptions(cmd);
1518
- await publishCommand(
1519
- {
1520
- bump: options.bump,
1521
- tag: options.tag
1522
- },
1523
- globalOptions
1524
- );
1376
+ 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) => {
1377
+ await publishCommand({
1378
+ bump: options.bump,
1379
+ tag: options.tag
1380
+ });
1525
1381
  });
1526
- program.command("unpublish <specifier>").description("Remove a published skill version").option("--force", "Confirm destructive action").action(async (specifier, options, cmd) => {
1527
- const globalOptions = getGlobalOptions(cmd);
1528
- await unpublish(specifier, { force: options.force }, globalOptions);
1382
+ program.command("unpublish <specifier>").description("Remove a published skill version").option("--force", "Confirm destructive action").action(async (specifier, options) => {
1383
+ await unpublish(specifier, { force: options.force });
1529
1384
  });
1530
1385
  program.parse();
1531
1386
  //# sourceMappingURL=index.js.map