@anytio/pspm 0.3.0 → 0.4.0

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,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, lstat, unlink, cp, readlink, symlink } from 'fs/promises';
2
+ import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, symlink, lstat, unlink, cp, readlink } from 'fs/promises';
3
3
  import { homedir } from 'os';
4
- import { dirname, join, basename, relative } from 'path';
4
+ import { dirname, join, basename, resolve, relative } from 'path';
5
5
  import * as ini from 'ini';
6
6
  import ignore from 'ignore';
7
7
  import { createHash, randomBytes } from 'crypto';
8
8
  import * as semver from 'semver';
9
+ import semver__default from 'semver';
9
10
  import { checkbox } from '@inquirer/prompts';
10
11
  import { readFileSync } from 'fs';
11
12
  import { fileURLToPath, URL as URL$1 } from 'url';
@@ -26,7 +27,7 @@ var __export = (target, all) => {
26
27
  __defProp(target, name, { get: all[name], enumerable: true });
27
28
  };
28
29
 
29
- // ../../packages/shared/sdk/src/fetcher.ts
30
+ // src/sdk/fetcher.ts
30
31
  function configure(options) {
31
32
  config = options;
32
33
  }
@@ -67,15 +68,15 @@ async function customFetch(url, options) {
67
68
  }
68
69
  var config;
