bfi-cli 0.1.94 → 0.1.96

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.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+
3
+ import module from 'node:module';
4
+
5
+ if (module.enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) {
6
+ try {
7
+ module.enableCompileCache();
8
+ } catch {
9
+ // Ignore errors
10
+ }
11
+ }
12
+
13
+ await import('../dist/mcp-weknora/main.mjs');
package/dist/cli.mjs CHANGED
@@ -7162,6 +7162,7 @@ async function handleInstall(args, api, globalOpts) {
7162
7162
  console.error(`${RED$1}获取包信息失败:${error.message}${RESET$3}`);
7163
7163
  process.exit(1);
7164
7164
  }
7165
+ if (pkgInfo.kind === "PLUGIN") throw new Error("这是完整插件,不是技能组合;请使用 --as plugin --agent <目标Agent> 安装,插件可能包含 MCP 和 Hooks。");
7165
7166
  const skills = pkgInfo.skills || [];
7166
7167
  if (skills.length === 0) {
7167
7168
  console.log(`${YELLOW$1}包中没有可独立安装的技能。${RESET$3}`);
@@ -7484,7 +7485,9 @@ async function handleUpdate(args, api, globalOpts) {
7484
7485
  console.log(`${DIM$3}正在更新 ${packagesToUpdate.length} 个包...${RESET$3}`);
7485
7486
  for (const pkg of packagesToUpdate) try {
7486
7487
  const pkgInfo = await api.getPackage(pkg.namespace, pkg.slug);
7487
- const skills = (pkgInfo.data || pkgInfo).skills || [];
7488
+ const info = pkgInfo.data || pkgInfo;
7489
+ if (info.kind === "PLUGIN") throw new Error("这是完整插件,请使用 --as plugin --agent <目标Agent> 更新;不会按技能组合安装。");
7490
+ const skills = info.skills || [];
7488
7491
  console.log(` ${DIM$3}更新 @${pkg.namespace}/${pkg.slug}(${skills.length} 个技能)...${RESET$3}`);
7489
7492
  for (const skill of skills) {
7490
7493
  const skillRef = skill.namespace ? `@${skill.namespace}/${skill.slug}` : skill.slug;
@@ -8115,17 +8118,6 @@ const ALLOWED_FLAGS = {
8115
8118
  "--app",
8116
8119
  "--type"
8117
8120
  ],
8118
- cases: [
8119
- "--type",
8120
- "--finger",
8121
- "--service",
8122
- "--kw",
8123
- "--limit",
8124
- "--file",
8125
- "--env",
8126
- "--confidence",
8127
- "--title"
8128
- ],
8129
8121
  wiki: [
8130
8122
  "--limit",
8131
8123
  "--source",
@@ -8568,68 +8560,6 @@ async function runYmc(args, globalOpts) {
8568
8560
  emit(await api.call("ymc/tool/list", body), jsonMode, rowsSummary("诊断文件"));
8569
8561
  break;
8570
8562
  }
8571
- case "cases": {
8572
- const sub2 = rest[0] || "search";
8573
- const rest2 = rest.slice(1);
8574
- if (sub2 === "search") {
8575
- const body = {};
8576
- for (const [k, name] of [
8577
- ["type", "--type"],
8578
- ["fingerprint", "--finger"],
8579
- ["service", "--service"],
8580
- ["keyword", "--kw"]
8581
- ]) {
8582
- const v = opt(rest2, name);
8583
- if (v) body[k] = v;
8584
- }
8585
- if (opt(rest2, "--limit")) body.limit = Number(opt(rest2, "--limit"));
8586
- emit(await api.call("cases/search", body), jsonMode, (data) => {
8587
- const d = data;
8588
- const list = d.cases || [];
8589
- if (!list.length) return "(无命中案例)";
8590
- return `✓ 命中 ${d.count} 条:\n` + list.map((x) => ` [${x.case_id}] (${x.type}/${x.confidence}) ${x.title}\n 指纹: ${JSON.stringify(x.fingerprint)} ${x.env || ""} ${x.service || ""} by ${x.author}`).join("\n");
8591
- });
8592
- } else if (sub2 === "show") {
8593
- const id = positionals(rest2)[0];
8594
- if (!id) {
8595
- console.error("用法:bfi ymc cases show <case_id>");
8596
- process.exit(1);
8597
- }
8598
- emit(await api.get(`cases/${id}`), jsonMode);
8599
- } else if (sub2 === "upload") {
8600
- const file = opt(rest2, "--file");
8601
- if (!file) {
8602
- console.error("用法:bfi ymc cases upload --file <case.md> [--type] [--finger \"a,b\"] [--env] [--service]");
8603
- process.exit(1);
8604
- }
8605
- const { readFileSync } = await import("node:fs");
8606
- const body = {
8607
- type: opt(rest2, "--type") || "review",
8608
- fingerprint: (opt(rest2, "--finger") || "").split(",").map((s) => s.trim()).filter(Boolean),
8609
- content: readFileSync(file, "utf-8")
8610
- };
8611
- for (const [k, name] of [
8612
- ["env", "--env"],
8613
- ["service", "--service"],
8614
- ["confidence", "--confidence"],
8615
- ["title", "--title"]
8616
- ]) {
8617
- const v = opt(rest2, name);
8618
- if (v) body[k] = v;
8619
- }
8620
- emit(await api.call("cases", body), jsonMode, (data) => `✓ 案例已上传: ${data.case_id}`);
8621
- } else if (sub2 === "index") emit(await api.get("cases/index/overview"), jsonMode, (data) => {
8622
- const d = data;
8623
- const byType = Object.entries(d.by_type || {}).map(([k, v]) => `${k}=${v}`).join(", ");
8624
- const fps = (d.top_fingerprints || []).map((x) => `${x.fingerprint}(${x.count})`).join(", ");
8625
- return `✓ 案例总数: ${d.total}\n 类型分布: ${byType}\n 高频指纹: ${fps}`;
8626
- });
8627
- else {
8628
- console.error("用法:bfi ymc cases <search|show|upload|index>");
8629
- process.exit(1);
8630
- }
8631
- break;
8632
- }
8633
8563
  case "wiki": {
8634
8564
  const sub2 = rest[0] || "search";
8635
8565
  const rest2 = rest.slice(1);
@@ -8866,6 +8796,7 @@ async function runYmc(args, globalOpts) {
8866
8796
  break;
8867
8797
  }
8868
8798
  default: {
8799
+ if (sub === "cases" || sub.startsWith("cases")) console.error("案例库已迁移 WeKnora:检索/归档改用 weknora-bfi MCP 工具(kb_search / kb_archive_case)。");
8869
8800
  console.error(`未知子命令:${sub}`);
8870
8801
  const hint = SUBCOMMAND_HINTS[sub];
8871
8802
  if (hint) console.error(`提示:${hint}`);
@@ -8891,7 +8822,9 @@ const HELP = {
8891
8822
  chain: `bfi ymc chain <trace_id> -e <env> [--ts <毫秒>] [--json]
8892
8823
  原子源:warningChain 全量 Span 链路(耗时分解/调用树)。trace 三源合一的链路通道单独调用。`,
8893
8824
  "sls-logs": `bfi ymc sls-logs <trace_id> -e <env> [--ts <毫秒>] [--json]
8894
- 原子源:SLS 业务日志(异常全文/堆栈)。按 traceid 索引检索。`,
8825
+ 原子源:SLS 业务日志(异常全文/堆栈)。按 traceid 索引检索。
8826
+ --json 结构:data 为对象(非数组)——日志行在 data.rows,计数在 data.count。
8827
+ 直接把 data 当数组迭代会得到 0 条(2026-10-16 实战教训)。`,
8895
8828
  "sls-raw": `bfi ymc sls-raw "<查询>" -e <env> [-t <time> | --start-time <s> --end-time <e> | --days N] [--line N] [--json]
8896
8829
  SLS 原始查询(阿里云 SLS 完整语法透传:索引检索 + | SELECT 分析语句)。
8897
8830
  参数:
@@ -9086,6 +9019,9 @@ function printHelp$2() {
9086
9019
  bfi event stat <dc> <date> [metric_type] [--page N] [--size N]
9087
9020
  date: yyyy-MM-dd 单日;metric_type: enter|fail|response_time_4s_|response_time_2s_4s|body_size_512k_1m|body_size_1m_
9088
9021
  bfi event record <dc> <date> --source-id S --event-type ET --node-code N --ds-code DS [--record-status fail] [--record-id ID] [--tenant-code T] [--size ≤20]
9022
+ bfi event dc-scan <date> [--event-type ET] [--node-code N]
9023
+ 全 DC 矩阵扫描:C1-C4 逐数据中心查 fail 统计,本事件命中高亮。
9024
+ ⚠️ monitor fail(不带 DC)存在数据中心盲区(实测漏 C3)——失败现场定位必须用本命令
9089
9025
  bfi event content <dc> <date> --event-id E --ds-code DS --tenant-code T
9090
9026
  bfi event dclist <dc>
9091
9027
  bfi event analyze-alert <dc> <date> --event-type ET --node-code N [--source-id S] [--tenant-code T]
@@ -9149,6 +9085,74 @@ async function runEvent(args, globalOpts) {
9149
9085
  });
9150
9086
  return;
9151
9087
  }
9088
+ if (sub === "dc-scan") {
9089
+ const date = reqs[0] ?? missing("<date>");
9090
+ const eventType = str("--event-type") ?? "";
9091
+ const nodeCode = str("--node-code") ?? "";
9092
+ const dcs = [
9093
+ "core1",
9094
+ "core2",
9095
+ "core3",
9096
+ "core4"
9097
+ ];
9098
+ const statOnce = async (dc) => {
9099
+ return (await api.call("event/stat", {
9100
+ dc,
9101
+ date,
9102
+ metric_type: "fail",
9103
+ page: 0,
9104
+ size: 1e3
9105
+ }))?.data?.data?.content ?? [];
9106
+ };
9107
+ const results = await Promise.all(dcs.map(async (dc) => {
9108
+ try {
9109
+ let content = await statOnce(dc);
9110
+ if (!content.length) content = await statOnce(dc);
9111
+ const hit = eventType ? content.filter((x) => x.eventType === eventType && (!nodeCode || x.nodeCode === nodeCode)) : content;
9112
+ return {
9113
+ dc,
9114
+ rows: hit,
9115
+ failNum: hit.reduce((acc, x) => acc + Number(x.num ?? 0), 0),
9116
+ total: content.length
9117
+ };
9118
+ } catch (e) {
9119
+ return {
9120
+ dc,
9121
+ rows: [],
9122
+ failNum: 0,
9123
+ total: 0,
9124
+ error: e instanceof Error ? e.message : String(e)
9125
+ };
9126
+ }
9127
+ }));
9128
+ if (jsonMode) {
9129
+ console.log(JSON.stringify({
9130
+ code: 0,
9131
+ msg: "success",
9132
+ data: {
9133
+ date,
9134
+ event_type: eventType,
9135
+ node_code: nodeCode,
9136
+ results
9137
+ }
9138
+ }, null, 2));
9139
+ return;
9140
+ }
9141
+ const lines = [`全 DC fail 矩阵(${date}${eventType ? ` · ${eventType}${nodeCode ? ` / ${nodeCode}` : ""}` : ""}):`, "DC 失败数 失败率 判定"];
9142
+ for (const r of results) {
9143
+ if (r.error) {
9144
+ lines.push(`${r.dc.padEnd(8)} 通道错误:${r.error}`);
9145
+ continue;
9146
+ }
9147
+ const rate = r.rows.length ? String(r.rows[0].failRate ?? "-") : "-";
9148
+ const verdict = r.total === 0 ? "✓ 无记录(排除证据)" : r.failNum === 0 ? "✓ 有流量零失败" : `🔴 失败现场(${r.rows.length} 个监听行)`;
9149
+ lines.push(`${r.dc.padEnd(8)} ${String(r.failNum).padEnd(8)} ${rate.padEnd(11)} ${verdict}`);
9150
+ }
9151
+ const hot = results.filter((r) => r.failNum > 0).map((r) => r.dc);
9152
+ lines.push(hot.length ? `→ 失败现场:${hot.join(" / ")}(对命中 DC 逐一 event analyze-alert;零命中 DC 是报告的排除证据)` : "→ 全 DC 无失败记录");
9153
+ console.log(lines.join("\n"));
9154
+ return;
9155
+ }
9152
9156
  if (sub === "monitor") {
9153
9157
  const metric = reqs[0];
9154
9158
  if (!metric || !METRICS.includes(metric)) {
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,308 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
4
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
5
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import os from "node:os";
9
+ const DEFAULT_WEKNORA_URL = process.env.WEKNORA_MCP_URL || "https://bfi.yyuap.com/weknora/mcp/e8e50146-81f6-4aca-b5cf-cce711bd2b99";
10
+ const CASE_KB_NAME = "案例库";
11
+ var WeknoraError = class extends Error {
12
+ errorKind;
13
+ constructor(errorKind, message) {
14
+ super(message);
15
+ this.errorKind = errorKind;
16
+ }
17
+ };
18
+ var WeknoraRemote = class {
19
+ url;
20
+ token;
21
+ client = null;
22
+ constructor(url, token) {
23
+ this.url = url;
24
+ this.token = token;
25
+ }
26
+ async listTools() {
27
+ const client = await this.ensure();
28
+ try {
29
+ return (await client.request({ method: "tools/list" }, ListToolsResultSchema)).tools;
30
+ } catch (e) {
31
+ this.handleFailure(e);
32
+ }
33
+ }
34
+ async callTool(name, args) {
35
+ if (!this.token()) throw new WeknoraError("unauthorized", this.loginHint());
36
+ const client = await this.ensure();
37
+ try {
38
+ return await client.request({
39
+ method: "tools/call",
40
+ params: {
41
+ name,
42
+ arguments: args ?? {}
43
+ }
44
+ }, CallToolResultSchema);
45
+ } catch (e) {
46
+ this.handleFailure(e);
47
+ }
48
+ }
49
+ async ensure() {
50
+ if (this.client) return this.client;
51
+ const token = this.token();
52
+ if (!token) throw new WeknoraError("unauthorized", this.loginHint());
53
+ const client = new Client({
54
+ name: "bfi-weknora-mcp",
55
+ version: "0.1.0"
56
+ });
57
+ const transport = new StreamableHTTPClientTransport(new URL(this.url), { requestInit: { headers: { Authorization: `Bearer ${token}` } } });
58
+ try {
59
+ await client.connect(transport);
60
+ } catch (e) {
61
+ throw new WeknoraError("weknora_unreachable", `WeKnora 服务不可达(${this.url}): ${e instanceof Error ? e.message : String(e)}`);
62
+ }
63
+ this.client = client;
64
+ return client;
65
+ }
66
+ handleFailure(e) {
67
+ this.client = null;
68
+ const message = e instanceof Error ? e.message : String(e);
69
+ if (/401|unauthorized|Unauthorized/i.test(message)) throw new WeknoraError("unauthorized", `WeKnora token 无效或过期。${this.loginHint()}`);
70
+ throw new WeknoraError("weknora_error", `WeKnora 远端调用失败: ${message}`);
71
+ }
72
+ loginHint() {
73
+ return "未找到 bfi token:请先执行 `bfi auth login --token <sk-token>`(token 获取地址 https://bfi.yyuap.com/user/profile),或设置 BFI_TOKEN 环境变量";
74
+ }
75
+ };
76
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".bfi");
77
+ const GLOBAL_CONFIG_FILE = path.join(GLOBAL_CONFIG_DIR, "config.json");
78
+ path.join(".bfi", "lock.json");
79
+ function loadGlobalConfig() {
80
+ try {
81
+ if (fs.existsSync(GLOBAL_CONFIG_FILE)) {
82
+ const content = fs.readFileSync(GLOBAL_CONFIG_FILE, "utf8");
83
+ return JSON.parse(content);
84
+ }
85
+ } catch (error) {
86
+ console.warn(`Warning: Failed to load global config: ${error.message}`);
87
+ }
88
+ return null;
89
+ }
90
+ function resolveToken() {
91
+ if (process.env.BFI_TOKEN) return process.env.BFI_TOKEN;
92
+ return loadGlobalConfig()?.token ?? null;
93
+ }
94
+ function textResult(payload, isError = false) {
95
+ return {
96
+ content: [{
97
+ type: "text",
98
+ text: JSON.stringify(payload, null, 2)
99
+ }],
100
+ isError
101
+ };
102
+ }
103
+ const TOOLS = [
104
+ {
105
+ name: "kb_search",
106
+ description: "跨库语义检索 BFI 知识库(案例库/wiki/jira-支持案例/供应链/领域知识全部覆盖)——诊断先验的主通道:查历史同类问题、已解决方案、领域知识。返回最相关文段(hybrid)。",
107
+ inputSchema: {
108
+ type: "object",
109
+ properties: {
110
+ query: {
111
+ type: "string",
112
+ description: "检索问题(症状/组件/错误关键词组合均可)"
113
+ },
114
+ top_k: {
115
+ type: "number",
116
+ description: "返回条数(默认 5)"
117
+ }
118
+ },
119
+ required: ["query"]
120
+ }
121
+ },
122
+ {
123
+ name: "kb_ask",
124
+ description: "向知识库提问,返回合成答案与引用来源——需要结论而非文段列表时用。",
125
+ inputSchema: {
126
+ type: "object",
127
+ properties: { question: {
128
+ type: "string",
129
+ description: "问题"
130
+ } },
131
+ required: ["question"]
132
+ }
133
+ },
134
+ {
135
+ name: "kb_grep",
136
+ description: "按正则/关键词精确搜索知识库文本块(大小写不敏感)——已知确切关键词时用。",
137
+ inputSchema: {
138
+ type: "object",
139
+ properties: {
140
+ pattern: {
141
+ type: "string",
142
+ description: "正则或关键词"
143
+ },
144
+ kb: {
145
+ type: "string",
146
+ description: "知识库名或 id(可选,默认全部在 scope 库)"
147
+ }
148
+ },
149
+ required: ["pattern"]
150
+ }
151
+ },
152
+ {
153
+ name: "kb_archive_case",
154
+ description: `把诊断结论归档到「${CASE_KB_NAME}」知识库(唯一写通道)。content_md 建议结构:# 标题 / ## 现象 / ## 根因链 / ## 修复 / ## 证据与复现 / 指纹一行(供先验检索)。归档后先验检索即可命中,避免同类问题重复排查。`,
155
+ inputSchema: {
156
+ type: "object",
157
+ properties: {
158
+ title: {
159
+ type: "string",
160
+ description: "案例标题(症状+组件,如「OOM OCR 切图重复解码」)"
161
+ },
162
+ content_md: {
163
+ type: "string",
164
+ description: "案例正文(Markdown)"
165
+ }
166
+ },
167
+ required: ["title", "content_md"]
168
+ }
169
+ },
170
+ {
171
+ name: "kb_list",
172
+ description: "列出全部可访问知识库(id/名称/描述)。",
173
+ inputSchema: {
174
+ type: "object",
175
+ properties: {}
176
+ }
177
+ },
178
+ {
179
+ name: "kb_docs",
180
+ description: "列出一个知识库内的文档(分页)。",
181
+ inputSchema: {
182
+ type: "object",
183
+ properties: { kb: {
184
+ type: "string",
185
+ description: "知识库名或 id"
186
+ } },
187
+ required: ["kb"]
188
+ }
189
+ },
190
+ {
191
+ name: "kb_read",
192
+ description: "读一篇知识文档的元数据与正文分块。",
193
+ inputSchema: {
194
+ type: "object",
195
+ properties: {
196
+ doc_id: {
197
+ type: "string",
198
+ description: "文档 id"
199
+ },
200
+ kb: {
201
+ type: "string",
202
+ description: "知识库名或 id"
203
+ }
204
+ },
205
+ required: ["doc_id"]
206
+ }
207
+ }
208
+ ];
209
+ async function callSemantic(remote, name, args) {
210
+ const a = args ?? {};
211
+ switch (name) {
212
+ case "kb_search": return {
213
+ tool: "search_knowledge",
214
+ arguments: {
215
+ query: a.query,
216
+ match_count: Number(a.top_k ?? 5)
217
+ }
218
+ };
219
+ case "kb_ask": return {
220
+ tool: "ask",
221
+ arguments: { question: a.question }
222
+ };
223
+ case "kb_grep": return {
224
+ tool: "grep_chunks",
225
+ arguments: {
226
+ pattern: a.pattern,
227
+ ...a.kb ? { kb_id: a.kb } : {}
228
+ }
229
+ };
230
+ case "kb_list": return {
231
+ tool: "list_knowledge_bases",
232
+ arguments: {}
233
+ };
234
+ case "kb_docs": return {
235
+ tool: "list_documents",
236
+ arguments: { kb_id: a.kb }
237
+ };
238
+ case "kb_read": return {
239
+ tool: "read_document",
240
+ arguments: {
241
+ knowledge_id: a.doc_id,
242
+ ...a.kb ? { kb_id: a.kb } : {}
243
+ }
244
+ };
245
+ default: return null;
246
+ }
247
+ }
248
+ function buildServer(remote) {
249
+ const weknora = remote ?? new WeknoraRemote(process.env.WEKNORA_MCP_URL || DEFAULT_WEKNORA_URL, resolveToken);
250
+ const server = new Server({
251
+ name: "bfi-weknora-mcp",
252
+ version: "0.1.0"
253
+ }, {
254
+ capabilities: { tools: {} },
255
+ instructions: [
256
+ `BFI 知识库/案例库通道(bfi cli 登录态鉴权,零配置)。知识库在 scope:`,
257
+ `案例库(诊断案例归档,唯一写目标)+ wiki×4 + jira-支持案例 + 供应链/领域知识。`,
258
+ `· 先验查询:kb_search(跨库语义检索,诊断前必查——历史同类问题/已解决方案)`,
259
+ ` kb_ask(要结论不要文段时)/ kb_grep(确切关键词)`,
260
+ `· 归档:kb_archive_case(诊断完成后把根因链+修复写回案例库,供下次先验命中)`,
261
+ `· 阅读:kb_list/kb_docs/kb_read + wiki_*(生成 wiki 浏览)`
262
+ ].join("\n")
263
+ });
264
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
265
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
266
+ const { name, arguments: args } = request.params;
267
+ try {
268
+ if (name === "kb_archive_case") {
269
+ const title = String(args?.title ?? "").trim();
270
+ const content = String(args?.content_md ?? "").trim();
271
+ if (!title || !content) return textResult({
272
+ ok: false,
273
+ error_kind: "invalid_params",
274
+ message: "title 与 content_md 必填"
275
+ }, true);
276
+ const md = `# ${title}\n\n${content}\n`;
277
+ return await weknora.callTool("add_document", {
278
+ kb_id: CASE_KB_NAME,
279
+ title,
280
+ content: md
281
+ });
282
+ }
283
+ if (name === "wiki_index" || name === "wiki_read_page" || name === "wiki_search") return await weknora.callTool(name, args ?? {});
284
+ const mapped = await callSemantic(weknora, name, args);
285
+ if (!mapped) return textResult({
286
+ ok: false,
287
+ error_kind: "unknown_tool",
288
+ message: `未知工具:${name}`
289
+ }, true);
290
+ return await weknora.callTool(mapped.tool, mapped.arguments);
291
+ } catch (e) {
292
+ return textResult({
293
+ ok: false,
294
+ error_kind: e instanceof WeknoraError ? e.errorKind : "internal_error",
295
+ message: e instanceof Error ? e.message : String(e)
296
+ }, true);
297
+ }
298
+ });
299
+ return server;
300
+ }
301
+ async function main() {
302
+ await buildServer().connect(new StdioServerTransport());
303
+ }
304
+ main().catch((e) => {
305
+ console.error("[bfi-weknora-mcp] 启动失败:", e);
306
+ process.exit(1);
307
+ });
308
+ export {};
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.94",
3
+ "version": "0.1.96",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "bfi": "bin/bfi.js",
8
8
  "bfi-db-mcp": "bin/bfi-db-mcp.js",
9
- "bfi-codesearch-mcp": "bin/bfi-codesearch-mcp.js"
9
+ "bfi-codesearch-mcp": "bin/bfi-codesearch-mcp.js",
10
+ "bfi-weknora-mcp": "bin/bfi-weknora-mcp.js"
10
11
  },
11
12
  "files": [
12
13
  "dist",