bfi-cli 0.1.78 → 0.1.80
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 +44 -1
- package/dist/mcp-db/main.mjs +7 -0
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -8199,7 +8199,6 @@ function timeOf(args, required = true) {
|
|
|
8199
8199
|
console.error(err);
|
|
8200
8200
|
process.exit(1);
|
|
8201
8201
|
}
|
|
8202
|
-
if (t && !err) validateTime(t);
|
|
8203
8202
|
return t ? { time: t } : {};
|
|
8204
8203
|
}
|
|
8205
8204
|
function timeOpts(args) {
|
|
@@ -9188,6 +9187,43 @@ async function runEvent(args, globalOpts) {
|
|
|
9188
9187
|
console.error(`未知子命令: ${sub}。运行 bfi event --help`);
|
|
9189
9188
|
process.exit(1);
|
|
9190
9189
|
}
|
|
9190
|
+
async function runDb(args, globalOpts) {
|
|
9191
|
+
const sub = args[0];
|
|
9192
|
+
const rest = args.slice(1);
|
|
9193
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
9194
|
+
console.log(`bfi db — DB 取证辅助命令
|
|
9195
|
+
|
|
9196
|
+
用法:
|
|
9197
|
+
bfi db tenant-locate <租户编码> # 按租户定位分库/实例(ywb 实时查询)
|
|
9198
|
+
返回 env_code(可直接用于 db_execute/db_explain,如 core1_3)+ dbhost + 数据中心 + 租户中文名
|
|
9199
|
+
触发场景:① 表名带租户后缀(tb_dimindex_qyic8c7o)② SQL 中 ytenant_id/tenant_id = 值,
|
|
9200
|
+
且目标分库未知——先定位再连,禁止分库盲枚举
|
|
9201
|
+
找不到租户返回 found=false(正常情况)
|
|
9202
|
+
全局: --json / --dry-run / --token <tok>`);
|
|
9203
|
+
return;
|
|
9204
|
+
}
|
|
9205
|
+
if (sub !== "tenant-locate") {
|
|
9206
|
+
console.error(`未知子命令: ${sub}。运行 bfi db --help`);
|
|
9207
|
+
process.exit(1);
|
|
9208
|
+
}
|
|
9209
|
+
const tenantId = positionals(rest)[0];
|
|
9210
|
+
if (!tenantId) {
|
|
9211
|
+
console.error("用法: bfi db tenant-locate <租户编码>(如 t78xbvzp)");
|
|
9212
|
+
process.exit(1);
|
|
9213
|
+
}
|
|
9214
|
+
const jsonMode = flag(rest, "--json");
|
|
9215
|
+
const dryRun = flag(rest, "--dry-run");
|
|
9216
|
+
const api = new YmcApi(globalOpts.token ?? null, void 0, dryRun);
|
|
9217
|
+
if (!dryRun && !api.token) {
|
|
9218
|
+
console.error("未认证。先运行:bfi auth login --token <sk-token>(或传 --token)");
|
|
9219
|
+
process.exit(1);
|
|
9220
|
+
}
|
|
9221
|
+
emit(await api.call("db/tenant-locate", { tenant_id: tenantId }), jsonMode, (data) => {
|
|
9222
|
+
const d = data;
|
|
9223
|
+
if (!d.found) return `未找到租户 ${tenantId}(ywb 无记录,非表不存在)——${d.note ?? ""}`;
|
|
9224
|
+
return d.matches.map((m) => `✓ ${m.env_code ?? "(无法识别 env_code)"} | ${m.tenant_group_name ?? ""} | ${m.tenant_ds_name}\n dbhost=${m.dbhost} dc=${m.dc} 租户名=${m.tenant_name ?? ""}`).join("\n");
|
|
9225
|
+
});
|
|
9226
|
+
}
|
|
9191
9227
|
function loadSourceMapConsumer() {
|
|
9192
9228
|
return createRequire(import.meta.url)("source-map").SourceMapConsumer;
|
|
9193
9229
|
}
|
|
@@ -9603,6 +9639,10 @@ ${BOLD}━━━ 观测查询(ymc)━━━${RESET}
|
|
|
9603
9639
|
ymc dump-list / call <route> 诊断文件 / 通用端点透传
|
|
9604
9640
|
(-e env: test/daily/pre/core1-4/commldev;-t: 10m/2h/3d/4w)
|
|
9605
9641
|
|
|
9642
|
+
${BOLD}━━━ DB 取证辅助(db)━━━${RESET}
|
|
9643
|
+
db tenant-locate <租户> 按租户定位分库/实例(表名带租户后缀或 SQL 有
|
|
9644
|
+
ytenant_id 条件且分库未知时,先定位再连)
|
|
9645
|
+
|
|
9606
9646
|
${BOLD}━━━ 配置 ━━━${RESET}
|
|
9607
9647
|
config get [key] 查看配置
|
|
9608
9648
|
config set <key> <value> [--global] 设置配置
|
|
@@ -9876,6 +9916,9 @@ async function main() {
|
|
|
9876
9916
|
case "event":
|
|
9877
9917
|
await runEvent(restArgs, globalOpts);
|
|
9878
9918
|
break;
|
|
9919
|
+
case "db":
|
|
9920
|
+
await runDb(restArgs, globalOpts);
|
|
9921
|
+
break;
|
|
9879
9922
|
case "auth":
|
|
9880
9923
|
if (restArgs[0] === "logout") await runLogout();
|
|
9881
9924
|
else if (restArgs[0] === "whoami") await runWhoami(globalOpts);
|
package/dist/mcp-db/main.mjs
CHANGED
|
@@ -209,6 +209,9 @@ async function explainSql(envCode, sql, fetchImpl) {
|
|
|
209
209
|
sql: requireParam("sql", sql)
|
|
210
210
|
}, fetchImpl);
|
|
211
211
|
}
|
|
212
|
+
async function locateTenant(tenantId, fetchImpl) {
|
|
213
|
+
return post("/bficli/api/v2/db/tenant-locate", { tenant_id: tenantId }, fetchImpl);
|
|
214
|
+
}
|
|
212
215
|
function textResult(payload, isError = false) {
|
|
213
216
|
return {
|
|
214
217
|
content: [{
|
|
@@ -252,6 +255,10 @@ function buildServer() {
|
|
|
252
255
|
]).optional().describe("环境类型过滤")
|
|
253
256
|
}
|
|
254
257
|
}, wrap((args) => listEnvs(args.keyword, args.env_type)));
|
|
258
|
+
server.registerTool("db_tenant_locate", {
|
|
259
|
+
description: "按租户编码定位其所在分库/实例(ywb 实时查询)。返回 env_code(可直接用于 db_execute/db_explain,如 core1_3 / core1_yonyou)+ tenant_ds_name + dbhost + 数据中心 + 租户中文名。触发场景:① 表名带租户后缀(tb_dimindex_qyic8c7o)② SQL 中 ytenant_id/tenant_id = 值,且目标分库未知——先定位再连,禁止分库盲枚举。找不到租户返回 found=false(正常,回退按 SQL 线索定位)。",
|
|
260
|
+
inputSchema: { tenant_id: z.string().min(1, "tenant_id 不能为空:从表名后缀或 SQL 的 ytenant_id/tenant_id 值提取").describe("租户编码(如 t78xbvzp / qyic8c7o)") }
|
|
261
|
+
}, wrap((args) => locateTenant(args.tenant_id)));
|
|
255
262
|
server.registerTool("db_execute", {
|
|
256
263
|
description: "在指定环境执行单条 SQL(只读取证)。仅 SELECT/WITH/SHOW/DESC/EXPLAIN;DML/DDL 需环境显式授权位否则 permission_denied。行数上限默认 200。非 mysql 库自动翻译(mysql 语法输入即可)。诊断场景优先 db_explain。",
|
|
257
264
|
inputSchema: {
|