@bgicli/bgicli 2.8.3 → 2.8.4

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 (4) hide show
  1. package/dist/bgi.js +111 -21
  2. package/dist/bio.js +111 -21
  3. package/dist/mbp.js +111 -21
  4. package/package.json +1 -1
package/dist/bgi.js CHANGED
@@ -17912,12 +17912,12 @@ function clearCheckpoints(sessionId) {
17912
17912
 
17913
17913
  // src/index.ts
17914
17914
  var import_fs7 = require("fs");
17915
- var VERSION2 = "2.8.3";
17915
+ var VERSION2 = "2.8.4";
17916
17916
  var BRAND2 = "bgi".toLowerCase();
17917
17917
  var SKILLHUB_HUBS = {
17918
- bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
17918
+ bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
17919
17919
  clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
17920
- tencent: { label: "Tencent", apiBase: "https://lightmake.site", backend: "tencent" }
17920
+ tencent: { label: "\u817E\u8BAF SkillHub", apiBase: "https://skillhub.tencent.com", backend: "tencent" }
17921
17921
  };
17922
17922
  function httpGetJson(url) {
17923
17923
  const mod = url.startsWith("https") ? import_https2.get : require("http").get;
@@ -17940,9 +17940,58 @@ function httpGetJson(url) {
17940
17940
  req.on("error", reject);
17941
17941
  });
17942
17942
  }