69
70
  var init_fetcher = __esm({
70
- "../../packages/shared/sdk/src/fetcher.ts"() {
71
+ "src/sdk/fetcher.ts"() {
71
72
  config = null;
72
73
  }
73
74
  });
74
75
 
75
- // ../../packages/shared/sdk/src/generated/index.ts
76
+ // src/sdk/generated/index.ts
76
77
  var getMeUrl, me, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getPublishSkillUrl, publishSkill, getDeleteSkillUrl, deleteSkill, getDeleteSkillVersionUrl, deleteSkillVersion;
77
78
  var init_generated = __esm({
78
- "../../packages/shared/sdk/src/generated/index.ts"() {
79
+ "src/sdk/generated/index.ts"() {
79
80
  init_fetcher();
80
81
  getMeUrl = () => {
81
82
  return `/api/skills/me`;
@@ -101,12 +102,12 @@ var init_generated = __esm({
101
102
  }
102
103
  );
103
104
  };
104
- getGetSkillVersionUrl = (username, name, version2) => {
105
- return `/api/skills/@user/${username}/${name}/${version2}`;
105
+ getGetSkillVersionUrl = (username, name, version3) => {
106
+ return `/api/skills/@user/${username}/${name}/${version3}`;
106
107
  };
107
- getSkillVersion = async (username, name, version2, options) => {
108
+ getSkillVersion = async (username, name, version3, options) => {
108
109
  return customFetch(
109
- getGetSkillVersionUrl(username, name, version2),
110
+ getGetSkillVersionUrl(username, name, version3),
110
111
  {
111
112
  ...options,
112
113
  method: "GET"
@@ -141,12 +142,12 @@ var init_generated = __esm({
141
142
  }
142
143
  );
143
144
  };
144
- getDeleteSkillVersionUrl = (name, version2) => {
145
- return `/api/skills/${name}/${version2}`;
145
+ getDeleteSkillVersionUrl = (name, version3) => {
146
+ return `/api/skills/${name}/${version3}`;
146
147
  };
147
- deleteSkillVersion = async (name, version2, options) => {
148
+ deleteSkillVersion = async (name, version3, options) => {
148
149
  return customFetch(
149
- getDeleteSkillVersionUrl(name, version2),
150
+ getDeleteSkillVersionUrl(name, version3),
150
151
  {
151
152
  ...options,
152
153
  method: "DELETE"
@@ -156,14 +157,6 @@ var init_generated = __esm({
156
157
  }
157
158
  });
158
159
 
159
- // ../../packages/shared/sdk/src/index.ts
160
- var init_src = __esm({
161
- "../../packages/shared/sdk/src/index.ts"() {
162
- init_fetcher();
163
- init_generated();
164
- }
165
- });
166
-
167
160
  // src/api-client.ts
168
161
  function registryUrlToBaseUrl(registryUrl) {
169
162
  return registryUrl.replace(/\/api\/skills\/?$/, "");
@@ -188,14 +181,14 @@ async function whoamiRequest(registryUrl, apiKey) {
188
181
  return null;
189
182
  }
190
183
  }
191
- async function deprecateSkillVersion(skillName, version2, message) {
184
+ async function deprecateSkillVersion(skillName, version3, message) {
192
185
  const config2 = getConfig();
193
186
  if (!config2) {
194
187
  return { status: 401, error: "SDK not configured" };
195
188
  }
196
189
  try {
197
190
  const response = await fetch(
198
- `${config2.baseUrl}/api/skills/${skillName}/${version2}/deprecate`,
191
+ `${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
199
192
  {
200
193
  method: "POST",
201
194
  headers: {
@@ -218,14 +211,14 @@ async function deprecateSkillVersion(skillName, version2, message) {
218
211
  };
219
212
  }
220
213
  }
221
- async function undeprecateSkillVersion(skillName, version2) {
214
+ async function undeprecateSkillVersion(skillName, version3) {
222
215
  const config2 = getConfig();
223
216
  if (!config2) {
224
217
  return { status: 401, error: "SDK not configured" };
225
218
  }
226
219
  try {
227
220
  const response = await fetch(
228
- `${config2.baseUrl}/api/skills/${skillName}/${version2}/deprecate`,
221
+ `${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
229
222
  {
230
223
  method: "DELETE",
231
224
  headers: {
@@ -286,11 +279,27 @@ async function changeSkillAccess(skillName, input) {
286
279
  }
287
280
  var init_api_client = __esm({
288
281
  "src/api-client.ts"() {
289
- init_src();
282
+ init_fetcher();
283
+ init_generated();
290
284
  }
291
285
  });
292
286
 
293
287
  // src/errors.ts
288
+ function getHttpStatusDescription(status) {
289
+ const descriptions = {
290
+ 400: "Bad Request - The request was malformed",
291
+ 401: "Unauthorized - Please run 'pspm login' first",
292
+ 403: "Forbidden - You don't have permission for this action",
293
+ 404: "Not Found - The endpoint or resource doesn't exist",
294
+ 409: "Conflict - The resource already exists or there's a version conflict",
295
+ 422: "Validation Error - The request data is invalid",
296
+ 429: "Too Many Requests - Please slow down and try again",
297
+ 500: "Internal Server Error - Something went wrong on the server",
298
+ 502: "Bad Gateway - The server is temporarily unavailable",
299
+ 503: "Service Unavailable - The server is temporarily unavailable"
300
+ };
301
+ return descriptions[status] || `HTTP Error ${status}`;
302
+ }
294
303
  function extractApiErrorMessage(response, fallbackMessage) {
295
304
  const errorData = response.data;
296
305
  if (process.env.PSPM_DEBUG) {
@@ -300,8 +309,20 @@ function extractApiErrorMessage(response, fallbackMessage) {
300
309
  JSON.stringify(errorData, null, 2)
301
310
  );
302
311
  }
303
- if (!errorData) {
304
- return `${fallbackMessage} (HTTP ${response.status})`;
312
+ if (typeof errorData === "string") {
313
+ if (response.status === 404) {
314
+ return `${fallbackMessage}: ${getHttpStatusDescription(404)}
315
+ The registry endpoint may be unavailable or misconfigured.`;
316
+ }
317
+ return `${fallbackMessage}: ${errorData} (HTTP ${response.status})`;
318
+ }
319
+ if (!errorData || typeof errorData !== "object") {
320
+ const statusDesc = getHttpStatusDescription(response.status);
321
+ if (response.status === 404) {
322
+ return `${fallbackMessage}: ${statusDesc}
323
+ Check that the registry URL is correct in your config.`;
324
+ }
325
+ return `${fallbackMessage}: ${statusDesc}`;
305
326
  }
306
327
  let errorMessage = errorData.message || fallbackMessage;
307
328
  if (errorData.code === "VALIDATION_ERROR" && errorData.details) {
@@ -319,6 +340,9 @@ ${issueMessages}`;
319
340
  if (errorData.code && !errorMessage.includes(errorData.code)) {
320
341
  errorMessage = `[${errorData.code}] ${errorMessage}`;
321
342
  }
343
+ if (response.status >= 400) {
344
+ errorMessage += ` (HTTP ${response.status})`;
345
+ }
322
346
  if (errorData.requestId) {
323
347
  errorMessage += `
324
348
  (Request ID: ${errorData.requestId})`;
@@ -617,7 +641,7 @@ var DEFAULT_REGISTRY_URL;
617
641
  var init_config = __esm({
618
642
  "src/config.ts"() {
619
643
  init_errors();
620
- DEFAULT_REGISTRY_URL = "https://pspm.dev";
644
+ DEFAULT_REGISTRY_URL = "https://registry.pspm.dev";
621
645
  }
622
646
  });
623
647
  async function loadIgnorePatterns(cwd = process.cwd()) {
@@ -668,6 +692,14 @@ var init_integrity = __esm({
668
692
  }
669
693
  });
670
694
 
695
+ // src/lib/lockfile.ts
696
+ var PSPM_LOCKFILE_SCHEMA_URL;
697
+ var init_lockfile = __esm({
698
+ "src/lib/lockfile.ts"() {
699
+ PSPM_LOCKFILE_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm-lock.json";
700
+ }
701
+ });
702
+
671
703
  // src/lib/manifest.ts
672
704
  function validateManifest(manifest) {
673
705
  if (!manifest.name) {
@@ -715,12 +747,12 @@ function findHighestSatisfying(ranges, availableVersions) {
715
747
  const normalizedRanges = ranges.map(
716
748
  (r) => !r || r === "latest" || r === "*" ? "*" : r
717
749
  );
718
- for (const version2 of sorted) {
750
+ for (const version3 of sorted) {
719
751
  const satisfiesAll = normalizedRanges.every(
720
- (range) => semver.satisfies(version2, range)
752
+ (range) => semver.satisfies(version3, range)
721
753
  );
722
754
  if (satisfiesAll) {
723
- return version2;
755
+ return version3;
724
756
  }
725
757
  }
726
758
  return null;
@@ -1111,6 +1143,7 @@ var init_lib = __esm({
1111
1143
  "src/lib/index.ts"() {
1112
1144
  init_ignore();
1113
1145
  init_integrity();
1146
+ init_lockfile();
1114
1147
  init_manifest();
1115
1148
  init_resolver();
1116
1149
  init_specifier();
@@ -1303,8 +1336,8 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
1303
1336
  const rootEntries = await readdir(sourcePath);
1304
1337
  const dirs = [];
1305
1338
  for (const entry of rootEntries) {
1306
- const stat7 = await lstat(join(sourcePath, entry)).catch(() => null);
1307
- if (stat7?.isDirectory() && !entry.startsWith(".")) {
1339
+ const stat8 = await lstat(join(sourcePath, entry)).catch(() => null);
1340
+ if (stat8?.isDirectory() && !entry.startsWith(".")) {
1308
1341
  dirs.push(entry);
1309
1342
  }
1310
1343
  }
@@ -1439,15 +1472,19 @@ async function writeLockfile(lockfile) {
1439
1472
  const hasDependencies = Object.values(packages).some(
1440
1473
  (pkg) => pkg.dependencies && Object.keys(pkg.dependencies).length > 0
1441
1474
  );
1442
- const version2 = hasDependencies ? 4 : 3;
1475
+ const version3 = hasDependencies ? 4 : 3;
1443
1476
  const normalized = {
1444
- lockfileVersion: version2,
1477
+ $schema: PSPM_LOCKFILE_SCHEMA_URL,
1478
+ lockfileVersion: version3,
1445
1479
  registryUrl: lockfile.registryUrl,
1446
1480
  packages
1447
1481
  };
1448
1482
  if (lockfile.githubPackages && Object.keys(lockfile.githubPackages).length > 0) {
1449
1483
  normalized.githubPackages = lockfile.githubPackages;
1450
1484
  }
1485
+ if (lockfile.localPackages && Object.keys(lockfile.localPackages).length > 0) {
1486
+ normalized.localPackages = lockfile.localPackages;
1487
+ }
1451
1488
  await writeFile(lockfilePath, `${JSON.stringify(normalized, null, 2)}
1452
1489
  `);
1453
1490
  }
@@ -1541,9 +1578,21 @@ async function listLockfileGitHubPackages() {
1541
1578
  entry
1542
1579
  }));
1543
1580
  }
1544
- var init_lockfile = __esm({
1581
+ async function addLocalToLockfile(specifier, entry) {
1582
+ let lockfile = await readLockfile();
1583
+ if (!lockfile) {
1584
+ lockfile = await createEmptyLockfile();
1585
+ }
1586
+ if (!lockfile.localPackages) {
1587
+ lockfile.localPackages = {};
1588
+ }
1589
+ lockfile.localPackages[specifier] = entry;
1590
+ await writeLockfile(lockfile);
1591
+ }
1592
+ var init_lockfile2 = __esm({
1545
1593
  "src/lockfile.ts"() {
1546
1594
  init_config();
1595
+ init_lib();
1547
1596
  }
1548
1597
  });
1549
1598
  function getManifestPath() {
@@ -1617,6 +1666,14 @@ async function removeGitHubDependency(specifier) {
1617
1666
  await writeManifest(manifest);
1618
1667
  return true;
1619
1668
  }
1669
+ async function addLocalDependency(specifier, version3 = "*") {
1670
+ const manifest = await ensureManifest();
1671
+ if (!manifest.localDependencies) {
1672
+ manifest.localDependencies = {};
1673
+ }
1674
+ manifest.localDependencies[specifier] = version3;
1675
+ await writeManifest(manifest);
1676
+ }
1620
1677
  var init_manifest2 = __esm({
1621
1678
  "src/manifest.ts"() {
1622
1679
  }
@@ -1696,6 +1753,9 @@ function getGitHubSkillPath(owner, repo, path) {
1696
1753
  }
1697
1754
  return `.pspm/skills/_github/${owner}/${repo}`;
1698
1755
  }
1756
+ function getLocalSkillPath(skillName) {
1757
+ return `.pspm/skills/_local/${skillName}`;
1758
+ }
1699
1759
  async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
1700
1760
  const linkedAgents = [];
1701
1761
  for (const agentName of agents) {
@@ -1723,13 +1783,31 @@ var add_exports = {};
1723
1783
  __export(add_exports, {
1724
1784
  add: () => add
1725
1785
  });
1786
+ function isLocalSpecifier2(specifier) {
1787
+ return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
1788
+ }
1789
+ function parseLocalPath(specifier) {
1790
+ if (specifier.startsWith("file:")) {
1791
+ return specifier.slice(5);
1792
+ }
1793
+ return specifier;
1794
+ }
1795
+ function normalizeToFileSpecifier(path) {
1796
+ if (path.startsWith("file:")) {
1797
+ return path;
1798
+ }
1799
+ return `file:${path}`;
1800
+ }
1726
1801
  async function add(specifiers, options) {
1727
1802
  console.log("Resolving packages...\n");
1728
1803
  const resolvedPackages = [];
1729
1804
  const validationErrors = [];
1730
1805
  for (const specifier of specifiers) {
1731
1806
  try {
1732
- if (isGitHubSpecifier(specifier)) {
1807
+ if (isLocalSpecifier2(specifier)) {
1808
+ const resolved = await validateLocalPackage(specifier);
1809
+ resolvedPackages.push(resolved);
1810
+ } else if (isGitHubSpecifier(specifier)) {
1733
1811
  const resolved = await validateGitHubPackage(specifier);
1734
1812
  resolvedPackages.push(resolved);
1735
1813
  } else {
@@ -1761,6 +1839,9 @@ async function add(specifiers, options) {
1761
1839
  const githubPackages = resolvedPackages.filter(
1762
1840
  (p) => p.type === "github"
1763
1841
  );
1842
+ const localPackages = resolvedPackages.filter(
1843
+ (p) => p.type === "local"
1844
+ );
1764
1845
  let resolutionResult = null;
1765
1846
  if (registryPackages.length > 0) {
1766
1847
  const rootDeps = {};
@@ -1845,6 +1926,24 @@ async function add(specifiers, options) {
1845
1926
  error: message
1846
1927
  });
1847
1928
  console.error(`Failed to install ${resolved.specifier}: ${message}
1929
+ `);
1930
+ }
1931
+ }
1932
+ for (const resolved of localPackages) {
1933
+ try {
1934
+ await installLocalPackage(resolved, {
1935
+ ...options,
1936
+ resolvedAgents: agents
1937
+ });
1938
+ results.push({ specifier: resolved.specifier, success: true });
1939
+ } catch (error) {
1940
+ const message = error instanceof Error ? error.message : "Unknown error";
1941
+ results.push({
1942
+ specifier: resolved.specifier,
1943
+ success: false,
1944
+ error: message
1945
+ });
1946
+ console.error(`Failed to install ${resolved.specifier}: ${message}
1848
1947
  `);
1849
1948
  }
1850
1949
  }
@@ -2069,6 +2168,91 @@ async function installGitHubPackage(resolved, options) {
2069
2168
  );
2070
2169
  console.log(`Location: ${destPath}`);
2071
2170
  }
2171
+ async function validateLocalPackage(specifier) {
2172
+ const path = parseLocalPath(specifier);
2173
+ const resolvedPath = resolve(process.cwd(), path);
2174
+ const normalizedSpecifier = normalizeToFileSpecifier(path);
2175
+ console.log(`Resolving ${specifier}...`);
2176
+ try {
2177
+ const stats = await stat(resolvedPath);
2178
+ if (!stats.isDirectory()) {
2179
+ throw new Error(`Path is not a directory: ${resolvedPath}`);
2180
+ }
2181
+ } catch (error) {
2182
+ if (error.code === "ENOENT") {
2183
+ throw new Error(
2184
+ `Directory not found: ${resolvedPath}
2185
+ Check that the path exists and is accessible.`
2186
+ );
2187
+ }
2188
+ throw error;
2189
+ }
2190
+ let hasSkillMd = false;
2191
+ let hasPspmJson = false;
2192
+ try {
2193
+ await stat(join(resolvedPath, "SKILL.md"));
2194
+ hasSkillMd = true;
2195
+ } catch {
2196
+ }
2197
+ try {
2198
+ await stat(join(resolvedPath, "pspm.json"));
2199
+ hasPspmJson = true;
2200
+ } catch {
2201
+ }
2202
+ if (!hasSkillMd && !hasPspmJson) {
2203
+ throw new Error(
2204
+ `Not a valid skill directory: ${resolvedPath}
2205
+ Missing both SKILL.md and pspm.json. At least one is required.`
2206
+ );
2207
+ }
2208
+ const name = basename(resolvedPath);
2209
+ console.log(`Resolved ${specifier} -> ${resolvedPath}`);
2210
+ return {
2211
+ type: "local",
2212
+ specifier,
2213
+ normalizedSpecifier,
2214
+ path,
2215
+ resolvedPath,
2216
+ name
2217
+ };
2218
+ }
2219
+ async function installLocalPackage(resolved, options) {
2220
+ const { specifier, normalizedSpecifier, path, resolvedPath, name } = resolved;
2221
+ console.log(`Installing ${specifier}...`);
2222
+ const skillsDir = getSkillsDir();
2223
+ const localSkillsDir = join(skillsDir, "_local");
2224
+ await mkdir(localSkillsDir, { recursive: true });
2225
+ const symlinkPath = join(localSkillsDir, name);
2226
+ const relativeTarget = relative(dirname(symlinkPath), resolvedPath);
2227
+ try {
2228
+ await rm(symlinkPath, { force: true });
2229
+ } catch {
2230
+ }
2231
+ await symlink(relativeTarget, symlinkPath);
2232
+ const entry = {
2233
+ version: "local",
2234
+ path,
2235
+ resolvedPath,
2236
+ name
2237
+ };
2238
+ await addLocalToLockfile(normalizedSpecifier, entry);
2239
+ await addLocalDependency(normalizedSpecifier);
2240
+ const agents = options.resolvedAgents;
2241
+ if (agents[0] !== "none") {
2242
+ const manifest = await readManifest();
2243
+ const skillInfo = {
2244
+ name,
2245
+ sourcePath: getLocalSkillPath(name)
2246
+ };
2247
+ await createAgentSymlinks([skillInfo], {
2248
+ agents,
2249
+ projectRoot: process.cwd(),
2250
+ agentConfigs: manifest?.agents
2251
+ });
2252
+ }
2253
+ console.log(`Installed ${specifier} (local)`);
2254
+ console.log(`Location: ${symlinkPath} -> ${resolvedPath}`);
2255
+ }
2072
2256
  var init_add = __esm({
2073
2257
  "src/commands/add.ts"() {
2074
2258
  init_agents();
@@ -2077,7 +2261,7 @@ var init_add = __esm({
2077
2261
  init_errors();
2078
2262
  init_github();
2079
2263
  init_lib();
2080
- init_lockfile();
2264
+ init_lockfile2();
2081
2265
  init_manifest2();
2082
2266
  init_symlinks();
2083
2267
  }
@@ -2087,6 +2271,9 @@ var init_add = __esm({
2087
2271
  init_api_client();
2088
2272
  init_config();
2089
2273
  init_lib();
2274
+ function isLocalSpecifier(specifier) {
2275
+ return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
2276
+ }
2090
2277
  async function access(specifier, options) {
2091
2278
  try {
2092
2279
  const apiKey = await requireApiKey();
@@ -2102,10 +2289,41 @@ async function access(specifier, options) {
2102
2289
  const visibility = options.public ? "public" : "private";
2103
2290
  let packageName;
2104
2291
  if (specifier) {
2292
+ if (isGitHubSpecifier(specifier)) {
2293
+ const ghSpec = parseGitHubSpecifier(specifier);
2294
+ if (ghSpec) {
2295
+ console.error(`Error: Cannot change visibility of GitHub packages.`);
2296
+ console.error(
2297
+ ` "${specifier}" is hosted on GitHub, not the PSPM registry.`
2298
+ );
2299
+ console.error(
2300
+ ` Visibility can only be changed for packages published to the registry.`
2301
+ );
2302
+ } else {
2303
+ console.error(`Error: Invalid GitHub specifier "${specifier}".`);
2304
+ console.error(` Use format: github:{owner}/{repo}[/{path}][@{ref}]`);
2305
+ }
2306
+ process.exit(1);
2307
+ }
2308
+ if (isLocalSpecifier(specifier)) {
2309
+ console.error(`Error: Cannot change visibility of local packages.`);
2310
+ console.error(
2311
+ ` "${specifier}" is a local directory, not a registry package.`
2312
+ );
2313
+ console.error(
2314
+ ` Visibility can only be changed for packages published to the registry.`
2315
+ );
2316
+ process.exit(1);
2317
+ }
2105
2318
  const parsed = parseSkillSpecifier(specifier);
2106
2319
  if (!parsed) {
2320
+ console.error(`Error: Invalid package specifier "${specifier}".`);
2321
+ console.error(` Use format: @user/{username}/{name}`);
2322
+ console.error(``);
2323
+ console.error(` Examples:`);
2324
+ console.error(` pspm access @user/myname/my-skill --public`);
2107
2325
  console.error(
2108
- `Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
2326
+ ` pspm access --public (uses current directory's pspm.json)`
2109
2327
  );
2110
2328
  process.exit(1);
2111
2329
  }
@@ -2301,10 +2519,10 @@ async function deprecate(specifier, message, options) {
2301
2519
  // src/commands/init.ts
2302
2520
  init_lib();
2303
2521
  function prompt(rl, question, defaultValue) {
2304
- return new Promise((resolve) => {
2522
+ return new Promise((resolve2) => {
2305
2523
  const displayDefault = defaultValue ? ` (${defaultValue})` : "";
2306
2524
  rl.question(`${question}${displayDefault} `, (answer) => {
2307
- resolve(answer.trim() || defaultValue);
2525
+ resolve2(answer.trim() || defaultValue);
2308
2526
  });
2309
2527
  });
2310
2528
  }
@@ -2355,8 +2573,8 @@ function sanitizeName(name) {
2355
2573
  function isValidName(name) {
2356
2574
  return /^[a-z][a-z0-9_-]*$/.test(name);
2357
2575
  }
2358
- function isValidVersion(version2) {
2359
- return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version2);
2576
+ function isValidVersion(version3) {
2577
+ return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version3);
2360
2578
  }
2361
2579
  async function init(options) {
2362
2580
  try {
@@ -2428,10 +2646,10 @@ async function init(options) {
2428
2646
  );
2429
2647
  name = await prompt(rl, "skill name:", sanitizeName(name));
2430
2648
  }
2431
- let version2 = await prompt(rl, "version:", defaultVersion);
2432
- while (!isValidVersion(version2)) {
2649
+ let version3 = await prompt(rl, "version:", defaultVersion);
2650
+ while (!isValidVersion(version3)) {
2433
2651
  console.log(" Version must be valid semver (e.g., 1.0.0)");
2434
- version2 = await prompt(rl, "version:", "0.1.0");
2652
+ version3 = await prompt(rl, "version:", "0.1.0");
2435
2653
  }
2436
2654
  const description = await prompt(
2437
2655
  rl,
@@ -2451,7 +2669,7 @@ async function init(options) {
2451
2669
  manifest = {
2452
2670
  $schema: PSPM_SCHEMA_URL,
2453
2671
  name,
2454
- version: version2,
2672
+ version: version3,
2455
2673
  description: description || void 0,
2456
2674
  author: author || void 0,
2457
2675
  license,
@@ -2488,9 +2706,9 @@ async function init(options) {
2488
2706
  input: process.stdin,
2489
2707
  output: process.stdout
2490
2708
  });
2491
- const confirm = await prompt(rl, "Is this OK?", "yes");
2709
+ const confirm2 = await prompt(rl, "Is this OK?", "yes");
2492
2710
  rl.close();
2493
- if (confirm.toLowerCase() !== "yes" && confirm.toLowerCase() !== "y") {
2711
+ if (confirm2.toLowerCase() !== "yes" && confirm2.toLowerCase() !== "y") {
2494
2712
  console.log("Aborted.");
2495
2713
  process.exit(0);
2496
2714
  }
@@ -2523,7 +2741,7 @@ init_config();
2523
2741
  init_errors();
2524
2742
  init_github();
2525
2743
  init_lib();
2526
- init_lockfile();
2744
+ init_lockfile2();
2527
2745
  init_manifest2();
2528
2746
  init_symlinks();
2529
2747
  function getCacheFilePath(cacheDir, integrity) {
@@ -2937,7 +3155,7 @@ All ${totalCount} skill(s) installed.`);
2937
3155
  // src/commands/link.ts
2938
3156
  init_agents();
2939
3157
  init_lib();
2940
- init_lockfile();
3158
+ init_lockfile2();
2941
3159
  init_manifest2();
2942
3160
  init_symlinks();
2943
3161
  async function link(options) {
@@ -3014,7 +3232,7 @@ async function link(options) {
3014
3232
  // src/commands/list.ts
3015
3233
  init_agents();
3016
3234
  init_lib();
3017
- init_lockfile();
3235
+ init_lockfile2();
3018
3236
  init_manifest2();
3019
3237
  init_symlinks();
3020
3238
  async function list(options) {
@@ -3141,7 +3359,11 @@ function getWebAppUrl(registryUrl) {
3141
3359
  }
3142
3360
  try {
3143
3361
  const url = new URL$1(registryUrl);
3144
- return `${url.protocol}//${url.host}`;
3362
+ let host = url.host;
3363
+ if (host.startsWith("registry.")) {
3364
+ host = host.slice("registry.".length);
3365
+ }
3366
+ return `${url.protocol}//${host}`;
3145
3367
  } catch {
3146
3368
  return DEFAULT_WEB_APP_URL;
3147
3369
  }
@@ -3149,7 +3371,11 @@ function getWebAppUrl(registryUrl) {
3149
3371
  function getServerUrl(registryUrl) {
3150
3372
  try {
3151
3373
  const url = new URL$1(registryUrl);
3152
- return `${url.protocol}//${url.host}`;
3374
+ let host = url.host;
3375
+ if (host.startsWith("registry.")) {
3376
+ host = host.slice("registry.".length);
3377
+ }
3378
+ return `${url.protocol}//${host}`;
3153
3379
  } catch {
3154
3380
  return DEFAULT_WEB_APP_URL;
3155
3381
  }
@@ -3175,8 +3401,8 @@ function startCallbackServer(expectedState) {
3175
3401
  let resolveToken;
3176
3402
  let rejectToken;
3177
3403
  let timeoutId;
3178
- const tokenPromise = new Promise((resolve, reject) => {
3179
- resolveToken = resolve;
3404
+ const tokenPromise = new Promise((resolve2, reject) => {
3405
+ resolveToken = resolve2;
3180
3406
  rejectToken = reject;
3181
3407
  });
3182
3408
  const server = http.createServer((req, res) => {
@@ -3330,7 +3556,7 @@ async function logout() {
3330
3556
 
3331
3557
  // src/commands/migrate.ts
3332
3558
  init_config();
3333
- init_lockfile();
3559
+ init_lockfile2();
3334
3560
  async function migrate(options) {
3335
3561
  try {
3336
3562
  const legacySkillsDir = getLegacySkillsDir();
@@ -3437,6 +3663,19 @@ init_config();
3437
3663
  init_errors();
3438
3664
  init_lib();
3439
3665
  var exec = promisify(exec$1);
3666
+ function confirm(question) {
3667
+ return new Promise((resolve2) => {
3668
+ const rl = createInterface({
3669
+ input: process.stdin,
3670
+ output: process.stdout
3671
+ });
3672
+ rl.question(`${question} (y/N) `, (answer) => {
3673
+ rl.close();
3674
+ const normalized = answer.trim().toLowerCase();
3675
+ resolve2(normalized === "y" || normalized === "yes");
3676
+ });
3677
+ });
3678
+ }
3440
3679
  async function detectManifest() {
3441
3680
  const cwd = process.cwd();
3442
3681
  const pspmJsonPath = join(cwd, "pspm.json");
@@ -3456,7 +3695,8 @@ async function detectManifest() {
3456
3695
  description: packageJson2.description,
3457
3696
  author: typeof packageJson2.author === "string" ? packageJson2.author : packageJson2.author?.name,
3458
3697
  license: packageJson2.license,
3459
- files: packageJson2.files
3698
+ files: packageJson2.files,
3699
+ dependencies: packageJson2.dependencies
3460
3700
  };
3461
3701
  return { type: "package.json", manifest, path: packageJsonPath };
3462
3702
  } catch {
@@ -3518,15 +3758,31 @@ async function publishCommand(options) {
3518
3758
  console.error(`Error: ${validation.error}`);
3519
3759
  process.exit(1);
3520
3760
  }
3761
+ if (options.access === "public") {
3762
+ console.log("");
3763
+ console.log("\u26A0\uFE0F Warning: You are about to publish this skill as PUBLIC.");
3764
+ console.log(
3765
+ " Once a skill is public, it CANNOT be made private again."
3766
+ );
3767
+ console.log(" This action is irreversible.");
3768
+ console.log("");
3769
+ const confirmed = await confirm("Do you want to continue?");
3770
+ if (!confirmed) {
3771
+ console.log("Publish cancelled.");
3772
+ process.exit(0);
3773
+ }
3774
+ console.log("");
3775
+ }
3521
3776
  const packageJson2 = {
3522
3777
  name: manifest.name,
3523
3778
  version: manifest.version,
3524
3779
  description: manifest.description,
3525
- files: manifest.files
3780
+ files: manifest.files,
3781
+ dependencies: manifest.dependencies
3526
3782
  };
3527
3783
  if (options.bump) {
3528
- const semver2 = await import('semver');
3529
- const newVersion = semver2.default.inc(packageJson2.version, options.bump);
3784
+ const semver3 = await import('semver');
3785
+ const newVersion = semver3.default.inc(packageJson2.version, options.bump);
3530
3786
  if (!newVersion) {
3531
3787
  console.error(
3532
3788
  `Error: Failed to bump version from ${packageJson2.version}`
@@ -3587,17 +3843,34 @@ async function publishCommand(options) {
3587
3843
  const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
3588
3844
  const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
3589
3845
  const integrity = `sha512-${integrityHash}`;
3846
+ const MAX_TARBALL_SIZE = 10 * 1024 * 1024;
3847
+ if (tarballSize > MAX_TARBALL_SIZE) {
3848
+ console.error("");
3849
+ console.error(
3850
+ `Error: Package size ${formatBytes(tarballSize)} exceeds the maximum allowed size of ${formatBytes(MAX_TARBALL_SIZE)}.`
3851
+ );
3852
+ console.error("");
3853
+ console.error("To reduce the package size:");
3854
+ console.error(
3855
+ ' - Add a "files" field in your manifest to include only necessary files'
3856
+ );
3857
+ console.error(" - Add patterns to .pspmignore to exclude large files");
3858
+ console.error(
3859
+ " - Remove build artifacts, tests, and documentation from the package"
3860
+ );
3861
+ process.exit(1);
3862
+ }
3590
3863
  console.log("");
3591
3864
  console.log("pspm notice");
3592
3865
  console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
3593
- console.log("pspm notice Tarball Contents");
3866
+ console.log("pspm notice === Tarball Contents ===");
3594
3867
  tarballContents.sort((a, b) => b.size - a.size);
3595
3868
  for (const file of tarballContents) {
3596
3869
  console.log(
3597
3870
  `pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
3598
3871
  );
3599
3872
  }
3600
- console.log("pspm notice Tarball Details");
3873
+ console.log("pspm notice === Tarball Details ===");
3601
3874
  console.log(`pspm notice name: ${packageJson2.name}`);
3602
3875
  console.log(`pspm notice version: ${packageJson2.version}`);
3603
3876
  console.log(`pspm notice filename: ${tarballName}`);
@@ -3609,11 +3882,20 @@ async function publishCommand(options) {
3609
3882
  );
3610
3883
  console.log(`pspm notice total files: ${tarballContents.length}`);
3611
3884
  console.log("pspm notice");
3885
+ const confirmed = await confirm(
3886
+ `Publish ${packageJson2.name}@${packageJson2.version} to ${registryUrl}?`
3887
+ );
3888
+ if (!confirmed) {
3889
+ console.log("Publish cancelled.");
3890
+ process.exit(0);
3891
+ }
3892
+ console.log("");
3612
3893
  console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
3613
3894
  configure2({ registryUrl, apiKey });
3614
3895
  const response = await publishSkill({
3615
3896
  manifest: packageJson2,
3616
- tarballBase64
3897
+ tarballBase64,
3898
+ visibility: options.access
3617
3899
  });
3618
3900
  if (response.status !== 200) {
3619
3901
  const errorMessage = extractApiErrorMessage(response, "Publish failed");
@@ -3626,28 +3908,17 @@ async function publishCommand(options) {
3626
3908
  throw new Error(errorMessage);
3627
3909
  }
3628
3910
  const result = response.data;
3911
+ const visibility = result.skill.visibility;
3912
+ const visibilityIcon = visibility === "public" ? "\u{1F310}" : "\u{1F512}";
3629
3913
  console.log(
3630
3914
  `+ @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
3631
3915
  );
3632
3916
  console.log(`Checksum: ${result.version.checksum}`);
3633
- if (options.access) {
3634
- console.log(`
3635
- Setting visibility to ${options.access}...`);
3636
- const accessResponse = await changeSkillAccess(packageJson2.name, {
3637
- visibility: options.access
3638
- });
3639
- if (accessResponse.status !== 200 || !accessResponse.data) {
3640
- console.warn(
3641
- `Warning: Failed to set visibility: ${accessResponse.error ?? "Unknown error"}`
3642
- );
3643
- } else {
3644
- console.log(`Package is now ${accessResponse.data.visibility}`);
3645
- if (options.access === "public") {
3646
- console.log(
3647
- "Note: This action is irreversible. Public packages cannot be made private."
3648
- );
3649
- }
3650
- }
3917
+ console.log(`Visibility: ${visibilityIcon} ${visibility}`);
3918
+ if (visibility === "public") {
3919
+ console.log(
3920
+ "Note: Public packages cannot be made private. This is irreversible."
3921
+ );
3651
3922
  }
3652
3923
  } finally {
3653
3924
  await exec(`rm -rf "${tempDir}"`).catch(() => {
@@ -3667,7 +3938,7 @@ Setting visibility to ${options.access}...`);
3667
3938
  init_agents();
3668
3939
  init_config();
3669
3940
  init_lib();
3670
- init_lockfile();
3941
+ init_lockfile2();
3671
3942
  init_manifest2();
3672
3943
  init_symlinks();
3673
3944
  async function remove(nameOrSpecifier) {
@@ -3837,7 +4108,7 @@ init_api_client();
3837
4108
  init_config();
3838
4109
  init_errors();
3839
4110
  init_lib();
3840
- init_lockfile();
4111
+ init_lockfile2();
3841
4112
  init_add();
3842
4113
  async function update(options) {
3843
4114
  try {
@@ -3910,6 +4181,52 @@ async function update(options) {
3910
4181
  }
3911
4182
  }
3912
4183
 
4184
+ // src/commands/version.ts
4185
+ init_manifest2();
4186
+ async function version(bump, options = {}) {
4187
+ try {
4188
+ const manifest = await readManifest();
4189
+ if (!manifest) {
4190
+ console.error("Error: No pspm.json found in current directory.");
4191
+ console.error("Run 'pspm init' to create one.");
4192
+ process.exit(1);
4193
+ }
4194
+ if (!manifest.version) {
4195
+ console.error("Error: pspm.json does not have a version field.");
4196
+ console.error(
4197
+ 'Add a version field (e.g., "version": "0.1.0") to your pspm.json.'
4198
+ );
4199
+ process.exit(1);
4200
+ }
4201
+ if (!semver__default.valid(manifest.version)) {
4202
+ console.error(
4203
+ `Error: Current version "${manifest.version}" is not valid semver.`
4204
+ );
4205
+ console.error(
4206
+ 'Fix the version in pspm.json to be valid semver (e.g., "1.0.0").'
4207
+ );
4208
+ process.exit(1);
4209
+ }
4210
+ const newVersion = semver__default.inc(manifest.version, bump);
4211
+ if (!newVersion) {
4212
+ console.error(`Error: Failed to bump version from ${manifest.version}`);
4213
+ process.exit(1);
4214
+ }
4215
+ if (options.dryRun) {
4216
+ console.log(`Would bump version: ${manifest.version} \u2192 ${newVersion}`);
4217
+ return;
4218
+ }
4219
+ manifest.version = newVersion;
4220
+ await writeManifest(manifest);
4221
+ console.log(`v${newVersion}`);
4222
+ console.log(`Updated ${getManifestPath()}`);
4223
+ } catch (error) {
4224
+ const message = error instanceof Error ? error.message : "Unknown error";
4225
+ console.error(`Error: ${message}`);
4226
+ process.exit(1);
4227
+ }
4228
+ }
4229
+
3913
4230
  // src/commands/whoami.ts
3914
4231
  init_api_client();
3915
4232
  init_config();
@@ -3942,9 +4259,9 @@ var __dirname$1 = dirname(fileURLToPath(import.meta.url));
3942
4259
  var packageJson = JSON.parse(
3943
4260
  readFileSync(join(__dirname$1, "..", "package.json"), "utf-8")
3944
4261
  );
3945
- var version = packageJson.version;
4262
+ var version2 = packageJson.version;
3946
4263
  var program = new Command();
3947
- program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version);
4264
+ program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version2);
3948
4265
  var configCmd = program.command("config").description("Manage PSPM configuration");
3949
4266
  configCmd.command("show").description("Show resolved configuration").action(async () => {
3950
4267
  await configShow();
@@ -4020,6 +4337,17 @@ program.command("link").description("Recreate agent symlinks without reinstallin
4020
4337
  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) => {
4021
4338
  await update({ dryRun: options.dryRun });
4022
4339
  });
4340
+ program.command("version <bump>").description("Bump package version (major, minor, patch)").option("--dry-run", "Show what would be changed without writing").action(async (bump, options) => {
4341
+ const validBumps = ["major", "minor", "patch"];
4342
+ if (!validBumps.includes(bump)) {
4343
+ console.error(`Error: Invalid version bump "${bump}".`);
4344
+ console.error("Must be one of: major, minor, patch");
4345
+ process.exit(1);
4346
+ }
4347
+ await version(bump, {
4348
+ dryRun: options.dryRun
4349
+ });
4350
+ });
4023
4351
  program.command("publish").description("Publish current directory as a skill").option("--bump <level>", "Bump version (major, minor, patch)").option("--tag <tag>", "Tag for the release").option("--access <level>", "Set package visibility (public or private)").action(async (options) => {
4024
4352
  await publishCommand({
4025
4353
  bump: options.bump,