bfi-cli 0.1.96 → 0.1.98
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/THIRD-PARTY-LICENSES.md +293 -0
- package/dist/_chunks/libs/@clack/core.mjs +58 -63
- package/dist/_chunks/libs/@clack/prompts.mjs +45 -46
- package/dist/_chunks/libs/@kwsites/file-exists.mjs +9 -10
- package/dist/_chunks/libs/simple-git.mjs +2 -4
- package/dist/_chunks/rolldown-runtime.mjs +1 -1
- package/dist/_chunks/skills.mjs +3 -6
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +100 -136
- package/dist/mcp-codesearch/main.d.mts +1 -1
- package/dist/mcp-codesearch/main.mjs +2 -0
- package/dist/mcp-db/main.d.mts +1 -1
- package/dist/mcp-db/main.mjs +12 -2
- package/dist/mcp-weknora/main.d.mts +1 -1
- package/dist/mcp-weknora/main.mjs +41 -158
- package/package.json +4 -2
- package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
|
@@ -3,6 +3,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
5
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
import JSONbig from "json-bigint";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import path from "node:path";
|
|
8
9
|
import os from "node:os";
|
|
@@ -87,10 +88,35 @@ function loadGlobalConfig() {
|
|
|
87
88
|
}
|
|
88
89
|
return null;
|
|
89
90
|
}
|
|
91
|
+
JSONbig({ storeAsString: true });
|
|
90
92
|
function resolveToken() {
|
|
91
93
|
if (process.env.BFI_TOKEN) return process.env.BFI_TOKEN;
|
|
92
94
|
return loadGlobalConfig()?.token ?? null;
|
|
93
95
|
}
|
|
96
|
+
const BLOCKED_PREFIXES = [
|
|
97
|
+
"create_",
|
|
98
|
+
"delete_",
|
|
99
|
+
"update_",
|
|
100
|
+
"add_"
|
|
101
|
+
];
|
|
102
|
+
const ARCHIVE_TOOL = {
|
|
103
|
+
name: "kb_archive_case",
|
|
104
|
+
description: `把诊断结论归档到「${CASE_KB_NAME}」知识库(唯一写通道)。content_md 建议结构:# 标题 / ## 现象 / ## 根因链 / ## 修复 / ## 证据与复现 / 指纹一行(供先验检索)。归档后先验检索即可命中,避免同类问题重复排查。`,
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
title: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "案例标题(症状+组件,如「OOM OCR 切图重复解码」)"
|
|
111
|
+
},
|
|
112
|
+
content_md: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "案例正文(Markdown)"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
required: ["title", "content_md"]
|
|
118
|
+
}
|
|
119
|
+
};
|
|
94
120
|
function textResult(payload, isError = false) {
|
|
95
121
|
return {
|
|
96
122
|
content: [{
|
|
@@ -100,150 +126,8 @@ function textResult(payload, isError = false) {
|
|
|
100
126
|
isError
|
|
101
127
|
};
|
|
102
128
|
}
|
|
103
|
-
|
|
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
|
-
}
|
|
129
|
+
function isBlocked(name) {
|
|
130
|
+
return BLOCKED_PREFIXES.some((p) => name.startsWith(p));
|
|
247
131
|
}
|
|
248
132
|
function buildServer(remote) {
|
|
249
133
|
const weknora = remote ?? new WeknoraRemote(process.env.WEKNORA_MCP_URL || DEFAULT_WEKNORA_URL, resolveToken);
|
|
@@ -253,15 +137,16 @@ function buildServer(remote) {
|
|
|
253
137
|
}, {
|
|
254
138
|
capabilities: { tools: {} },
|
|
255
139
|
instructions: [
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
`· 阅读:kb_list/kb_docs/kb_read + wiki_*(生成 wiki 浏览)`
|
|
140
|
+
"BFI 知识库/案例库通道(bfi cli 登录态鉴权,零配置)。",
|
|
141
|
+
"先验查询:search_knowledge(跨库语义检索:案例库+wiki×4+jira-支持案例+领域知识,诊断前必查)",
|
|
142
|
+
"ask(合成答案+引用)/ grep_chunks(确切关键词)",
|
|
143
|
+
"归档:kb_archive_case(诊断完成后把根因链+修复写回案例库,供下次先验命中;唯一写通道)",
|
|
144
|
+
"阅读:list_knowledge_bases/list_documents/read_document + wiki_*"
|
|
262
145
|
].join("\n")
|
|
263
146
|
});
|
|
264
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
147
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
148
|
+
return { tools: [...(await weknora.listTools()).filter((t) => !isBlocked(t.name)), ARCHIVE_TOOL] };
|
|
149
|
+
});
|
|
265
150
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
266
151
|
const { name, arguments: args } = request.params;
|
|
267
152
|
try {
|
|
@@ -275,19 +160,17 @@ function buildServer(remote) {
|
|
|
275
160
|
}, true);
|
|
276
161
|
const md = `# ${title}\n\n${content}\n`;
|
|
277
162
|
return await weknora.callTool("add_document", {
|
|
278
|
-
|
|
163
|
+
knowledge_base_id: CASE_KB_NAME,
|
|
279
164
|
title,
|
|
280
165
|
content: md
|
|
281
166
|
});
|
|
282
167
|
}
|
|
283
|
-
if (name
|
|
284
|
-
const mapped = await callSemantic(weknora, name, args);
|
|
285
|
-
if (!mapped) return textResult({
|
|
168
|
+
if (isBlocked(name)) return textResult({
|
|
286
169
|
ok: false,
|
|
287
|
-
error_kind: "
|
|
288
|
-
message:
|
|
170
|
+
error_kind: "write_blocked",
|
|
171
|
+
message: `写类工具 ${name} 不透传。诊断归档请用 kb_archive_case(自动写入案例库)`
|
|
289
172
|
}, true);
|
|
290
|
-
return await weknora.callTool(
|
|
173
|
+
return await weknora.callTool(name, args ?? {});
|
|
291
174
|
} catch (e) {
|
|
292
175
|
return textResult({
|
|
293
176
|
ok: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bfi-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.98",
|
|
4
4
|
"description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@clack/prompts": "^1.2.0",
|
|
38
38
|
"@types/bun": "latest",
|
|
39
|
+
"@types/json-bigint": "^1.0.4",
|
|
39
40
|
"@types/node": "^22.10.0",
|
|
40
41
|
"@types/tar-stream": "3.1.5",
|
|
41
42
|
"@types/yauzl": "3.4.0",
|
|
@@ -53,11 +54,12 @@
|
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
55
56
|
"@vercel/detect-agent": "^1.2.3",
|
|
57
|
+
"json-bigint": "^1.0.0",
|
|
56
58
|
"mysql2": "^3.14.0",
|
|
57
59
|
"source-map": "^0.7.4",
|
|
58
60
|
"tar-stream": "3.2.2",
|
|
59
|
-
"yauzl": "3.4.0",
|
|
60
61
|
"yaml": "^2.8.3",
|
|
62
|
+
"yauzl": "3.4.0",
|
|
61
63
|
"zod": "^3.25.0"
|
|
62
64
|
}
|
|
63
65
|
}
|
|
Binary file
|