openclaw-skills-cli 0.1.2 → 0.1.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/dist/commands/install.js +40 -25
- package/dist/commands/publish.js +8 -2
- package/dist/templates/paidRemoteStub.js +36 -0
- package/jest.config.cjs +22 -0
- package/package.json +1 -1
- package/templates/paid-remote-stub.md +35 -0
package/dist/commands/install.js
CHANGED
|
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.installCommand = void 0;
|
|
40
|
+
exports.installToolOrDomain = installToolOrDomain;
|
|
40
41
|
const commander_1 = require("commander");
|
|
41
42
|
const chalk_1 = __importDefault(require("chalk"));
|
|
42
43
|
const ora_1 = __importDefault(require("ora"));
|
|
@@ -46,6 +47,7 @@ const os = __importStar(require("node:os"));
|
|
|
46
47
|
const prompts_1 = require("@inquirer/prompts");
|
|
47
48
|
const client_js_1 = require("../api/client.js");
|
|
48
49
|
const errors_js_1 = require("../utils/errors.js");
|
|
50
|
+
const paidRemoteStub_js_1 = require("../templates/paidRemoteStub.js");
|
|
49
51
|
function parseSkillArg(arg) {
|
|
50
52
|
const atIndex = arg.lastIndexOf('@');
|
|
51
53
|
let fullName;
|
|
@@ -139,23 +141,41 @@ async function installToolOrDomain(namespace, name, targetVersion, installConfig
|
|
|
139
141
|
fs.rmSync(installDir, { recursive: true, force: true });
|
|
140
142
|
}
|
|
141
143
|
const spinner = (0, ora_1.default)(`Instalando ${chalk_1.default.cyan(namespace)}/${chalk_1.default.bold(name)}${chalk_1.default.gray('@' + targetVersion)}...`).start();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
const isPaidRemoteOnly = Boolean(installConfig.remoteExecutionOnly || (installConfig.tier && installConfig.tier !== 'free'));
|
|
145
|
+
if (isPaidRemoteOnly) {
|
|
146
|
+
const tier = installConfig.tier || 'pro';
|
|
147
|
+
const executeEndpoint = installConfig.executeEndpoint || `/v1/skills/${namespace}/${name}/execute`;
|
|
148
|
+
fs.mkdirSync(installDir, { recursive: true });
|
|
149
|
+
fs.writeFileSync(path.join(installDir, 'SKILL.md'), (0, paidRemoteStub_js_1.buildPaidStubSkillMd)({
|
|
150
|
+
namespace,
|
|
151
|
+
name,
|
|
152
|
+
tier,
|
|
153
|
+
authorizeEndpoint: installConfig.authorizeEndpoint || null,
|
|
154
|
+
executeEndpoint,
|
|
155
|
+
}), 'utf-8');
|
|
156
|
+
fs.writeFileSync(path.join(installDir, 'manifest.json'), JSON.stringify((0, paidRemoteStub_js_1.buildPaidStubManifest)({
|
|
157
|
+
namespace,
|
|
158
|
+
name,
|
|
159
|
+
tier,
|
|
160
|
+
authorizeEndpoint: installConfig.authorizeEndpoint || null,
|
|
161
|
+
executeEndpoint,
|
|
162
|
+
}), null, 2), 'utf-8');
|
|
163
|
+
spinner.succeed(chalk_1.default.green(`Instalado en modo remoto (stub local) en ~/.openclaw/skills/${namespace}/${name}/`));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
144
166
|
let filesData;
|
|
145
|
-
if (
|
|
167
|
+
if (installConfig.filesUrl) {
|
|
146
168
|
// Download from Supabase Storage
|
|
147
|
-
const response = await fetch(
|
|
169
|
+
const response = await fetch(installConfig.filesUrl);
|
|
148
170
|
if (response.ok) {
|
|
149
171
|
filesData = await response.json();
|
|
150
172
|
}
|
|
151
173
|
else {
|
|
152
|
-
|
|
153
|
-
const versionData = await (0, client_js_1.getVersion)(namespace, name, targetVersion);
|
|
154
|
-
filesData = versionData.files || {};
|
|
174
|
+
throw new Error(`No se pudieron descargar archivos desde filesUrl (${response.status})`);
|
|
155
175
|
}
|
|
156
176
|
}
|
|
157
177
|
else {
|
|
158
|
-
filesData =
|
|
178
|
+
filesData = installConfig.files || {};
|
|
159
179
|
}
|
|
160
180
|
// Handle both formats: object (new) or base64 tarball (legacy)
|
|
161
181
|
if (typeof filesData === 'string') {
|
|
@@ -181,12 +201,6 @@ async function installToolOrDomain(namespace, name, targetVersion, installConfig
|
|
|
181
201
|
fs.writeFileSync(fullPath, content, 'utf-8');
|
|
182
202
|
}
|
|
183
203
|
}
|
|
184
|
-
try {
|
|
185
|
-
await (0, client_js_1.registerInstall)(namespace, name, targetVersion);
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
// Install tracking is best-effort
|
|
189
|
-
}
|
|
190
204
|
spinner.succeed(chalk_1.default.green(`Instalado en ~/.openclaw/skills/${namespace}/${name}/`));
|
|
191
205
|
}
|
|
192
206
|
async function installMcpServer(name, mcpConfig, targets, targetFlag) {
|
|
@@ -238,6 +252,7 @@ exports.installCommand = new commander_1.Command('install')
|
|
|
238
252
|
let namespace;
|
|
239
253
|
let name;
|
|
240
254
|
let version;
|
|
255
|
+
let skillTier = 'free';
|
|
241
256
|
if (opts.licenseToken) {
|
|
242
257
|
const consumed = await (0, client_js_1.consumeInstallPack)(opts.licenseToken);
|
|
243
258
|
if (!consumed.ok || !consumed.install) {
|
|
@@ -256,17 +271,14 @@ exports.installCommand = new commander_1.Command('install')
|
|
|
256
271
|
name = parsed.name;
|
|
257
272
|
version = parsed.version;
|
|
258
273
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
console.log(chalk_1.default.red('Este skill no tiene versiones publicadas'));
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
targetVersion = latest.version;
|
|
274
|
+
const skill = await (0, client_js_1.getSkill)(namespace, name);
|
|
275
|
+
const latest = skill.versions?.[0];
|
|
276
|
+
skillTier = skill.tier || 'free';
|
|
277
|
+
if (!latest && !version) {
|
|
278
|
+
console.log(chalk_1.default.red('Este skill no tiene versiones publicadas'));
|
|
279
|
+
return;
|
|
269
280
|
}
|
|
281
|
+
const targetVersion = version || latest.version;
|
|
270
282
|
// Get install config to determine type
|
|
271
283
|
const installConfig = await (0, client_js_1.getInstallConfig)(namespace, name);
|
|
272
284
|
if (installConfig.type === 'MCP_SERVER') {
|
|
@@ -274,7 +286,10 @@ exports.installCommand = new commander_1.Command('install')
|
|
|
274
286
|
}
|
|
275
287
|
else {
|
|
276
288
|
// TOOL or DOMAIN — file-based installation
|
|
277
|
-
await installToolOrDomain(namespace, name, targetVersion,
|
|
289
|
+
await installToolOrDomain(namespace, name, targetVersion, {
|
|
290
|
+
...installConfig,
|
|
291
|
+
tier: installConfig.tier || skillTier,
|
|
292
|
+
});
|
|
278
293
|
}
|
|
279
294
|
// Register install (best-effort)
|
|
280
295
|
try {
|
package/dist/commands/publish.js
CHANGED
|
@@ -182,7 +182,7 @@ exports.publishCommand = new commander_1.Command('publish')
|
|
|
182
182
|
const spinner = (0, ora_1.default)(`Publicando ${chalk_1.default.bold(name)}${chalk_1.default.gray('@' + version)}...`).start();
|
|
183
183
|
const files = readFilesRecursive(resolvedFolder, resolvedFolder);
|
|
184
184
|
try {
|
|
185
|
-
await (0, client_js_1.publishSkill)({
|
|
185
|
+
const published = await (0, client_js_1.publishSkill)({
|
|
186
186
|
namespace,
|
|
187
187
|
name,
|
|
188
188
|
description,
|
|
@@ -194,6 +194,9 @@ exports.publishCommand = new commander_1.Command('publish')
|
|
|
194
194
|
tier,
|
|
195
195
|
});
|
|
196
196
|
spinner.succeed(chalk_1.default.green(`Skill publicado: ${namespace}/${name}`));
|
|
197
|
+
if (published?.moderation?.status === 'pending_review') {
|
|
198
|
+
console.log(chalk_1.default.yellow('Submitted for review, pending approval.'));
|
|
199
|
+
}
|
|
197
200
|
}
|
|
198
201
|
catch (error) {
|
|
199
202
|
if (axios_1.default.isAxiosError(error) && error.response?.status === 409) {
|
|
@@ -207,8 +210,11 @@ exports.publishCommand = new commander_1.Command('publish')
|
|
|
207
210
|
return;
|
|
208
211
|
}
|
|
209
212
|
const versionSpinner = (0, ora_1.default)(`Publicando versión ${version}...`).start();
|
|
210
|
-
await (0, client_js_1.publishVersion)(namespace, name, { version, files });
|
|
213
|
+
const publishedVersion = await (0, client_js_1.publishVersion)(namespace, name, { version, files });
|
|
211
214
|
versionSpinner.succeed(chalk_1.default.green(`Versión ${version} publicada: ${namespace}/${name}`));
|
|
215
|
+
if (publishedVersion?.moderation?.status === 'pending_review') {
|
|
216
|
+
console.log(chalk_1.default.yellow('Submitted for review, pending approval.'));
|
|
217
|
+
}
|
|
212
218
|
}
|
|
213
219
|
else {
|
|
214
220
|
spinner.fail('Error al publicar');
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPaidStubSkillMd = buildPaidStubSkillMd;
|
|
4
|
+
exports.buildPaidStubManifest = buildPaidStubManifest;
|
|
5
|
+
function buildPaidStubSkillMd(data) {
|
|
6
|
+
return `# ${data.namespace}/${data.name}
|
|
7
|
+
|
|
8
|
+
## Resumen
|
|
9
|
+
Este skill se instala en modo remoto. El código fuente no se descarga localmente.
|
|
10
|
+
|
|
11
|
+
## Cuándo usar
|
|
12
|
+
Usa este skill cuando necesites ejecutar sus capacidades desde el registry por API.
|
|
13
|
+
|
|
14
|
+
## Ejemplos
|
|
15
|
+
- Autorizar acceso: \`POST ${data.authorizeEndpoint || '/v1/skills/{namespace}/{name}/authorize'}\`
|
|
16
|
+
- Ejecutar skill: \`POST ${data.executeEndpoint || '/v1/skills/{namespace}/{name}/execute'}\`
|
|
17
|
+
|
|
18
|
+
## Notas
|
|
19
|
+
- Requiere suscripción activa para este tier (\`${data.tier}\`).
|
|
20
|
+
- La ejecución ocurre de forma remota por API.
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
function buildPaidStubManifest(data) {
|
|
24
|
+
const manifest = {
|
|
25
|
+
namespace: data.namespace,
|
|
26
|
+
name: data.name,
|
|
27
|
+
tier: data.tier,
|
|
28
|
+
executionMode: 'remote',
|
|
29
|
+
remoteExecutionOnly: true,
|
|
30
|
+
authorizeEndpoint: data.authorizeEndpoint,
|
|
31
|
+
};
|
|
32
|
+
if (data.executeEndpoint) {
|
|
33
|
+
manifest.executeEndpoint = data.executeEndpoint;
|
|
34
|
+
}
|
|
35
|
+
return manifest;
|
|
36
|
+
}
|
package/jest.config.cjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
testEnvironment: 'node',
|
|
3
|
+
roots: ['<rootDir>/src'],
|
|
4
|
+
testMatch: ['**/*.test.js'],
|
|
5
|
+
moduleFileExtensions: ['ts', 'js', 'json'],
|
|
6
|
+
transform: {
|
|
7
|
+
'^.+\\.ts$': [
|
|
8
|
+
'ts-jest',
|
|
9
|
+
{
|
|
10
|
+
tsconfig: {
|
|
11
|
+
module: 'commonjs',
|
|
12
|
+
target: 'es2022',
|
|
13
|
+
esModuleInterop: true,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
moduleNameMapper: {
|
|
19
|
+
'^(\\.{1,2}/.*)\\.js$': '$1',
|
|
20
|
+
},
|
|
21
|
+
clearMocks: true,
|
|
22
|
+
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Paid Remote-Only Stub Template
|
|
2
|
+
|
|
3
|
+
## SKILL.md
|
|
4
|
+
|
|
5
|
+
```md
|
|
6
|
+
# {{namespace}}/{{name}}
|
|
7
|
+
|
|
8
|
+
## Resumen
|
|
9
|
+
Este skill se instala en modo remoto. El código fuente no se descarga localmente.
|
|
10
|
+
|
|
11
|
+
## Cuándo usar
|
|
12
|
+
Usa este skill cuando necesites ejecutar sus capacidades desde el registry por API.
|
|
13
|
+
|
|
14
|
+
## Ejemplos
|
|
15
|
+
- Autorizar acceso: `POST {{authorizeEndpoint}}`
|
|
16
|
+
- Ejecutar skill: `POST {{executeEndpoint}}`
|
|
17
|
+
|
|
18
|
+
## Notas
|
|
19
|
+
- Requiere suscripción activa para este tier (`{{tier}}`).
|
|
20
|
+
- La ejecución ocurre de forma remota por API.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## manifest.json
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"namespace": "{{namespace}}",
|
|
28
|
+
"name": "{{name}}",
|
|
29
|
+
"tier": "{{tier}}",
|
|
30
|
+
"executionMode": "remote",
|
|
31
|
+
"remoteExecutionOnly": true,
|
|
32
|
+
"authorizeEndpoint": "{{authorizeEndpoint}}",
|
|
33
|
+
"executeEndpoint": "{{executeEndpoint}}"
|
|
34
|
+
}
|
|
35
|
+
```
|