@bgicli/bgicli 2.2.12 → 2.2.14

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.
Files changed (2) hide show
  1. package/dist/bgi.js +185 -13
  2. package/package.json +1 -1
package/dist/bgi.js CHANGED
@@ -15410,7 +15410,85 @@ function clearCheckpoints(sessionId) {
15410
15410
 
15411
15411
  // src/index.ts
15412
15412
  var import_fs6 = require("fs");
15413
- var VERSION2 = "2.2.12";
15413
+ var VERSION2 = "2.2.14";
15414
+ var SKILLHUB_HUBS = {
15415
+ bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
15416
+ clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
15417
+ tencent: { label: "Tencent", apiBase: "https://lightmake.site", backend: "tencent" }
15418
+ };
15419
+ function httpGetJson(url) {
15420
+ const mod = url.startsWith("https") ? import_https2.get : require("http").get;
15421
+ return new Promise((resolve3, reject) => {
15422
+ const req = mod(url, { headers: { "User-Agent": `bgicli/${VERSION2}`, Accept: "application/json" } }, (res) => {
15423
+ const chunks = [];
15424
+ res.on("data", (c2) => chunks.push(c2));
15425
+ res.on("end", () => {
15426
+ try {
15427
+ resolve3(JSON.parse(Buffer.concat(chunks).toString()));
15428
+ } catch (e2) {
15429
+ reject(new Error(`JSON parse error from ${url}`));
15430
+ }
15431
+ });
15432
+ });
15433
+ req.setTimeout(1e4, () => {
15434
+ req.destroy();
15435
+ reject(new Error("timeout"));
15436
+ });
15437
+ req.on("error", reject);
15438
+ });
15439
+ }
15440
+ async function searchSkillHub(query, hub, limit2 = 10) {
15441
+ const cfg = SKILLHUB_HUBS[hub];
15442
+ if (cfg.backend === "tencent") {
15443
+ const data = await httpGetJson(
15444
+ `${cfg.apiBase}/api/skills?page=1&pageSize=${limit2}&keyword=${encodeURIComponent(query)}`
15445
+ );
15446
+ if (data.code !== 0 || !data.data?.skills) return [];
15447
+ return data.data.skills.map((s2) => ({
15448
+ slug: s2.slug,
15449
+ name: s2.name,
15450
+ summary: s2.description ?? "",
15451
+ version: s2.version,
15452
+ owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*clawhub\.ai\/([^/]+)\/.*/, "$1") : void 0)
15453
+ }));
15454
+ } else {
15455
+ const data = await httpGetJson(
15456
+ `${cfg.apiBase}/api/v1/search?q=${encodeURIComponent(query)}&limit=${limit2}&nonSuspiciousOnly=true`
15457
+ );
15458
+ if (!data.results) return [];
15459
+ return data.results.map((s2) => ({
15460
+ slug: s2.slug,
15461
+ name: s2.displayName ?? s2.slug,
15462
+ summary: s2.summary ?? "",
15463
+ version: s2.version ?? void 0
15464
+ }));
15465
+ }
15466
+ }
15467
+ async function downloadSkillMd(slug) {
15468
+ const data = await new Promise((resolve3, reject) => {
15469
+ const req = (0, import_https2.get)(
15470
+ `https://clawhub.ai/api/v1/skills/${encodeURIComponent(slug)}/file?path=SKILL.md`,
15471
+ { headers: { "User-Agent": `bgicli/${VERSION2}` } },
15472
+ (res) => {
15473
+ if (res.statusCode === 404) {
15474
+ req.destroy();
15475
+ reject(new Error("not_found"));
15476
+ return;
15477
+ }
15478
+ const chunks = [];
15479
+ res.on("data", (c2) => chunks.push(c2));
15480
+ res.on("end", () => resolve3(Buffer.concat(chunks).toString()));
15481
+ }
15482
+ );
15483
+ req.setTimeout(15e3, () => {
15484
+ req.destroy();
15485
+ reject(new Error("timeout"));
15486
+ });
15487
+ req.on("error", reject);
15488
+ });
15489
+ return data;
15490
+ }
15491
+ var _lastSearchResults = [];
15414
15492
  function isNewer(latest, current) {
15415
15493
  const [lM, lm, lp] = latest.split(".").map(Number);
15416
15494
  const [cM, cm, cp] = current.split(".").map(Number);
@@ -15453,13 +15531,10 @@ async function checkAndAutoUpdate() {
15453
15531
  `)
15454
15532
  );
15455
15533
  const ok = await new Promise((resolve3) => {
15456
- const child = (0, import_child_process2.spawn)(
15457
- "npm",
15458
- ["install", "-g", `@bgicli/bgicli@${latest}`, "--registry", "https://registry.npmjs.org"],
15459
- { stdio: "inherit", shell: true }
15534
+ (0, import_child_process2.exec)(
15535
+ `npm install -g @bgicli/bgicli@${latest} --registry https://registry.npmjs.org`,
15536
+ (error) => resolve3(!error)
15460
15537
  );
15461
- child.on("close", (code) => resolve3(code === 0));
15462
- child.on("error", () => resolve3(false));
15463
15538
  });
