chattercatcher 0.1.12 → 0.1.13

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.js CHANGED
@@ -8,7 +8,7 @@ import fs13 from "fs/promises";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "chattercatcher",
11
- version: "0.1.12",
11
+ version: "0.1.13",
12
12
  description: "\u672C\u5730\u4F18\u5148\u7684\u98DE\u4E66/Lark \u5BB6\u5EAD\u7FA4\u77E5\u8BC6\u5E93\u673A\u5668\u4EBA",
13
13
  type: "module",
14
14
  main: "dist/index.js",
@@ -1945,6 +1945,80 @@ async function restoreLocalData(input2) {
1945
1945
  };
1946
1946
  }
1947
1947
 
1948
+ // src/feishu/bot-info.ts
1949
+ function getOpenApiBaseUrl(domain) {
1950
+ return domain === "lark" ? "https://open.larksuite.com/open-apis" : "https://open.feishu.cn/open-apis";
1951
+ }
1952
+ async function readFeishuJson(response) {
1953
+ if (!response.ok) {
1954
+ throw new Error(`\u98DE\u4E66\u63A5\u53E3\u8BF7\u6C42\u5931\u8D25\uFF1AHTTP ${response.status}`);
1955
+ }
1956
+ return response.json();
1957
+ }
1958
+ function assertFeishuSuccess(payload, fallbackMessage) {
1959
+ if (!payload || typeof payload !== "object") {
1960
+ throw new Error(fallbackMessage);
1961
+ }
1962
+ const code = payload.code;
1963
+ if (code !== 0) {
1964
+ const message = payload.msg;
1965
+ throw new Error(typeof message === "string" ? message : fallbackMessage);
1966
+ }
1967
+ }
1968
+ async function resolveFeishuBotOpenId(config, secrets, options = {}) {
1969
+ if (!config.feishu.appId || !secrets.feishu.appSecret) {
1970
+ throw new Error("\u98DE\u4E66 App ID \u6216 App Secret \u672A\u914D\u7F6E\u3002");
1971
+ }
1972
+ const fetchImpl = options.fetch ?? fetch;
1973
+ const baseUrl = getOpenApiBaseUrl(config.feishu.domain);
1974
+ const tokenPayload = await readFeishuJson(
1975
+ await fetchImpl(`${baseUrl}/auth/v3/tenant_access_token/internal`, {
1976
+ method: "POST",
1977
+ headers: { "content-type": "application/json" },
1978
+ body: JSON.stringify({
1979
+ app_id: config.feishu.appId,
1980
+ app_secret: secrets.feishu.appSecret
1981
+ })
1982
+ })
1983
+ );
1984
+ assertFeishuSuccess(tokenPayload, "\u83B7\u53D6\u98DE\u4E66 tenant_access_token \u5931\u8D25\u3002");
1985
+ const tenantAccessToken = tokenPayload.tenant_access_token;
1986
+ if (typeof tenantAccessToken !== "string" || !tenantAccessToken) {
1987
+ throw new Error("\u98DE\u4E66 tenant_access_token \u54CD\u5E94\u7F3A\u5C11 token\u3002");
1988
+ }
1989
+ const botInfoPayload = await readFeishuJson(
1990
+ await fetchImpl(`${baseUrl}/bot/v3/info`, {
1991
+ method: "GET",
1992
+ headers: { Authorization: `Bearer ${tenantAccessToken}` }
1993
+ })
1994
+ );
1995
+ assertFeishuSuccess(botInfoPayload, "\u83B7\u53D6\u98DE\u4E66\u673A\u5668\u4EBA\u4FE1\u606F\u5931\u8D25\u3002");
1996
+ const bot = botInfoPayload.bot;
1997
+ if (!bot || typeof bot !== "object") {
1998
+ throw new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u4FE1\u606F\u54CD\u5E94\u7F3A\u5C11 bot\u3002");
1999
+ }
2000
+ const openId = bot.open_id;
2001
+ if (typeof openId !== "string" || !openId) {
2002
+ throw new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u4FE1\u606F\u54CD\u5E94\u7F3A\u5C11 open_id\u3002");
2003
+ }
2004
+ return openId;
2005
+ }
2006
+ async function ensureFeishuBotOpenId(config, secrets, options = {}) {
2007
+ if (config.feishu.botOpenId) {
2008
+ return config.feishu.botOpenId;
2009
+ }
2010
+ const openId = await resolveFeishuBotOpenId(config, secrets, options);
2011
+ const previousOpenId = config.feishu.botOpenId;
2012
+ config.feishu.botOpenId = openId;
2013
+ try {
2014
+ await options.onSave?.();
2015
+ } catch (error) {
2016
+ config.feishu.botOpenId = previousOpenId;
2017
+ throw error;
2018
+ }
2019
+ return openId;
2020
+ }
2021
+
1948
2022
  // src/feishu/gateway.ts
