skillhub 0.1.1 → 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/index.js +87 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
// src/index.ts
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import chalk5 from "chalk";
|
|
15
|
+
import { createRequire } from "module";
|
|
15
16
|
|
|
16
17
|
// src/commands/install.ts
|
|
17
18
|
import fs from "fs-extra";
|
|
@@ -21,25 +22,78 @@ import ora from "ora";
|
|
|
21
22
|
import { parseSkillMd } from "skillhub-core";
|
|
22
23
|
|
|
23
24
|
// src/utils/api.ts
|
|
25
|
+
import https from "https";
|
|
26
|
+
import http from "http";
|
|
24
27
|
var API_BASE_URL = process.env.SKILLHUB_API_URL || "https://skills.palebluedot.live/api";
|
|
25
28
|
var API_TIMEOUT = parseInt(process.env.SKILLHUB_API_TIMEOUT || "30000");
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
function httpsRequest(url, options = {}) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const parsedUrl = new URL(url);
|
|
32
|
+
const isHttps = parsedUrl.protocol === "https:";
|
|
33
|
+
const lib = isHttps ? https : http;
|
|
34
|
+
const reqOptions = {
|
|
35
|
+
hostname: parsedUrl.hostname,
|
|
36
|
+
port: parsedUrl.port || (isHttps ? 443 : 80),
|
|
37
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
38
|
+
method: options.method || "GET",
|
|
39
|
+
headers: {
|
|
40
|
+
"User-Agent": "skillhub-cli",
|
|
41
|
+
"Accept": "application/json",
|
|
42
|
+
...options.headers
|
|
43
|
+
},
|
|
44
|
+
timeout: API_TIMEOUT
|
|
45
|
+
};
|
|
46
|
+
const req = lib.request(reqOptions, (res) => {
|
|
47
|
+
const chunks = [];
|
|
48
|
+
let resolved = false;
|
|
49
|
+
const tryResolve = () => {
|
|
50
|
+
if (resolved) return;
|
|
51
|
+
const data = Buffer.concat(chunks).toString();
|
|
52
|
+
if (data.startsWith("{") || data.startsWith("[")) {
|
|
53
|
+
try {
|
|
54
|
+
JSON.parse(data);
|
|
55
|
+
resolved = true;
|
|
56
|
+
res.destroy();
|
|
57
|
+
resolve({
|
|
58
|
+
statusCode: res.statusCode || 0,
|
|
59
|
+
data
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
res.on("data", (chunk) => {
|
|
66
|
+
chunks.push(chunk);
|
|
67
|
+
tryResolve();
|
|
68
|
+
});
|
|
69
|
+
res.on("end", () => {
|
|
70
|
+
if (!resolved) {
|
|
71
|
+
resolve({
|
|
72
|
+
statusCode: res.statusCode || 0,
|
|
73
|
+
data: Buffer.concat(chunks).toString()
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
res.setTimeout(API_TIMEOUT, () => {
|
|
78
|
+
if (!resolved) {
|
|
79
|
+
res.destroy();
|
|
80
|
+
reject(new Error(`Response timeout after ${API_TIMEOUT / 1e3}s`));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
33
83
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
84
|
+
req.on("error", (err) => {
|
|
85
|
+
if (err.code === "ERR_STREAM_DESTROYED") return;
|
|
86
|
+
reject(new Error(`Network error: ${err.message}`));
|
|
87
|
+
});
|
|
88
|
+
req.on("timeout", () => {
|
|
89
|
+
req.destroy();
|
|
90
|
+
reject(new Error(`Request timeout after ${API_TIMEOUT / 1e3}s`));
|
|
91
|
+
});
|
|
92
|
+
if (options.body) {
|
|
93
|
+
req.write(options.body);
|
|
38
94
|
}
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
clearTimeout(timeoutId);
|
|
42
|
-
}
|
|
95
|
+
req.end();
|
|
96
|
+
});
|
|
43
97
|
}
|
|
44
98
|
async function searchSkills(query, options = {}) {
|
|
45
99
|
const params = new URLSearchParams({
|
|
@@ -50,27 +104,25 @@ async function searchSkills(query, options = {}) {
|
|
|
50
104
|
if (options.platform) {
|
|
51
105
|
params.set("platform", options.platform);
|
|
52
106
|
}
|
|
53
|
-
const response = await
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
throw new Error(`API error ${response.status}: ${text || response.statusText}`);
|
|
107
|
+
const response = await httpsRequest(`${API_BASE_URL}/skills?${params}`);
|
|
108
|
+
if (response.statusCode !== 200) {
|
|
109
|
+
throw new Error(`API error ${response.statusCode}: ${response.data || "Unknown error"}`);
|
|
57
110
|
}
|
|
58
|
-
return response.
|
|
111
|
+
return JSON.parse(response.data);
|
|
59
112
|
}
|
|
60
113
|
async function getSkill(id) {
|
|
61
|
-
const response = await
|
|
62
|
-
if (response.
|
|
114
|
+
const response = await httpsRequest(`${API_BASE_URL}/skills/${encodeURIComponent(id)}`);
|
|
115
|
+
if (response.statusCode === 404) {
|
|
63
116
|
return null;
|
|
64
117
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
throw new Error(`API error ${response.status}: ${text || response.statusText}`);
|
|
118
|
+
if (response.statusCode !== 200) {
|
|
119
|
+
throw new Error(`API error ${response.statusCode}: ${response.data || "Unknown error"}`);
|
|
68
120
|
}
|
|
69
|
-
return response.
|
|
121
|
+
return JSON.parse(response.data);
|
|
70
122
|
}
|
|
71
123
|
async function trackInstall(skillId, platform, method = "cli") {
|
|
72
124
|
try {
|
|
73
|
-
await
|
|
125
|
+
await httpsRequest(`${API_BASE_URL}/skills/${encodeURIComponent(skillId)}/install`, {
|
|
74
126
|
method: "POST",
|
|
75
127
|
headers: { "Content-Type": "application/json" },
|
|
76
128
|
body: JSON.stringify({ platform, method })
|
|
@@ -324,7 +376,11 @@ async function search(query, options) {
|
|
|
324
376
|
}
|
|
325
377
|
} catch (error) {
|
|
326
378
|
spinner.fail("Search failed");
|
|
327
|
-
|
|
379
|
+
const err = error;
|
|
380
|
+
console.error(chalk2.red(err.message || "Unknown error"));
|
|
381
|
+
if (process.env.DEBUG) {
|
|
382
|
+
console.error(chalk2.dim("Stack:"), err.stack);
|
|
383
|
+
}
|
|
328
384
|
process.exit(1);
|
|
329
385
|
}
|
|
330
386
|
}
|
|
@@ -475,7 +531,9 @@ function maskSecret(value) {
|
|
|
475
531
|
}
|
|
476
532
|
|
|
477
533
|
// src/index.ts
|
|
478
|
-
var
|
|
534
|
+
var require2 = createRequire(import.meta.url);
|
|
535
|
+
var pkg = require2("../package.json");
|
|
536
|
+
var VERSION = pkg.version;
|
|
479
537
|
var program = new Command();
|
|
480
538
|
program.name("skillhub").description("CLI for managing AI Agent skills").version(VERSION);
|
|
481
539
|
program.command("install <skill-id>").description("Install a skill from the registry").option("-p, --platform <platform>", "Target platform (claude, codex, copilot, cursor, windsurf)", "claude").option("--project", "Install in the current project instead of globally").option("-f, --force", "Overwrite existing skill").action(async (skillId, options) => {
|
package/package.json
CHANGED