17943
+ function searchLocalSkills(query, limit2) {
17944
+ const kw = query.toLowerCase();
17945
+ const results = [];
17946
+ const seen = /* @__PURE__ */ new Set();
17947
+ const scanDir = (dir) => {
17948
+ if (!(0, import_fs6.existsSync)(dir)) return;
17949
+ let entries;
17950
+ try {
17951
+ entries = (0, import_fs6.readdirSync)(dir);
17952
+ } catch {
17953
+ return;
17954
+ }
17955
+ for (const entry of entries) {
17956
+ if (seen.has(entry)) continue;
17957
+ const skillDir = (0, import_path6.join)(dir, entry);
17958
+ try {
17959
+ if (!(0, import_fs6.statSync)(skillDir).isDirectory()) continue;
17960
+ } catch {
17961
+ continue;
17962
+ }
17963
+ let name = entry;
17964
+ let summary = "";
17965
+ const mdPath = (0, import_path6.join)(skillDir, "SKILL.md");
17966
+ if ((0, import_fs6.existsSync)(mdPath)) {
17967
+ try {
17968
+ const lines = (0, import_fs6.readFileSync)(mdPath, "utf8").split("\n").slice(0, 30);
17969
+ for (const line of lines) {
17970
+ const nm = line.match(/^name:\s*["']?(.+?)["']?\s*$/);
17971
+ const sd = line.match(/^short-description:\s*["']?(.+?)["']?\s*$/);
17972
+ const dsc = line.match(/^description:\s*["']?(.+?)["']?\s*$/);
17973
+ if (nm) name = nm[1].trim();
17974
+ if (sd) summary = sd[1].trim();
17975
+ else if (dsc && !summary) summary = dsc[1].trim();
17976
+ }
17977
+ } catch {
17978
+ }
17979
+ }
17980
+ if (entry.toLowerCase().includes(kw) || name.toLowerCase().includes(kw) || summary.toLowerCase().includes(kw)) {
17981
+ seen.add(entry);
17982
+ results.push({ slug: entry, name, summary });
17983
+ }
17984
+ }
17985
+ };
17986
+ scanDir(BIO_SKILLS_DIR);
17987
+ scanDir(USER_SKILLS_DIR);
17988
+ return results.slice(0, limit2);
17989
+ }
17943
17990
  async function searchSkillHub(query, hub, limit2 = 10) {
17944
17991
  const cfg = SKILLHUB_HUBS[hub];
17945
- if (cfg.backend === "tencent") {
17992
+ if (cfg.backend === "local") {
17993
+ return searchLocalSkills(query, limit2);
17994
+ } else if (cfg.backend === "tencent") {
17946
17995
  const data = await httpGetJson(
17947
17996
  `${cfg.apiBase}/api/skills?page=1&pageSize=${limit2}&keyword=${encodeURIComponent(query)}`
17948
17997
  );
@@ -17952,7 +18001,7 @@ async function searchSkillHub(query, hub, limit2 = 10) {
17952
18001
  name: s2.name,
17953
18002
  summary: s2.description ?? "",
17954
18003
  version: s2.version,
17955
- owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*clawhub\.ai\/([^/]+)\/.*/, "$1") : void 0)
18004
+ owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*skillhub\.tencent\.com\/([^/]+)\/.*/, "$1") : void 0)
17956
18005
  }));
17957
18006
  } else {
17958
18007
  const data = await httpGetJson(
@@ -18229,7 +18278,7 @@ function printHelp() {
18229
18278
  console.log(source_default.bold.cyan("\u2500\u2500\u2500 Skill \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"));
18230
18279
  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`);
18231
18280
  console.log(` ${source_default.cyan("/check-env")} [id] \u68C0\u6D4B Skill \u6240\u9700 R/Python \u5305\u662F\u5426\u5DF2\u5B89\u88C5`);
18232
- 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]")}`);
18281
+ console.log(` ${source_default.cyan("/search")} <\u5173\u952E\u8BCD> \u641C\u7D22 Skills ${source_default.dim("[--hub=bgi|clawhub|tencent|all]")}`);
18233
18282
  console.log(` ${source_default.cyan("/install")} <url|slug> \u4ECE GitHub \u6216 SkillHub \u5B89\u88C5 Skill\uFF08\u542B\u5B89\u5168\u626B\u63CF\uFF09`);
18234
18283
  console.log(` ${source_default.cyan("/uninstall")} <id> \u5378\u8F7D\u5DF2\u5B89\u88C5\u7684\u7B2C\u4E09\u65B9 Skill`);
18235
18284
  console.log();
@@ -19107,30 +19156,71 @@ ${paramSummary}
19107
19156
  // ── /search SkillHub ─────────────────────────────────────────────────────
19108
19157
  case "search": {
19109
19158
  if (!arg) {
19110
- console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent]");
19111
- console.log(source_default.dim("\u793A\u4F8B: /search rnaseq"));
19112
- console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19113
- console.log(source_default.dim(" /search genomics --hub=clawhub"));
19114
- console.log(source_default.dim("\n\u9ED8\u8BA4\u641C\u7D22 BGI \u5185\u7F51 SkillHub (http://172.16.218.40:8080)"));
19159
+ console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent|all]");
19160
+ console.log(source_default.dim(" bgi \u2014 BGI \u672C\u5730\u5DF2\u5B89\u88C5 Skills\uFF08\u9ED8\u8BA4\uFF0C\u6781\u5FEB\uFF09"));
19161
+ console.log(source_default.dim(" clawhub \u2014 clawhub.ai \u5B98\u65B9 SkillHub"));
19162
+ console.log(source_default.dim(" tencent \u2014 \u817E\u8BAF SkillHub (skillhub.tencent.com)"));
19163
+ console.log(source_default.dim(" all \u2014 \u540C\u65F6\u641C\u7D22\u5168\u90E8\u4E09\u4E2A\u6765\u6E90"));
19164
+ console.log(source_default.dim("\n\u793A\u4F8B:"));
19165
+ console.log(source_default.dim(" /search rnaseq"));
19166
+ console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19167
+ console.log(source_default.dim(" /search genomics --hub=all"));
19115
19168
  break;
19116
19169
  }
19117
- let hubKey = "bgi";
19118
19170
  const hubMatch = arg.match(/--hub=(\w+)/);
19119
19171
  const query = arg.replace(/--hub=\w+/g, "").trim();
19120
- if (hubMatch) {
19121
- const hk = hubMatch[1];
19122
- if (hk in SKILLHUB_HUBS) hubKey = hk;
19123
- else {
19124
- console.log(source_default.red(`\u672A\u77E5 hub: ${hubMatch[1]}\uFF0C\u53EF\u9009: bgi, clawhub, tencent`));
19125
- break;
19126
- }
19127
- }
19172
+ const hubArg = hubMatch ? hubMatch[1] : "bgi";
19128
19173
  if (!query) {
19129
19174
  console.log(source_default.yellow("\u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD"));
19130
19175
  break;
19131
19176
  }
19177
+ if (hubArg === "all") {
19178
+ console.log(source_default.dim(`
19179
+ \u6B63\u5728\u641C\u7D22\u5168\u90E8 SkillHub: "${query}"...
19180
+ `));
19181
+ const hubKeys = ["bgi", "clawhub", "tencent"];
19182
+ const allResults = [];
19183
+ await Promise.all(hubKeys.map(async (hk) => {
19184
+ try {
19185
+ const results = await searchSkillHub(query, hk, 5);
19186
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results });
19187
+ } catch (e2) {
19188
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results: [], error: e2 instanceof Error ? e2.message : String(e2) });
19189
+ }
19190
+ }));
19191
+ allResults.sort((a2, b2) => hubKeys.indexOf(a2.hub) - hubKeys.indexOf(b2.hub));
19192
+ _lastSearchResults = [];
19193
+ let globalIdx = 1;
19194
+ for (const { label, results, error } of allResults) {
19195
+ if (error) {
19196
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500`) + source_default.red(` \u641C\u7D22\u5931\u8D25: ${error}`));
19197
+ } else if (results.length === 0) {
19198
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500 \u65E0\u7ED3\u679C`));
19199
+ } else {
19200
+ console.log(source_default.bold.dim(` \u2500\u2500 ${label} (${results.length}) \u2500\u2500`));
19201
+ for (const s2 of results) {
19202
+ const ver = s2.version ? source_default.dim(` v${s2.version}`) : "";
19203
+ const owner = s2.owner ? source_default.dim(` @${s2.owner}`) : "";
19204
+ console.log(` ${source_default.cyan(`[${globalIdx}]`)} ${source_default.bold(s2.name)}${owner}${ver}`);
19205
+ console.log(` ${source_default.dim(s2.summary.substring(0, 90))}${s2.summary.length > 90 ? "\u2026" : ""}`);
19206
+ console.log(` ${source_default.dim(`slug: ${s2.slug}`)}`);
19207
+ _lastSearchResults.push(s2);
19208
+ globalIdx++;
19209
+ }
19210
+ }
19211
+ console.log();
19212
+ }
19213
+ if (_lastSearchResults.length > 0)
19214
+ console.log(source_default.dim(`\u5B89\u88C5: /install <slug> \u6216 /install <\u5E8F\u53F7> (\u5982: /install 1)`));
19215
+ break;
19216
+ }
19217
+ if (!(hubArg in SKILLHUB_HUBS)) {
19218
+ console.log(source_default.red(`\u672A\u77E5 hub: ${hubArg}\uFF0C\u53EF\u9009: bgi, clawhub, tencent, all`));
19219
+ break;
19220
+ }
19221
+ const hubKey = hubArg;
19132
19222
  const hubLabel = SKILLHUB_HUBS[hubKey].label;
