liangzimixin 0.2.17 → 0.3.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 CHANGED
@@ -3658,7 +3658,7 @@ __export(index_exports, {
3658
3658
  startPlugin: () => startPlugin
3659
3659
  });
3660
3660
  module.exports = __toCommonJS(index_exports);
3661
- var import_node_path3 = require("path");
3661
+ var import_node_path2 = require("path");
3662
3662
  var import_node_os = require("os");
3663
3663
 
3664
3664
  // node_modules/zod/v4/classic/external.js
@@ -17454,14 +17454,6 @@ var AccountConfigSchema = external_exports.object({
17454
17454
  "quantum-appId": external_exports.string().min(1, "quantum-appId \u4E0D\u80FD\u4E3A\u7A7A"),
17455
17455
  /** 🔴 量子服务密钥 — 用于量子密钥分发 */
17456
17456
  "quantum-appSecret": external_exports.string().min(1, "quantum-appSecret \u4E0D\u80FD\u4E3A\u7A7A"),
17457
- /** 🔴 PIN 口令 — 保护本地敏感数据 (切勿泄露, 修改后需删除旧密钥数据) */
17458
- pin: external_exports.string().min(1, "pin \u4E0D\u80FD\u4E3A\u7A7A"),
17459
- /**
17460
- * 🟡 量子密服地址 — 默认生产环境
17461
- * 测试环境: http://223.244.14.238:8552
17462
- * 生产环境: https://cmsp.zdxlz.com:8552
17463
- */
17464
- "quantum-url": external_exports.string().url().optional().default("https://cmsp.zdxlz.com:8552"),
17465
17457
  /**
17466
17458
  * 🟡 Bot 自己的用户 ID — 用于 anti-loop 检查
17467
17459
  * 如果不填,需要通过其他 API 在运行时获取。
@@ -17473,8 +17465,6 @@ var AccountConfigSchema = external_exports.object({
17473
17465
  quantumAccount: raw["quantum-account"],
17474
17466
  quantumAppId: raw["quantum-appId"],
17475
17467
  quantumAppSecret: raw["quantum-appSecret"],
17476
- pin: raw.pin,
17477
- quantumUrl: raw["quantum-url"],
17478
17468
  botUserId: raw.botUserId
17479
17469
  }));
17480
17470
  var DEFAULT_INTERNAL_CONFIG = {
@@ -17493,12 +17483,14 @@ var DEFAULT_INTERNAL_CONFIG = {
17493
17483
  }
17494
17484
  },
17495
17485
  auth: {
17496
- serverUrl: process.env.LZMX_AUTH_URL || "https://imtwo.zdxlz.com/open-apis/v1",
17486
+ serverUrl: process.env.LZMX_AUTH_URL || "https://seal.example.com",
17487
+ clientName: "liangzimixin",
17488
+ scopes: ["openid", "im_sdk", "data_operate", "offline_access"],
17489
+ autoRegister: true,
17497
17490
  refreshAheadMs: 3e5
17498
17491
  },
17499
17492
  crypto: {
17500
- enabled: false,
17501
- // 暂时关闭量子加密 (SDK 尚未部署到生产环境)
17493
+ enabled: true,
17502
17494
  keySource: "env",
17503
17495
  envKey: "QUANTUM_ENCRYPTION_KEY"
17504
17496
  },
@@ -17982,7 +17974,7 @@ async function resolveAndUploadMedia(params) {
17982
17974
  };
17983
17975
  }
17984
17976
  const msgType = fileType;
17985
- const contentPayload = fileType === "file" ? { fileId: uploadResult.fileKey, fileName, size: uploadResult.fileSize } : { fileId: uploadResult.fileKey };
17977
+ const contentPayload = fileType === "file" ? { fileKey: uploadResult.fileKey, filename: fileName, size: uploadResult.fileSize } : { fileKey: uploadResult.fileKey };
17986
17978
  await messagePipe.sendMessage({
17987
17979
  chatId,
17988
17980
  senderId: chatId,
@@ -17992,7 +17984,7 @@ async function resolveAndUploadMedia(params) {
17992
17984
  });
17993
17985
  log3.info("media:sent", {
17994
17986
  chatId,
17995
- fileId: uploadResult.fileKey,
17987
+ fileKey: uploadResult.fileKey,
17996
17988
  msgType
17997
17989
  });
17998
17990
  return {
@@ -18119,20 +18111,20 @@ ${body}` : body || raw.content;
18119
18111
  }
18120
18112
  case "image": {
18121
18113
  const c = parsed;
18122
- fileId = c?.fileId;
18114
+ fileId = c?.fileKey;
18123
18115
  text = c?.altText ?? (fileId ? `![image](${fileId})` : "[image]");
18124
18116
  break;
18125
18117
  }
18126
18118
  case "file": {
18127
18119
  const c = parsed;
18128
- fileId = c?.fileId;
18129
- fileName = c?.fileName;
18120
+ fileId = c?.fileKey;
18121
+ fileName = c?.filename;
18130
18122
  text = fileName ? `[File: ${fileName}]` : "[file]";
18131
18123
  break;
18132
18124
  }
18133
18125
  case "voice": {
18134
18126
  const c = parsed;
18135
- fileId = c?.fileId;
18127
+ fileId = c?.fileKey;
18136
18128
  const durationMs = c?.duration;
18137
18129
  const durationStr = durationMs != null ? ` ${(durationMs / 1e3).toFixed(1)}s` : "";
18138
18130
  text = `[Voice${durationStr}]`;
@@ -18140,7 +18132,7 @@ ${body}` : body || raw.content;
18140
18132
  }
18141
18133
  case "video": {
18142
18134
  const c = parsed;
18143
- fileId = c?.fileId;
18135
+ fileId = c?.fileKey;
18144
18136
  const durationMs = c?.duration;
18145
18137
  const durationStr = durationMs != null ? ` ${(durationMs / 1e3).toFixed(1)}s` : "";
18146
18138
  text = `[Video${durationStr}]`;
@@ -18462,7 +18454,7 @@ var QUANTUM_IM_CONFIG_JSON_SCHEMA = {
18462
18454
  title: "\u91CF\u5B50\u5BC6\u4FE1 IM \u63D2\u4EF6\u914D\u7F6E",
18463
18455
  description: "\u5BC6\u4FE1 IM Channel \u63D2\u4EF6\uFF0C\u652F\u6301\u91CF\u5B50\u52A0\u5BC6\u7684\u5B89\u5168\u5373\u65F6\u901A\u4FE1\u3002",
18464
18456
  type: "object",
18465
- required: ["appId", "appSecret", "quantum-account", "quantum-appId", "quantum-appSecret", "pin"],
18457
+ required: ["appId", "appSecret", "quantum-account", "quantum-appId", "quantum-appSecret"],
18466
18458
  properties: {
18467
18459
  appId: {
18468
18460
  type: "string",
@@ -18496,19 +18488,6 @@ var QUANTUM_IM_CONFIG_JSON_SCHEMA = {
18496
18488
  minLength: 1,
18497
18489
  format: "password"
18498
18490
  },
18499
- pin: {
18500
- type: "string",
18501
- title: "PIN \u53E3\u4EE4",
18502
- description: "\u4FDD\u62A4\u672C\u5730\u654F\u611F\u6570\u636E\u7684\u53E3\u4EE4\uFF0C\u7531\u7528\u6237\u81EA\u5B9A\u4E49\uFF08\u5207\u52FF\u6CC4\u9732\uFF0C\u4FEE\u6539\u540E\u8BF7\u5220\u9664\u65E7\u5BC6\u94A5\u6570\u636E\uFF09",
18503
- minLength: 1,
18504
- format: "password"
18505
- },
18506
- "quantum-url": {
18507
- type: "string",
18508
- title: "\u91CF\u5B50\u5BC6\u670D\u5730\u5740",
18509
- description: "\u91CF\u5B50\u5BC6\u94A5\u7BA1\u7406\u670D\u52A1\u5730\u5740\u3002\u6D4B\u8BD5\u73AF\u5883: http://223.244.14.238:8552\uFF0C\u751F\u4EA7\u73AF\u5883: https://cmsp.zdxlz.com:8552",
18510
- default: "https://cmsp.zdxlz.com:8552"
18511
- },
18512
18491
  botUserId: {
18513
18492
  type: "string",
18514
18493
  title: "Bot \u7528\u6237 ID",
@@ -18602,7 +18581,6 @@ var quantumImOnboarding = {
18602
18581
  "\u8BF7\u51C6\u5907\u4EE5\u4E0B\u4FE1\u606F:",
18603
18582
  " 1. \u5E73\u53F0\u7533\u8BF7\u7684 appId \u548C appSecret",
18604
18583
  " 2. \u91CF\u5B50\u52A0\u5BC6\u670D\u52A1\u7684\u8D26\u6237\u3001appId \u548C appSecret",
18605
- " 3. \u4FDD\u62A4\u672C\u5730\u5BC6\u94A5\u6570\u636E\u7684 PIN \u53E3\u4EE4",
18606
18584
  "",
18607
18585
  "\u5982\u6709\u7591\u95EE\u8BF7\u8054\u7CFB\u5E73\u53F0\u7BA1\u7406\u5458\u83B7\u53D6\u3002"
18608
18586
  ].join("\n"),
@@ -18634,36 +18612,6 @@ var quantumImOnboarding = {
18634
18612
  initialValue: existing["quantum-appSecret"] ?? void 0,
18635
18613
  validate: required2
18636
18614
  });
18637
- const pin = await prompter.text({
18638
- message: "PIN \u53E3\u4EE4 (\u4FDD\u62A4\u672C\u5730\u654F\u611F\u6570\u636E, \u5207\u52FF\u6CC4\u9732)",
18639
- initialValue: existing.pin ?? void 0,
18640
- validate: required2
18641
- });
18642
- const urlChoice = await prompter.select({
18643
- message: "\u91CF\u5B50\u5BC6\u670D\u73AF\u5883",
18644
- options: [
18645
- { value: "https://cmsp.zdxlz.com:8552", label: "\u751F\u4EA7\u73AF\u5883", hint: "https://cmsp.zdxlz.com:8552" },
18646
- { value: "http://223.244.14.238:8552", label: "\u6D4B\u8BD5\u73AF\u5883", hint: "http://223.244.14.238:8552" },
18647
- { value: "custom", label: "\u81EA\u5B9A\u4E49\u5730\u5740" }
18648
- ],
18649
- initialValue: existing["quantum-url"] ?? "https://cmsp.zdxlz.com:8552"
18650
- });
18651
- let quantumUrl = urlChoice;
18652
- if (urlChoice === "custom") {
18653
- quantumUrl = await prompter.text({
18654
- message: "\u8BF7\u8F93\u5165\u91CF\u5B50\u5BC6\u670D\u5730\u5740",
18655
- placeholder: "https://your-server:8552",
18656
- validate: (v) => {
18657
- if (!v.trim()) return "\u4E0D\u80FD\u4E3A\u7A7A";
18658
- try {
18659
- new URL(v);
18660
- } catch {
18661
- return "\u8BF7\u8F93\u5165\u5408\u6CD5\u7684 URL";
18662
- }
18663
- return void 0;
18664
- }
18665
- });
18666
- }
18667
18615
  const channels = cfg.channels ?? {};
18668
18616
  const channelCfg = channels[CHANNEL_ID] ?? {};
18669
18617
  const accounts = channelCfg.accounts ?? {};
@@ -18681,9 +18629,7 @@ var quantumImOnboarding = {
18681
18629
  appSecret: appSecret.trim(),
18682
18630
  "quantum-account": quantumAccount.trim(),
18683
18631
  "quantum-appId": quantumAppId.trim(),
18684
- "quantum-appSecret": quantumAppSecret.trim(),
18685
- pin: pin.trim(),
18686
- "quantum-url": quantumUrl.trim()
18632
+ "quantum-appSecret": quantumAppSecret.trim()
18687
18633
  }
18688
18634
  }
18689
18635
  }
@@ -18868,7 +18814,6 @@ var quantumImPlugin = {
18868
18814
 
18869
18815
  // src/crypto/quantun-plug-adapter.ts
18870
18816
  var import_node_module = require("module");
18871
- var import_node_url = require("url");
18872
18817
  var import_meta = {};
18873
18818
  var log14 = createLogger("crypto/quantun-plug-adapter");
18874
18819
  var SM4_MODE = {
@@ -18878,8 +18823,7 @@ var SM4_MODE = {
18878
18823
  CBC_PKCS7PADDING: 4
18879
18824
  };
18880
18825
  var DEFAULT_ENCRYPT_MODE = SM4_MODE.CBC_PKCS7PADDING;
18881
- var _currentUrl = typeof __filename !== "undefined" ? (0, import_node_url.pathToFileURL)(__filename).href : import_meta.url;
18882
- var require2 = (0, import_node_module.createRequire)(_currentUrl);
18826
+ var require2 = (0, import_node_module.createRequire)(import_meta.url);
18883
18827
  var quantunPlug = null;
18884
18828
  try {
18885
18829
  quantunPlug = require2("./sdk/index.min.cjs");
@@ -18890,32 +18834,8 @@ try {
18890
18834
  }
18891
18835
  var quantun_plug_adapter_default = quantunPlug;
18892
18836
 
18893
- // src/crypto/quantum-config-writer.ts
18894
- var import_node_fs = require("fs");
18895
- var import_node_path = require("path");
18896
- var import_node_url2 = require("url");
18897
- var import_meta2 = {};
18898
- var log15 = createLogger("crypto/quantum-config-writer");
18899
- var _currentDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
18900
- var QUANTUM_JSON_PATH = (0, import_node_path.join)(
18901
- _currentDir,
18902
- "sdk",
18903
- "quantum.json"
18904
- );
18905
- function writeQuantumConfig(credentials) {
18906
- const sdkConfig = {
18907
- account: credentials.quantumAccount,
18908
- appID: credentials.quantumAppId,
18909
- pin: credentials.pin,
18910
- authCode: credentials.quantumAppSecret,
18911
- url: credentials.quantumUrl
18912
- };
18913
- (0, import_node_fs.writeFileSync)(QUANTUM_JSON_PATH, JSON.stringify(sdkConfig, null, 2), "utf-8");
18914
- log15.info("quantum.json written to", QUANTUM_JSON_PATH);
18915
- }
18916
-
18917
18837
  // src/crypto/crypto-engine.ts
18918
- var log16 = createLogger("crypto/crypto-engine");
18838
+ var log15 = createLogger("crypto/crypto-engine");
18919
18839
  var PASSTHROUGH_KEY_ID = "passthrough";
18920
18840
  var FILE_CHUNK_SIZE = 10 * 1024 * 1024;
18921
18841
  var FILE_DECRYPT_CHUNK_SIZE = FILE_CHUNK_SIZE + 16;
@@ -18926,26 +18846,20 @@ var CryptoEngine = class _CryptoEngine {
18926
18846
  initialized;
18927
18847
  /** 是否为透传模式 (不加密, 明文直接透传) */
18928
18848
  passthrough;
18929
- /** 用户凭据 — 用于生成 quantum.json (透传模式下为 undefined) */
18930
- credentials;
18931
18849
  /**
18932
18850
  * 构造加密引擎
18933
18851
  *
18934
- * @param opts - 构造选项
18935
- * @param opts.passthrough - true 为透传模式 (不加密); false 为加密模式 (默认)
18936
- * @param opts.credentials - 用户凭据 (加密模式必需, 用于生成 quantum.json)
18852
+ * @param passthrough - true 为透传模式 (不加密); false 为加密模式 (默认)
18937
18853
  *
18938
18854
  * 请使用静态工厂方法:
18939
- * - new CryptoEngine({ credentials }) → 加密模式, 使用量子 SDK
18855
+ * - new CryptoEngine() → 加密模式, 使用量子 SDK
18940
18856
  * - CryptoEngine.createPassthrough() → 透传模式, 无需 init()
18941
18857
  */
18942
- constructor(opts = {}) {
18943
- const { passthrough = false, credentials } = opts;
18858
+ constructor(passthrough = false) {
18944
18859
  this.passthrough = passthrough;
18945
- this.credentials = credentials;
18946
18860
  this.plug = passthrough ? null : quantun_plug_adapter_default;
18947
18861
  this.initialized = passthrough;
18948
- log16.info(`CryptoEngine created (${passthrough ? "passthrough mode \u2014 crypto disabled" : "quantum SDK mode"})`);
18862
+ log15.info(`CryptoEngine created (${passthrough ? "passthrough mode \u2014 crypto disabled" : "quantum SDK mode"})`);
18949
18863
  }
18950
18864
  /**
18951
18865
  * 创建透传模式的加密引擎 (静态工厂方法)
@@ -18959,7 +18873,7 @@ var CryptoEngine = class _CryptoEngine {
18959
18873
  * 上层模块 (TokenStore, MessagePipe) 无需感知加密是否开启。
18960
18874
  */
18961
18875
  static createPassthrough() {
18962
- return new _CryptoEngine({ passthrough: true });
18876
+ return new _CryptoEngine(true);
18963
18877
  }
18964
18878
  /**
18965
18879
  * 初始化加密引擎
@@ -18977,12 +18891,9 @@ var CryptoEngine = class _CryptoEngine {
18977
18891
  if (!this.plug) {
18978
18892
  throw new Error("Quantum encryption SDK is missing. Cannot initialize in encryption mode (check dist/index.min.cjs).");
18979
18893
  }
18980
- if (this.credentials) {
18981
- writeQuantumConfig(this.credentials);
18982
- }
18983
18894
  await this.plug.init();
18984
18895
  this.initialized = true;
18985
- log16.info("CryptoEngine initialized \u2713");
18896
+ log15.info("CryptoEngine initialized \u2713");
18986
18897
  }
18987
18898
  /**
18988
18899
  * 加密明文
@@ -18998,12 +18909,12 @@ var CryptoEngine = class _CryptoEngine {
18998
18909
  */
18999
18910
  async encrypt(plaintext) {
19000
18911
  if (this.passthrough) {
19001
- log16.debug("Encrypt (passthrough)", { length: plaintext.length });
18912
+ log15.debug("Encrypt (passthrough)", { length: plaintext.length });
19002
18913
  return { ciphertext: plaintext, keyId: PASSTHROUGH_KEY_ID };
19003
18914
  }
19004
18915
  const plug = this.requirePlug();
19005
18916
  const result = await plug.encrypt(plaintext, DEFAULT_ENCRYPT_MODE);
19006
- log16.debug("Encrypted", { length: plaintext.length, keyId: result.keyId });
18917
+ log15.debug("Encrypted", { length: plaintext.length, keyId: result.keyId });
19007
18918
  return { ciphertext: result.cipherText, keyId: result.keyId };
19008
18919
  }
19009
18920
  /**
@@ -19019,12 +18930,12 @@ var CryptoEngine = class _CryptoEngine {
19019
18930
  */
19020
18931
  async decrypt(ciphertext, keyId) {
19021
18932
  if (this.passthrough) {
19022
- log16.debug("Decrypt (passthrough)", { keyId });
18933
+ log15.debug("Decrypt (passthrough)", { keyId });
19023
18934
  return ciphertext;
19024
18935
  }
19025
18936
  const plug = this.requirePlug();
19026
18937
  const result = await plug.decrypt(ciphertext, keyId, DEFAULT_ENCRYPT_MODE);
19027
- log16.debug("Decrypted", { keyId });
18938
+ log15.debug("Decrypted", { keyId });
19028
18939
  return result.plainText;
19029
18940
  }
19030
18941
  /**
@@ -19041,7 +18952,7 @@ var CryptoEngine = class _CryptoEngine {
19041
18952
  */
19042
18953
  async encryptFile(fileData) {
19043
18954
  if (this.passthrough) {
19044
- log16.debug("EncryptFile (passthrough)", { size: fileData.length });
18955
+ log15.debug("EncryptFile (passthrough)", { size: fileData.length });
19045
18956
  return { fileBuffer: fileData, keyId: PASSTHROUGH_KEY_ID };
19046
18957
  }
19047
18958
  if (fileData.length === 0) {
@@ -19053,7 +18964,7 @@ var CryptoEngine = class _CryptoEngine {
19053
18964
  let sessionKey;
19054
18965
  let fillKey;
19055
18966
  const plug = this.requirePlug();
19056
- log16.debug("EncryptFile", { size: fileData.length, chunks: total });
18967
+ log15.debug("EncryptFile", { size: fileData.length, chunks: total });
19057
18968
  for (let i = 0; i < total; i++) {
19058
18969
  const start = i * FILE_CHUNK_SIZE;
19059
18970
  const end = Math.min(start + FILE_CHUNK_SIZE, fileData.length);
@@ -19068,7 +18979,7 @@ var CryptoEngine = class _CryptoEngine {
19068
18979
  sessionKey = result.sessionKey;
19069
18980
  fillKey = result.fillKey;
19070
18981
  }
19071
- log16.debug("EncryptFile done", { keyId, chunks: total });
18982
+ log15.debug("EncryptFile done", { keyId, chunks: total });
19072
18983
  return { fileBuffer: Buffer.concat(chunks), keyId: keyId ?? "" };
19073
18984
  }
19074
18985
  /**
@@ -19086,7 +18997,7 @@ var CryptoEngine = class _CryptoEngine {
19086
18997
  */
19087
18998
  async decryptFile(fileData, keyId) {
19088
18999
  if (this.passthrough) {
19089
- log16.debug("DecryptFile (passthrough)", { keyId });
19000
+ log15.debug("DecryptFile (passthrough)", { keyId });
19090
19001
  return fileData;
19091
19002
  }
19092
19003
  if (fileData.length === 0) {
@@ -19097,7 +19008,7 @@ var CryptoEngine = class _CryptoEngine {
19097
19008
  const total = Math.ceil(fileData.length / FILE_DECRYPT_CHUNK_SIZE);
19098
19009
  let sessionKey;
19099
19010
  let fillKey;
19100
- log16.debug("DecryptFile", { size: fileData.length, chunks: total, keyId });
19011
+ log15.debug("DecryptFile", { size: fileData.length, chunks: total, keyId });
19101
19012
  for (let i = 0; i < total; i++) {
19102
19013
  const start = i * FILE_DECRYPT_CHUNK_SIZE;
19103
19014
  const end = Math.min(start + FILE_DECRYPT_CHUNK_SIZE, fileData.length);
@@ -19110,7 +19021,7 @@ var CryptoEngine = class _CryptoEngine {
19110
19021
  sessionKey = result.sessionKey;
19111
19022
  fillKey = result.fillKey;
19112
19023
  }
19113
- log16.debug("DecryptFile done", { keyId, chunks: total });
19024
+ log15.debug("DecryptFile done", { keyId, chunks: total });
19114
19025
  return Buffer.concat(chunks);
19115
19026
  }
19116
19027
  /**
@@ -19133,14 +19044,14 @@ var CryptoEngine = class _CryptoEngine {
19133
19044
  };
19134
19045
 
19135
19046
  // src/auth/oauth-client.ts
19136
- var log17 = createLogger("auth/oauth-client");
19137
- var ApiError = class extends Error {
19047
+ var log16 = createLogger("auth/oauth-client");
19048
+ var SealApiError = class extends Error {
19138
19049
  constructor(status, body, endpoint) {
19139
- super(`API error: ${status} on ${endpoint}`);
19050
+ super(`Seal API error: ${status} on ${endpoint}`);
19140
19051
  this.status = status;
19141
19052
  this.body = body;
19142
19053
  this.endpoint = endpoint;
19143
- this.name = "ApiError";
19054
+ this.name = "SealApiError";
19144
19055
  }
19145
19056
  };
19146
19057
  var TokenAcquireError = class extends Error {
@@ -19157,21 +19068,28 @@ function sleep(ms) {
19157
19068
  return new Promise((resolve2) => setTimeout(resolve2, ms));
19158
19069
  }
19159
19070
  var DEFAULT_TIMEOUT_MS = 3e4;
19160
- var GRANT_TYPE = "client_credentials";
19161
- var SCOPE = "client_credentials refresh_token";
19162
- var OAuthClient = class {
19071
+ var SealClient = class {
19163
19072
  baseUrl;
19164
- appId;
19165
- appSecret;
19073
+ clientId;
19074
+ clientSecret;
19075
+ clientName;
19076
+ scopes;
19166
19077
  constructor(config2) {
19167
- this.baseUrl = config2.baseUrl.replace(/\/+$/, "");
19168
- this.appId = config2.appId;
19169
- this.appSecret = config2.appSecret;
19170
- log17.info("OAuthClient initialized", { baseUrl: this.baseUrl, appId: sanitize(this.appId) });
19078
+ this.baseUrl = config2.serverUrl.replace(/\/+$/, "");
19079
+ this.clientId = config2.clientId;
19080
+ this.clientSecret = config2.clientSecret;
19081
+ this.clientName = config2.clientName;
19082
+ this.scopes = config2.scopes;
19083
+ log16.info("SealClient initialized", { serverUrl: this.baseUrl, clientName: config2.clientName });
19171
19084
  }
19172
19085
  // ── 通用 HTTP 请求 ──
19173
19086
  /**
19174
19087
  * 统一 HTTP 请求封装 — 含超时、日志脱敏和错误处理
19088
+ * @param method - HTTP 方法
19089
+ * @param path - 请求路径 (如 '/seal/client/register')
19090
+ * @param options - 请求选项
19091
+ * @returns 解析后的 JSON 响应
19092
+ * @throws SealApiError — HTTP 非 2xx 响应
19175
19093
  */
19176
19094
  async request(method, path2, options = {}) {
19177
19095
  const url2 = `${this.baseUrl}${path2}`;
@@ -19187,7 +19105,7 @@ var OAuthClient = class {
19187
19105
  bodyStr = JSON.stringify(options.body);
19188
19106
  }
19189
19107
  }
19190
- log17.debug("HTTP request", { method, url: url2 });
19108
+ log16.debug("HTTP request", { method, url: url2 });
19191
19109
  const response = await fetch(url2, {
19192
19110
  method,
19193
19111
  headers,
@@ -19202,39 +19120,110 @@ var OAuthClient = class {
19202
19120
  } catch {
19203
19121
  parsedBody = responseBody;
19204
19122
  }
19205
- log17.error("HTTP error", { method, url: url2, status: response.status });
19206
- throw new ApiError(response.status, parsedBody, path2);
19123
+ log16.error("HTTP error", { method, url: url2, status: response.status });
19124
+ throw new SealApiError(response.status, parsedBody, path2);
19207
19125
  }
19208
- log17.debug("HTTP response", { method, url: url2, status: response.status });
19126
+ log16.debug("HTTP response", { method, url: url2, status: response.status });
19209
19127
  try {
19210
19128
  return JSON.parse(responseBody);
19211
19129
  } catch {
19212
- throw new ApiError(response.status, responseBody, path2);
19130
+ throw new SealApiError(response.status, responseBody, path2);
19213
19131
  }
19214
19132
  }
19215
19133
  // ── 公共方法 ──
19134
+ /** 判断是否已注册 (有 clientId + clientSecret) */
19135
+ isRegistered() {
19136
+ return !!(this.clientId && this.clientSecret);
19137
+ }
19138
+ /** 更新 clientId / clientSecret (注册成功后或从持久化加载后调用) */
19139
+ setCredentials(clientId, clientSecret) {
19140
+ this.clientId = clientId;
19141
+ this.clientSecret = clientSecret;
19142
+ log16.info("Credentials updated", { clientId: sanitize(clientId) });
19143
+ }
19216
19144
  /**
19217
- * 获取访问令牌 → POST /auth/token (client_credentials)
19145
+ * 动态注册客户端 → POST /seal/client/register
19218
19146
  *
19219
- * 请求参数 (x-www-form-urlencoded):
19220
- * - grant_type: client_credentials (写死)
19221
- * - client_id: appId
19222
- * - client_secret: appSecret
19223
- * - scope: client_credentials refresh_token (写死)
19147
+ * 首次运行时自动调用,获取 clientId 和 clientSecret。
19148
+ * 注册成功后自动更新内部凭据。
19149
+ */
19150
+ async register(params) {
19151
+ const body = {
19152
+ client_name: params.clientName,
19153
+ scopes: params.scopes,
19154
+ authentication_methods: params.authMethods ?? ["client_secret_post"],
19155
+ grant_types: params.grantTypes ?? ["authorization_code", "client_credentials", "refresh_token"],
19156
+ redirect_uris: params.redirectUris ?? ["https://placeholder.local"],
19157
+ logout_redirect_uris: [],
19158
+ client_settings: {
19159
+ "settings.client.require-authorization-consent": true
19160
+ }
19161
+ };
19162
+ if (params.tokenSettings) {
19163
+ const ts = {};
19164
+ if (params.tokenSettings.accessTokenTtl) {
19165
+ ts["settings.token.access-token-time-to-live"] = params.tokenSettings.accessTokenTtl;
19166
+ }
19167
+ if (params.tokenSettings.refreshTokenTtl) {
19168
+ ts["settings.token.refresh-token-time-to-live"] = params.tokenSettings.refreshTokenTtl;
19169
+ }
19170
+ if (params.tokenSettings.accessTokenFormat) {
19171
+ ts["settings.token.access-token-format"] = params.tokenSettings.accessTokenFormat;
19172
+ }
19173
+ if (params.tokenSettings.reuseRefreshTokens !== void 0) {
19174
+ ts["settings.token.reuse-refresh-tokens"] = params.tokenSettings.reuseRefreshTokens;
19175
+ }
19176
+ ts["settings.token.authorization-code-time-to-live"] = "300";
19177
+ body.token_settings = ts;
19178
+ }
19179
+ log16.info("Registering OAuth client", { clientName: params.clientName });
19180
+ const response = await this.request(
19181
+ "POST",
19182
+ "/seal/client/register",
19183
+ { body, contentType: "json" }
19184
+ );
19185
+ const registration = {
19186
+ clientId: response.client_id,
19187
+ clientSecret: response.client_secret,
19188
+ clientSecretExpiresAt: response.client_secret_expires_at ?? "",
19189
+ clientIdIssuedAt: response.client_id_issued_at ?? "",
19190
+ scopes: response.scopes ?? params.scopes
19191
+ };
19192
+ this.setCredentials(registration.clientId, registration.clientSecret);
19193
+ log16.info("OAuth client registered", {
19194
+ clientId: sanitize(registration.clientId),
19195
+ clientSecret: sanitize(registration.clientSecret),
19196
+ scopes: registration.scopes,
19197
+ expiresAt: registration.clientSecretExpiresAt
19198
+ });
19199
+ return registration;
19200
+ }
19201
+ /**
19202
+ * 获取访问令牌 → POST /seal/oauth2/token (client_credentials)
19224
19203
  *
19204
+ * 使用客户端凭证模式获取 Access Token。
19205
+ * 前置条件: clientId 和 clientSecret 必须存在 (通过 register 或 setCredentials 设置)
19206
+ *
19207
+ * @param scope - 请求的权限范围 (空格分隔),不传则使用注册时的全部 scope
19225
19208
  * @returns TokenData 包含 access_token、过期时间等
19226
- * @throws ApiErrorHTTP 错误
19209
+ * @throws ErrorclientId/clientSecret 未设置
19210
+ * @throws SealApiError — HTTP 错误
19227
19211
  */
19228
- async getToken() {
19212
+ async getToken(scope) {
19213
+ if (!this.clientId || !this.clientSecret) {
19214
+ throw new Error("Cannot get token: clientId and clientSecret are required. Call register() or setCredentials() first.");
19215
+ }
19229
19216
  const params = new URLSearchParams();
19230
- params.set("grant_type", GRANT_TYPE);
19231
- params.set("client_id", this.appId);
19232
- params.set("client_secret", this.appSecret);
19233
- params.set("scope", SCOPE);
19234
- log17.info("Requesting access token", { appId: sanitize(this.appId) });
19217
+ params.set("grant_type", "client_credentials");
19218
+ params.set("client_id", this.clientId);
19219
+ params.set("client_secret", this.clientSecret);
19220
+ if (scope) {
19221
+ params.set("scope", scope);
19222
+ }
19223
+ log16.info("Requesting access token", { clientId: sanitize(this.clientId) });
19235
19224
  const response = await this.request(
19236
19225
  "POST",
19237
- "/auth/token",
19226
+ "/seal/oauth2/token",
19238
19227
  { body: params, contentType: "form" }
19239
19228
  );
19240
19229
  const now = Date.now();
@@ -19245,28 +19234,32 @@ var OAuthClient = class {
19245
19234
  expiresIn,
19246
19235
  scope: response.scope ?? "",
19247
19236
  refreshToken: void 0,
19237
+ // Seal 不返回 refresh_token
19248
19238
  grantedAt: now,
19249
19239
  expiresAt: now + expiresIn * 1e3
19250
19240
  };
19251
- log17.info("Access token acquired", {
19241
+ log16.info("Access token acquired", {
19252
19242
  accessToken: sanitize(tokenData.accessToken),
19253
19243
  expiresIn: tokenData.expiresIn,
19254
19244
  scope: tokenData.scope
19255
19245
  });
19256
19246
  return tokenData;
19257
19247
  }
19258
- /** 获取 baseUrl (供其他模块复用) */
19259
- getBaseUrl() {
19260
- return this.baseUrl;
19248
+ /**
19249
+ * 令牌校验 → GET /seal/oauth2/introspect
19250
+ * 暂不实现 — 保留接口签名,后续需要时再补充
19251
+ */
19252
+ async introspect(_token) {
19253
+ throw new Error("introspect() not implemented yet \u2014 Seal introspect API \u6682\u4E0D\u4F7F\u7528");
19261
19254
  }
19262
19255
  };
19263
19256
 
19264
19257
  // src/auth/token-store.ts
19265
19258
  var import_promises = require("fs/promises");
19266
- var import_node_fs2 = require("fs");
19267
- var import_node_path2 = require("path");
19259
+ var import_node_fs = require("fs");
19260
+ var import_node_path = require("path");
19268
19261
  var import_node_crypto = require("crypto");
19269
- var log18 = createLogger("auth/token-store");
19262
+ var log17 = createLogger("auth/token-store");
19270
19263
  var TokenStore = class {
19271
19264
  /** 存储目录路径 */
19272
19265
  storageDir;
@@ -19281,7 +19274,7 @@ var TokenStore = class {
19281
19274
  constructor(storageDir, crypto) {
19282
19275
  this.storageDir = storageDir;
19283
19276
  this.crypto = crypto;
19284
- log18.info("TokenStore initialized", { storageDir });
19277
+ log17.info("TokenStore initialized", { storageDir });
19285
19278
  }
19286
19279
  /**
19287
19280
  * 确保存储目录存在并设置正确的权限。
@@ -19289,9 +19282,9 @@ var TokenStore = class {
19289
19282
  */
19290
19283
  async ensureDir() {
19291
19284
  if (this.dirEnsured) return;
19292
- if (!(0, import_node_fs2.existsSync)(this.storageDir)) {
19285
+ if (!(0, import_node_fs.existsSync)(this.storageDir)) {
19293
19286
  await (0, import_promises.mkdir)(this.storageDir, { recursive: true, mode: 448 });
19294
- log18.debug("Storage directory created", { dir: this.storageDir });
19287
+ log17.debug("Storage directory created", { dir: this.storageDir });
19295
19288
  }
19296
19289
  this.dirEnsured = true;
19297
19290
  }
@@ -19300,7 +19293,7 @@ var TokenStore = class {
19300
19293
  * @param key - 存储键名 (如 'token', 'credentials')
19301
19294
  */
19302
19295
  filePath(key) {
19303
- return (0, import_node_path2.join)(this.storageDir, `${key}.enc`);
19296
+ return (0, import_node_path.join)(this.storageDir, `${key}.enc`);
19304
19297
  }
19305
19298
  /**
19306
19299
  * 保存 Token — 加密写入文件
@@ -19326,7 +19319,7 @@ var TokenStore = class {
19326
19319
  try {
19327
19320
  await (0, import_promises.writeFile)(tmpPath, storageJson, { mode: 384 });
19328
19321
  await (0, import_promises.rename)(tmpPath, targetPath);
19329
- log18.debug("Token saved", { key, path: targetPath });
19322
+ log17.debug("Token saved", { key, path: targetPath });
19330
19323
  } catch (err) {
19331
19324
  try {
19332
19325
  await (0, import_promises.unlink)(tmpPath);
@@ -19348,8 +19341,8 @@ var TokenStore = class {
19348
19341
  */
19349
19342
  async load(key) {
19350
19343
  const filePath = this.filePath(key);
19351
- if (!(0, import_node_fs2.existsSync)(filePath)) {
19352
- log18.debug("Token file not found", { key, path: filePath });
19344
+ if (!(0, import_node_fs.existsSync)(filePath)) {
19345
+ log17.debug("Token file not found", { key, path: filePath });
19353
19346
  return null;
19354
19347
  }
19355
19348
  try {
@@ -19357,10 +19350,10 @@ var TokenStore = class {
19357
19350
  const storage = JSON.parse(raw);
19358
19351
  const json2 = await this.crypto.decrypt(storage.ciphertext, storage.keyId);
19359
19352
  const data = JSON.parse(json2);
19360
- log18.debug("Token loaded", { key, path: filePath });
19353
+ log17.debug("Token loaded", { key, path: filePath });
19361
19354
  return data;
19362
19355
  } catch (err) {
19363
- log18.warn("Failed to load token (corrupted or key mismatch), treating as empty", {
19356
+ log17.warn("Failed to load token (corrupted or key mismatch), treating as empty", {
19364
19357
  key,
19365
19358
  error: err instanceof Error ? err.message : String(err)
19366
19359
  });
@@ -19376,7 +19369,7 @@ var TokenStore = class {
19376
19369
  const filePath = this.filePath(key);
19377
19370
  try {
19378
19371
  await (0, import_promises.unlink)(filePath);
19379
- log18.debug("Token file cleared", { key, path: filePath });
19372
+ log17.debug("Token file cleared", { key, path: filePath });
19380
19373
  } catch (err) {
19381
19374
  if (err.code !== "ENOENT") {
19382
19375
  throw err;
@@ -19386,15 +19379,17 @@ var TokenStore = class {
19386
19379
  };
19387
19380
 
19388
19381
  // src/auth/token-manager.ts
19389
- var log19 = createLogger("auth/token-manager");
19382
+ var log18 = createLogger("auth/token-manager");
19390
19383
  var DEFAULT_REFRESH_AHEAD_MS = 5 * 60 * 1e3;
19391
19384
  var MAX_RETRIES = 3;
19392
19385
  var RETRY_BASE_MS = 1e3;
19393
19386
  var TokenManager = class {
19394
- oauthClient;
19387
+ sealClient;
19395
19388
  tokenStore;
19396
19389
  /** Token 过期前提前刷新的时间 (ms) */
19397
19390
  refreshAheadMs;
19391
+ /** 自动注册的参数 */
19392
+ autoRegisterParams;
19398
19393
  // ── 内存缓存 ──
19399
19394
  /** 内存中缓存的 access_token */
19400
19395
  cachedToken = null;
@@ -19408,10 +19403,11 @@ var TokenManager = class {
19408
19403
  /** 定时刷新器句柄 */
19409
19404
  refreshTimer = null;
19410
19405
  constructor(deps) {
19411
- this.oauthClient = deps.oauthClient;
19406
+ this.sealClient = deps.sealClient;
19412
19407
  this.tokenStore = deps.tokenStore;
19413
19408
  this.refreshAheadMs = deps.refreshAheadMs ?? DEFAULT_REFRESH_AHEAD_MS;
19414
- log19.info("TokenManager initialized", { refreshAheadMs: this.refreshAheadMs });
19409
+ this.autoRegisterParams = deps.autoRegisterParams;
19410
+ log18.info("TokenManager initialized", { refreshAheadMs: this.refreshAheadMs });
19415
19411
  }
19416
19412
  // ── 核心方法 ──
19417
19413
  /**
@@ -19429,7 +19425,7 @@ var TokenManager = class {
19429
19425
  return this.cachedToken;
19430
19426
  }
19431
19427
  if (this.refreshLock) {
19432
- log19.debug("Waiting for concurrent token acquisition");
19428
+ log18.debug("Waiting for concurrent token acquisition");
19433
19429
  return this.refreshLock;
19434
19430
  }
19435
19431
  this.refreshLock = this._acquireTokenWithRetry();
@@ -19439,6 +19435,13 @@ var TokenManager = class {
19439
19435
  this.refreshLock = null;
19440
19436
  }
19441
19437
  }
19438
+ /**
19439
+ * 令牌自省 — 暂不实现,后续补充。
19440
+ * 返回的 identity_id 用于 gate.ts 的 anti-loop 检查 (bot 自己的 ID)。
19441
+ */
19442
+ async introspect() {
19443
+ throw new Error("introspect() not implemented yet \u2014 Seal introspect API \u6682\u4E0D\u4F7F\u7528");
19444
+ }
19442
19445
  /** 检查当前令牌是否包含指定的 scope */
19443
19446
  hasScope(scope) {
19444
19447
  if (!this.cachedScope) return false;
@@ -19455,13 +19458,13 @@ var TokenManager = class {
19455
19458
  this.cachedToken = null;
19456
19459
  this.cachedScope = null;
19457
19460
  this.currentTokenData = null;
19458
- log19.info("Token revoked and cleared");
19461
+ log18.info("Token revoked and cleared");
19459
19462
  }
19460
19463
  /** 清理定时器和并发锁 — 优雅关闭时调用 */
19461
19464
  shutdown() {
19462
19465
  this.clearRefreshTimer();
19463
19466
  this.refreshLock = null;
19464
- log19.info("TokenManager shutdown");
19467
+ log18.info("TokenManager shutdown");
19465
19468
  }
19466
19469
  // ── 内部方法 ──
19467
19470
  /**
@@ -19469,26 +19472,26 @@ var TokenManager = class {
19469
19472
  *
19470
19473
  * 重试策略:
19471
19474
  * - 网络错误 / 5xx → 重试 (最多 3 次)
19472
- * - 401/403 → 不重试 (凭证可能无效)
19475
+ * - 401/403 → 不重试 (client_secret 可能无效)
19473
19476
  */
19474
19477
  async _acquireTokenWithRetry() {
19475
19478
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
19476
19479
  try {
19477
19480
  return await this._acquireToken();
19478
19481
  } catch (err) {
19479
- if (err instanceof ApiError && (err.status === 401 || err.status === 403)) {
19480
- log19.error("Token acquire failed with auth error, not retrying", { status: err.status });
19482
+ if (err instanceof SealApiError && (err.status === 401 || err.status === 403)) {
19483
+ log18.error("Token acquire failed with auth error, not retrying", { status: err.status });
19481
19484
  throw err;
19482
19485
  }
19483
19486
  if (attempt === MAX_RETRIES) {
19484
- log19.error("Token acquire failed after all retries", { attempts: attempt + 1 });
19487
+ log18.error("Token acquire failed after all retries", { attempts: attempt + 1 });
19485
19488
  throw new TokenAcquireError(
19486
19489
  `Token acquire failed after ${attempt + 1} attempts`,
19487
19490
  { cause: err instanceof Error ? err : void 0 }
19488
19491
  );
19489
19492
  }
19490
19493
  const delay = RETRY_BASE_MS * Math.pow(2, attempt);
19491
- log19.warn("Token acquire failed, retrying", {
19494
+ log18.warn("Token acquire failed, retrying", {
19492
19495
  attempt: attempt + 1,
19493
19496
  maxRetries: MAX_RETRIES,
19494
19497
  retryInMs: delay,
@@ -19504,27 +19507,63 @@ var TokenManager = class {
19504
19507
  *
19505
19508
  * 流程:
19506
19509
  * 1. 尝试从 TokenStore 加载缓存
19507
- * 2. 调用 OAuthClient.getToken() 获取新 Token
19508
- * 3. 保存到内存缓存 + TokenStore
19509
- * 4. 设置定时刷新器
19510
+ * 2. 检查是否需要注册客户端
19511
+ * 3. 调用 SealClient.getToken() 获取新 Token
19512
+ * 4. 保存到内存缓存 + TokenStore
19513
+ * 5. 设置定时刷新器
19510
19514
  */
19511
19515
  async _acquireToken() {
19512
19516
  try {
19513
19517
  const stored = await this.tokenStore.load("token");
19514
19518
  if (stored && !this.isTokenHardExpired(stored)) {
19515
- log19.info("Token loaded from store (still valid)");
19519
+ log18.info("Token loaded from store (still valid)");
19516
19520
  this.updateCache(stored);
19517
19521
  this.scheduleRefresh(stored);
19518
19522
  return stored.accessToken;
19519
19523
  }
19520
19524
  if (stored) {
19521
- log19.info("Stored token has expired, acquiring new one");
19525
+ log18.info("Stored token has expired, acquiring new one");
19522
19526
  }
19523
19527
  } catch {
19524
- log19.warn("Failed to load token from store, acquiring new one");
19528
+ log18.warn("Failed to load token from store, acquiring new one");
19529
+ }
19530
+ if (!this.sealClient.isRegistered()) {
19531
+ try {
19532
+ const savedCreds = await this.tokenStore.load("credentials");
19533
+ if (savedCreds?.clientId && savedCreds?.clientSecret) {
19534
+ this.sealClient.setCredentials(
19535
+ savedCreds.clientId,
19536
+ savedCreds.clientSecret
19537
+ );
19538
+ log18.info("Credentials loaded from store");
19539
+ }
19540
+ } catch {
19541
+ log18.debug("No saved credentials found");
19542
+ }
19543
+ }
19544
+ if (!this.sealClient.isRegistered()) {
19545
+ if (!this.autoRegisterParams) {
19546
+ throw new Error("SealClient not registered and autoRegisterParams not provided. Call setCredentials() or enable autoRegister.");
19547
+ }
19548
+ log18.info("Auto-registering OAuth client");
19549
+ const registration = await this.sealClient.register({
19550
+ clientName: this.autoRegisterParams.clientName,
19551
+ scopes: this.autoRegisterParams.scopes,
19552
+ tokenSettings: this.autoRegisterParams.tokenSettings ? {
19553
+ accessTokenTtl: this.autoRegisterParams.tokenSettings.accessTokenTtl,
19554
+ refreshTokenTtl: this.autoRegisterParams.tokenSettings.refreshTokenTtl,
19555
+ accessTokenFormat: this.autoRegisterParams.tokenSettings.accessTokenFormat
19556
+ } : void 0
19557
+ });
19558
+ await this.tokenStore.save("credentials", {
19559
+ clientId: registration.clientId,
19560
+ clientSecret: registration.clientSecret,
19561
+ clientSecretExpiresAt: registration.clientSecretExpiresAt
19562
+ });
19563
+ log18.info("OAuth client registered and credentials saved");
19525
19564
  }
19526
- log19.info("Acquiring new access token via POST /auth/token");
19527
- const tokenData = await this.oauthClient.getToken();
19565
+ log18.info("Acquiring new access token");
19566
+ const tokenData = await this.sealClient.getToken();
19528
19567
  this.updateCache(tokenData);
19529
19568
  await this.tokenStore.save("token", tokenData);
19530
19569
  this.scheduleRefresh(tokenData);
@@ -19554,22 +19593,22 @@ var TokenManager = class {
19554
19593
  this.clearRefreshTimer();
19555
19594
  const refreshInMs = tokenData.expiresAt - this.refreshAheadMs - Date.now();
19556
19595
  if (refreshInMs <= 0) {
19557
- log19.debug("Token already within refresh window, not scheduling timer");
19596
+ log18.debug("Token already within refresh window, not scheduling timer");
19558
19597
  return;
19559
19598
  }
19560
- log19.debug("Scheduling token refresh", {
19599
+ log18.debug("Scheduling token refresh", {
19561
19600
  refreshInMs,
19562
19601
  refreshAt: new Date(Date.now() + refreshInMs).toISOString()
19563
19602
  });
19564
19603
  this.refreshTimer = setTimeout(async () => {
19565
19604
  try {
19566
- log19.info("Scheduled token refresh triggered");
19605
+ log18.info("Scheduled token refresh triggered");
19567
19606
  this.cachedToken = null;
19568
19607
  this.currentTokenData = null;
19569
19608
  await this.getValidToken();
19570
- log19.info("Scheduled token refresh completed");
19609
+ log18.info("Scheduled token refresh completed");
19571
19610
  } catch (err) {
19572
- log19.error("Scheduled token refresh failed", {
19611
+ log18.error("Scheduled token refresh failed", {
19573
19612
  error: err instanceof Error ? err.message : String(err)
19574
19613
  });
19575
19614
  }
@@ -19597,13 +19636,13 @@ var wrapper_default = import_websocket.default;
19597
19636
 
19598
19637
  // src/transport/ws-client.ts
19599
19638
  var import_node_events = require("events");
19600
- var log20 = createLogger("transport/ws-client");
19639
+ var log19 = createLogger("transport/ws-client");
19601
19640
  var WSClient = class extends import_node_events.EventEmitter {
19602
19641
  /** 底层 WebSocket 实例 */
19603
19642
  ws = null;
19604
19643
  constructor() {
19605
19644
  super();
19606
- log20.info("WSClient initialized");
19645
+ log19.info("WSClient initialized");
19607
19646
  }
19608
19647
  /**
19609
19648
  * 连接到 WebSocket 服务器并绑定事件。
@@ -19619,11 +19658,11 @@ var WSClient = class extends import_node_events.EventEmitter {
19619
19658
  this.ws = null;
19620
19659
  }
19621
19660
  const { url: url2, protocols, headers } = options;
19622
- log20.info("ws:connecting", { url: url2 });
19661
+ log19.info("ws:connecting", { url: url2 });
19623
19662
  return new Promise((resolve2, reject) => {
19624
19663
  const ws = new wrapper_default(url2, protocols, { headers });
19625
19664
  ws.on("open", () => {
19626
- log20.info("ws:connected", { url: url2 });
19665
+ log19.info("ws:connected", { url: url2 });
19627
19666
  this.emit("open");
19628
19667
  resolve2();
19629
19668
  });
@@ -19631,11 +19670,11 @@ var WSClient = class extends import_node_events.EventEmitter {
19631
19670
  this.emit("message", data);
19632
19671
  });
19633
19672
  ws.on("close", (code, reason) => {
19634
- log20.info("ws:closed", { code, reason: reason.toString() });
19673
+ log19.info("ws:closed", { code, reason: reason.toString() });
19635
19674
  this.emit("close", code, reason.toString());
19636
19675
  });
19637
19676
  ws.on("error", (err) => {
19638
- log20.error("ws:error", { error: err.message });
19677
+ log19.error("ws:error", { error: err.message });
19639
19678
  this.emit("error", err);
19640
19679
  if (this.ws !== ws) {
19641
19680
  reject(err);
@@ -19647,7 +19686,7 @@ var WSClient = class extends import_node_events.EventEmitter {
19647
19686
  /** 发送数据到服务器 — 前置检查连接状态 */
19648
19687
  send(data) {
19649
19688
  if (!this.ws || this.ws.readyState !== wrapper_default.OPEN) {
19650
- log20.warn("ws:send skipped, not connected", { readyState: this.ws?.readyState });
19689
+ log19.warn("ws:send skipped, not connected", { readyState: this.ws?.readyState });
19651
19690
  return;
19652
19691
  }
19653
19692
  this.ws.send(data);
@@ -19658,7 +19697,7 @@ var WSClient = class extends import_node_events.EventEmitter {
19658
19697
  this.ws.removeAllListeners();
19659
19698
  this.ws.close(code, reason);
19660
19699
  this.ws = null;
19661
- log20.info("ws:close requested", { code, reason });
19700
+ log19.info("ws:close requested", { code, reason });
19662
19701
  }
19663
19702
  }
19664
19703
  /** 当前连接状态 (0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED) */
@@ -19668,7 +19707,7 @@ var WSClient = class extends import_node_events.EventEmitter {
19668
19707
  };
19669
19708
 
19670
19709
  // src/transport/dedup.ts
19671
- var log21 = createLogger("transport/dedup");
19710
+ var log20 = createLogger("transport/dedup");
19672
19711
  var MessageDedup = class {
19673
19712
  /** 去重缓存生存时间 (ms) */
19674
19713
  ttlMs;
@@ -19679,7 +19718,7 @@ var MessageDedup = class {
19679
19718
  constructor(config2) {
19680
19719
  this.ttlMs = config2?.ttlMs ?? 3e5;
19681
19720
  this.maxEntries = config2?.maxEntries ?? 5e3;
19682
- log21.info("MessageDedup initialized", { ttlMs: this.ttlMs, maxEntries: this.maxEntries });
19721
+ log20.info("MessageDedup initialized", { ttlMs: this.ttlMs, maxEntries: this.maxEntries });
19683
19722
  }
19684
19723
  /**
19685
19724
  * 检查消息是否重复。
@@ -19715,7 +19754,7 @@ var MessageDedup = class {
19715
19754
 
19716
19755
  // src/transport/message-pipe.ts
19717
19756
  var import_node_crypto2 = require("crypto");
19718
- var log22 = createLogger("transport/message-pipe");
19757
+ var log21 = createLogger("transport/message-pipe");
19719
19758
  var MessagePipe = class {
19720
19759
  wsClient;
19721
19760
  dedup;
@@ -19734,15 +19773,15 @@ var MessagePipe = class {
19734
19773
  this.messageServiceBaseUrl = deps.messageServiceBaseUrl;
19735
19774
  this.wsClient.on("message", (rawData) => {
19736
19775
  this.handleInbound(rawData).catch((err) => {
19737
- log22.error("inbound:error", { step: "handleInbound", error: err.message });
19776
+ log21.error("inbound:error", { step: "handleInbound", error: err.message });
19738
19777
  });
19739
19778
  });
19740
- log22.info("MessagePipe initialized");
19779
+ log21.info("MessagePipe initialized");
19741
19780
  }
19742
19781
  /** 注册入站消息回调 — 解密后的消息会通过此回调传给 L4 层 */
19743
19782
  onMessage(callback) {
19744
19783
  this.messageCallback = callback;
19745
- log22.info("Inbound message callback registered");
19784
+ log21.info("Inbound message callback registered");
19746
19785
  }
19747
19786
  /**
19748
19787
  * 出站发送 — 通过 HTTP API 发送消息到 IM 服务器。
@@ -19762,7 +19801,7 @@ var MessagePipe = class {
19762
19801
  }
19763
19802
  const result = await this.callMessageApi("/messages/v1/send", body, "outbound");
19764
19803
  if (!result) return;
19765
- log22.info("outbound:sent", {
19804
+ log21.info("outbound:sent", {
19766
19805
  chatId: msg.chatId,
19767
19806
  senderId: msg.senderId,
19768
19807
  msgType: msg.msgType,
@@ -19786,7 +19825,7 @@ var MessagePipe = class {
19786
19825
  };
19787
19826
  const result = await this.callMessageApi("/messages/v1/recall", body, "recall");
19788
19827
  if (!result) return;
19789
- log22.info("recall:sent", {
19828
+ log21.info("recall:sent", {
19790
19829
  messageId: params.messageId,
19791
19830
  requestId: result.request_id
19792
19831
  });
@@ -19813,7 +19852,7 @@ var MessagePipe = class {
19813
19852
  body: JSON.stringify(body)
19814
19853
  });
19815
19854
  if (!resp.ok) {
19816
- log22.error(`${logTag}:http-error`, {
19855
+ log21.error(`${logTag}:http-error`, {
19817
19856
  status: resp.status,
19818
19857
  statusText: resp.statusText,
19819
19858
  url: url2
@@ -19822,7 +19861,7 @@ var MessagePipe = class {
19822
19861
  }
19823
19862
  const result = await resp.json();
19824
19863
  if (result.code !== 0) {
19825
- log22.error(`${logTag}:api-error`, {
19864
+ log21.error(`${logTag}:api-error`, {
19826
19865
  code: result.code,
19827
19866
  msg: result.msg,
19828
19867
  requestId: result.request_id
@@ -19831,7 +19870,7 @@ var MessagePipe = class {
19831
19870
  }
19832
19871
  return result;
19833
19872
  } catch (err) {
19834
- log22.error(`${logTag}:network-error`, {
19873
+ log21.error(`${logTag}:network-error`, {
19835
19874
  url: url2,
19836
19875
  error: err.message
19837
19876
  });
@@ -19853,7 +19892,7 @@ var MessagePipe = class {
19853
19892
  try {
19854
19893
  frame = JSON.parse(String(rawData));
19855
19894
  } catch (err) {
19856
- log22.warn("inbound:json-parse-error", { error: err.message });
19895
+ log21.warn("inbound:json-parse-error", { error: err.message });
19857
19896
  return;
19858
19897
  }
19859
19898
  const timestamp = frame["X-CTQ-Timestamp"];
@@ -19864,7 +19903,7 @@ var MessagePipe = class {
19864
19903
  const signatureInput = timestamp + nonce + frame.data;
19865
19904
  const expected = (0, import_node_crypto2.createHmac)("sha256", token).update(signatureInput).digest("hex");
19866
19905
  if (expected !== signature) {
19867
- log22.warn("inbound:signature-fail", { timestamp, nonce });
19906
+ log21.warn("inbound:signature-fail", { timestamp, nonce });
19868
19907
  return;
19869
19908
  }
19870
19909
  }
@@ -19878,37 +19917,30 @@ var MessagePipe = class {
19878
19917
  try {
19879
19918
  callbackData = JSON.parse(dataStr);
19880
19919
  } catch (err) {
19881
- log22.warn("inbound:data-parse-error", { error: err.message });
19920
+ log21.warn("inbound:data-parse-error", { error: err.message });
19882
19921
  return;
19883
19922
  }
19884
- if (callbackData.eventType !== "callback:direct") {
19885
- log22.debug("inbound:event-ignored", { eventType: callbackData.eventType });
19923
+ if (callbackData.eventType !== "MessageReceived") {
19924
+ log21.debug("inbound:event-ignored", { eventType: callbackData.eventType });
19886
19925
  return;
19887
19926
  }
19888
- const msg = {
19889
- messageId: callbackData.msgUid,
19890
- chatId: callbackData.groupId || callbackData.userId,
19891
- senderId: callbackData.userId,
19892
- msgType: callbackData.type,
19893
- content: JSON.stringify(callbackData.content),
19894
- timestamp: Date.now()
19895
- };
19896
- log22.debug("inbound:frame", { messageId: msg.messageId, eventType: callbackData.eventType });
19927
+ const msg = callbackData.content;
19928
+ log21.debug("inbound:frame", { messageId: msg.messageId, eventType: callbackData.eventType });
19897
19929
  if (this.dedup.isDuplicate(msg.messageId)) {
19898
- log22.debug("inbound:dedup-hit", { messageId: msg.messageId });
19930
+ log21.debug("inbound:dedup-hit", { messageId: msg.messageId });
19899
19931
  return;
19900
19932
  }
19901
- log22.info("inbound:verified", { messageId: msg.messageId, chatId: msg.chatId });
19933
+ log21.info("inbound:verified", { messageId: msg.messageId, chatId: msg.chatId });
19902
19934
  if (this.messageCallback) {
19903
19935
  this.messageCallback(msg);
19904
19936
  } else {
19905
- log22.warn("inbound:no-callback", { messageId: msg.messageId });
19937
+ log21.warn("inbound:no-callback", { messageId: msg.messageId });
19906
19938
  }
19907
19939
  }
19908
19940
  };
19909
19941
 
19910
19942
  // src/transport/connection-manager.ts
19911
- var log23 = createLogger("transport/connection-manager");
19943
+ var log22 = createLogger("transport/connection-manager");
19912
19944
  function sleep2(ms) {
19913
19945
  return new Promise((resolve2) => setTimeout(resolve2, ms));
19914
19946
  }
@@ -19938,7 +19970,7 @@ var ConnectionManager = class {
19938
19970
  reconnectMaxMs: options?.reconnectMaxMs ?? 6e4,
19939
19971
  maxReconnectAttempts: options?.maxReconnectAttempts ?? 10
19940
19972
  };
19941
- log23.info("ConnectionManager initialized", this.options);
19973
+ log22.info("ConnectionManager initialized", this.options);
19942
19974
  }
19943
19975
  /**
19944
19976
  * 启动连接 — 连接 WS + 开始心跳 + 注册重连逻辑
@@ -19953,33 +19985,29 @@ var ConnectionManager = class {
19953
19985
  this.running = true;
19954
19986
  this.reconnectAttempts = 0;
19955
19987
  const token = await tokenFn();
19956
- const wsUrl = url2.replace(/\/+$/, "") + "/events/stream";
19957
19988
  await this.client.connect({
19958
- url: wsUrl,
19989
+ url: url2,
19959
19990
  token,
19960
- headers: {
19961
- "Authorization": token,
19962
- ...this.appId ? { "X-App-ID": this.appId } : {}
19963
- }
19991
+ headers: this.appId ? { "X-App-ID": this.appId } : void 0
19964
19992
  });
19965
19993
  this.client.on("close", () => {
19966
19994
  if (this.running) {
19967
- log23.warn("ws:disconnected, scheduling reconnect");
19995
+ log22.warn("ws:disconnected, scheduling reconnect");
19968
19996
  this.scheduleReconnect();
19969
19997
  }
19970
19998
  });
19971
19999
  this.client.on("error", (err) => {
19972
- log23.error("ws:connection-error", { error: err.message });
20000
+ log22.error("ws:connection-error", { error: err.message });
19973
20001
  });
19974
20002
  this.startHeartbeat();
19975
- log23.info("ConnectionManager started \u2713", { url: url2 });
20003
+ log22.info("ConnectionManager started \u2713", { url: url2 });
19976
20004
  }
19977
20005
  /** 启动心跳保活 — 定时检查连接状态 */
19978
20006
  startHeartbeat() {
19979
20007
  this.stopHeartbeat();
19980
20008
  this.heartbeatTimer = setInterval(() => {
19981
20009
  if (this.client.readyState !== wrapper_default.OPEN) {
19982
- log23.warn("heartbeat: connection not open, scheduling reconnect");
20010
+ log22.warn("heartbeat: connection not open, scheduling reconnect");
19983
20011
  this.scheduleReconnect();
19984
20012
  }
19985
20013
  }, this.options.heartbeatIntervalMs);
@@ -20007,34 +20035,30 @@ var ConnectionManager = class {
20007
20035
  this.options.reconnectBaseMs * 2 ** this.reconnectAttempts,
20008
20036
  this.options.reconnectMaxMs
20009
20037
  );
20010
- log23.info("ws:reconnecting", { attempt: this.reconnectAttempts + 1, delayMs: delay });
20038
+ log22.info("ws:reconnecting", { attempt: this.reconnectAttempts + 1, delayMs: delay });
20011
20039
  await sleep2(delay);
20012
20040
  if (!this.running) return;
20013
20041
  this.reconnectAttempts++;
20014
20042
  try {
20015
20043
  const token = await this.tokenFn();
20016
- const wsUrl = this.url.replace(/\/+$/, "") + "/events/stream";
20017
20044
  await this.client.connect({
20018
- url: wsUrl,
20045
+ url: this.url,
20019
20046
  token,
20020
- headers: {
20021
- "Authorization": token,
20022
- ...this.appId ? { "X-App-ID": this.appId } : {}
20023
- }
20047
+ headers: this.appId ? { "X-App-ID": this.appId } : void 0
20024
20048
  });
20025
20049
  this.reconnectAttempts = 0;
20026
20050
  this.startHeartbeat();
20027
- log23.info("ws:reconnected", { attempt: this.reconnectAttempts, url: this.url });
20051
+ log22.info("ws:reconnected", { attempt: this.reconnectAttempts, url: this.url });
20028
20052
  return;
20029
20053
  } catch (err) {
20030
- log23.warn("ws:reconnect-failed", {
20054
+ log22.warn("ws:reconnect-failed", {
20031
20055
  attempt: this.reconnectAttempts,
20032
20056
  error: err.message
20033
20057
  });
20034
20058
  }
20035
20059
  }
20036
20060
  if (this.running) {
20037
- log23.error("ws:max-reconnect-reached", {
20061
+ log22.error("ws:max-reconnect-reached", {
20038
20062
  maxAttempts: this.options.maxReconnectAttempts
20039
20063
  });
20040
20064
  }
@@ -20044,7 +20068,7 @@ var ConnectionManager = class {
20044
20068
  this.running = false;
20045
20069
  this.stopHeartbeat();
20046
20070
  this.client.close(1e3, "shutdown");
20047
- log23.info("ConnectionManager stopped");
20071
+ log22.info("ConnectionManager stopped");
20048
20072
  }
20049
20073
  /** 当前是否已连接 (WebSocket readyState === OPEN) */
20050
20074
  get isConnected() {
@@ -20053,7 +20077,7 @@ var ConnectionManager = class {
20053
20077
  };
20054
20078
 
20055
20079
  // src/push/cockatoo-client.ts
20056
- var log24 = createLogger("push/cockatoo-client");
20080
+ var log23 = createLogger("push/cockatoo-client");
20057
20081
  var DEFAULT_TIMEOUT_MS2 = 3e4;
20058
20082
  var CockatooPushError = class extends Error {
20059
20083
  constructor(status, body, endpoint) {
@@ -20087,7 +20111,7 @@ var CockatooClient = class {
20087
20111
  const base = config2.endpoint.replace(/\/+$/, "");
20088
20112
  this.pushUrl = `${base}/api/v1/push`;
20089
20113
  this.healthUrl = `${base}/health`;
20090
- log24.info("CockatooClient initialized", { endpoint: config2.endpoint });
20114
+ log23.info("CockatooClient initialized", { endpoint: config2.endpoint });
20091
20115
  }
20092
20116
  /**
20093
20117
  * 推送消息到 Cockatoo 服务。
@@ -20118,7 +20142,7 @@ var CockatooClient = class {
20118
20142
  }
20119
20143
  throw new CockatooPushError(resp.status, body, this.pushUrl);
20120
20144
  }
20121
- log24.debug("push:sent", { type: payload.type });
20145
+ log23.debug("push:sent", { type: payload.type });
20122
20146
  }
20123
20147
  /**
20124
20148
  * 执行一次健康检查。
@@ -20136,11 +20160,11 @@ var CockatooClient = class {
20136
20160
  });
20137
20161
  const isHealthy = resp.ok;
20138
20162
  if (!isHealthy) {
20139
- log24.warn("health-check:unhealthy", { status: resp.status });
20163
+ log23.warn("health-check:unhealthy", { status: resp.status });
20140
20164
  }
20141
20165
  return isHealthy;
20142
20166
  } catch (err) {
20143
- log24.warn("health-check:error", { error: err.message });
20167
+ log23.warn("health-check:error", { error: err.message });
20144
20168
  return false;
20145
20169
  }
20146
20170
  }
@@ -20152,7 +20176,7 @@ var CockatooClient = class {
20152
20176
  this.healthy = await this.healthCheck();
20153
20177
  } catch {
20154
20178
  this.healthy = false;
20155
- log24.warn("Cockatoo health check failed");
20179
+ log23.warn("Cockatoo health check failed");
20156
20180
  }
20157
20181
  }, this.config.healthCheckIntervalMs ?? 6e4);
20158
20182
  if (typeof this.healthCheckTimer === "object" && "unref" in this.healthCheckTimer) {
@@ -20173,7 +20197,7 @@ var CockatooClient = class {
20173
20197
  };
20174
20198
 
20175
20199
  // src/push/push-queue.ts
20176
- var log25 = createLogger("push/push-queue");
20200
+ var log24 = createLogger("push/push-queue");
20177
20201
  var RETRY_BASE_MS2 = 1e3;
20178
20202
  var PushQueue = class {
20179
20203
  client;
@@ -20215,7 +20239,7 @@ var PushQueue = class {
20215
20239
  this.unhealthyRetryMs = config2?.unhealthyRetryMs ?? 5e3;
20216
20240
  this.drainOnStop = config2?.drainOnStop ?? false;
20217
20241
  this.drainTimeoutMs = config2?.drainTimeoutMs ?? 5e3;
20218
- log25.info("PushQueue initialized", {
20242
+ log24.info("PushQueue initialized", {
20219
20243
  maxSize: this.maxSize,
20220
20244
  retryAttempts: this.retryAttempts,
20221
20245
  processIntervalMs: this.processIntervalMs
@@ -20226,7 +20250,7 @@ var PushQueue = class {
20226
20250
  start() {
20227
20251
  if (this.running) return;
20228
20252
  this.running = true;
20229
- log25.info("PushQueue started");
20253
+ log24.info("PushQueue started");
20230
20254
  this.scheduleNext(0);
20231
20255
  }
20232
20256
  /**
@@ -20240,10 +20264,10 @@ var PushQueue = class {
20240
20264
  this.running = false;
20241
20265
  this.clearTimer();
20242
20266
  if (this.drainOnStop && this.queue.length > 0) {
20243
- log25.info("PushQueue draining", { remaining: this.queue.length });
20267
+ log24.info("PushQueue draining", { remaining: this.queue.length });
20244
20268
  await this.drain();
20245
20269
  }
20246
- log25.info("PushQueue stopped", {
20270
+ log24.info("PushQueue stopped", {
20247
20271
  remaining: this.queue.length,
20248
20272
  sent: this.sentCount,
20249
20273
  dropped: this.droppedCount,
@@ -20258,13 +20282,13 @@ var PushQueue = class {
20258
20282
  if (this.queue.length >= this.maxSize) {
20259
20283
  const dropped = this.queue.shift();
20260
20284
  this.droppedCount++;
20261
- log25.warn("queue:full, dropping oldest", {
20285
+ log24.warn("queue:full, dropping oldest", {
20262
20286
  droppedType: dropped?.payload.type,
20263
20287
  queueSize: this.queue.length
20264
20288
  });
20265
20289
  }
20266
20290
  this.queue.push({ payload, retries: 0, eligibleAt: 0 });
20267
- log25.debug("queue:enqueued", { type: payload.type, queueSize: this.queue.length });
20291
+ log24.debug("queue:enqueued", { type: payload.type, queueSize: this.queue.length });
20268
20292
  }
20269
20293
  /** 当前队列长度 */
20270
20294
  get size() {
@@ -20289,7 +20313,7 @@ var PushQueue = class {
20289
20313
  this.clearTimer();
20290
20314
  this.processTimer = setTimeout(() => {
20291
20315
  this.tick().catch((err) => {
20292
- log25.error("tick:unexpected-error", { error: err.message });
20316
+ log24.error("tick:unexpected-error", { error: err.message });
20293
20317
  if (this.running) {
20294
20318
  this.scheduleNext(this.idleIntervalMs);
20295
20319
  }
@@ -20311,7 +20335,7 @@ var PushQueue = class {
20311
20335
  async tick() {
20312
20336
  if (!this.running) return;
20313
20337
  if (!this.client.isHealthy) {
20314
- log25.debug("tick:service-unhealthy, pausing");
20338
+ log24.debug("tick:service-unhealthy, pausing");
20315
20339
  this.scheduleNext(this.unhealthyRetryMs);
20316
20340
  return;
20317
20341
  }
@@ -20331,7 +20355,7 @@ var PushQueue = class {
20331
20355
  try {
20332
20356
  await this.processItem(item);
20333
20357
  } catch (err) {
20334
- log25.error("tick:process-unexpected", { error: err.message });
20358
+ log24.error("tick:process-unexpected", { error: err.message });
20335
20359
  } finally {
20336
20360
  this.processing = false;
20337
20361
  }
@@ -20350,14 +20374,14 @@ var PushQueue = class {
20350
20374
  try {
20351
20375
  await this.client.push(item.payload);
20352
20376
  this.sentCount++;
20353
- log25.debug("push:success", {
20377
+ log24.debug("push:success", {
20354
20378
  type: item.payload.type,
20355
20379
  retries: item.retries
20356
20380
  });
20357
20381
  } catch (err) {
20358
20382
  if (err instanceof CockatooPushError && err.isClientError) {
20359
20383
  this.droppedCount++;
20360
- log25.warn("push:4xx-dropped", {
20384
+ log24.warn("push:4xx-dropped", {
20361
20385
  type: item.payload.type,
20362
20386
  status: err.status,
20363
20387
  retries: item.retries
@@ -20366,7 +20390,7 @@ var PushQueue = class {
20366
20390
  }
20367
20391
  if (item.retries >= this.retryAttempts) {
20368
20392
  this.droppedCount++;
20369
- log25.error("push:max-retries-dropped", {
20393
+ log24.error("push:max-retries-dropped", {
20370
20394
  type: item.payload.type,
20371
20395
  retries: item.retries,
20372
20396
  error: err.message
@@ -20379,7 +20403,7 @@ var PushQueue = class {
20379
20403
  item.eligibleAt = Date.now() + backoffMs;
20380
20404
  this.queue.push(item);
20381
20405
  const errorDetail = err instanceof CockatooPushError ? `HTTP ${err.status}` : err.message;
20382
- log25.warn("push:retry-enqueued", {
20406
+ log24.warn("push:retry-enqueued", {
20383
20407
  type: item.payload.type,
20384
20408
  retries: item.retries,
20385
20409
  backoffMs,
@@ -20403,22 +20427,22 @@ var PushQueue = class {
20403
20427
  try {
20404
20428
  await this.client.push(item.payload);
20405
20429
  this.sentCount++;
20406
- log25.debug("drain:sent", { type: item.payload.type });
20430
+ log24.debug("drain:sent", { type: item.payload.type });
20407
20431
  } catch (err) {
20408
20432
  this.droppedCount++;
20409
- log25.warn("drain:dropped", {
20433
+ log24.warn("drain:dropped", {
20410
20434
  type: item.payload.type,
20411
20435
  error: err.message
20412
20436
  });
20413
20437
  }
20414
20438
  }
20415
20439
  if (this.queue.length > 0) {
20416
- log25.warn("drain:timeout", {
20440
+ log24.warn("drain:timeout", {
20417
20441
  remaining: this.queue.length,
20418
20442
  timeoutMs: this.drainTimeoutMs
20419
20443
  });
20420
20444
  } else {
20421
- log25.info("drain:complete");
20445
+ log24.info("drain:complete");
20422
20446
  }
20423
20447
  }
20424
20448
  // ── 内部工具 ──
@@ -20432,32 +20456,43 @@ var PushQueue = class {
20432
20456
  };
20433
20457
 
20434
20458
  // src/index.ts
20435
- var log26 = createLogger("plugin");
20459
+ var log25 = createLogger("plugin");
20436
20460
  async function startPlugin(accountConfig, internalOverrides) {
20437
20461
  const config2 = buildPluginConfig(accountConfig, internalOverrides);
20438
- log26.info("Config built \u2713", { pluginId: config2.pluginId });
20462
+ log25.info("Config built \u2713", { pluginId: config2.pluginId });
20439
20463
  let cryptoEngine;
20440
20464
  if (config2.crypto.enabled) {
20441
- cryptoEngine = new CryptoEngine({ credentials: accountConfig });
20465
+ cryptoEngine = new CryptoEngine();
20442
20466
  await cryptoEngine.init();
20443
- log26.info("Crypto initialized \u2713");
20467
+ log25.info("Crypto initialized \u2713");
20444
20468
  } else {
20445
20469
  cryptoEngine = CryptoEngine.createPassthrough();
20446
- log26.info("Crypto passthrough mode \u2713 (disabled by config)");
20447
- }
20448
- const oauthClient = new OAuthClient({
20449
- baseUrl: config2.auth.serverUrl,
20450
- appId: accountConfig.appId,
20451
- appSecret: accountConfig.appSecret
20470
+ log25.info("Crypto passthrough mode \u2713 (disabled by config)");
20471
+ }
20472
+ const sealClient = new SealClient({
20473
+ serverUrl: config2.auth.serverUrl,
20474
+ clientName: config2.auth.clientName,
20475
+ clientId: config2.auth.clientId,
20476
+ clientSecret: config2.auth.clientSecret,
20477
+ scopes: config2.auth.scopes
20452
20478
  });
20453
- const tokenStorePath = (0, import_node_path3.join)((0, import_node_os.homedir)(), TOKEN_STORE_DIR, "tokens");
20479
+ const tokenStorePath = (0, import_node_path2.join)((0, import_node_os.homedir)(), TOKEN_STORE_DIR, "tokens");
20454
20480
  const tokenStore = new TokenStore(tokenStorePath, cryptoEngine);
20455
20481
  const tokenManager = new TokenManager({
20456
- oauthClient,
20482
+ sealClient,
20457
20483
  tokenStore,
20458
- refreshAheadMs: config2.auth.refreshAheadMs
20484
+ refreshAheadMs: config2.auth.refreshAheadMs,
20485
+ autoRegisterParams: config2.auth.autoRegister ? {
20486
+ clientName: config2.auth.clientName,
20487
+ scopes: config2.auth.scopes,
20488
+ tokenSettings: config2.auth.tokenSettings ? {
20489
+ accessTokenTtl: config2.auth.tokenSettings.accessTokenTtl,
20490
+ refreshTokenTtl: config2.auth.tokenSettings.refreshTokenTtl,
20491
+ accessTokenFormat: config2.auth.tokenSettings.accessTokenFormat
20492
+ } : void 0
20493
+ } : void 0
20459
20494
  });
20460
- log26.info("Auth initialized \u2713");
20495
+ log25.info("Auth initialized \u2713");
20461
20496
  let pushQueue = null;
20462
20497
  let cockatooClient = null;
20463
20498
  if (config2.push?.enabled) {
@@ -20472,7 +20507,7 @@ async function startPlugin(accountConfig, internalOverrides) {
20472
20507
  });
20473
20508
  cockatooClient.startHealthCheck();
20474
20509
  pushQueue.start();
20475
- log26.info("Push initialized \u2713");
20510
+ log25.info("Push initialized \u2713");
20476
20511
  }
20477
20512
  const wsClient = new WSClient();
20478
20513
  const dedup = new MessageDedup(config2.transport.dedup);
@@ -20490,8 +20525,8 @@ async function startPlugin(accountConfig, internalOverrides) {
20490
20525
  reconnectMaxMs: config2.transport.reconnectMaxMs,
20491
20526
  maxReconnectAttempts: config2.transport.maxReconnectAttempts
20492
20527
  });
20493
- log26.info("Transport initialized \u2713");
20494
- log26.info("Plugin started \u2713");
20528
+ log25.info("Transport initialized \u2713");
20529
+ log25.info("Plugin started \u2713");
20495
20530
  return {
20496
20531
  config: config2,
20497
20532
  messagePipe,
@@ -20499,22 +20534,22 @@ async function startPlugin(accountConfig, internalOverrides) {
20499
20534
  tokenManager,
20500
20535
  pushQueue,
20501
20536
  shutdown: async () => {
20502
- log26.info("Shutting down...");
20537
+ log25.info("Shutting down...");
20503
20538
  await connectionManager.stop();
20504
20539
  if (pushQueue) await pushQueue.stop();
20505
20540
  if (cockatooClient) cockatooClient.stopHealthCheck();
20506
20541
  tokenManager.shutdown();
20507
- log26.info("Shutdown complete \u2713");
20542
+ log25.info("Shutdown complete \u2713");
20508
20543
  }
20509
20544
  };
20510
20545
  }
20511
20546
  var plugin = {
20512
- id: CHANNEL_ID,
20547
+ id: PLUGIN_ID,
20513
20548
  name: "\u91CF\u5B50\u5BC6\u4FE1",
20514
20549
  description: "Quantum-encrypted IM channel plugin",
20515
20550
  register(api) {
20516
20551
  api.registerChannel({ plugin: quantumImPlugin });
20517
- log26.info("plugin registered \u2713");
20552
+ log25.info("plugin registered \u2713");
20518
20553
  }
20519
20554
  };
20520
20555
  var index_default = plugin;