@lark-apaas/openclaw-scripts-diagnose-cli 0.1.5 → 0.1.6-alpha.1
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/index.cjs +281 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -53,7 +53,7 @@ let json_diff = require("json-diff");
|
|
|
53
53
|
* it terse and parseable.
|
|
54
54
|
*/
|
|
55
55
|
function getVersion() {
|
|
56
|
-
return "0.1.
|
|
56
|
+
return "0.1.6-alpha.1";
|
|
57
57
|
}
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/rule-engine/base.ts
|
|
@@ -1381,11 +1381,11 @@ OldMiaodaPluginsCleanupRule = __decorate([Rule({
|
|
|
1381
1381
|
//#region src/rules/lark-plugin-allow.ts
|
|
1382
1382
|
const LARK_PLUGIN = "openclaw-lark";
|
|
1383
1383
|
const LEGACY_LARK_PLUGIN = "feishu-openclaw-plugin";
|
|
1384
|
-
const LARK_PLUGIN_NAMES = [LARK_PLUGIN, LEGACY_LARK_PLUGIN];
|
|
1384
|
+
const LARK_PLUGIN_NAMES$1 = [LARK_PLUGIN, LEGACY_LARK_PLUGIN];
|
|
1385
1385
|
let LarkPluginAllowRule = class LarkPluginAllowRule extends DiagnoseRule {
|
|
1386
1386
|
validate(ctx) {
|
|
1387
1387
|
const allow = getAllow(ctx.config);
|
|
1388
|
-
if (LARK_PLUGIN_NAMES.some((name) => allow.includes(name))) return { pass: true };
|
|
1388
|
+
if (LARK_PLUGIN_NAMES$1.some((name) => allow.includes(name))) return { pass: true };
|
|
1389
1389
|
const installed = detectInstalledLarkPlugin(getExtensionsDir(ctx.configPath));
|
|
1390
1390
|
if (installed == null) return { pass: true };
|
|
1391
1391
|
return {
|
|
@@ -1404,7 +1404,7 @@ let LarkPluginAllowRule = class LarkPluginAllowRule extends DiagnoseRule {
|
|
|
1404
1404
|
const rawAllow = pluginsMap.allow;
|
|
1405
1405
|
const original = Array.isArray(rawAllow) ? rawAllow : [];
|
|
1406
1406
|
const stringAllow = original.filter((e) => typeof e === "string");
|
|
1407
|
-
if (LARK_PLUGIN_NAMES.some((name) => stringAllow.includes(name))) return;
|
|
1407
|
+
if (LARK_PLUGIN_NAMES$1.some((name) => stringAllow.includes(name))) return;
|
|
1408
1408
|
original.push(installed);
|
|
1409
1409
|
pluginsMap.allow = original;
|
|
1410
1410
|
}
|
|
@@ -4210,6 +4210,210 @@ function finalize(results, aborted) {
|
|
|
4210
4210
|
};
|
|
4211
4211
|
}
|
|
4212
4212
|
//#endregion
|
|
4213
|
+
//#region src/lark-cli-init.ts
|
|
4214
|
+
const LARK_PLUGIN_NAMES = ["openclaw-lark", "feishu-openclaw-plugin"];
|
|
4215
|
+
const PE_XML_TAG = "lark-pe";
|
|
4216
|
+
const PE_PLACEHOLDER = `\n<${PE_XML_TAG}>\n<!-- TODO: replace with actual prompt engineering content -->\n</${PE_XML_TAG}>\n`;
|
|
4217
|
+
function isLarkPluginInstalled(configPath) {
|
|
4218
|
+
const extDir = getExtensionsDir(configPath);
|
|
4219
|
+
return LARK_PLUGIN_NAMES.some((name) => {
|
|
4220
|
+
try {
|
|
4221
|
+
return node_fs.default.existsSync(node_path.default.join(extDir, name, "package.json"));
|
|
4222
|
+
} catch {
|
|
4223
|
+
return false;
|
|
4224
|
+
}
|
|
4225
|
+
});
|
|
4226
|
+
}
|
|
4227
|
+
function isLarkCliAvailable() {
|
|
4228
|
+
try {
|
|
4229
|
+
return (0, node_child_process.spawnSync)("lark-cli", ["--version"], {
|
|
4230
|
+
encoding: "utf-8",
|
|
4231
|
+
timeout: 5e3,
|
|
4232
|
+
stdio: [
|
|
4233
|
+
"ignore",
|
|
4234
|
+
"pipe",
|
|
4235
|
+
"ignore"
|
|
4236
|
+
]
|
|
4237
|
+
}).status === 0;
|
|
4238
|
+
} catch {
|
|
4239
|
+
return false;
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
function readConfig(configPath) {
|
|
4243
|
+
try {
|
|
4244
|
+
const raw = node_fs.default.readFileSync(configPath, "utf-8");
|
|
4245
|
+
const parsed = loadJSON5().parse(raw);
|
|
4246
|
+
return parsed != null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
4247
|
+
} catch {
|
|
4248
|
+
return null;
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
/**
|
|
4252
|
+
* Resolve the feishu app secret for the given appId.
|
|
4253
|
+
*
|
|
4254
|
+
* Lookup order:
|
|
4255
|
+
* 1. channels.feishu.appSecret (single-agent: feishu.appId === appId)
|
|
4256
|
+
* 2. channels.feishu.accounts[key].appSecret (multi-agent: account.appId === appId)
|
|
4257
|
+
*
|
|
4258
|
+
* Value interpretation:
|
|
4259
|
+
* - string → use directly
|
|
4260
|
+
* - object → secret is managed by a provider; use `feishuAppSecret` param instead
|
|
4261
|
+
*
|
|
4262
|
+
* Returns null when the secret cannot be determined.
|
|
4263
|
+
*/
|
|
4264
|
+
function resolveAppSecret(appId, config, feishuAppSecret) {
|
|
4265
|
+
const feishu = getNestedMap(config, "channels", "feishu");
|
|
4266
|
+
if (!feishu) return null;
|
|
4267
|
+
let rawSecret;
|
|
4268
|
+
if (typeof feishu.appId === "string" && feishu.appId === appId) rawSecret = feishu.appSecret;
|
|
4269
|
+
else {
|
|
4270
|
+
const accounts = asRecord(feishu.accounts);
|
|
4271
|
+
if (accounts) for (const [, val] of Object.entries(accounts)) {
|
|
4272
|
+
const account = asRecord(val);
|
|
4273
|
+
if (account?.appId === appId) {
|
|
4274
|
+
rawSecret = account.appSecret;
|
|
4275
|
+
break;
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
if (typeof rawSecret === "string" && rawSecret) return rawSecret;
|
|
4280
|
+
if (rawSecret != null && typeof rawSecret === "object") return feishuAppSecret ?? null;
|
|
4281
|
+
return null;
|
|
4282
|
+
}
|
|
4283
|
+
/**
|
|
4284
|
+
* Resolve the agents.md path for the given appId from the openclaw config.
|
|
4285
|
+
*
|
|
4286
|
+
* Case 1: appId matches channels.feishu.appId (single-agent path)
|
|
4287
|
+
* → WORKSPACE_DIR/AGENTS.md
|
|
4288
|
+
*
|
|
4289
|
+
* Case 2: appId found in channels.feishu.accounts (multi-agent path)
|
|
4290
|
+
* → find account key where account.appId === appId
|
|
4291
|
+
* → find binding where match.channel=feishu && match.accountId=that key
|
|
4292
|
+
* → if agentId === 'main' → WORKSPACE_DIR/agents.md
|
|
4293
|
+
* → else find agent in agents.list by id → agent.workspace/agents.md
|
|
4294
|
+
*
|
|
4295
|
+
* Returns null when the path cannot be determined.
|
|
4296
|
+
*/
|
|
4297
|
+
function resolveAgentsMdPath(appId, config) {
|
|
4298
|
+
const feishu = getNestedMap(config, "channels", "feishu");
|
|
4299
|
+
if (!feishu) return null;
|
|
4300
|
+
if (typeof feishu.appId === "string" && feishu.appId === appId) return node_path.default.join(WORKSPACE_DIR, "AGENTS.md");
|
|
4301
|
+
const accounts = asRecord(feishu.accounts);
|
|
4302
|
+
if (!accounts) return null;
|
|
4303
|
+
let accountId;
|
|
4304
|
+
for (const [key, val] of Object.entries(accounts)) if (asRecord(val)?.appId === appId) {
|
|
4305
|
+
accountId = key;
|
|
4306
|
+
break;
|
|
4307
|
+
}
|
|
4308
|
+
if (!accountId) return null;
|
|
4309
|
+
const bindings = Array.isArray(config.bindings) ? config.bindings : [];
|
|
4310
|
+
let agentId;
|
|
4311
|
+
for (const b of bindings) {
|
|
4312
|
+
const binding = asRecord(b);
|
|
4313
|
+
if (!binding) continue;
|
|
4314
|
+
const match = asRecord(binding.match);
|
|
4315
|
+
if (match?.channel === "feishu" && match?.accountId === accountId) {
|
|
4316
|
+
if (typeof binding.agentId === "string") {
|
|
4317
|
+
agentId = binding.agentId;
|
|
4318
|
+
break;
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
if (!agentId) return null;
|
|
4323
|
+
if (agentId === "main") return node_path.default.join(WORKSPACE_DIR, "agents.md");
|
|
4324
|
+
const agentsObj = asRecord(config.agents);
|
|
4325
|
+
const list = Array.isArray(agentsObj?.list) ? agentsObj.list : [];
|
|
4326
|
+
for (const a of list) {
|
|
4327
|
+
const agent = asRecord(a);
|
|
4328
|
+
if (agent?.id === agentId && typeof agent.workspace === "string") return node_path.default.join(agent.workspace, "agents.md");
|
|
4329
|
+
}
|
|
4330
|
+
return null;
|
|
4331
|
+
}
|
|
4332
|
+
function appendPeToAgentsMd(agentsMdPath) {
|
|
4333
|
+
const dir = node_path.default.dirname(agentsMdPath);
|
|
4334
|
+
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
4335
|
+
const existing = node_fs.default.existsSync(agentsMdPath) ? node_fs.default.readFileSync(agentsMdPath, "utf-8") : "";
|
|
4336
|
+
if (existing.includes(`<${PE_XML_TAG}>`)) {
|
|
4337
|
+
console.error(`lark-cli-init: <${PE_XML_TAG}> already present in ${agentsMdPath}, skipping`);
|
|
4338
|
+
return;
|
|
4339
|
+
}
|
|
4340
|
+
const sep = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
4341
|
+
node_fs.default.appendFileSync(agentsMdPath, `${sep}${PE_PLACEHOLDER}`, "utf-8");
|
|
4342
|
+
console.error(`lark-cli-init: appended PE placeholder to ${agentsMdPath}`);
|
|
4343
|
+
}
|
|
4344
|
+
function runLarkCliInit(opts) {
|
|
4345
|
+
const configPath = opts.configPath ?? CONFIG_PATH;
|
|
4346
|
+
if (!isLarkPluginInstalled(configPath)) {
|
|
4347
|
+
console.error("lark-cli-init: skipping — openclaw-lark plugin not installed");
|
|
4348
|
+
return {
|
|
4349
|
+
ok: true,
|
|
4350
|
+
skipped: true,
|
|
4351
|
+
skipReason: "openclaw-lark plugin not installed"
|
|
4352
|
+
};
|
|
4353
|
+
}
|
|
4354
|
+
if (!isLarkCliAvailable()) {
|
|
4355
|
+
console.error("lark-cli-init: skipping — lark-cli command not found");
|
|
4356
|
+
return {
|
|
4357
|
+
ok: true,
|
|
4358
|
+
skipped: true,
|
|
4359
|
+
skipReason: "lark-cli command not found"
|
|
4360
|
+
};
|
|
4361
|
+
}
|
|
4362
|
+
const config = readConfig(configPath);
|
|
4363
|
+
if (!config) return {
|
|
4364
|
+
ok: false,
|
|
4365
|
+
error: `could not read config at ${configPath}`
|
|
4366
|
+
};
|
|
4367
|
+
const agentsMdPath = opts.agentsMdPath ?? resolveAgentsMdPath(opts.appId, config);
|
|
4368
|
+
if (!agentsMdPath) return {
|
|
4369
|
+
ok: false,
|
|
4370
|
+
error: `could not resolve agents.md path for appId=${opts.appId}`
|
|
4371
|
+
};
|
|
4372
|
+
console.error(`lark-cli-init: agents.md path=${agentsMdPath}`);
|
|
4373
|
+
const appSecret = resolveAppSecret(opts.appId, config, opts.feishuAppSecret);
|
|
4374
|
+
if (!appSecret) return {
|
|
4375
|
+
ok: false,
|
|
4376
|
+
error: `could not resolve appSecret for appId=${opts.appId}`
|
|
4377
|
+
};
|
|
4378
|
+
console.error(`lark-cli-init: running lark-cli config init --app-id=${opts.appId}`);
|
|
4379
|
+
const initRes = (0, node_child_process.spawnSync)("lark-cli", [
|
|
4380
|
+
"config",
|
|
4381
|
+
"init",
|
|
4382
|
+
"--name",
|
|
4383
|
+
opts.appId,
|
|
4384
|
+
"--app-id",
|
|
4385
|
+
opts.appId,
|
|
4386
|
+
"--brand",
|
|
4387
|
+
"feishu",
|
|
4388
|
+
"--app-secret-stdin"
|
|
4389
|
+
], {
|
|
4390
|
+
stdio: [
|
|
4391
|
+
"pipe",
|
|
4392
|
+
"pipe",
|
|
4393
|
+
"pipe"
|
|
4394
|
+
],
|
|
4395
|
+
encoding: "utf-8",
|
|
4396
|
+
input: appSecret
|
|
4397
|
+
});
|
|
4398
|
+
if (initRes.stdout?.trim()) console.error(`lark-cli config init stdout: ${initRes.stdout.trim()}`);
|
|
4399
|
+
if (initRes.stderr?.trim()) console.error(`lark-cli config init stderr: ${initRes.stderr.trim()}`);
|
|
4400
|
+
if (initRes.error) return {
|
|
4401
|
+
ok: false,
|
|
4402
|
+
error: `lark-cli config init spawn error: ${initRes.error.message}`
|
|
4403
|
+
};
|
|
4404
|
+
if (initRes.status !== 0) return {
|
|
4405
|
+
ok: false,
|
|
4406
|
+
configInitExitCode: initRes.status ?? void 0,
|
|
4407
|
+
error: `lark-cli config init exited with code ${initRes.status}`
|
|
4408
|
+
};
|
|
4409
|
+
appendPeToAgentsMd(agentsMdPath);
|
|
4410
|
+
return {
|
|
4411
|
+
ok: true,
|
|
4412
|
+
configInitExitCode: 0,
|
|
4413
|
+
agentsMdPath
|
|
4414
|
+
};
|
|
4415
|
+
}
|
|
4416
|
+
//#endregion
|
|
4213
4417
|
//#region src/innerapi/reportCliRun.ts
|
|
4214
4418
|
/**
|
|
4215
4419
|
* CLI-side client for studio_server's `openclaw.report_cli_run` inner
|
|
@@ -4289,7 +4493,7 @@ async function reportCliRun(opts) {
|
|
|
4289
4493
|
//#region src/help.ts
|
|
4290
4494
|
const BIN = "mclaw-diagnose";
|
|
4291
4495
|
function versionBanner() {
|
|
4292
|
-
return `v0.1.
|
|
4496
|
+
return `v0.1.6-alpha.1`;
|
|
4293
4497
|
}
|
|
4294
4498
|
const COMMANDS = [
|
|
4295
4499
|
{
|
|
@@ -4498,6 +4702,58 @@ OPTIONS
|
|
|
4498
4702
|
--skip-config-update Leave plugins.installs in openclaw.json untouched.
|
|
4499
4703
|
--ctx=<base64> Opaque ctx; see install-openclaw for semantics.
|
|
4500
4704
|
--oss_file_map=... Pre-built OSS URL map (base64 JSON).
|
|
4705
|
+
`
|
|
4706
|
+
},
|
|
4707
|
+
{
|
|
4708
|
+
name: "lark-cli-init",
|
|
4709
|
+
hidden: false,
|
|
4710
|
+
summary: "Initialize lark-cli bot config and append PE to agents.md",
|
|
4711
|
+
help: `USAGE
|
|
4712
|
+
${BIN} lark-cli-init --app-id=<app-id> [--feishu-app-secret=<secret>] [--agents-md=<path>]
|
|
4713
|
+
|
|
4714
|
+
DESCRIPTION
|
|
4715
|
+
Two-step initialization for a Lark (Feishu) bot when prerequisites are met:
|
|
4716
|
+
|
|
4717
|
+
Prerequisites (both must be satisfied, otherwise the command exits 0 with
|
|
4718
|
+
skipped=true and no side effects):
|
|
4719
|
+
1. openclaw-lark plugin installed under extensions/.
|
|
4720
|
+
2. lark-cli command available on PATH.
|
|
4721
|
+
|
|
4722
|
+
The app secret is resolved from config before running lark-cli:
|
|
4723
|
+
- channels.feishu.appSecret (single-agent) or
|
|
4724
|
+
channels.feishu.accounts[key].appSecret (multi-agent, matched by appId)
|
|
4725
|
+
- If the value is a plain string → used directly.
|
|
4726
|
+
- If the value is a provider-ref object → --feishu-app-secret must be supplied.
|
|
4727
|
+
|
|
4728
|
+
Step 1 — lark-cli config init:
|
|
4729
|
+
Pipes the resolved secret via stdin and runs:
|
|
4730
|
+
lark-cli config init \\
|
|
4731
|
+
--name <app-id> \\
|
|
4732
|
+
--app-id <app-id> \\
|
|
4733
|
+
--brand feishu \\
|
|
4734
|
+
--app-secret-stdin
|
|
4735
|
+
|
|
4736
|
+
Step 2 — append PE to agents.md:
|
|
4737
|
+
Resolves the target agents.md from config (see path resolution below)
|
|
4738
|
+
and appends a <lark-pe> placeholder block (idempotent: skipped if already present).
|
|
4739
|
+
|
|
4740
|
+
agents.md path resolution:
|
|
4741
|
+
- channels.feishu.appId === appId → WORKSPACE/AGENTS.md (single-agent)
|
|
4742
|
+
- accounts[key].appId === appId → look up binding by accountId:
|
|
4743
|
+
agentId === 'main' → WORKSPACE/agents.md
|
|
4744
|
+
otherwise → agents.list[agentId].workspace/agents.md
|
|
4745
|
+
|
|
4746
|
+
ARGUMENTS
|
|
4747
|
+
--app-id=<app-id> Required. Bot app ID, e.g. cli_a9659e1f0ab89ccd.
|
|
4748
|
+
|
|
4749
|
+
OPTIONS
|
|
4750
|
+
--feishu-app-secret=<secret> Required when config stores appSecret as a
|
|
4751
|
+
provider-ref object (ctx.vars.feishuAppSecret).
|
|
4752
|
+
--agents-md=<path> Override the resolved agents.md path.
|
|
4753
|
+
|
|
4754
|
+
EXIT CODES
|
|
4755
|
+
0 Success or skipped (prerequisites not met).
|
|
4756
|
+
1 Secret/path unresolvable, lark-cli failed, or config unreadable.
|
|
4501
4757
|
`
|
|
4502
4758
|
},
|
|
4503
4759
|
{
|
|
@@ -4977,6 +5233,26 @@ async function main() {
|
|
|
4977
5233
|
if (error) throw error;
|
|
4978
5234
|
break;
|
|
4979
5235
|
}
|
|
5236
|
+
case "lark-cli-init": {
|
|
5237
|
+
const appId = getFlag(args, "app-id");
|
|
5238
|
+
if (!appId) {
|
|
5239
|
+
console.error("Usage: lark-cli-init --app-id=<app-id> [--agents-md=<path>]");
|
|
5240
|
+
node_process.default.exit(1);
|
|
5241
|
+
}
|
|
5242
|
+
const result = runLarkCliInit({
|
|
5243
|
+
appId,
|
|
5244
|
+
agentsMdPath: getFlag(args, "agents-md"),
|
|
5245
|
+
feishuAppSecret: getFlag(args, "feishu-app-secret")
|
|
5246
|
+
});
|
|
5247
|
+
console.error(`lark-cli-init: result=${JSON.stringify(result)}`);
|
|
5248
|
+
await reportRun("lark-cli-init", rc, void 0, args.join(" "), Date.now() - t0, {
|
|
5249
|
+
success: result.ok,
|
|
5250
|
+
result,
|
|
5251
|
+
error: result.ok ? void 0 : new Error(result.error ?? "lark-cli-init failed")
|
|
5252
|
+
});
|
|
5253
|
+
if (!result.ok) node_process.default.exit(1);
|
|
5254
|
+
break;
|
|
5255
|
+
}
|
|
4980
5256
|
default:
|
|
4981
5257
|
node_process.default.stderr.write(`Unknown command: ${mode}\n\n`);
|
|
4982
5258
|
node_process.default.stderr.write(formatTopLevelHelp(helpFlags.expert));
|