19133
- process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel} SkillHub: "${query}"...
19223
+ process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel}: "${query}"...
19134
19224
  `));
19135
19225
  try {
19136
19226
  const results = await searchSkillHub(query, hubKey, 10);
package/dist/bio.js CHANGED
@@ -17912,12 +17912,12 @@ function clearCheckpoints(sessionId) {
17912
17912
 
17913
17913
  // src/index.ts
17914
17914
  var import_fs7 = require("fs");
17915
- var VERSION2 = "2.8.3";
17915
+ var VERSION2 = "2.8.4";
17916
17916
  var BRAND2 = "bio".toLowerCase();
17917
17917
  var SKILLHUB_HUBS = {
17918
- bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
17918
+ bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
17919
17919
  clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
17920
- tencent: { label: "Tencent", apiBase: "https://lightmake.site", backend: "tencent" }
17920
+ tencent: { label: "\u817E\u8BAF SkillHub", apiBase: "https://skillhub.tencent.com", backend: "tencent" }
17921
17921
  };
17922
17922
  function httpGetJson(url) {
17923
17923
  const mod = url.startsWith("https") ? import_https2.get : require("http").get;
@@ -17940,9 +17940,58 @@ function httpGetJson(url) {
17940
17940
  req.on("error", reject);
17941
17941
  });
17942
17942
  }
17943
+ function searchLocalSkills(query, limit2) {
17944
+ const kw = query.toLowerCase();
17945
+ const results = [];
17946
+ const seen = /* @__PURE__ */ new Set();
17947
+ const scanDir = (dir) => {
17948
+ if (!(0, import_fs6.existsSync)(dir)) return;
17949
+ let entries;
17950
+ try {
17951
+ entries = (0, import_fs6.readdirSync)(dir);
17952
+ } catch {
17953
+ return;
17954
+ }
17955
+ for (const entry of entries) {
17956
+ if (seen.has(entry)) continue;
17957
+ const skillDir = (0, import_path6.join)(dir, entry);
17958
+ try {
17959
+ if (!(0, import_fs6.statSync)(skillDir).isDirectory()) continue;
17960
+ } catch {
17961
+ continue;
17962
+ }
17963
+ let name = entry;
17964
+ let summary = "";
17965
+ const mdPath = (0, import_path6.join)(skillDir, "SKILL.md");
17966
+ if ((0, import_fs6.existsSync)(mdPath)) {
17967
+ try {
17968
+ const lines = (0, import_fs6.readFileSync)(mdPath, "utf8").split("\n").slice(0, 30);
17969
+ for (const line of lines) {
17970
+ const nm = line.match(/^name:\s*["']?(.+?)["']?\s*$/);
17971
+ const sd = line.match(/^short-description:\s*["']?(.+?)["']?\s*$/);
17972
+ const dsc = line.match(/^description:\s*["']?(.+?)["']?\s*$/);
17973
+ if (nm) name = nm[1].trim();
17974
+ if (sd) summary = sd[1].trim();
17975
+ else if (dsc && !summary) summary = dsc[1].trim();
17976
+ }
17977
+ } catch {
17978
+ }
17979
+ }
17980
+ if (entry.toLowerCase().includes(kw) || name.toLowerCase().includes(kw) || summary.toLowerCase().includes(kw)) {
17981
+ seen.add(entry);
17982
+ results.push({ slug: entry, name, summary });
17983
+ }
17984
+ }
17985
+ };
17986
+ scanDir(BIO_SKILLS_DIR);
17987
+ scanDir(USER_SKILLS_DIR);
17988
+ return results.slice(0, limit2);
17989
+ }
17943
17990
  async function searchSkillHub(query, hub, limit2 = 10) {
17944
17991
  const cfg = SKILLHUB_HUBS[hub];
17945
- if (cfg.backend === "tencent") {
17992
+ if (cfg.backend === "local") {
17993
+ return searchLocalSkills(query, limit2);
17994
+ } else if (cfg.backend === "tencent") {
17946
17995
  const data = await httpGetJson(
17947
17996
  `${cfg.apiBase}/api/skills?page=1&pageSize=${limit2}&keyword=${encodeURIComponent(query)}`
17948
17997
  );
@@ -17952,7 +18001,7 @@ async function searchSkillHub(query, hub, limit2 = 10) {
17952
18001
  name: s2.name,
17953
18002
  summary: s2.description ?? "",
17954
18003
  version: s2.version,
17955
- owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*clawhub\.ai\/([^/]+)\/.*/, "$1") : void 0)
18004
+ owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*skillhub\.tencent\.com\/([^/]+)\/.*/, "$1") : void 0)
17956
18005
  }));
17957
18006
  } else {
17958
18007
  const data = await httpGetJson(
@@ -18229,7 +18278,7 @@ function printHelp() {
18229
18278
  console.log(source_default.bold.cyan("\u2500\u2500\u2500 Skill \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"));
18230
18279
  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`);
