bfi-cli 0.1.26 → 0.1.29
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/cli.mjs +145 -42
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -4471,6 +4471,7 @@ async function cloneWithGitHubFallback(url, ref, spinner) {
|
|
|
4471
4471
|
}
|
|
4472
4472
|
}
|
|
4473
4473
|
async function installFromSkillHub(parsed, options, spinner) {
|
|
4474
|
+
let tempDir = null;
|
|
4474
4475
|
const config = resolveConfig();
|
|
4475
4476
|
const api = new SkillHubAPI(config.registry, config.token);
|
|
4476
4477
|
const rawRef = parsed.url.startsWith("skillhub:") ? parsed.url.slice(9) : parsed.url;
|
|
@@ -4492,6 +4493,15 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4492
4493
|
return (b.score || 0) - (a.score || 0);
|
|
4493
4494
|
}).slice(0, 20);
|
|
4494
4495
|
if (hits.length === 0) {
|
|
4496
|
+
spinner.stop("SkillHub 未找到,尝试作为 Git 仓库...");
|
|
4497
|
+
const gitSource = parseSource(rawRef);
|
|
4498
|
+
if (gitSource.type === "git" || gitSource.type === "github" || gitSource.type === "gitlab") {
|
|
4499
|
+
tempDir = await cloneWithGitHubFallback(gitSource.url, gitSource.ref, spinner);
|
|
4500
|
+
return {
|
|
4501
|
+
skills: await discoverSkills(tempDir, gitSource.subpath, { includeInternal: true }),
|
|
4502
|
+
tempDir
|
|
4503
|
+
};
|
|
4504
|
+
}
|
|
4495
4505
|
spinner.stop(import_picocolors.default.red("无结果"));
|
|
4496
4506
|
outro(import_picocolors.default.red(`No skills found on SkillHub for "${rawRef}".`));
|
|
4497
4507
|
process.exit(1);
|
|
@@ -4536,7 +4546,7 @@ async function installFromSkillHub(parsed, options, spinner) {
|
|
|
4536
4546
|
}
|
|
4537
4547
|
const meta = metadata;
|
|
4538
4548
|
spinner.stop(`Skill: ${import_picocolors.default.cyan(`@${namespace}/${slug}`)}${meta.description ? ` — ${import_picocolors.default.dim(meta.description)}` : ""}`);
|
|
4539
|
-
|
|
4549
|
+
tempDir = join(tmpdir(), `.bfi-skillhub-${canonicalSlug.replace(/[/:@]/g, "-")}-${Date.now()}`);
|
|
4540
4550
|
mkdirSync(tempDir, { recursive: true });
|
|
4541
4551
|
const zipPath = join(tempDir, "skill.zip");
|
|
4542
4552
|
spinner.start("正在下载技能...");
|
|
@@ -6242,7 +6252,7 @@ async function updateGlobalSkills(options = {}) {
|
|
|
6242
6252
|
console.log(` ${DIM$9}✗ Cannot update ${safeName}: lock file is missing sourceUrl for this generic Git source${RESET$9}`);
|
|
6243
6253
|
continue;
|
|
6244
6254
|
}
|
|
6245
|
-
const cliEntry = join(__dirname$1, "..", "bin", "
|
|
6255
|
+
const cliEntry = join(__dirname$1, "..", "bin", "bfi.mjs");
|
|
6246
6256
|
if (!existsSync(cliEntry)) {
|
|
6247
6257
|
failCount++;
|
|
6248
6258
|
console.log(` ${DIM$9}✗ Failed to update ${safeName}: CLI entrypoint not found at ${cliEntry}${RESET$9}`);
|
|
@@ -6326,7 +6336,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
6326
6336
|
bySource.set(source, existing);
|
|
6327
6337
|
}
|
|
6328
6338
|
const localLock = await readLocalLock();
|
|
6329
|
-
const cliEntry = join(__dirname$1, "..", "bin", "
|
|
6339
|
+
const cliEntry = join(__dirname$1, "..", "bin", "bfi.mjs");
|
|
6330
6340
|
if (!existsSync(cliEntry)) {
|
|
6331
6341
|
console.log(`${DIM$9}✗ CLI 入口未找到 ${cliEntry}${RESET$9}`);
|
|
6332
6342
|
return {
|
|
@@ -6901,29 +6911,31 @@ const MARKETPLACE_API = process.env.SKILLS_API_URL || "https://skills.sh";
|
|
|
6901
6911
|
async function runSearch(args, globalOpts) {
|
|
6902
6912
|
const query = parseSearchQuery(args);
|
|
6903
6913
|
const namespace = args.includes("--namespace") ? getOptionValue$2(args, "--namespace") : void 0;
|
|
6914
|
+
const json = args.includes("--json");
|
|
6904
6915
|
if (!query) {
|
|
6905
|
-
console.log("用法:bfi search <query> [--namespace <ns>] [--marketplace]");
|
|
6916
|
+
console.log("用法:bfi search <query> [--namespace <ns>] [--marketplace] [--json]");
|
|
6906
6917
|
console.log();
|
|
6907
6918
|
console.log("选项:");
|
|
6908
6919
|
console.log(" --namespace <ns> 按 SkillHub 命名空间筛选");
|
|
6909
6920
|
console.log(" --marketplace 仅搜索 skills.sh 市场");
|
|
6910
6921
|
console.log(" --all 同时搜索 SkillHub 和市场");
|
|
6922
|
+
console.log(" --json 以 JSON 格式输出结果");
|
|
6911
6923
|
return;
|
|
6912
6924
|
}
|
|
6913
6925
|
const useMarketplace = args.includes("--marketplace");
|
|
6914
6926
|
const searchAll = args.includes("--all");
|
|
6915
6927
|
if (useMarketplace) {
|
|
6916
|
-
await searchMarketplace(query);
|
|
6928
|
+
await searchMarketplace(query, json);
|
|
6917
6929
|
return;
|
|
6918
6930
|
}
|
|
6919
6931
|
if (searchAll) {
|
|
6920
6932
|
console.log(`${BOLD$5}=== SkillHub 注册表 ===${RESET$8}\n`);
|
|
6921
|
-
await searchSkillHub(query, namespace, globalOpts);
|
|
6933
|
+
await searchSkillHub(query, namespace, globalOpts, json);
|
|
6922
6934
|
console.log(`\n${BOLD$5}=== skills.sh 市场 ===${RESET$8}\n`);
|
|
6923
|
-
await searchMarketplace(query);
|
|
6935
|
+
await searchMarketplace(query, json);
|
|
6924
6936
|
return;
|
|
6925
6937
|
}
|
|
6926
|
-
await searchSkillHub(query, namespace, globalOpts);
|
|
6938
|
+
await searchSkillHub(query, namespace, globalOpts, json);
|
|
6927
6939
|
}
|
|
6928
6940
|
function parseSearchQuery(args) {
|
|
6929
6941
|
const parts = [];
|
|
@@ -6938,7 +6950,7 @@ function parseSearchQuery(args) {
|
|
|
6938
6950
|
}
|
|
6939
6951
|
return parts.join(" ");
|
|
6940
6952
|
}
|
|
6941
|
-
async function searchSkillHub(query, namespace, globalOpts) {
|
|
6953
|
+
async function searchSkillHub(query, namespace, globalOpts, json = false) {
|
|
6942
6954
|
const { registry, token } = resolveConfig(globalOpts);
|
|
6943
6955
|
const api = new SkillHubAPI(registry, token);
|
|
6944
6956
|
try {
|
|
@@ -6949,7 +6961,30 @@ async function searchSkillHub(query, namespace, globalOpts) {
|
|
|
6949
6961
|
});
|
|
6950
6962
|
const skills = result.results || result.data || [];
|
|
6951
6963
|
if (skills.length === 0) {
|
|
6952
|
-
console.log(
|
|
6964
|
+
if (json) console.log(JSON.stringify({
|
|
6965
|
+
source: "skillhub",
|
|
6966
|
+
count: 0,
|
|
6967
|
+
results: []
|
|
6968
|
+
}, null, 2));
|
|
6969
|
+
else console.log(`${DIM$8}SkillHub 上未找到 "${query}" 的技能${RESET$8}`);
|
|
6970
|
+
return;
|
|
6971
|
+
}
|
|
6972
|
+
if (json) {
|
|
6973
|
+
const results = skills.map((skill) => {
|
|
6974
|
+
const canonicalSlug = skill.slug || "";
|
|
6975
|
+
const displaySlug = canonicalSlug.indexOf("--") > 0 ? canonicalSlug : `global--${canonicalSlug}`;
|
|
6976
|
+
return {
|
|
6977
|
+
name: skill.displayName || skill.name || skill.slug,
|
|
6978
|
+
slug: displaySlug,
|
|
6979
|
+
description: skill.summary || skill.description || "",
|
|
6980
|
+
version: skill.version || null
|
|
6981
|
+
};
|
|
6982
|
+
});
|
|
6983
|
+
console.log(JSON.stringify({
|
|
6984
|
+
source: "skillhub",
|
|
6985
|
+
count: results.length,
|
|
6986
|
+
results
|
|
6987
|
+
}, null, 2));
|
|
6953
6988
|
return;
|
|
6954
6989
|
}
|
|
6955
6990
|
console.log(`SkillHub 上找到 ${skills.length} 个技能:\n`);
|
|
@@ -6969,7 +7004,7 @@ async function searchSkillHub(query, namespace, globalOpts) {
|
|
|
6969
7004
|
console.error(`${DIM$8}SkillHub 搜索失败:${error.message}${RESET$8}`);
|
|
6970
7005
|
}
|
|
6971
7006
|
}
|
|
6972
|
-
async function searchMarketplace(query) {
|
|
7007
|
+
async function searchMarketplace(query, json = false) {
|
|
6973
7008
|
try {
|
|
6974
7009
|
const params = new URLSearchParams({
|
|
6975
7010
|
q: query,
|
|
@@ -6978,12 +7013,37 @@ async function searchMarketplace(query) {
|
|
|
6978
7013
|
const url = `${MARKETPLACE_API}/api/search?${params.toString()}`;
|
|
6979
7014
|
const res = await fetch(url);
|
|
6980
7015
|
if (!res.ok) {
|
|
6981
|
-
console.log(
|
|
7016
|
+
if (json) console.log(JSON.stringify({
|
|
7017
|
+
source: "marketplace",
|
|
7018
|
+
count: 0,
|
|
7019
|
+
results: []
|
|
7020
|
+
}, null, 2));
|
|
7021
|
+
else console.log(`${DIM$8}skills.sh 市场无结果${RESET$8}`);
|
|
6982
7022
|
return;
|
|
6983
7023
|
}
|
|
6984
7024
|
const skills = (await res.json()).skills || [];
|
|
6985
7025
|
if (skills.length === 0) {
|
|
6986
|
-
console.log(
|
|
7026
|
+
if (json) console.log(JSON.stringify({
|
|
7027
|
+
source: "marketplace",
|
|
7028
|
+
count: 0,
|
|
7029
|
+
results: []
|
|
7030
|
+
}, null, 2));
|
|
7031
|
+
else console.log(`${DIM$8}skills.sh 上未找到 "${query}" 的技能${RESET$8}`);
|
|
7032
|
+
return;
|
|
7033
|
+
}
|
|
7034
|
+
if (json) {
|
|
7035
|
+
const results = skills.slice(0, 12).map((skill) => ({
|
|
7036
|
+
name: skill.name,
|
|
7037
|
+
source: skill.source || null,
|
|
7038
|
+
installs: skill.installs || 0,
|
|
7039
|
+
url: `https://skills.sh/${skill.id}`,
|
|
7040
|
+
installCommand: skill.source ? `bfi skills add github:${skill.source}` : null
|
|
7041
|
+
}));
|
|
7042
|
+
console.log(JSON.stringify({
|
|
7043
|
+
source: "marketplace",
|
|
7044
|
+
count: results.length,
|
|
7045
|
+
results
|
|
7046
|
+
}, null, 2));
|
|
6987
7047
|
return;
|
|
6988
7048
|
}
|
|
6989
7049
|
console.log(`skills.sh 上找到 ${skills.length} 个技能:\n`);
|
|
@@ -7022,19 +7082,21 @@ const YELLOW$2 = "\x1B[33m";
|
|
|
7022
7082
|
const RED$2 = "\x1B[31m";
|
|
7023
7083
|
const GREEN$4 = "\x1B[32m";
|
|
7024
7084
|
async function runInfo(args, globalOpts) {
|
|
7025
|
-
const
|
|
7026
|
-
if (!
|
|
7027
|
-
console.log("用法:bfi info <skill-
|
|
7028
|
-
console.log("示例:bfi info global/my-skill");
|
|
7085
|
+
const ref = args[0];
|
|
7086
|
+
if (!ref) {
|
|
7087
|
+
console.log("用法:bfi info <skill-ref>");
|
|
7088
|
+
console.log("示例:bfi info @global/my-skill");
|
|
7029
7089
|
process.exit(1);
|
|
7030
7090
|
}
|
|
7031
7091
|
const { registry, token } = resolveConfig(globalOpts);
|
|
7032
7092
|
const api = new SkillHubAPI(registry, token);
|
|
7093
|
+
const { namespace, slug } = parseSkillRef(ref, "global");
|
|
7094
|
+
const canonical = toCanonicalSlug(namespace, slug);
|
|
7033
7095
|
try {
|
|
7034
|
-
const result = await api.getSkill(
|
|
7096
|
+
const result = await api.getSkill(canonical);
|
|
7035
7097
|
const skill = result.data || result.skill || result;
|
|
7036
7098
|
if (!skill || !skill.slug) {
|
|
7037
|
-
console.log(`${DIM$7}未找到技能:${
|
|
7099
|
+
console.log(`${DIM$7}未找到技能:${ref}${RESET$7}`);
|
|
7038
7100
|
process.exit(1);
|
|
7039
7101
|
}
|
|
7040
7102
|
console.log();
|
|
@@ -7095,7 +7157,7 @@ async function runInfo(args, globalOpts) {
|
|
|
7095
7157
|
}
|
|
7096
7158
|
console.log();
|
|
7097
7159
|
} catch (error) {
|
|
7098
|
-
if (error.status === 404) console.error(`未找到技能:${
|
|
7160
|
+
if (error.status === 404) console.error(`未找到技能:${ref}`);
|
|
7099
7161
|
else console.error(`获取技能信息失败:${error.message}`);
|
|
7100
7162
|
process.exit(1);
|
|
7101
7163
|
}
|
|
@@ -7706,11 +7768,11 @@ async function runPackage(args, globalOpts) {
|
|
|
7706
7768
|
function printPackageHelp() {
|
|
7707
7769
|
console.log();
|
|
7708
7770
|
console.log(`${BOLD$1}包命令:${RESET$3}`);
|
|
7709
|
-
console.log(` ${DIM$3}bfi package list${RESET$3}
|
|
7710
|
-
console.log(` ${DIM$3}bfi package info <ref>${RESET$3}
|
|
7711
|
-
console.log(` ${DIM$3}bfi package create <slug>${RESET$3}
|
|
7712
|
-
console.log(` ${DIM$3}bfi package add <pkg>
|
|
7713
|
-
console.log(` ${DIM$3}bfi package remove <pkg>
|
|
7771
|
+
console.log(` ${DIM$3}bfi skills package list${RESET$3} 列出包`);
|
|
7772
|
+
console.log(` ${DIM$3}bfi skills package info <ref>${RESET$3} 查看包详情`);
|
|
7773
|
+
console.log(` ${DIM$3}bfi skills package create <slug>${RESET$3} 创建新包`);
|
|
7774
|
+
console.log(` ${DIM$3}bfi skills package add <pkg> [skills]${RESET$3} 添加技能到包(默认全部)`);
|
|
7775
|
+
console.log(` ${DIM$3}bfi skills package remove <pkg> [skills]${RESET$3} 从包移除技能(默认全部)`);
|
|
7714
7776
|
console.log();
|
|
7715
7777
|
console.log(`${BOLD$1}选项:${RESET$3}`);
|
|
7716
7778
|
console.log(` --namespace <ns> 目标命名空间`);
|
|
@@ -7720,11 +7782,11 @@ function printPackageHelp() {
|
|
|
7720
7782
|
console.log(` --json 以 JSON 输出`);
|
|
7721
7783
|
console.log();
|
|
7722
7784
|
console.log(`${BOLD$1}示例:${RESET$3}`);
|
|
7723
|
-
console.log(` ${DIM$3}$ ${RESET$3}bfi package list --namespace myteam`);
|
|
7724
|
-
console.log(` ${DIM$3}$ ${RESET$3}bfi package info @myteam/my-package`);
|
|
7725
|
-
console.log(` ${DIM$3}$ ${RESET$3}bfi package create my-utils --namespace myteam`);
|
|
7726
|
-
console.log(` ${DIM$3}$ ${RESET$3}bfi package add @myteam/my-package @myteam/skill-a @myteam/skill-b`);
|
|
7727
|
-
console.log(` ${DIM$3}$ ${RESET$3}bfi package remove @myteam/my-package @myteam/skill-a`);
|
|
7785
|
+
console.log(` ${DIM$3}$ ${RESET$3}bfi skills package list --namespace myteam`);
|
|
7786
|
+
console.log(` ${DIM$3}$ ${RESET$3}bfi skills package info @myteam/my-package`);
|
|
7787
|
+
console.log(` ${DIM$3}$ ${RESET$3}bfi skills package create my-utils --namespace myteam`);
|
|
7788
|
+
console.log(` ${DIM$3}$ ${RESET$3}bfi skills package add @myteam/my-package @myteam/skill-a @myteam/skill-b`);
|
|
7789
|
+
console.log(` ${DIM$3}$ ${RESET$3}bfi skills package remove @myteam/my-package @myteam/skill-a`);
|
|
7728
7790
|
console.log();
|
|
7729
7791
|
}
|
|
7730
7792
|
async function handleList(args, api, globalOpts) {
|
|
@@ -7734,11 +7796,15 @@ async function handleList(args, api, globalOpts) {
|
|
|
7734
7796
|
const result = await api.listPackages(namespace);
|
|
7735
7797
|
const packages = result.packages || result.data || [];
|
|
7736
7798
|
if (json) {
|
|
7737
|
-
console.log(JSON.stringify({
|
|
7799
|
+
console.log(JSON.stringify({
|
|
7800
|
+
namespace,
|
|
7801
|
+
packages
|
|
7802
|
+
}, null, 2));
|
|
7738
7803
|
return;
|
|
7739
7804
|
}
|
|
7740
7805
|
if (packages.length === 0) {
|
|
7741
|
-
console.log(
|
|
7806
|
+
console.log(`命名空间 "${namespace}" 中没有包。`);
|
|
7807
|
+
console.log(`使用 --namespace <ns> 查看其他命名空间,或 bfi whoami 查看你的命名空间列表。`);
|
|
7742
7808
|
return;
|
|
7743
7809
|
}
|
|
7744
7810
|
console.log();
|
|
@@ -7762,11 +7828,11 @@ async function handleList(args, api, globalOpts) {
|
|
|
7762
7828
|
async function handleInfo(args, api, globalOpts) {
|
|
7763
7829
|
const pkgRef = args[0];
|
|
7764
7830
|
if (!pkgRef) {
|
|
7765
|
-
console.error("Usage: bfi package info <package-ref>");
|
|
7831
|
+
console.error("Usage: bfi skills package info <package-ref>");
|
|
7766
7832
|
console.log();
|
|
7767
7833
|
console.log("Examples:");
|
|
7768
|
-
console.log(" bfi package info @myteam/my-package");
|
|
7769
|
-
console.log(" bfi package info myteam--my-package");
|
|
7834
|
+
console.log(" bfi skills package info @myteam/my-package");
|
|
7835
|
+
console.log(" bfi skills package info myteam--my-package");
|
|
7770
7836
|
process.exit(1);
|
|
7771
7837
|
}
|
|
7772
7838
|
const json = args.includes("--json");
|
|
@@ -7800,7 +7866,7 @@ async function handleInfo(args, api, globalOpts) {
|
|
|
7800
7866
|
async function handleCreate(args, api, globalOpts) {
|
|
7801
7867
|
const slug = args[0];
|
|
7802
7868
|
if (!slug) {
|
|
7803
|
-
console.error("用法:bfi package create <slug> [options]");
|
|
7869
|
+
console.error("用法:bfi skills package create <slug> [options]");
|
|
7804
7870
|
process.exit(1);
|
|
7805
7871
|
}
|
|
7806
7872
|
const namespace = getOptionValue(args, "--namespace") || globalOpts.namespace || "global";
|
|
@@ -7828,12 +7894,33 @@ async function handleCreate(args, api, globalOpts) {
|
|
|
7828
7894
|
async function handleAdd(args, api, globalOpts) {
|
|
7829
7895
|
const pkgRef = args[0];
|
|
7830
7896
|
const skillRefs = args.slice(1);
|
|
7831
|
-
if (!pkgRef
|
|
7832
|
-
console.error("用法:bfi package add <package-ref>
|
|
7897
|
+
if (!pkgRef) {
|
|
7898
|
+
console.error("用法:bfi skills package add <package-ref> [skill-ref...]");
|
|
7899
|
+
console.error(" 不指定技能时,添加当前命名空间的所有技能到包");
|
|
7833
7900
|
process.exit(1);
|
|
7834
7901
|
}
|
|
7835
7902
|
const { namespace, slug } = parseSkillRef(pkgRef, globalOpts.namespace);
|
|
7836
|
-
|
|
7903
|
+
let skills;
|
|
7904
|
+
if (skillRefs.length === 0) try {
|
|
7905
|
+
skills = ((await api.searchSkills("", {
|
|
7906
|
+
namespace,
|
|
7907
|
+
limit: 1e3
|
|
7908
|
+
})).results || []).map((r) => {
|
|
7909
|
+
const { namespace: ns, slug: s } = parseSkillRef(r.slug, namespace);
|
|
7910
|
+
return {
|
|
7911
|
+
namespace: ns,
|
|
7912
|
+
slug: s
|
|
7913
|
+
};
|
|
7914
|
+
});
|
|
7915
|
+
if (skills.length === 0) {
|
|
7916
|
+
console.error(`命名空间 "${namespace}" 中没有技能。`);
|
|
7917
|
+
process.exit(1);
|
|
7918
|
+
}
|
|
7919
|
+
} catch (error) {
|
|
7920
|
+
console.error(`获取技能列表失败:${error.message}`);
|
|
7921
|
+
process.exit(1);
|
|
7922
|
+
}
|
|
7923
|
+
else skills = skillRefs.map((ref) => {
|
|
7837
7924
|
const { namespace: skillNs, slug: skillSlug } = parseSkillRef(ref, namespace);
|
|
7838
7925
|
return {
|
|
7839
7926
|
namespace: skillNs,
|
|
@@ -7852,12 +7939,28 @@ async function handleAdd(args, api, globalOpts) {
|
|
|
7852
7939
|
async function handleRemove(args, api, globalOpts) {
|
|
7853
7940
|
const pkgRef = args[0];
|
|
7854
7941
|
const skillRefs = args.slice(1);
|
|
7855
|
-
if (!pkgRef
|
|
7856
|
-
console.error("用法:bfi package remove <package-ref>
|
|
7942
|
+
if (!pkgRef) {
|
|
7943
|
+
console.error("用法:bfi skills package remove <package-ref> [skill-ref...]");
|
|
7944
|
+
console.error(" 不指定技能时,移除包中所有技能");
|
|
7857
7945
|
process.exit(1);
|
|
7858
7946
|
}
|
|
7859
7947
|
const { namespace, slug } = parseSkillRef(pkgRef, globalOpts.namespace);
|
|
7860
|
-
|
|
7948
|
+
let skills;
|
|
7949
|
+
if (skillRefs.length === 0) try {
|
|
7950
|
+
const existingSkills = (await api.getPackage(namespace, slug)).skills || [];
|
|
7951
|
+
if (existingSkills.length === 0) {
|
|
7952
|
+
console.log("包中没有技能。");
|
|
7953
|
+
return;
|
|
7954
|
+
}
|
|
7955
|
+
skills = existingSkills.map((s) => ({
|
|
7956
|
+
namespace: s.namespace || namespace,
|
|
7957
|
+
slug: s.slug
|
|
7958
|
+
}));
|
|
7959
|
+
} catch (error) {
|
|
7960
|
+
console.error(`获取包信息失败:${error.message}`);
|
|
7961
|
+
process.exit(1);
|
|
7962
|
+
}
|
|
7963
|
+
else skills = skillRefs.map((ref) => {
|
|
7861
7964
|
const { namespace: skillNs, slug: skillSlug } = parseSkillRef(ref, namespace);
|
|
7862
7965
|
return {
|
|
7863
7966
|
namespace: skillNs,
|