engine7 7.1.25 → 7.1.27
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 +173 -3
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -575,6 +575,138 @@ import * as path2 from "node:path";
|
|
|
575
575
|
import * as fs2 from "node:fs";
|
|
576
576
|
import * as readline from "node:readline";
|
|
577
577
|
import { fileURLToPath } from "node:url";
|
|
578
|
+
|
|
579
|
+
// src/feishu-quick-register.ts
|
|
580
|
+
var ACCOUNTS_URL = {
|
|
581
|
+
feishu: "https://accounts.feishu.cn",
|
|
582
|
+
lark: "https://accounts.larksuite.com"
|
|
583
|
+
};
|
|
584
|
+
var REGISTRATION_PATH = "/oauth/v1/app/registration";
|
|
585
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
586
|
+
var DEFAULT_POLL_INTERVAL = 5;
|
|
587
|
+
async function postRegistration(domain, body) {
|
|
588
|
+
const url = `${ACCOUNTS_URL[domain]}${REGISTRATION_PATH}`;
|
|
589
|
+
const res = await fetch(url, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
592
|
+
body: new URLSearchParams(body).toString(),
|
|
593
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
594
|
+
});
|
|
595
|
+
if (!res.ok) {
|
|
596
|
+
throw new Error(`\u98DE\u4E66\u6CE8\u518C\u63A5\u53E3\u8FD4\u56DE ${res.status}: ${await res.text()}`);
|
|
597
|
+
}
|
|
598
|
+
return res.json();
|
|
599
|
+
}
|
|
600
|
+
async function initRegistration(domain) {
|
|
601
|
+
const res = await postRegistration(domain, { action: "init" });
|
|
602
|
+
if (!res.supported_auth_methods?.includes("client_secret")) {
|
|
603
|
+
throw new Error("\u5F53\u524D\u98DE\u4E66\u73AF\u5883\u4E0D\u652F\u6301 client_secret \u8BA4\u8BC1\uFF0C\u65E0\u6CD5\u81EA\u52A8\u6CE8\u518C");
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
async function beginRegistration(domain) {
|
|
607
|
+
const res = await postRegistration(domain, {
|
|
608
|
+
action: "begin",
|
|
609
|
+
archetype: "PersonalAgent",
|
|
610
|
+
auth_method: "client_secret",
|
|
611
|
+
request_user_info: "open_id"
|
|
612
|
+
});
|
|
613
|
+
if (!res.device_code || !res.verification_uri_complete) {
|
|
614
|
+
throw new Error(`\u98DE\u4E66\u6CE8\u518C\u5931\u8D25: \u672A\u8FD4\u56DE device_code
|
|
615
|
+
${JSON.stringify(res)}`);
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
deviceCode: res.device_code,
|
|
619
|
+
qrUrl: res.verification_uri_complete,
|
|
620
|
+
userCode: res.user_code,
|
|
621
|
+
interval: res.interval ?? DEFAULT_POLL_INTERVAL,
|
|
622
|
+
expireIn: res.expire_in ?? 300
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
async function pollRegistration(domain, deviceCode, interval, deadline, onLog, signal) {
|
|
626
|
+
let currentInterval = interval;
|
|
627
|
+
let currentDomain = domain;
|
|
628
|
+
while (Date.now() < deadline) {
|
|
629
|
+
if (signal?.aborted) return null;
|
|
630
|
+
let res;
|
|
631
|
+
try {
|
|
632
|
+
res = await postRegistration(currentDomain, {
|
|
633
|
+
action: "poll",
|
|
634
|
+
device_code: deviceCode
|
|
635
|
+
});
|
|
636
|
+
} catch {
|
|
637
|
+
await sleep(currentInterval * 1e3);
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (res.user_info?.tenant_brand === "lark" && currentDomain === "feishu") {
|
|
641
|
+
currentDomain = "lark";
|
|
642
|
+
onLog?.("\u68C0\u6D4B\u5230 Lark \u8D26\u53F7\uFF0C\u5207\u6362\u57DF\u540D...");
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
if (res.client_id && res.client_secret) {
|
|
646
|
+
return {
|
|
647
|
+
appId: res.client_id,
|
|
648
|
+
appSecret: res.client_secret,
|
|
649
|
+
openId: res.user_info?.open_id,
|
|
650
|
+
domain: currentDomain
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
if (res.error) {
|
|
654
|
+
if (res.error === "authorization_pending") {
|
|
655
|
+
} else if (res.error === "slow_down") {
|
|
656
|
+
currentInterval += 5;
|
|
657
|
+
} else if (res.error === "access_denied") {
|
|
658
|
+
throw new Error("\u7528\u6237\u62D2\u7EDD\u4E86\u6388\u6743");
|
|
659
|
+
} else if (res.error === "expired_token") {
|
|
660
|
+
throw new Error("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F");
|
|
661
|
+
} else {
|
|
662
|
+
throw new Error(`\u98DE\u4E66\u6CE8\u518C\u9519\u8BEF: ${res.error} \u2014 ${res.error_description ?? ""}`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
await sleep(currentInterval * 1e3);
|
|
666
|
+
}
|
|
667
|
+
return null;
|
|
668
|
+
}
|
|
669
|
+
async function registerFeishuApp(options = {}) {
|
|
670
|
+
const domain = options.domain ?? "feishu";
|
|
671
|
+
const timeoutSec = options.timeoutSec ?? 300;
|
|
672
|
+
const log = options.onLog ?? (() => {
|
|
673
|
+
});
|
|
674
|
+
log("\u68C0\u67E5\u98DE\u4E66\u73AF\u5883...");
|
|
675
|
+
await initRegistration(domain);
|
|
676
|
+
log("\u751F\u6210\u4E8C\u7EF4\u7801...");
|
|
677
|
+
const { deviceCode, qrUrl, interval, expireIn } = await beginRegistration(domain);
|
|
678
|
+
options.onQrCode?.(qrUrl);
|
|
679
|
+
log(`\u8BF7\u7528\u98DE\u4E66 App \u626B\u63CF\u4E8C\u7EF4\u7801\uFF08${expireIn}\u79D2\u540E\u8FC7\u671F\uFF09...`);
|
|
680
|
+
const deadline = Date.now() + Math.min(expireIn, timeoutSec) * 1e3;
|
|
681
|
+
const result = await pollRegistration(domain, deviceCode, interval, deadline, log, options.signal);
|
|
682
|
+
if (result) {
|
|
683
|
+
log(`\u2705 \u6CE8\u518C\u6210\u529F\uFF01App ID: ${result.appId}`);
|
|
684
|
+
} else {
|
|
685
|
+
log("\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F");
|
|
686
|
+
}
|
|
687
|
+
return result;
|
|
688
|
+
}
|
|
689
|
+
function sleep(ms) {
|
|
690
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/qr-render.ts
|
|
694
|
+
import { createRequire } from "node:module";
|
|
695
|
+
var require2 = createRequire(import.meta.url);
|
|
696
|
+
async function renderQrTerminal(url, options) {
|
|
697
|
+
return new Promise((resolve2, reject) => {
|
|
698
|
+
try {
|
|
699
|
+
const qt = require2("qrcode-terminal");
|
|
700
|
+
qt.generate(url, { small: options?.small ?? true }, (output) => {
|
|
701
|
+
resolve2(output);
|
|
702
|
+
});
|
|
703
|
+
} catch (err) {
|
|
704
|
+
reject(err);
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/cli-init.ts
|
|
578
710
|
var __filename = fileURLToPath(import.meta.url);
|
|
579
711
|
var __dirname = path2.dirname(__filename);
|
|
580
712
|
var SCHEMA_VERSION = 1;
|
|
@@ -747,9 +879,47 @@ async function interactiveConfig(rl, defaults) {
|
|
|
747
879
|
const feishuAns = await ask(rl, "\u542F\u7528\u98DE\u4E66? (y/n)", "n");
|
|
748
880
|
v.feishuEnabled = feishuAns.toLowerCase() === "y";
|
|
749
881
|
if (v.feishuEnabled) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
882
|
+
console.log("\n \u98DE\u4E66\u914D\u7F6E\u65B9\u5F0F\uFF1A");
|
|
883
|
+
console.log(" 1. \u626B\u7801\u81EA\u52A8\u521B\u5EFA\uFF08\u63A8\u8350\uFF0C30\u79D2\u641E\u5B9A\uFF09");
|
|
884
|
+
console.log(" 2. \u624B\u52A8\u8F93\u5165 App ID / App Secret");
|
|
885
|
+
const feishuMode = await ask(rl, "\u9009\u62E9 (1/2)", "1");
|
|
886
|
+
if (feishuMode === "1") {
|
|
887
|
+
console.log("\n\u{1F4DD} \u6B63\u5728\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801...\n");
|
|
888
|
+
const result = await registerFeishuApp({
|
|
889
|
+
onLog: (msg) => console.log(` ${msg}`),
|
|
890
|
+
onQrCode: async (url) => {
|
|
891
|
+
try {
|
|
892
|
+
const qr = await renderQrTerminal(url, { small: true });
|
|
893
|
+
console.log(qr);
|
|
894
|
+
} catch {
|
|
895
|
+
console.log(`
|
|
896
|
+
\u8BF7\u5728\u624B\u673A\u6D4F\u89C8\u5668\u6253\u5F00\u6B64\u94FE\u63A5\u626B\u7801\uFF1A
|
|
897
|
+
${url}
|
|
898
|
+
`);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
if (result) {
|
|
903
|
+
v.feishuAppId = result.appId;
|
|
904
|
+
v.feishuAppSecret = result.appSecret;
|
|
905
|
+
v.feishuOpenId = result.openId || "";
|
|
906
|
+
console.log(`
|
|
907
|
+
\u2705 App ID: ${result.appId}`);
|
|
908
|
+
console.log(` \u2705 App Secret: ${result.appSecret.slice(0, 6)}...`);
|
|
909
|
+
if (result.openId) {
|
|
910
|
+
console.log(` \u2705 Open ID: ${result.openId}`);
|
|
911
|
+
}
|
|
912
|
+
} else {
|
|
913
|
+
console.log("\n \u26A0\uFE0F \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u8F93\u5165");
|
|
914
|
+
v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
|
|
915
|
+
v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
|
|
916
|
+
v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
917
|
+
}
|
|
918
|
+
} else {
|
|
919
|
+
v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
|
|
920
|
+
v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
|
|
921
|
+
v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
922
|
+
}
|
|
753
923
|
}
|
|
754
924
|
const tavilyKey = await ask(rl, "Tavily API Key\uFF08\u8054\u7F51\u641C\u7D22\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
755
925
|
v.tavilyKey = tavilyKey;
|