18231
18280
  console.log(` ${source_default.cyan("/check-env")} [id] \u68C0\u6D4B Skill \u6240\u9700 R/Python \u5305\u662F\u5426\u5DF2\u5B89\u88C5`);
18232
- 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]")}`);
18281
+ console.log(` ${source_default.cyan("/search")} <\u5173\u952E\u8BCD> \u641C\u7D22 Skills ${source_default.dim("[--hub=bgi|clawhub|tencent|all]")}`);
18233
18282
  console.log(` ${source_default.cyan("/install")} <url|slug> \u4ECE GitHub \u6216 SkillHub \u5B89\u88C5 Skill\uFF08\u542B\u5B89\u5168\u626B\u63CF\uFF09`);
18234
18283
  console.log(` ${source_default.cyan("/uninstall")} <id> \u5378\u8F7D\u5DF2\u5B89\u88C5\u7684\u7B2C\u4E09\u65B9 Skill`);
18235
18284
  console.log();
@@ -19107,30 +19156,71 @@ ${paramSummary}
19107
19156
  // ── /search SkillHub ─────────────────────────────────────────────────────
19108
19157
  case "search": {
19109
19158
  if (!arg) {
19110
- console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent]");
19111
- console.log(source_default.dim("\u793A\u4F8B: /search rnaseq"));
19112
- console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19113
- console.log(source_default.dim(" /search genomics --hub=clawhub"));
19114
- console.log(source_default.dim("\n\u9ED8\u8BA4\u641C\u7D22 BGI \u5185\u7F51 SkillHub (http://172.16.218.40:8080)"));
19159
+ console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent|all]");
19160
+ console.log(source_default.dim(" bgi \u2014 BGI \u672C\u5730\u5DF2\u5B89\u88C5 Skills\uFF08\u9ED8\u8BA4\uFF0C\u6781\u5FEB\uFF09"));
19161
+ console.log(source_default.dim(" clawhub \u2014 clawhub.ai \u5B98\u65B9 SkillHub"));
19162
+ console.log(source_default.dim(" tencent \u2014 \u817E\u8BAF SkillHub (skillhub.tencent.com)"));
19163
+ console.log(source_default.dim(" all \u2014 \u540C\u65F6\u641C\u7D22\u5168\u90E8\u4E09\u4E2A\u6765\u6E90"));
19164
+ console.log(source_default.dim("\n\u793A\u4F8B:"));
19165
+ console.log(source_default.dim(" /search rnaseq"));
19166
+ console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19167
+ console.log(source_default.dim(" /search genomics --hub=all"));
19115
19168
  break;
