@anytio/pspm 0.10.0 → 0.11.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/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to the PSPM CLI will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.11.0] - 2026-03-17
9
+
10
+ ### Added
11
+
12
+ - **Skill list install**: Install all skills from a curated skill list with `pspm install --list @user/username/list-name`
13
+ - Supports both user and org lists: `@user/{username}/{list-name}` or `@org/{orgname}/{list-name}`
14
+ - Fetches list from the registry API and resolves items to registry specifiers
15
+ - Respects pinned versions when specified in the list
16
+ - Can be combined with explicit specifiers for additional packages
17
+
18
+ ### Changed
19
+
20
+ - Updated all dependencies to latest versions
21
+
8
22
  ## [0.10.0] - 2026-03-14
9
23
 
10
24
  ### Added
package/README.md CHANGED
@@ -146,6 +146,10 @@ pspm install --dir ./custom-path
146
146
 
147
147
  # Install specific packages
148
148
  pspm install @user/alice/skill1 github:org/repo
149
+
150
+ # Install all skills from a skill list
151
+ pspm install --list @user/alice/my-favorites
152
+ pspm install --list @org/myorg/team-skills
149
153
  ```
150
154
 
151
155
  ### `pspm search`
package/dist/index.js CHANGED
@@ -37,6 +37,9 @@ function getConfig() {
37
37
  }
38
38
  return config;
39
39
  }
40
+ function isConfigured() {
41
+ return config !== null;
42
+ }
40
43
  async function customFetch(url, options) {
41
44
  const { baseUrl, apiKey } = getConfig();
42
45
  const fullUrl = `${baseUrl}${url}`;
@@ -66,18 +69,42 @@ async function customFetch(url, options) {
66
69
  headers: response.headers
67
70
  };
68
71
  }
69
- var config;
72
+ var config, SDKError;
70
73
  var init_fetcher = __esm({
71
74
  "src/sdk/fetcher.ts"() {
72
75
  config = null;
76
+ SDKError = class extends Error {
77
+ constructor(message, status, body) {
78
+ super(message);
79
+ this.status = status;
80
+ this.body = body;
81
+ this.name = "SDKError";
82
+ }
83
+ };
73
84
  }
74
85
  });
75
86
 
76
87
  // src/sdk/generated/index.ts
77
- var getMeUrl, me, getExplorePublicSkillsUrl, explorePublicSkills, getDeleteSkillUrl, deleteSkill, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getDeleteSkillVersionUrl, deleteSkillVersion, getPublishSkillUrl, publishSkill, getListOrgSkillVersionsUrl, listOrgSkillVersions, getGetOrgSkillVersionUrl, getOrgSkillVersion, getPublishOrgSkillUrl, publishOrgSkill;
88
+ var getExchangeCliTokenUrl, exchangeCliToken, getMeUrl, me, getExplorePublicSkillsUrl, explorePublicSkills, getListMySkillsUrl, listMySkills, getListUserSkillsUrl, listUserSkills, getGetSkillUrl, getSkill, getDeleteSkillUrl, deleteSkill, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getDeleteSkillVersionUrl, deleteSkillVersion, getPublishSkillUrl, publishSkill, getListOrgSkillVersionsUrl, listOrgSkillVersions, getGetOrgSkillVersionUrl, getOrgSkillVersion, getPublishOrgSkillUrl, publishOrgSkill;
78
89
  var init_generated = __esm({
79
90
  "src/sdk/generated/index.ts"() {
80
91
  init_fetcher();
92
+ getExchangeCliTokenUrl = () => {
93
+ return `/api/api-keys/cli-token-exchange`;
94
+ };
95
+ exchangeCliToken = async (exchangeCliTokenInput, options) => {
96
+ return customFetch(
97
+ getExchangeCliTokenUrl(),
98
+ {
99
+ ...options,
100
+ method: "POST",
101
+ headers: { "Content-Type": "application/json", ...options?.headers },
102
+ body: JSON.stringify(
103
+ exchangeCliTokenInput
104
+ )
105
+ }
106
+ );
107
+ };
81
108
  getMeUrl = () => {
82
109
  return `/api/skills/-/me`;
83
110
  };
@@ -109,6 +136,42 @@ var init_generated = __esm({
109
136
  }
110
137
  );
111
138
  };
139
+ getListMySkillsUrl = () => {
140
+ return `/api/skills/-/mine`;
141
+ };
142
+ listMySkills = async (options) => {
143
+ return customFetch(
144
+ getListMySkillsUrl(),
145
+ {
146
+ ...options,
147
+ method: "GET"
148
+ }
149
+ );
150
+ };
151
+ getListUserSkillsUrl = (username) => {
152
+ return `/api/skills/@user/${username}`;
153
+ };
154
+ listUserSkills = async (username, options) => {
155
+ return customFetch(
156
+ getListUserSkillsUrl(username),
157
+ {
158
+ ...options,
159
+ method: "GET"
160
+ }
161
+ );
162
+ };
163
+ getGetSkillUrl = (username, name) => {
164
+ return `/api/skills/@user/${username}/${name}`;
165
+ };
166
+ getSkill = async (username, name, options) => {
167
+ return customFetch(
168
+ getGetSkillUrl(username, name),
169
+ {
170
+ ...options,
171
+ method: "GET"
172
+ }
173
+ );
174
+ };
112
175
  getDeleteSkillUrl = (username, name) => {
113
176
  return `/api/skills/@user/${username}/${name}`;
114
177
  };
@@ -217,6 +280,33 @@ var init_generated = __esm({
217
280
  });
218
281
 
219
282
  // src/api-client.ts
283
+ var api_client_exports = {};
284
+ __export(api_client_exports, {
285
+ SDKError: () => SDKError,
286
+ changeSkillAccess: () => changeSkillAccess,
287
+ configure: () => configure2,
288
+ deleteSkill: () => deleteSkill,
289
+ deleteSkillVersion: () => deleteSkillVersion,
290
+ deprecateSkillVersion: () => deprecateSkillVersion,
291
+ exchangeCliToken: () => exchangeCliToken,
292
+ fetchSkillList: () => fetchSkillList,
293
+ getConfig: () => getConfig,
294
+ getGithubSkillVersion: () => getGithubSkillVersion,
295
+ getOrgSkillVersion: () => getOrgSkillVersion,
296
+ getSkill: () => getSkill,
297
+ getSkillVersion: () => getSkillVersion,
298
+ isConfigured: () => isConfigured,
299
+ listGithubSkillVersions: () => listGithubSkillVersions,
300
+ listMySkills: () => listMySkills,
301
+ listOrgSkillVersions: () => listOrgSkillVersions,
302
+ listSkillVersions: () => listSkillVersions,
303
+ listUserSkills: () => listUserSkills,
304
+ me: () => me,
305
+ publishOrgSkill: () => publishOrgSkill,
306
+ publishSkill: () => publishSkill,
307
+ undeprecateSkillVersion: () => undeprecateSkillVersion,
308
+ whoamiRequest: () => whoamiRequest
309
+ });
220
310
  function registryUrlToBaseUrl(registryUrl) {
221
311
  return registryUrl.replace(/\/api\/skills\/?$/, "");
222
312
  }
@@ -298,6 +388,32 @@ async function undeprecateSkillVersion(username, skillName, version3) {
298
388
  };
299
389
  }
300
390
  }
391
+ async function fetchSkillList(ownerType, ownerName, listName) {
392
+ const config2 = getConfig();
393
+ try {
394
+ const response = await fetch(
395
+ `${config2.baseUrl}/api/skill-lists/lists/@${ownerType}/${ownerName}/${listName}`,
396
+ {
397
+ method: "GET",
398
+ headers: {
399
+ "Content-Type": "application/json",
400
+ ...config2.apiKey ? { Authorization: `Bearer ${config2.apiKey}` } : {}
401
+ }
402
+ }
403
+ );
404
+ if (!response.ok) {
405
+ const error = await response.text();
406
+ return { status: response.status, error };
407
+ }
408
+ const data = await response.json();
409
+ return { status: response.status, data };
410
+ } catch (error) {
411
+ return {
412
+ status: 500,
413
+ error: error instanceof Error ? error.message : "Unknown error"
414
+ };
415
+ }
416
+ }
301
417
  async function listGithubSkillVersions(owner, repo, name) {
302
418
  const config2 = getConfig();
303
419
  try {
@@ -3951,6 +4067,22 @@ async function install(specifiers, options) {
3951
4067
  const { setGlobalMode: setGlobalMode2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3952
4068
  setGlobalMode2(true);
3953
4069
  }
4070
+ if (options.list) {
4071
+ const listSpecifiers = await resolveListToSpecifiers(options.list);
4072
+ if (listSpecifiers.length === 0) {
4073
+ console.log("No skills in the list to install.");
4074
+ return;
4075
+ }
4076
+ const allSpecifiers = [...specifiers, ...listSpecifiers];
4077
+ const { add: add2 } = await Promise.resolve().then(() => (init_add(), add_exports));
4078
+ await add2(allSpecifiers, {
4079
+ save: true,
4080
+ agent: options.agent,
4081
+ yes: options.yes,
4082
+ global: options.global
4083
+ });
4084
+ return;
4085
+ }
3954
4086
  if (specifiers.length > 0) {
3955
4087
  const { add: add2 } = await Promise.resolve().then(() => (init_add(), add_exports));
3956
4088
  await add2(specifiers, {
@@ -3963,6 +4095,52 @@ async function install(specifiers, options) {
3963
4095
  }
3964
4096
  await installFromLockfile(options);
3965
4097
  }
4098
+ async function resolveListToSpecifiers(listSpec) {
4099
+ const match = listSpec.match(/^@(user|org)\/([^/]+)\/([^/]+)$/);
4100
+ if (!match) {
4101
+ console.error(
4102
+ `Error: Invalid list specifier "${listSpec}". Use format: @user/{username}/{list-name} or @org/{orgname}/{list-name}`
4103
+ );
4104
+ process.exit(1);
4105
+ }
4106
+ const [, ownerType, ownerName, listName] = match;
4107
+ const config2 = await resolveConfig();
4108
+ configure2({
4109
+ registryUrl: config2.registryUrl,
4110
+ apiKey: getTokenForRegistry(config2, config2.registryUrl)
4111
+ });
4112
+ console.log(
4113
+ `Fetching skill list @${ownerType}/${ownerName}/${listName}...
4114
+ `
4115
+ );
4116
+ const { fetchSkillList: fetchSkillList2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
4117
+ const response = await fetchSkillList2(
4118
+ ownerType,
4119
+ ownerName,
4120
+ listName
4121
+ );
4122
+ if (response.status !== 200 || !response.data) {
4123
+ const errorMsg = response.status === 404 ? `List "@${ownerType}/${ownerName}/${listName}" not found or is private.` : response.error || "Failed to fetch list";
4124
+ console.error(`Error: ${errorMsg}`);
4125
+ process.exit(1);
4126
+ }
4127
+ const list2 = response.data;
4128
+ console.log(
4129
+ `List: ${list2.name}${list2.description ? ` \u2014 ${list2.description}` : ""}`
4130
+ );
4131
+ console.log(`Skills: ${list2.items.length}
4132
+ `);
4133
+ const specifiers = [];
4134
+ for (const item of list2.items) {
4135
+ const ns = item.namespace === "org" ? "org" : "user";
4136
+ let spec = `@${ns}/${item.ownerName}/${item.skillName}`;
4137
+ if (item.pinnedVersion) {
4138
+ spec += `@${item.pinnedVersion}`;
4139
+ }
4140
+ specifiers.push(spec);
4141
+ }
4142
+ return specifiers;
4143
+ }
3966
4144
  async function installFromLockfile(options) {
3967
4145
  try {
3968
4146
  const config2 = await resolveConfig();
@@ -6100,11 +6278,15 @@ program.command("install [specifiers...]").alias("i").description(
6100
6278
  ).option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").option(
6101
6279
  "--agent <agents>",
6102
6280
  'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
6281
+ ).option(
6282
+ "--list <specifier>",
6283
+ "Install all skills from a skill list (e.g. @user/username/list-name)"
6103
6284
  ).option("-g, --global", "Install to user home directory instead of project").option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
6104
6285
  await install(specifiers, {
6105
6286
  frozenLockfile: options.frozenLockfile,
6106
6287
  dir: options.dir,
6107
6288
  agent: options.agent,
6289
+ list: options.list,
6108
6290
  yes: options.yes,
6109
6291
  global: options.global
6110
6292
  });