@anytio/pspm 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -0
- package/dist/index.js +133 -90
- package/dist/index.js.map +1 -1
- package/package.json +65 -59
package/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# PSPM - Prompt Skill Package Manager
|
|
2
|
+
|
|
3
|
+
A CLI for managing prompt skills across AI coding agents.
|
|
4
|
+
|
|
5
|
+
## What is PSPM?
|
|
6
|
+
|
|
7
|
+
PSPM (Prompt Skill Package Manager) is a package manager for prompt skills - small, discoverable capabilities packaged as `SKILL.md` files. Think of it as npm for AI agent skills.
|
|
8
|
+
|
|
9
|
+
Skills are designed to work with any AI coding agent that supports the SKILL.md format, including Claude Code, Cursor, Windsurf, and others.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @anytio/pspm
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or use with npx:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @anytio/pspm <command>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Login with your API key
|
|
27
|
+
pspm login --api-key <your-api-key>
|
|
28
|
+
|
|
29
|
+
# Add a skill to your project
|
|
30
|
+
pspm add @user/username/skill-name
|
|
31
|
+
|
|
32
|
+
# List installed skills
|
|
33
|
+
pspm list
|
|
34
|
+
|
|
35
|
+
# Install all skills from lockfile
|
|
36
|
+
pspm install
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Commands
|
|
40
|
+
|
|
41
|
+
### Authentication
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pspm login --api-key <key> # Authenticate with API key
|
|
45
|
+
pspm logout # Clear stored credentials
|
|
46
|
+
pspm whoami # Show current user info
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Skill Management
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pspm add <specifier> # Add and install a skill
|
|
53
|
+
pspm remove <name> # Remove an installed skill (alias: rm)
|
|
54
|
+
pspm list # List installed skills (alias: ls)
|
|
55
|
+
pspm install # Install all skills from lockfile (alias: i)
|
|
56
|
+
pspm update # Update skills to latest compatible versions
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Specifier formats:**
|
|
60
|
+
- `@user/username/skillname` - Latest version
|
|
61
|
+
- `@user/username/skillname@2.0.0` - Specific version
|
|
62
|
+
- `@user/username/skillname@^2.0.0` - Semver range
|
|
63
|
+
|
|
64
|
+
### Publishing
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pspm publish # Publish current directory as a skill
|
|
68
|
+
pspm publish --bump patch # Auto-bump version (major, minor, patch)
|
|
69
|
+
pspm unpublish <spec> --force # Remove a published skill version
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Configuration
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pspm config list # List all profiles
|
|
76
|
+
pspm config show # Show resolved configuration
|
|
77
|
+
pspm config add <name> # Create a new profile
|
|
78
|
+
pspm config use <name> # Set the default profile
|
|
79
|
+
pspm config set <profile> <key> <value> # Set a profile field
|
|
80
|
+
pspm config delete <name> # Delete a profile
|
|
81
|
+
pspm config init # Create .pspmrc in current directory
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
### User Config (`~/.pspm/config.json`)
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"version": 2,
|
|
91
|
+
"defaultProfile": "default",
|
|
92
|
+
"profiles": {
|
|
93
|
+
"default": {
|
|
94
|
+
"registryUrl": "https://pspm.dev/api/skills",
|
|
95
|
+
"apiKey": "sk_...",
|
|
96
|
+
"username": "myuser"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Project Config (`.pspmrc`)
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"profile": "production",
|
|
107
|
+
"registryUrl": "https://custom-registry.example.com/api/skills"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Lockfile (`skill-lock.json`)
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"lockfileVersion": 1,
|
|
116
|
+
"registryUrl": "https://pspm.dev/api/skills",
|
|
117
|
+
"skills": {
|
|
118
|
+
"@user/username/skillname": {
|
|
119
|
+
"version": "1.0.0",
|
|
120
|
+
"resolved": "https://pspm.dev/api/skills/@user/username/skillname/1.0.0/download",
|
|
121
|
+
"integrity": "sha256-..."
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Environment Variables
|
|
128
|
+
|
|
129
|
+
| Variable | Description |
|
|
130
|
+
|----------|-------------|
|
|
131
|
+
| `PSPM_PROFILE` | Select active profile |
|
|
132
|
+
| `PSPM_REGISTRY_URL` | Override registry URL |
|
|
133
|
+
| `PSPM_API_KEY` | Override API key |
|
|
134
|
+
| `PSPM_DEBUG` | Enable debug logging |
|
|
135
|
+
|
|
136
|
+
## Directory Structure
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
project/
|
|
140
|
+
├── .pspmrc # Project config (optional)
|
|
141
|
+
├── skill-lock.json # Lockfile
|
|
142
|
+
└── .skills/ # Installed skills
|
|
143
|
+
└── username/
|
|
144
|
+
└── skillname/
|
|
145
|
+
├── SKILL.md
|
|
146
|
+
└── ...
|
|
147
|
+
|
|
148
|
+
~/.pspm/
|
|
149
|
+
└── config.json # User config
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Creating a Skill
|
|
153
|
+
|
|
154
|
+
A skill is a directory containing at minimum a `package.json` and `SKILL.md`:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
my-skill/
|
|
158
|
+
├── package.json # Required: name, version
|
|
159
|
+
├── SKILL.md # Required: skill instructions
|
|
160
|
+
├── runtime/ # Optional: runtime files
|
|
161
|
+
├── scripts/ # Optional: scripts
|
|
162
|
+
└── data/ # Optional: data files
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**package.json:**
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"name": "@user/myusername/my-skill",
|
|
169
|
+
"version": "1.0.0",
|
|
170
|
+
"description": "A helpful skill for...",
|
|
171
|
+
"files": ["package.json", "SKILL.md", "runtime", "scripts", "data"]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**SKILL.md:**
|
|
176
|
+
```markdown
|
|
177
|
+
---
|
|
178
|
+
name: my-skill
|
|
179
|
+
description: A helpful skill that does X
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
# Instructions
|
|
183
|
+
|
|
184
|
+
When activated, this skill helps you...
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## CI/CD Integration
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Use environment variables
|
|
191
|
+
export PSPM_API_KEY=sk_ci_key
|
|
192
|
+
export PSPM_REGISTRY_URL=https://registry.example.com/api/skills
|
|
193
|
+
|
|
194
|
+
# Install with frozen lockfile (fails if lockfile is outdated)
|
|
195
|
+
pspm install --frozen-lockfile
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Multi-Registry Setup
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Create profiles for different registries
|
|
202
|
+
pspm config add production --registry-url https://prod.example.com/api/skills
|
|
203
|
+
pspm config add staging --registry-url https://staging.example.com/api/skills
|
|
204
|
+
|
|
205
|
+
# Login to each
|
|
206
|
+
pspm login --api-key sk_prod_xxx --profile production
|
|
207
|
+
pspm login --api-key sk_staging_xxx --profile staging
|
|
208
|
+
|
|
209
|
+
# Use specific profile for operations
|
|
210
|
+
pspm add @user/bsheng/skill --profile production
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
See LICENSE file.
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ function resolveVersion(range, availableVersions) {
|
|
|
38
38
|
return semver.maxSatisfying(sorted, range);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// ../../packages/sdk/src/
|
|
41
|
+
// ../../packages/sdk/src/fetcher.ts
|
|
42
42
|
var config = null;
|
|
43
43
|
function configure(options) {
|
|
44
44
|
config = options;
|
|
@@ -49,18 +49,10 @@ function getConfig() {
|
|
|
49
49
|
}
|
|
50
50
|
return config;
|
|
51
51
|
}
|
|
52
|
-
|
|
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 = {}) {
|
|
52
|
+
async function customFetch(url, options) {
|
|
61
53
|
const { baseUrl, apiKey } = getConfig();
|
|
62
|
-
const
|
|
63
|
-
const response = await fetch(
|
|
54
|
+
const fullUrl = `${baseUrl}${url}`;
|
|
55
|
+
const response = await fetch(fullUrl, {
|
|
64
56
|
...options,
|
|
65
57
|
headers: {
|
|
66
58
|
...options.headers,
|
|
@@ -68,64 +60,114 @@ async function apiFetch(path, options = {}) {
|
|
|
68
60
|
"Content-Type": "application/json"
|
|
69
61
|
}
|
|
70
62
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
const text = await response.text();
|
|
64
|
+
let data = null;
|
|
65
|
+
if (text) {
|
|
74
66
|
try {
|
|
75
|
-
|
|
76
|
-
if (errorJson.message) {
|
|
77
|
-
errorMessage = errorJson.message;
|
|
78
|
-
} else if (errorJson.error) {
|
|
79
|
-
errorMessage = errorJson.error;
|
|
80
|
-
}
|
|
67
|
+
data = JSON.parse(text);
|
|
81
68
|
} catch {
|
|
82
|
-
|
|
83
|
-
errorMessage = errorText;
|
|
84
|
-
}
|
|
69
|
+
data = text;
|
|
85
70
|
}
|
|
86
|
-
throw new SDKError(errorMessage, response.status, errorText);
|
|
87
|
-
}
|
|
88
|
-
const text = await response.text();
|
|
89
|
-
if (!text) {
|
|
90
|
-
return null;
|
|
91
71
|
}
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
72
|
+
return {
|
|
73
|
+
data,
|
|
74
|
+
status: response.status,
|
|
75
|
+
headers: response.headers
|
|
76
|
+
};
|
|
96
77
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
78
|
+
|
|
79
|
+
// ../../packages/sdk/src/generated/index.ts
|
|
80
|
+
var getMeUrl = () => {
|
|
81
|
+
return `/me`;
|
|
82
|
+
};
|
|
83
|
+
var me = async (options) => {
|
|
84
|
+
return customFetch(
|
|
85
|
+
getMeUrl(),
|
|
86
|
+
{
|
|
87
|
+
...options,
|
|
88
|
+
method: "GET"
|
|
89
|
+
}
|
|
101
90
|
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
91
|
+
};
|
|
92
|
+
var getListSkillVersionsUrl = (username, name) => {
|
|
93
|
+
return `/@user/${username}/${name}/versions`;
|
|
94
|
+
};
|
|
95
|
+
var listSkillVersions = async (username, name, options) => {
|
|
96
|
+
return customFetch(
|
|
97
|
+
getListSkillVersionsUrl(username, name),
|
|
98
|
+
{
|
|
99
|
+
...options,
|
|
100
|
+
method: "GET"
|
|
101
|
+
}
|
|
107
102
|
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
103
|
+
};
|
|
104
|
+
var getGetSkillVersionUrl = (username, name, version2) => {
|
|
105
|
+
return `/@user/${username}/${name}/${version2}`;
|
|
106
|
+
};
|
|
107
|
+
var getSkillVersion = async (username, name, version2, options) => {
|
|
108
|
+
return customFetch(
|
|
109
|
+
getGetSkillVersionUrl(username, name, version2),
|
|
110
|
+
{
|
|
111
|
+
...options,
|
|
112
|
+
method: "GET"
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
var getPublishSkillUrl = () => {
|
|
117
|
+
return `/publish`;
|
|
118
|
+
};
|
|
119
|
+
var publishSkill = async (publishSkillBody, options) => {
|
|
120
|
+
return customFetch(
|
|
121
|
+
getPublishSkillUrl(),
|
|
122
|
+
{
|
|
123
|
+
...options,
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
126
|
+
body: JSON.stringify(
|
|
127
|
+
publishSkillBody
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
var getDeleteSkillUrl = (name) => {
|
|
133
|
+
return `/${name}`;
|
|
134
|
+
};
|
|
135
|
+
var deleteSkill = async (name, deleteSkillBody, options) => {
|
|
136
|
+
return customFetch(
|
|
137
|
+
getDeleteSkillUrl(name),
|
|
138
|
+
{
|
|
139
|
+
...options,
|
|
140
|
+
method: "DELETE",
|
|
141
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
142
|
+
body: JSON.stringify(
|
|
143
|
+
deleteSkillBody
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
var getDeleteSkillVersionUrl = (name, version2) => {
|
|
149
|
+
return `/${name}/${version2}`;
|
|
150
|
+
};
|
|
151
|
+
var deleteSkillVersion = async (name, version2, deleteSkillVersionBody, options) => {
|
|
152
|
+
return customFetch(
|
|
153
|
+
getDeleteSkillVersionUrl(name, version2),
|
|
154
|
+
{
|
|
155
|
+
...options,
|
|
156
|
+
method: "DELETE",
|
|
157
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
158
|
+
body: JSON.stringify(
|
|
159
|
+
deleteSkillVersionBody
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
};
|
|
123
164
|
|
|
124
165
|
// src/api-client.ts
|
|
125
166
|
async function whoamiRequest(registryUrl, apiKey) {
|
|
126
167
|
try {
|
|
127
|
-
configure({ baseUrl:
|
|
128
|
-
const
|
|
168
|
+
configure({ baseUrl: registryUrl, apiKey });
|
|
169
|
+
const response = await me();
|
|
170
|
+
const user = response.data;
|
|
129
171
|
if (!user) {
|
|
130
172
|
return null;
|
|
131
173
|
}
|
|
@@ -492,9 +534,10 @@ async function add(specifier, _options, globalOptions) {
|
|
|
492
534
|
process.exit(1);
|
|
493
535
|
}
|
|
494
536
|
const { username, name, versionRange } = parsed;
|
|
495
|
-
configure({ baseUrl:
|
|
537
|
+
configure({ baseUrl: registryUrl, apiKey });
|
|
496
538
|
console.log(`Resolving ${specifier}...`);
|
|
497
|
-
const
|
|
539
|
+
const versionsResponse = await listSkillVersions(username, name);
|
|
540
|
+
const versions = versionsResponse.data;
|
|
498
541
|
if (versions.length === 0) {
|
|
499
542
|
console.error(`Error: Skill @user/${username}/${name} not found`);
|
|
500
543
|
process.exit(1);
|
|
@@ -509,11 +552,8 @@ async function add(specifier, _options, globalOptions) {
|
|
|
509
552
|
process.exit(1);
|
|
510
553
|
}
|
|
511
554
|
console.log(`Installing @user/${username}/${name}@${resolved}...`);
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
name,
|
|
515
|
-
version: resolved
|
|
516
|
-
});
|
|
555
|
+
const versionResponse = await getSkillVersion(username, name, resolved);
|
|
556
|
+
const versionInfo = versionResponse.data;
|
|
517
557
|
if (!versionInfo) {
|
|
518
558
|
console.error(`Error: Version ${resolved} not found`);
|
|
519
559
|
process.exit(1);
|
|
@@ -924,9 +964,9 @@ function getServerUrl(registryUrl) {
|
|
|
924
964
|
return DEFAULT_WEB_APP_URL;
|
|
925
965
|
}
|
|
926
966
|
}
|
|
927
|
-
async function
|
|
967
|
+
async function exchangeCliToken2(registryUrl, token) {
|
|
928
968
|
const serverUrl = getServerUrl(registryUrl);
|
|
929
|
-
const rpcUrl = `${serverUrl}/api/api-keys/
|
|
969
|
+
const rpcUrl = `${serverUrl}/api/api-keys/cli-token-exchange`;
|
|
930
970
|
const response = await fetch(rpcUrl, {
|
|
931
971
|
method: "POST",
|
|
932
972
|
headers: {
|
|
@@ -1050,7 +1090,7 @@ async function browserLogin(globalOptions) {
|
|
|
1050
1090
|
const token = await tokenPromise;
|
|
1051
1091
|
cleanup();
|
|
1052
1092
|
console.log("Received token, exchanging for API key...");
|
|
1053
|
-
const { apiKey, username } = await
|
|
1093
|
+
const { apiKey, username } = await exchangeCliToken2(registryUrl, token);
|
|
1054
1094
|
await setProfileCredentials(
|
|
1055
1095
|
resolved.profileName,
|
|
1056
1096
|
apiKey,
|
|
@@ -1175,11 +1215,17 @@ async function publishCommand(options, globalOptions) {
|
|
|
1175
1215
|
);
|
|
1176
1216
|
const tarballBuffer = await readFile(tarballPath);
|
|
1177
1217
|
const tarballBase64 = tarballBuffer.toString("base64");
|
|
1178
|
-
configure({ baseUrl:
|
|
1179
|
-
const
|
|
1218
|
+
configure({ baseUrl: registryUrl, apiKey });
|
|
1219
|
+
const response = await publishSkill({
|
|
1180
1220
|
manifest: packageJson2,
|
|
1181
1221
|
tarballBase64
|
|
1182
1222
|
});
|
|
1223
|
+
if (response.status !== 200) {
|
|
1224
|
+
const errorData = response.data;
|
|
1225
|
+
const errorMessage = errorData?.error || errorData?.message || "Publish failed";
|
|
1226
|
+
throw new Error(errorMessage);
|
|
1227
|
+
}
|
|
1228
|
+
const result = response.data;
|
|
1183
1229
|
console.log(
|
|
1184
1230
|
`
|
|
1185
1231
|
Published @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
|
|
@@ -1295,7 +1341,7 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1295
1341
|
process.exit(1);
|
|
1296
1342
|
}
|
|
1297
1343
|
const { username, name, versionRange } = parsed;
|
|
1298
|
-
configure({ baseUrl:
|
|
1344
|
+
configure({ baseUrl: registryUrl, apiKey });
|
|
1299
1345
|
if (versionRange) {
|
|
1300
1346
|
console.log(`Unpublishing ${specifier}...`);
|
|
1301
1347
|
if (!options.force) {
|
|
@@ -1304,16 +1350,14 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1304
1350
|
);
|
|
1305
1351
|
process.exit(1);
|
|
1306
1352
|
}
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
console.log(`Unpublished @user/${username}/${name}@${versionRange}`);
|
|
1313
|
-
} else {
|
|
1314
|
-
console.error(`Error: Failed to unpublish. Version may not exist.`);
|
|
1353
|
+
const response = await deleteSkillVersion(name, versionRange);
|
|
1354
|
+
if (response.status !== 200) {
|
|
1355
|
+
const errorData = response.data;
|
|
1356
|
+
const errorMessage = errorData?.error || errorData?.message || "Failed to unpublish. Version may not exist.";
|
|
1357
|
+
console.error(`Error: ${errorMessage}`);
|
|
1315
1358
|
process.exit(1);
|
|
1316
1359
|
}
|
|
1360
|
+
console.log(`Unpublished @user/${username}/${name}@${versionRange}`);
|
|
1317
1361
|
} else {
|
|
1318
1362
|
console.log(`Unpublishing all versions of @user/${username}/${name}...`);
|
|
1319
1363
|
if (!options.force) {
|
|
@@ -1322,13 +1366,14 @@ async function unpublish(specifier, options, globalOptions) {
|
|
|
1322
1366
|
);
|
|
1323
1367
|
process.exit(1);
|
|
1324
1368
|
}
|
|
1325
|
-
const
|
|
1326
|
-
if (
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
console.error(`Error:
|
|
1369
|
+
const response = await deleteSkill(name);
|
|
1370
|
+
if (response.status !== 200) {
|
|
1371
|
+
const errorData = response.data;
|
|
1372
|
+
const errorMessage = errorData?.error || errorData?.message || "Failed to unpublish. Skill may not exist.";
|
|
1373
|
+
console.error(`Error: ${errorMessage}`);
|
|
1330
1374
|
process.exit(1);
|
|
1331
1375
|
}
|
|
1376
|
+
console.log(`Unpublished @user/${username}/${name} (all versions)`);
|
|
1332
1377
|
}
|
|
1333
1378
|
} catch (error) {
|
|
1334
1379
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -1347,7 +1392,7 @@ async function update(options, globalOptions) {
|
|
|
1347
1392
|
console.log("No skills installed.");
|
|
1348
1393
|
return;
|
|
1349
1394
|
}
|
|
1350
|
-
configure({ baseUrl:
|
|
1395
|
+
configure({ baseUrl: registryUrl, apiKey });
|
|
1351
1396
|
const updates = [];
|
|
1352
1397
|
console.log("Checking for updates...\n");
|
|
1353
1398
|
for (const { name, entry } of skills) {
|
|
@@ -1355,10 +1400,8 @@ async function update(options, globalOptions) {
|
|
|
1355
1400
|
if (!match) continue;
|
|
1356
1401
|
const [, username, skillName] = match;
|
|
1357
1402
|
try {
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
name: skillName
|
|
1361
|
-
});
|
|
1403
|
+
const versionsResponse = await listSkillVersions(username, skillName);
|
|
1404
|
+
const versions = versionsResponse.data;
|
|
1362
1405
|
if (versions.length === 0) continue;
|
|
1363
1406
|
const versionStrings = versions.map(
|
|
1364
1407
|
(v) => v.version
|