19116
19169
  }
19117
- let hubKey = "bgi";
19118
19170
  const hubMatch = arg.match(/--hub=(\w+)/);
19119
19171
  const query = arg.replace(/--hub=\w+/g, "").trim();
19120
- if (hubMatch) {
19121
- const hk = hubMatch[1];
19122
- if (hk in SKILLHUB_HUBS) hubKey = hk;
19123
- else {
19124
- console.log(source_default.red(`\u672A\u77E5 hub: ${hubMatch[1]}\uFF0C\u53EF\u9009: bgi, clawhub, tencent`));
19125
- break;
19126
- }
19127
- }
19172
+ const hubArg = hubMatch ? hubMatch[1] : "bgi";
19128
19173
  if (!query) {
19129
19174
  console.log(source_default.yellow("\u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD"));
19130
19175
  break;
19131
19176
  }
19177
+ if (hubArg === "all") {
19178
+ console.log(source_default.dim(`
19179
+ \u6B63\u5728\u641C\u7D22\u5168\u90E8 SkillHub: "${query}"...
19180
+ `));
19181
+ const hubKeys = ["bgi", "clawhub", "tencent"];
19182
+ const allResults = [];
19183
+ await Promise.all(hubKeys.map(async (hk) => {
19184
+ try {
19185
+ const results = await searchSkillHub(query, hk, 5);
19186
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results });
19187
+ } catch (e2) {
19188
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results: [], error: e2 instanceof Error ? e2.message : String(e2) });
19189
+ }
19190
+ }));
19191
+ allResults.sort((a2, b2) => hubKeys.indexOf(a2.hub) - hubKeys.indexOf(b2.hub));
19192
+ _lastSearchResults = [];
19193
+ let globalIdx = 1;
19194
+ for (const { label, results, error } of allResults) {
19195
+ if (error) {
19196
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500`) + source_default.red(` \u641C\u7D22\u5931\u8D25: ${error}`));
19197
+ } else if (results.length === 0) {
19198
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500 \u65E0\u7ED3\u679C`));
19199
+ } else {
19200
+ console.log(source_default.bold.dim(` \u2500\u2500 ${label} (${results.length}) \u2500\u2500`));
19201
+ for (const s2 of results) {
19202
+ const ver = s2.version ? source_default.dim(` v${s2.version}`) : "";
19203
+ const owner = s2.owner ? source_default.dim(` @${s2.owner}`) : "";
19204
+ console.log(` ${source_default.cyan(`[${globalIdx}]`)} ${source_default.bold(s2.name)}${owner}${ver}`);
19205
+ console.log(` ${source_default.dim(s2.summary.substring(0, 90))}${s2.summary.length > 90 ? "\u2026" : ""}`);
19206
+ console.log(` ${source_default.dim(`slug: ${s2.slug}`)}`);
19207
+ _lastSearchResults.push(s2);
19208
+ globalIdx++;
19209
+ }
19210
+ }
19211
+ console.log();
19212
+ }
19213
+ if (_lastSearchResults.length > 0)
19214
+ console.log(source_default.dim(`\u5B89\u88C5: /install <slug> \u6216 /install <\u5E8F\u53F7> (\u5982: /install 1)`));
19215
+ break;
19216
+ }
19217
+ if (!(hubArg in SKILLHUB_HUBS)) {
19218
+ console.log(source_default.red(`\u672A\u77E5 hub: ${hubArg}\uFF0C\u53EF\u9009: bgi, clawhub, tencent, all`));
19219
+ break;
19220
+ }
19221
+ const hubKey = hubArg;
19132
19222
  const hubLabel = SKILLHUB_HUBS[hubKey].label;
