bfi-cli 0.1.35 → 0.1.38

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 CHANGED
@@ -905,6 +905,11 @@ function setConfigValue(key, value, isGlobal = false) {
905
905
  saveProjectConfig(workdir, config);
906
906
  }
907
907
  }
908
+ var skill_ref_exports = /* @__PURE__ */ __exportAll({
909
+ parseSkillRef: () => parseSkillRef,
910
+ toCanonicalSlug: () => toCanonicalSlug,
911
+ toSkillRefString: () => toSkillRefString
912
+ });
908
913
  function parseSkillRef(ref, defaultNamespace = "global") {
909
914
  if (!ref || typeof ref !== "string") throw new Error("Skill reference is required");
910
915
  const trimmed = ref.trim();
@@ -4115,19 +4120,18 @@ async function promptForBfiSkill(options, targetAgents) {
4115
4120
  console.log();
4116
4121
  log.step("正在安装 skillhub-skills 技能...");
4117
4122
  try {
4118
- await runAdd(["bfi/skillhub-skills"], {
4119
- skill: ["skillhub-skills"],
4123
+ await runAdd(["@global/skillhub-skills"], {
4120
4124
  global: true,
4121
4125
  yes: true,
4122
4126
  agent: bfiSkillAgents
4123
4127
  });
4124
4128
  } catch {
4125
4129
  log.warn("安装 skillhub-skills 失败。你可以稍后重试:");
4126
- log.message(import_picocolors.default.dim(" bfi skills add bfi/skillhub-skills --skill skillhub-skills -g -y"));
4130
+ log.message(import_picocolors.default.dim(" bfi skills add @global/skillhub-skills -g -y"));
4127
4131
  }
4128
4132
  } else {
4129
4133
  await dismissPrompt("bfiSkillPrompt");
4130
- log.message(import_picocolors.default.dim("你可以稍后通过以下命令安装:bfi skills add bfi/skillhub-skills --skill skillhub-skills -g -y"));
4134
+ log.message(import_picocolors.default.dim("你可以稍后通过以下命令安装:bfi skills add @global/skillhub-skills -g -y"));
4131
4135
  }
4132
4136
  } catch {}
4133
4137
  }
@@ -5040,7 +5044,29 @@ async function updateGlobalSkills(options = {}) {
5040
5044
  let tempDir = null;
5041
5045
  process.stdout.write(`\r${DIM$9}Checking skills from source: ${source}${RESET$9}\x1b[K\n`);
5042
5046
  if (firstEntry.sourceType === "skillhub") {
5043
- console.log(` ${DIM$9}SkillHub 技能请使用 bfi skills add 重新安装来更新${RESET$9}`);
5047
+ const skillhubRef = source.replace(/^skillhub:/, "");
5048
+ const { parseSkillRef, toCanonicalSlug } = await Promise.resolve().then(() => skill_ref_exports);
5049
+ const { SkillHubAPI } = await Promise.resolve().then(() => api_exports);
5050
+ const { resolveConfig } = await Promise.resolve().then(() => config_exports);
5051
+ const cfg = resolveConfig({});
5052
+ new SkillHubAPI(cfg.registry, cfg.token);
5053
+ for (const item of itemsForSource) {
5054
+ const safeName = sanitizeMetadata(item.name);
5055
+ console.log(`${TEXT$7}正在更新 ${safeName}...${RESET$9}`);
5056
+ try {
5057
+ const parts = skillhubRef.split("/");
5058
+ const ref = parts.length === 2 ? `@${parts[0]}/${parts[1]}` : skillhubRef;
5059
+ const { runAdd } = await Promise.resolve().then(() => add_exports);
5060
+ await runAdd([ref], {
5061
+ global: options.global,
5062
+ yes: true
5063
+ });
5064
+ successCount++;
5065
+ } catch (error) {
5066
+ console.log(` ${DIM$9}✗ ${safeName}: ${error.message}${RESET$9}`);
5067
+ failCount++;
5068
+ }
5069
+ }
5044
5070
  continue;
5045
5071
  }
5046
5072
  try {
@@ -5221,6 +5247,32 @@ async function updateProjectSkills(options = {}) {
5221
5247
  const firstEntry = skillsForSource[0].entry;
5222
5248
  const sourceUrl = firstEntry.sourceUrl || firstEntry.source;
5223
5249
  const ref = firstEntry.ref;
5250
+ if (firstEntry.sourceType === "skillhub") {
5251
+ const skillhubRef = source.replace(/^skillhub:/, "");
5252
+ const { parseSkillRef, toCanonicalSlug } = await Promise.resolve().then(() => skill_ref_exports);
5253
+ const { SkillHubAPI } = await Promise.resolve().then(() => api_exports);
5254
+ const { resolveConfig } = await Promise.resolve().then(() => config_exports);
5255
+ const cfg = resolveConfig({});
5256
+ new SkillHubAPI(cfg.registry, cfg.token);
5257
+ for (const item of skillsForSource) {
5258
+ const safeName = sanitizeMetadata(item.name);
5259
+ console.log(`${TEXT$7}正在更新 ${safeName}...${RESET$9}`);
5260
+ try {
5261
+ const parts = skillhubRef.split("/");
5262
+ const ref = parts.length === 2 ? `@${parts[0]}/${parts[1]}` : skillhubRef;
5263
+ const { runAdd } = await Promise.resolve().then(() => add_exports);
5264
+ await runAdd([ref], {
5265
+ global: false,
5266
+ yes: true
5267
+ });
5268
+ successCount++;
5269
+ } catch (error) {
5270
+ console.log(` ${DIM$9}✗ ${safeName}: ${error.message}${RESET$9}`);
5271
+ failCount++;
5272
+ }
5273
+ }
5274
+ continue;
5275
+ }
5224
5276
  const allLockedForSource = Object.entries(localLock.skills).filter(([_, entry]) => (entry.sourceUrl || entry.source) === source).map(([name, _]) => name);
5225
5277
  let tempDir = null;
5226
5278
  let deletedSkills = [];
@@ -6579,6 +6631,7 @@ function truncate(text, maxLen) {
6579
6631
  if (text.length <= maxLen) return text;
6580
6632
  return text.slice(0, maxLen) + "...";
6581
6633
  }
6634
+ var package_exports = /* @__PURE__ */ __exportAll({ runPackage: () => runPackage });
6582
6635
  const RESET$3 = "\x1B[0m";
6583
6636
  const BOLD$1 = "\x1B[1m";
6584
6637
  const DIM$3 = "\x1B[38;5;102m";
@@ -6998,7 +7051,16 @@ const GREEN = "\x1B[32m";
6998
7051
  const YELLOW = "\x1B[33m";
6999
7052
  async function runInstall(args, globalOpts) {
7000
7053
  const yes = args.includes("--yes") || args.includes("-y");
7001
- const lock = loadLockfile(globalOpts.workdir || process.cwd());
7054
+ const workdir = globalOpts.workdir || process.cwd();
7055
+ const lock = loadLockfile(workdir);
7056
+ try {
7057
+ const skillsLock = await readLocalLock(workdir);
7058
+ for (const [name, entry] of Object.entries(skillsLock.skills)) if (!lock.skills[name]) lock.skills[name] = {
7059
+ ...entry,
7060
+ namespace: "global",
7061
+ slug: name
7062
+ };
7063
+ } catch {}
7002
7064
  const skillEntries = Object.entries(lock.skills);
7003
7065
  const packageEntries = Object.entries(lock.packages);
7004
7066
  if (skillEntries.length === 0 && packageEntries.length === 0) {
@@ -7015,39 +7077,44 @@ async function runInstall(args, globalOpts) {
7015
7077
  let failedCount = 0;
7016
7078
  for (const [skillName, entry] of skillEntries) {
7017
7079
  const skillEntry = entry;
7018
- const sourceType = String(skillEntry.sourceType || "");
7080
+ const sourceType = String(skillEntry.sourceType || skillEntry.source || "");
7019
7081
  const namespace = String(skillEntry.namespace || "global");
7020
7082
  const slug = String(skillEntry.slug || skillName);
7021
7083
  const source = String(skillEntry.source || "");
7022
- String(skillEntry.version || "latest");
7023
7084
  let installSource;
7024
- if (sourceType === "skillhub" || namespace !== "global") installSource = `@${namespace}/${slug}`;
7025
- else if (source) installSource = source;
7085
+ if (sourceType === "skillhub") installSource = `@${namespace}/${slug}`;
7086
+ else if (sourceType === "github" || sourceType === "gitlab") installSource = source;
7087
+ else if (source && (source.startsWith("http://") || source.startsWith("https://") || source.startsWith("git@"))) installSource = source;
7026
7088
  else {
7027
- console.log(` ${YELLOW}跳过 ${skillName}:未知源类型${RESET$1}`);
7089
+ console.log(` ${YELLOW}跳过 ${skillName}:未知源类型 (${sourceType})${RESET$1}`);
7028
7090
  continue;
7029
7091
  }
7030
- console.log(` ${TEXT$1}正在从 ${installSource} 安装 ${skillName}...${RESET$1}`);
7092
+ console.log(` ${TEXT$1}正在安装 ${installSource}...${RESET$1}`);
7031
7093
  try {
7032
7094
  await runAdd([installSource], { yes });
7033
7095
  installedCount++;
7034
7096
  console.log(` ${GREEN}✓ ${skillName}${RESET$1}`);
7035
7097
  } catch (error) {
7036
7098
  failedCount++;
7037
- console.error(` ${YELLOW}失败:${error.message}${RESET$1}`);
7099
+ console.error(` ${YELLOW}✗ ${error.message}${RESET$1}`);
7038
7100
  }
7039
7101
  }
7040
7102
  for (const [pkgRef, entry] of packageEntries) {
7041
7103
  const pkgEntry = entry;
7042
- const installSource = `@${String(pkgEntry.namespace || "global")}/${String(pkgEntry.slug || pkgRef)}`;
7043
- console.log(` ${TEXT$1}正在从 ${installSource} 安装包 ${pkgRef}...${RESET$1}`);
7104
+ const namespace = String(pkgEntry.namespace || "global");
7105
+ const slug = String(pkgEntry.slug || pkgRef);
7106
+ console.log(` ${TEXT$1}正在安装包 @${namespace}/${slug}...${RESET$1}`);
7044
7107
  try {
7045
- await runAdd([installSource], { yes });
7108
+ const { runPackage } = await Promise.resolve().then(() => package_exports);
7109
+ await runPackage(["install", `@${namespace}/${slug}`], {
7110
+ ...globalOpts,
7111
+ yes
7112
+ });
7046
7113
  installedCount++;
7047
7114
  console.log(` ${GREEN}✓ ${pkgRef}${RESET$1}`);
7048
7115
  } catch (error) {
7049
7116
  failedCount++;
7050
- console.error(` ${YELLOW}失败:${error.message}${RESET$1}`);
7117
+ console.error(` ${YELLOW}✗ ${error.message}${RESET$1}`);
7051
7118
  }
7052
7119
  }
7053
7120
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.35",
3
+ "version": "0.1.38",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,24 +7,18 @@ description: 使用 bfi CLI 在 SkillHub 上搜索、安装、发布和管理技
7
7
 
8
8
  bfi 是 SkillHub 生态的统一命令行工具。融合了开源 agent skills 生态能力和 SkillHub 专有功能。
9
9
 
10
- ## ⚠️ 第零步:检查 bfi CLI 是否安装(最早执行)
10
+ ## 第零步:检查 bfi CLI 是否安装
11
11
 
12
- **在执行任何 SkillHub 操作之前,必须先确认 bfi CLI 已安装。**
13
-
14
- 静默运行 `bfi --version`。如果返回错误或未找到命令:
12
+ 静默运行 `bfi --version`。如果未找到:
15
13
 
16
14
  ```
17
15
  需要安装 bfi CLI 工具。正在安装:
18
-
19
- ```bash
20
16
  npm install -g bfi-cli
21
17
  ```
22
18
 
23
- 安装完成后,继续执行后续步骤。
19
+ ## 第一步:检查登录状态
24
20
 
25
- **在做任何操作之前,必须先确认用户已登录。**
26
-
27
- 静默运行 `bfi whoami`。如果返回错误或未认证:
21
+ 静默运行 `bfi whoami`。如果未认证:
28
22
 
29
23
  ```
30
24
  你需要登录 SkillHub 才能继续。请提供你的 API Token。
@@ -34,154 +28,94 @@ npm install -g bfi-cli
34
28
  请直接回复你的 Token,我会自动完成登录。
35
29
  ```
36
30
 
37
- 用户提供 Token 后,立即静默执行:
38
- ```bash
39
- bfi auth login --token <用户提供的Token>
40
- ```
31
+ 用户提供 Token 后,立即执行 `bfi auth login --token <Token>`。登录成功后继续用户原请求。
41
32
 
42
- 登录成功后,继续执行用户原本请求的操作,无需用户再次输入。如果登录失败,告知用户 Token 无效,请重新提供。
33
+ ## ⚠️ 关键区分:使用 vs 管理
43
34
 
44
- ## 判断场景
35
+ - **使用**:只读取 SkillHub 数据或操作本地文件。包括:搜索、查看、安装、卸载、更新、列表、日志。
36
+ - **管理**:会修改 SkillHub 服务端数据,需要写权限。包括:发布技能、创建包、添加/移除包内技能。
45
37
 
46
- 根据用户意图选择对应场景:
47
-
48
- ### 场景 1:使用技能(搜索、安装、使用、查看)
38
+ ---
49
39
 
50
- 用户想找技能、安装技能、试用技能、查看已安装的技能。
40
+ ## 场景 1:使用技能
51
41
 
52
- **1.1 搜索技能**
42
+ ### 1.1 搜索
53
43
  ```bash
54
- bfi skills search <关键词> # 搜索 SkillHub(默认)
55
- bfi skills search <关键词> --marketplace # 搜索 skills.sh 公开市场
44
+ bfi skills search <关键词>
45
+ bfi skills search <关键词> --marketplace # skills.sh 公开市场
56
46
  ```
57
47
 
58
- **1.2 查看技能详情**
48
+ ### 1.2 查看详情
59
49
  ```bash
60
50
  bfi skills info <@namespace/slug 或 namespace--slug>
61
51
  ```
62
52
 
63
- **1.3 安装技能**
53
+ ### 1.3 安装
64
54
  ```bash
65
- # SkillHub
66
- bfi skills add @命名空间/技能名
67
- bfi skills add 命名空间--技能名
68
-
69
- # Git 仓库(默认 git.yyrd.com)
70
- bfi skills add owner/repo --skill <name> # 指定仓库中的某个技能
71
- bfi skills add owner/repo # 安装全部技能
72
- bfi skills add owner/repo --branch <分支> # 指定分支
73
-
74
- # GitHub
75
- bfi skills add github:owner/repo # 强制走 github.com
76
-
77
- # 安装选项
78
- bfi skills add <来源> -y # 跳过交互确认
79
- bfi skills add <来源> --list # 仅列出技能,不安装
55
+ bfi skills add @命名空间/技能名 # SkillHub
56
+ bfi skills add owner/repo --skill <name> # Git 仓库(默认 git.yyrd.com)
57
+ bfi skills add github:owner/repo # GitHub
58
+ bfi skills add <来源> -y # 跳过确认
80
59
  ```
81
60
 
82
- **1.4 安装技能包**
61
+ ### 1.4 安装技能包
83
62
  ```bash
84
- bfi skills package install @namespace/package-name
63
+ bfi skills package install @namespace/pkg
85
64
  ```
86
65
 
87
- **1.5 查看已安装**
66
+ ### 1.5 查看已安装
88
67
  ```bash
89
68
  bfi skills list
90
- bfi skills ls -g # 全局安装的技能
69
+ bfi skills ls -g # 全局
91
70
  ```
92
71
 
93
- **1.6 使用技能(不安装)**
72
+ ### 1.6 卸载
94
73
  ```bash
95
- bfi skills use <来源> # 生成 prompt 文本
74
+ bfi skills remove <技能名> -y
96
75
  ```
97
76
 
98
- ### 场景 2:管理技能(发布、更新、卸载、包管理)
99
-
100
- 用户想发布技能、管理包、更新/卸载技能。
101
-
102
- **2.1 发布技能**
77
+ ### 1.7 更新
103
78
  ```bash
104
- # 从 Git 发布(推荐,自动发现所有技能)
105
- bfi skills publish owner/repo --from git --namespace <ns>
106
-
107
- # 从本地目录发布
108
- bfi skills publish <路径> --namespace <ns>
109
-
110
- # 从 ZIP 发布
111
- bfi skills publish <路径> --from zip --namespace <ns>
112
-
113
- # 选项
114
- # --visibility public 公开发布(默认)
115
- # --branch <分支> 指定分支(默认 main)
116
- # --skill <name> 只发布指定技能
117
- # -y 跳过确认
79
+ bfi skills update
80
+ bfi skills update <技能名>
118
81
  ```
119
82
 
120
- **2.2 卸载技能**
83
+ ### 1.8 记录调用
121
84
  ```bash
122
- bfi skills remove <技能名> -y
85
+ bfi skills log <技能名> "简要描述"
123
86
  ```
124
87
 
125
- **2.3 更新技能**
88
+ ---
89
+
90
+ ## 场景 2:管理技能
91
+
92
+ ### 2.1 发布
126
93
  ```bash
127
- bfi skills update # 更新全部
128
- bfi skills update <技能名>
129
- # Git 来源的技能会检查远端更新
130
- # SkillHub 来源的技能请用 bfi skills add 重新安装
94
+ bfi skills publish owner/repo --from git --namespace <ns>
95
+ bfi skills publish <路径> --namespace <ns>
96
+ # 选项:--branch <分支>、--skill <name>、--visibility public(默认)、-y
131
97
  ```
132
98
 
133
- **2.4 技能包管理**
99
+ ### 2.2 技能包管理(服务端)
134
100
  ```bash
135
- # 创建包
136
101
  bfi skills package create <slug> --namespace <ns>
137
-
138
- # 添加技能到包
139
102
  bfi skills package add-skills @ns/pkg <skill...>
140
-
141
- # 从包移除技能
142
103
  bfi skills package remove-skills @ns/pkg <skill...>
143
-
144
- # 安装包
145
- bfi skills package install @ns/pkg
146
-
147
- # 卸载包
148
- bfi skills package uninstall @ns/pkg
149
-
150
- # 查看已安装的包
151
- bfi skills package list
152
- ```
153
-
154
- ### 场景 3:记录技能调用
155
-
156
- **每次使用技能时必须记录:**
157
- ```bash
158
- bfi skills log <技能名> "简要描述"
159
104
  ```
160
105
 
161
106
  ## 技能引用格式
162
107
 
163
- | 格式 | 示例 | 说明 |
164
- |------|------|------|
165
- | `@ns/slug` | `@retail/skill-pm` | SkillHub 技能 |
166
- | `ns--slug` | `retail--skill-pm` | 兼容格式 |
167
- | `owner/repo` | `bfi/bfi-skill` | Git 仓库(默认 git.yyrd.com) |
168
- | `github:owner/repo` | `github:vercel-labs/agent-skills` | 强制 GitHub |
108
+ | 格式 | 说明 |
109
+ |------|------|
110
+ | `@ns/slug` | SkillHub 技能 |
111
+ | `ns--slug` | 兼容格式 |
112
+ | `owner/repo` | Git 仓库(默认 git.yyrd.com) |
113
+ | `github:owner/repo` | 强制 GitHub |
169
114
 
170
115
  ## 配置
171
116
 
172
117
  ```bash
173
- bfi config get # 查看全部配置
174
- bfi config set registry <url> --global # 设置 API 地址
175
- bfi config set namespace <ns> # 设置默认命名空间
118
+ bfi config get
119
+ bfi config set registry <url> --global
120
+ bfi config set namespace <ns>
176
121
  ```
177
-
178
- ## 常见问题
179
-
180
- **Q: 公司 GitLab 仓库中的技能找不到?**
181
- A: 默认从 git.yyrd.com 克隆。如果是 GitHub 上的技能,使用 `github:` 前缀。
182
-
183
- **Q: 如何更新 SkillHub 上的技能?**
184
- A: 用 `bfi skills publish` 重新发布即可,服务端自动版本管理。
185
-
186
- **Q: 发布失败?**
187
- A: 确保 SKILL.md 文件在发布目录或仓库中,且包含 name 和 description 字段。