15464
15539
  if (ok) {
15465
15540
  process.stdout.write(source_default.green(` \u2713 \u5DF2\u66F4\u65B0\u81F3 v${latest}\uFF0C\u91CD\u542F bgi \u540E\u751F\u6548
@@ -15558,7 +15633,8 @@ function printHelp() {
15558
15633
  console.log(source_default.bold.cyan("\u2500\u2500\u2500 \u5DE5\u4F5C\u6D41\u5411\u5BFC \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15559
15634
  console.log(` ${source_default.cyan("/run")} <skill-id> \u4EA4\u4E92\u5F0F\u53C2\u6570\u5411\u5BFC\uFF0C\u81EA\u52A8\u751F\u6210\u5E76\u6267\u884C\u5206\u6790\u811A\u672C`);
15560
15635
  console.log(` ${source_default.cyan("/check-env")} [id] \u68C0\u6D4B Skill \u6240\u9700 R/Python \u5305\u662F\u5426\u5DF2\u5B89\u88C5`);
15561
- console.log(` ${source_default.cyan("/install")} <url> \u4ECE GitHub \u5B89\u88C5\u7B2C\u4E09\u65B9 Skill`);
15636
+ console.log(` ${source_default.cyan("/search")} <\u5173\u952E\u8BCD> \u5728 SkillHub \u641C\u7D22\u5E76\u4E0B\u8F7D\u6280\u80FD ${source_default.dim("[--hub=bgi|clawhub|tencent]")}`);
15637
+ console.log(` ${source_default.cyan("/install")} <url|slug> \u4ECE GitHub \u6216 SkillHub \u5B89\u88C5 Skill`);
15562
15638
  console.log(` ${source_default.cyan("/uninstall")} <id> \u5378\u8F7D\u5DF2\u5B89\u88C5\u7684\u7B2C\u4E09\u65B9 Skill`);
15563
15639
  console.log();
15564
15640
  console.log(source_default.bold.cyan("\u2500\u2500\u2500 \u6587\u4EF6 & \u76EE\u5F55 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
@@ -16420,15 +16496,110 @@ ${paramSummary}
16420
16496
  }
16421
16497
  break;
16422
16498
  }
16423
- // ── /install from GitHub ─────────────────────────────────────────────────
16499
+ // ── /search SkillHub ─────────────────────────────────────────────────────
16500
+ case "search": {
16501
+ if (!arg) {
16502
+ console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent]");
16503
+ console.log(source_default.dim("\u793A\u4F8B: /search rnaseq"));
16504
+ console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
16505
+ console.log(source_default.dim(" /search genomics --hub=clawhub"));
16506
+ console.log(source_default.dim("\n\u9ED8\u8BA4\u641C\u7D22 BGI \u5185\u7F51 SkillHub (http://172.16.218.40:8080)"));
16507
+ break;
16508
+ }
16509
+ let hubKey = "bgi";
16510
+ const hubMatch = arg.match(/--hub=(\w+)/);
16511
+ const query = arg.replace(/--hub=\w+/g, "").trim();
16512
+ if (hubMatch) {
16513
+ const hk = hubMatch[1];
16514
+ if (hk in SKILLHUB_HUBS) hubKey = hk;
16515
+ else {
16516
+ console.log(source_default.red(`\u672A\u77E5 hub: ${hubMatch[1]}\uFF0C\u53EF\u9009: bgi, clawhub, tencent`));
16517
+ break;
16518
+ }
16519
+ }
16520
+ if (!query) {
16521
+ console.log(source_default.yellow("\u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD"));
16522
+ break;
16523
+ }
16524
+ const hubLabel = SKILLHUB_HUBS[hubKey].label;
16525
+ process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel} SkillHub: "${query}"...
16526
+ `));
16527
+ try {
16528
+ const results = await searchSkillHub(query, hubKey, 10);
16529
+ if (results.length === 0) {
16530
+ console.log(source_default.yellow(` \u672A\u627E\u5230\u76F8\u5173 Skill\uFF0C\u8BF7\u5C1D\u8BD5\u5176\u4ED6\u5173\u952E\u8BCD`));
16531
+ break;
16532
+ }
16533
+ _lastSearchResults = results;
16534
+ console.log(source_default.bold(`
16535
+ \u641C\u7D22\u7ED3\u679C (${hubLabel}) \u2014 \u5171 ${results.length} \u4E2A:
16536
+ `));
16537
+ results.forEach((s2, i2) => {
16538
+ const ver = s2.version ? source_default.dim(` v${s2.version}`) : "";
16539
+ const owner = s2.owner ? source_default.dim(` @${s2.owner}`) : "";
16540
+ console.log(` ${source_default.cyan(`[${i2 + 1}]`)} ${source_default.bold(s2.name)}${owner}${ver}`);
16541
+ console.log(` ${source_default.dim(s2.summary.substring(0, 90))}${s2.summary.length > 90 ? "\u2026" : ""}`);
16542
+ console.log(` ${source_default.dim(`slug: ${s2.slug}`)}`);
16543
+ console.log();
16544
+ });
16545
+ console.log(source_default.dim(`\u5B89\u88C5: /install <slug> \u6216 /install <\u5E8F\u53F7> (\u5982: /install 1)`));
16546
+ } catch (e2) {
16547
+ console.log(source_default.red(`\u641C\u7D22\u5931\u8D25: ${e2 instanceof Error ? e2.message : String(e2)}`));
16548
+ }
16549
+ break;
16550
+ }
16551
+ // ── /install from GitHub or SkillHub ──────────────────────────────────────
16424
16552
  case "install": {
16425
16553
  if (!arg) {
16426
- console.log("\u7528\u6CD5: /install <github-url>");
16554
+ console.log("\u7528\u6CD5: /install <github-url | slug | \u641C\u7D22\u5E8F\u53F7>");
16427
16555
  console.log(source_default.dim("\u793A\u4F8B: /install https://github.com/user/my-skill"));
16428
- console.log(source_default.dim(" /install user/repo (GitHub \u7B80\u5199)"));
16556
+ console.log(source_default.dim(" /install user/repo (GitHub \u7B80\u5199)"));
16557
+ console.log(source_default.dim(" /install personal-genomics (SkillHub slug)"));
16558
+ console.log(source_default.dim(" /install 2 (\u641C\u7D22\u7ED3\u679C\u5E8F\u53F7)"));
16559
+ break;
16560
+ }
16561
+ let installArg = arg;
16562
+ const searchNum = /^\d+$/.test(installArg) ? parseInt(installArg, 10) : 0;
16563
+ if (searchNum > 0 && _lastSearchResults.length > 0) {
16564
+ if (searchNum > _lastSearchResults.length) {
16565
+ console.log(source_default.red(`\u5E8F\u53F7 ${searchNum} \u8D85\u51FA\u8303\u56F4\uFF08\u5171 ${_lastSearchResults.length} \u4E2A\u7ED3\u679C\uFF09`));
16566
+ break;
16567
+ }
16568
+ const picked = _lastSearchResults[searchNum - 1];
16569
+ console.log(source_default.dim(`\u4ECE\u641C\u7D22\u7ED3\u679C\u5B89\u88C5: ${picked.name} (${picked.slug})`));
16570
+ installArg = picked.slug;
16571
+ }
16572
+ const isGitHub = installArg.includes("github.com") || installArg.includes("gitlab") || installArg.includes("bitbucket") || /^[^/]+\/[^/]+$/.test(installArg);
16573
+ if (!isGitHub && !installArg.startsWith("http")) {
16574
+ const slug = installArg.trim();
16575
+ const installTarget2 = (0, import_path5.join)(SKILLS_DIR, slug);
16576
+ if ((0, import_fs5.existsSync)(installTarget2)) {
16577
+ console.log(source_default.yellow(`Skill "${slug}" \u5DF2\u5B58\u5728\uFF0C\u5982\u9700\u66F4\u65B0\u8BF7\u5148 /uninstall ${slug}`));
16578
+ break;
16579
+ }
16580
+ process.stdout.write(source_default.dim(`\u6B63\u5728\u4ECE SkillHub \u4E0B\u8F7D Skill: ${slug}...
16581
+ `));
16582
+ try {
16583
+ const skillMdContent = await downloadSkillMd(slug);
16584
+ (0, import_fs5.mkdirSync)(installTarget2, { recursive: true });
16585
+ (0, import_fs5.writeFileSync)((0, import_path5.join)(installTarget2, "SKILL.md"), skillMdContent, "utf8");
16586
+ const { name: name2, shortDesc: shortDesc2 } = parseSkillMeta(skillMdContent);
16587
+ console.log(source_default.green(`\u2713 SkillHub Skill \u5B89\u88C5\u6210\u529F!`));
16588
+ console.log(` ID: ${source_default.cyan(slug)}`);
16589
+ console.log(` \u540D\u79F0: ${name2 || slug}`);
16590
+ if (shortDesc2) console.log(` \u529F\u80FD: ${source_default.dim(shortDesc2)}`);
16591
+ console.log(source_default.dim(` \u4F7F\u7528 /sk ${slug} \u52A0\u8F7D`));
16592
+ } catch (e2) {
16593
+ const msg = e2 instanceof Error ? e2.message : String(e2);
16594
+ if (msg === "not_found") {
16595
+ console.log(source_default.red(`SkillHub \u672A\u627E\u5230 "${slug}"\uFF0C\u8BF7\u5148\u7528 /search \u641C\u7D22\u786E\u8BA4 slug`));
16596
+ } else {
16597
+ console.log(source_default.red(`\u4E0B\u8F7D\u5931\u8D25: ${msg}`));
16598
+ }
16599
+ }
16429
16600
  break;
16430
16601
  }
16431
- let repoUrl = arg;
16602
+ let repoUrl = installArg;
16432
16603
  if (!repoUrl.startsWith("http")) {
16433
16604
  repoUrl = `https://github.com/${repoUrl}`;
16434
16605
  }
@@ -16691,7 +16862,8 @@ ${summary}` },
16691
16862
  async function main() {
16692
16863
  installBundledData();
16693
16864
  printBanner();
16694
- await checkAndAutoUpdate();
16865
+ await checkAndAutoUpdate().catch(() => {
16866
+ });
16695
16867
  const rl = (0, import_readline.createInterface)({
16696
16868
  input: process.stdin,
16697
16869
  output: process.stdout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.2.12",
3
+ "version": "2.2.14",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js"