19133
- process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel} SkillHub: "${query}"...
19223
+ process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel}: "${query}"...
19134
19224
  `));
19135
19225
  try {
19136
19226
  const results = await searchSkillHub(query, hubKey, 10);
package/dist/mbp.js CHANGED
@@ -17912,12 +17912,12 @@ function clearCheckpoints(sessionId) {
17912
17912
 
17913
17913
  // src/index.ts
17914
17914
  var import_fs7 = require("fs");
17915
- var VERSION2 = "2.8.3";
17915
+ var VERSION2 = "2.8.4";
17916
17916
  var BRAND2 = "mbp".toLowerCase();
17917
17917
  var SKILLHUB_HUBS = {
17918
- bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
17918
+ bgi: { label: "BGI \u672C\u5730", apiBase: "", backend: "local" },
17919
17919
  clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
17920
- tencent: { label: "Tencent", apiBase: "https://lightmake.site", backend: "tencent" }
17920
+ tencent: { label: "\u817E\u8BAF SkillHub", apiBase: "https://skillhub.tencent.com", backend: "tencent" }
17921
17921
  };
17922
17922
  function httpGetJson(url) {
17923
17923
  const mod = url.startsWith("https") ? import_https2.get : require("http").get;
@@ -17940,9 +17940,58 @@ function httpGetJson(url) {
17940
17940
  req.on("error", reject);
17941
17941
  });
17942
17942
  }
17943
+ function searchLocalSkills(query, limit2) {
17944
+ const kw = query.toLowerCase();
17945
+ const results = [];
17946
+ const seen = /* @__PURE__ */ new Set();
17947
+ const scanDir = (dir) => {
17948
+ if (!(0, import_fs6.existsSync)(dir)) return;
17949
+ let entries;
17950
+ try {
17951
+ entries = (0, import_fs6.readdirSync)(dir);
17952
+ } catch {
17953
+ return;
17954
+ }
17955
+ for (const entry of entries) {
17956
+ if (seen.has(entry)) continue;
17957
+ const skillDir = (0, import_path6.join)(dir, entry);
17958
+ try {
17959
+ if (!(0, import_fs6.statSync)(skillDir).isDirectory()) continue;
17960
+ } catch {
17961
+ continue;
17962
+ }
17963
+ let name = entry;
17964
+ let summary = "";
17965
+ const mdPath = (0, import_path6.join)(skillDir, "SKILL.md");
17966
+ if ((0, import_fs6.existsSync)(mdPath)) {
17967
+ try {
17968
+ const lines = (0, import_fs6.readFileSync)(mdPath, "utf8").split("\n").slice(0, 30);
17969
+ for (const line of lines) {
17970
+ const nm = line.match(/^name:\s*["']?(.+?)["']?\s*$/);
17971
+ const sd = line.match(/^short-description:\s*["']?(.+?)["']?\s*$/);
17972
+ const dsc = line.match(/^description:\s*["']?(.+?)["']?\s*$/);
17973
+ if (nm) name = nm[1].trim();
17974
+ if (sd) summary = sd[1].trim();
17975
+ else if (dsc && !summary) summary = dsc[1].trim();
17976
+ }
17977
+ } catch {
17978
+ }
17979
+ }
17980
+ if (entry.toLowerCase().includes(kw) || name.toLowerCase().includes(kw) || summary.toLowerCase().includes(kw)) {
17981
+ seen.add(entry);
17982
+ results.push({ slug: entry, name, summary });
17983
+ }
17984
+ }
17985
+ };
17986
+ scanDir(BIO_SKILLS_DIR);
17987
+ scanDir(USER_SKILLS_DIR);
17988
+ return results.slice(0, limit2);
17989
+ }
17943
17990
  async function searchSkillHub(query, hub, limit2 = 10) {
17944
17991
  const cfg = SKILLHUB_HUBS[hub];
17945
- if (cfg.backend === "tencent") {
17992
+ if (cfg.backend === "local") {
17993
+ return searchLocalSkills(query, limit2);
17994
+ } else if (cfg.backend === "tencent") {
17946
17995
  const data = await httpGetJson(
17947
17996
  `${cfg.apiBase}/api/skills?page=1&pageSize=${limit2}&keyword=${encodeURIComponent(query)}`
17948
17997
  );
@@ -17952,7 +18001,7 @@ async function searchSkillHub(query, hub, limit2 = 10) {
17952
18001
  name: s2.name,
17953
18002
  summary: s2.description ?? "",
17954
18003
  version: s2.version,
17955
- owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*clawhub\.ai\/([^/]+)\/.*/, "$1") : void 0)
18004
+ owner: s2.ownerName ?? (s2.homepage ? s2.homepage.replace(/.*skillhub\.tencent\.com\/([^/]+)\/.*/, "$1") : void 0)
17956
18005
  }));
17957
18006
  } else {
17958
18007
  const data = await httpGetJson(
@@ -18229,7 +18278,7 @@ function printHelp() {
18229
18278
  console.log(source_default.bold.cyan("\u2500\u2500\u2500 Skill \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"));
18230
18279
  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`);
