engine7 7.1.24 → 7.1.26
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 +192 -3
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -575,6 +575,157 @@ 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
|
+
var qrcodeModule = null;
|
|
695
|
+
async function getQrModule() {
|
|
696
|
+
if (qrcodeModule) return qrcodeModule;
|
|
697
|
+
try {
|
|
698
|
+
qrcodeModule = await import("qrcode-terminal");
|
|
699
|
+
} catch {
|
|
700
|
+
try {
|
|
701
|
+
qrcodeModule = await import("qrcode");
|
|
702
|
+
} catch {
|
|
703
|
+
throw new Error("\u8BF7\u5148\u5B89\u88C5 qrcode-terminal: npm install qrcode-terminal");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
return qrcodeModule;
|
|
707
|
+
}
|
|
708
|
+
async function renderQrTerminal(url, options) {
|
|
709
|
+
const mod = await getQrModule();
|
|
710
|
+
return new Promise((resolve2, reject) => {
|
|
711
|
+
try {
|
|
712
|
+
if (mod.generate) {
|
|
713
|
+
mod.generate(url, { small: options?.small ?? true }, (output) => {
|
|
714
|
+
resolve2(output);
|
|
715
|
+
});
|
|
716
|
+
} else if (mod.toString) {
|
|
717
|
+
const output = mod.toString(url, { type: "terminal", small: options?.small ?? true });
|
|
718
|
+
resolve2(output);
|
|
719
|
+
} else {
|
|
720
|
+
reject(new Error("\u4E0D\u652F\u6301\u7684\u4E8C\u7EF4\u7801\u5E93"));
|
|
721
|
+
}
|
|
722
|
+
} catch (err) {
|
|
723
|
+
reject(err);
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// src/cli-init.ts
|
|
578
729
|
var __filename = fileURLToPath(import.meta.url);
|
|
579
730
|
var __dirname = path2.dirname(__filename);
|
|
580
731
|
var SCHEMA_VERSION = 1;
|
|
@@ -747,9 +898,47 @@ async function interactiveConfig(rl, defaults) {
|
|
|
747
898
|
const feishuAns = await ask(rl, "\u542F\u7528\u98DE\u4E66? (y/n)", "n");
|
|
748
899
|
v.feishuEnabled = feishuAns.toLowerCase() === "y";
|
|
749
900
|
if (v.feishuEnabled) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
901
|
+
console.log("\n \u98DE\u4E66\u914D\u7F6E\u65B9\u5F0F\uFF1A");
|
|
902
|
+
console.log(" 1. \u626B\u7801\u81EA\u52A8\u521B\u5EFA\uFF08\u63A8\u8350\uFF0C30\u79D2\u641E\u5B9A\uFF09");
|
|
903
|
+
console.log(" 2. \u624B\u52A8\u8F93\u5165 App ID / App Secret");
|
|
904
|
+
const feishuMode = await ask(rl, "\u9009\u62E9 (1/2)", "1");
|
|
905
|
+
if (feishuMode === "1") {
|
|
906
|
+
console.log("\n\u{1F4DD} \u6B63\u5728\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801...\n");
|
|
907
|
+
const result = await registerFeishuApp({
|
|
908
|
+
onLog: (msg) => console.log(` ${msg}`),
|
|
909
|
+
onQrCode: async (url) => {
|
|
910
|
+
try {
|
|
911
|
+
const qr = await renderQrTerminal(url, { small: true });
|
|
912
|
+
console.log(qr);
|
|
913
|
+
} catch {
|
|
914
|
+
console.log(`
|
|
915
|
+
\u8BF7\u5728\u624B\u673A\u6D4F\u89C8\u5668\u6253\u5F00\u6B64\u94FE\u63A5\u626B\u7801\uFF1A
|
|
916
|
+
${url}
|
|
917
|
+
`);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
if (result) {
|
|
922
|
+
v.feishuAppId = result.appId;
|
|
923
|
+
v.feishuAppSecret = result.appSecret;
|
|
924
|
+
v.feishuOpenId = result.openId || "";
|
|
925
|
+
console.log(`
|
|
926
|
+
\u2705 App ID: ${result.appId}`);
|
|
927
|
+
console.log(` \u2705 App Secret: ${result.appSecret.slice(0, 6)}...`);
|
|
928
|
+
if (result.openId) {
|
|
929
|
+
console.log(` \u2705 Open ID: ${result.openId}`);
|
|
930
|
+
}
|
|
931
|
+
} else {
|
|
932
|
+
console.log("\n \u26A0\uFE0F \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u8F93\u5165");
|
|
933
|
+
v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
|
|
934
|
+
v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
|
|
935
|
+
v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
936
|
+
}
|
|
937
|
+
} else {
|
|
938
|
+
v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
|
|
939
|
+
v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
|
|
940
|
+
v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
941
|
+
}
|
|
753
942
|
}
|
|
754
943
|
const tavilyKey = await ask(rl, "Tavily API Key\uFF08\u8054\u7F51\u641C\u7D22\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
|
|
755
944
|
v.tavilyKey = tavilyKey;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engine7",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Engine 7 — Self-hosted AI agent engine",
|
|
6
6
|
"main": "dist/main.mjs",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"chokidar": "^5.0.0",
|
|
36
36
|
"croner": "^10.0.1",
|
|
37
37
|
"discord.js": "^14.26.4",
|
|
38
|
+
"qrcode-terminal": "^0.12.0",
|
|
38
39
|
"sharp": "^0.34.5",
|
|
39
40
|
"sqlite-vec": "^0.1.9",
|
|
40
41
|
"turndown": "^7.2.4",
|