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.
Files changed (2) hide show
  1. package/dist/cli.mjs +173 -3
  2. 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
- v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
751
- v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
752
- v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id");
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engine7",
3
- "version": "7.1.25",
3
+ "version": "7.1.27",
4
4
  "type": "module",
5
5
  "description": "Engine 7 — Self-hosted AI agent engine",
6
6
  "main": "dist/main.mjs",