18231
18280
  console.log(` ${source_default.cyan("/check-env")} [id] \u68C0\u6D4B Skill \u6240\u9700 R/Python \u5305\u662F\u5426\u5DF2\u5B89\u88C5`);
18232
- 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]")}`);
18281
+ console.log(` ${source_default.cyan("/search")} <\u5173\u952E\u8BCD> \u641C\u7D22 Skills ${source_default.dim("[--hub=bgi|clawhub|tencent|all]")}`);
18233
18282
  console.log(` ${source_default.cyan("/install")} <url|slug> \u4ECE GitHub \u6216 SkillHub \u5B89\u88C5 Skill\uFF08\u542B\u5B89\u5168\u626B\u63CF\uFF09`);
18234
18283
  console.log(` ${source_default.cyan("/uninstall")} <id> \u5378\u8F7D\u5DF2\u5B89\u88C5\u7684\u7B2C\u4E09\u65B9 Skill`);
18235
18284
  console.log();
@@ -19107,30 +19156,71 @@ ${paramSummary}
19107
19156
  // ── /search SkillHub ─────────────────────────────────────────────────────
19108
19157
  case "search": {
19109
19158
  if (!arg) {
19110
- console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent]");
19111
- console.log(source_default.dim("\u793A\u4F8B: /search rnaseq"));
19112
- console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19113
- console.log(source_default.dim(" /search genomics --hub=clawhub"));
19114
- console.log(source_default.dim("\n\u9ED8\u8BA4\u641C\u7D22 BGI \u5185\u7F51 SkillHub (http://172.16.218.40:8080)"));
19159
+ console.log("\u7528\u6CD5: /search <\u5173\u952E\u8BCD> [--hub=bgi|clawhub|tencent|all]");
19160
+ console.log(source_default.dim(" bgi \u2014 BGI \u672C\u5730\u5DF2\u5B89\u88C5 Skills\uFF08\u9ED8\u8BA4\uFF0C\u6781\u5FEB\uFF09"));
19161
+ console.log(source_default.dim(" clawhub \u2014 clawhub.ai \u5B98\u65B9 SkillHub"));
19162
+ console.log(source_default.dim(" tencent \u2014 \u817E\u8BAF SkillHub (skillhub.tencent.com)"));
19163
+ console.log(source_default.dim(" all \u2014 \u540C\u65F6\u641C\u7D22\u5168\u90E8\u4E09\u4E2A\u6765\u6E90"));
19164
+ console.log(source_default.dim("\n\u793A\u4F8B:"));
19165
+ console.log(source_default.dim(" /search rnaseq"));
19166
+ console.log(source_default.dim(" /search \u86CB\u767D\u8D28\u7ED3\u6784\u9884\u6D4B --hub=tencent"));
19167
+ console.log(source_default.dim(" /search genomics --hub=all"));
19115
19168
  break;
19116
19169
  }
19117
- let hubKey = "bgi";
19118
19170
  const hubMatch = arg.match(/--hub=(\w+)/);