1949
2023
  import * as lark2 from "@larksuiteoapi/node-sdk";
1950
2024
 
@@ -3591,14 +3665,11 @@ async function promptForConfiguration(config, secrets) {
3591
3665
  default: config.feishu.domain
3592
3666
  });
3593
3667
  config.feishu.appId = await input({ message: "\u98DE\u4E66 App ID", default: config.feishu.appId });
3594
- config.feishu.botOpenId = await input({
3595
- message: "\u98DE\u4E66\u673A\u5668\u4EBA Open ID\uFF08\u5FC5\u586B\uFF0C\u7528\u4E8E\u533A\u5206 @ \u673A\u5668\u4EBA\u548C @ \u5176\u4ED6\u4EBA\uFF09",
3596
- default: config.feishu.botOpenId
3597
- });
3598
3668
  secrets.feishu.appSecret = applySecretInput(
3599
3669
  secrets.feishu.appSecret,
3600
3670
  await password({ message: secrets.feishu.appSecret ? "\u98DE\u4E66 App Secret\uFF08\u7559\u7A7A\u4FDD\u7559\uFF09" : "\u98DE\u4E66 App Secret", mask: "*" })
3601
3671
  );
3672
+ await tryEnsureFeishuBotOpenId(config, secrets);
3602
3673
  config.llm.baseUrl = await input({ message: "LLM Base URL\uFF08OpenAI-compatible\uFF09", default: config.llm.baseUrl });
3603
3674
  secrets.llm.apiKey = applySecretInput(
3604
3675
  secrets.llm.apiKey,
@@ -3630,6 +3701,17 @@ async function promptForConfiguration(config, secrets) {
3630
3701
  default: config.feishu.requireMention
3631
3702
  });
3632
3703
  }
3704
+ async function tryEnsureFeishuBotOpenId(config, secrets) {
3705
+ if (config.feishu.botOpenId || !config.feishu.appId || !secrets.feishu.appSecret) {
3706
+ return;
3707
+ }
3708
+ try {
3709
+ const openId = await ensureFeishuBotOpenId(config, secrets, { onSave: () => saveConfig(config) });
3710
+ console.log(`\u5DF2\u81EA\u52A8\u83B7\u53D6\u98DE\u4E66\u673A\u5668\u4EBA Open ID\uFF1A${openId}`);
3711
+ } catch (error) {
3712
+ console.log(`\u6682\u65F6\u65E0\u6CD5\u81EA\u52A8\u83B7\u53D6\u98DE\u4E66\u673A\u5668\u4EBA Open ID\uFF1A${error instanceof Error ? error.message : String(error)}`);
3713
+ }
3714
+ }
3633
3715
  function printSettings(config, secrets) {
3634
3716
  console.log(JSON.stringify(
3635
3717
  {
@@ -3728,6 +3810,7 @@ async function startGatewayForegroundCommand() {
3728
3810
  await startWebServer(config);
3729
3811
  return;
3730
3812
  }
3813
+ await tryEnsureFeishuBotOpenId(config, secrets);
3731
3814
  writeGatewayPidRecord(void 0, {
3732
3815
  ...pidRecordBase,
3733
3816
  mode: "gateway"
@@ -3782,6 +3865,7 @@ async function startGatewayCommand(options = {}) {
3782
3865
  }
3783
3866
  const config = await loadConfig();
3784
3867
  const secrets = await loadSecrets();
3868
+ await tryEnsureFeishuBotOpenId(config, secrets);
3785
3869
  const result = await startDetachedGateway({ config, secrets });
3786
3870
  console.log(result.message);
3787
3871
  if (result.pid) {