19119
19171
  const query = arg.replace(/--hub=\w+/g, "").trim();
19120
- if (hubMatch) {
19121
- const hk = hubMatch[1];
19122
- if (hk in SKILLHUB_HUBS) hubKey = hk;
19123
- else {
19124
- console.log(source_default.red(`\u672A\u77E5 hub: ${hubMatch[1]}\uFF0C\u53EF\u9009: bgi, clawhub, tencent`));
19125
- break;
19126
- }
19127
- }
19172
+ const hubArg = hubMatch ? hubMatch[1] : "bgi";
19128
19173
  if (!query) {
19129
19174
  console.log(source_default.yellow("\u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD"));
19130
19175
  break;
19131
19176
  }
19177
+ if (hubArg === "all") {
19178
+ console.log(source_default.dim(`
19179
+ \u6B63\u5728\u641C\u7D22\u5168\u90E8 SkillHub: "${query}"...
19180
+ `));
19181
+ const hubKeys = ["bgi", "clawhub", "tencent"];
19182
+ const allResults = [];
19183
+ await Promise.all(hubKeys.map(async (hk) => {
19184
+ try {
19185
+ const results = await searchSkillHub(query, hk, 5);
19186
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results });
19187
+ } catch (e2) {
19188
+ allResults.push({ hub: hk, label: SKILLHUB_HUBS[hk].label, results: [], error: e2 instanceof Error ? e2.message : String(e2) });
19189
+ }
19190
+ }));
19191
+ allResults.sort((a2, b2) => hubKeys.indexOf(a2.hub) - hubKeys.indexOf(b2.hub));
19192
+ _lastSearchResults = [];
19193
+ let globalIdx = 1;
19194
+ for (const { label, results, error } of allResults) {
19195
+ if (error) {
19196
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500`) + source_default.red(` \u641C\u7D22\u5931\u8D25: ${error}`));
19197
+ } else if (results.length === 0) {
19198
+ console.log(source_default.dim(` \u2500\u2500 ${label} \u2500\u2500 \u65E0\u7ED3\u679C`));
19199
+ } else {
19200
+ console.log(source_default.bold.dim(` \u2500\u2500 ${label} (${results.length}) \u2500\u2500`));
19201
+ for (const s2 of results) {
19202
+ const ver = s2.version ? source_default.dim(` v${s2.version}`) : "";
19203
+ const owner = s2.owner ? source_default.dim(` @${s2.owner}`) : "";
19204
+ console.log(` ${source_default.cyan(`[${globalIdx}]`)} ${source_default.bold(s2.name)}${owner}${ver}`);
19205
+ console.log(` ${source_default.dim(s2.summary.substring(0, 90))}${s2.summary.length > 90 ? "\u2026" : ""}`);
19206
+ console.log(` ${source_default.dim(`slug: ${s2.slug}`)}`);
19207
+ _lastSearchResults.push(s2);
19208
+ globalIdx++;
19209
+ }
19210
+ }
19211
+ console.log();
19212
+ }
19213
+ if (_lastSearchResults.length > 0)
19214
+ console.log(source_default.dim(`\u5B89\u88C5: /install <slug> \u6216 /install <\u5E8F\u53F7> (\u5982: /install 1)`));
19215
+ break;
19216
+ }
19217
+ if (!(hubArg in SKILLHUB_HUBS)) {
19218
+ console.log(source_default.red(`\u672A\u77E5 hub: ${hubArg}\uFF0C\u53EF\u9009: bgi, clawhub, tencent, all`));
19219
+ break;
19220
+ }
19221
+ const hubKey = hubArg;
19132
19222
  const hubLabel = SKILLHUB_HUBS[hubKey].label;
19133
- process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel} SkillHub: "${query}"...
19223
+ process.stdout.write(source_default.dim(`\u6B63\u5728\u641C\u7D22 ${hubLabel}: "${query}"...
19134
19224
  `));
19135
19225
  try {
19136
19226
  const results = await searchSkillHub(query, hubKey, 10);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgicli/bgicli",
3
- "version": "2.8.3",
3
+ "version": "2.8.4",
4
4
  "description": "BGI CLI — Bioinformatics AI terminal for Chinese researchers (百炼/DeepSeek/Kimi/Qwen)",
5
5
  "bin": {
6
6
  "bgi": "dist/bgi.js",