liangzimixin 0.3.69 → 0.3.71
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 +161 -73
- package/dist/index.d.cts +12 -6
- package/dist/setup-entry.cjs +161 -73
- package/package.json +1 -1
- package/scripts/liangzimixin_install.bat +107 -93
- package/scripts/liangzimixin_install.sh +45 -23
package/dist/index.cjs
CHANGED
|
@@ -18488,12 +18488,25 @@ async function resolveAndUploadMedia(params) {
|
|
|
18488
18488
|
timeoutMs
|
|
18489
18489
|
});
|
|
18490
18490
|
} catch (err) {
|
|
18491
|
-
|
|
18491
|
+
const errMsg = err.message;
|
|
18492
|
+
log5.warn("media:upload failed, \u964D\u7EA7\u5904\u7406", { error: errMsg });
|
|
18493
|
+
try {
|
|
18494
|
+
const tipText = "\u26A0\uFE0F \u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
18495
|
+
await messagePipe.sendMessage({
|
|
18496
|
+
chatId,
|
|
18497
|
+
senderId: chatId,
|
|
18498
|
+
msgType: "text",
|
|
18499
|
+
content: JSON.stringify({ content: tipText }),
|
|
18500
|
+
skipEncrypt: true
|
|
18501
|
+
});
|
|
18502
|
+
} catch (tipErr) {
|
|
18503
|
+
log5.warn("media:upload-failed tip send error", { error: tipErr.message });
|
|
18504
|
+
}
|
|
18492
18505
|
return {
|
|
18493
18506
|
channel: CHANNEL_ID,
|
|
18494
18507
|
messageId: "",
|
|
18495
18508
|
chatId,
|
|
18496
|
-
warning: `\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: ${
|
|
18509
|
+
warning: `\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: ${errMsg}`
|
|
18497
18510
|
};
|
|
18498
18511
|
}
|
|
18499
18512
|
const msgType = fileType;
|
|
@@ -18519,7 +18532,7 @@ async function resolveAndUploadMedia(params) {
|
|
|
18519
18532
|
content: JSON.stringify(contentPayload),
|
|
18520
18533
|
skipEncrypt: params.skipEncrypt,
|
|
18521
18534
|
encryptionMeta
|
|
18522
|
-
// 文件加密的 keyId/iv → sendMessage 用于构建
|
|
18535
|
+
// 文件加密的 keyId/iv → sendMessage 用于构建 extraContent
|
|
18523
18536
|
});
|
|
18524
18537
|
log5.info("media:sent", {
|
|
18525
18538
|
chatId,
|
|
@@ -18759,6 +18772,10 @@ var quantumImOutbound = {
|
|
|
18759
18772
|
/** 发送文本消息 — 通过 messagePipe 发送 */
|
|
18760
18773
|
sendText: async ({ cfg, to, text, accountId }) => {
|
|
18761
18774
|
log7.info("sendText called", { to, textLength: text.length });
|
|
18775
|
+
if (!text?.trim()) {
|
|
18776
|
+
log7.warn("outbound:sendText skipped \u2014 empty text", { to });
|
|
18777
|
+
return { channel: CHANNEL_ID, messageId: "", chatId: to };
|
|
18778
|
+
}
|
|
18762
18779
|
if (!messagePipeGetter) {
|
|
18763
18780
|
log7.error("outbound:sendText failed, messagePipe not initialized");
|
|
18764
18781
|
return { channel: CHANNEL_ID, messageId: "", chatId: to };
|
|
@@ -19121,19 +19138,27 @@ function createQuantumImDeliverFn(deps) {
|
|
|
19121
19138
|
const hasMedia = mediaUrls.length > 0;
|
|
19122
19139
|
if (!hasText && !hasMedia) return;
|
|
19123
19140
|
if (hasText) {
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
19133
|
-
|
|
19134
|
-
|
|
19135
|
-
|
|
19136
|
-
|
|
19141
|
+
try {
|
|
19142
|
+
await messagePipe.sendMessage({
|
|
19143
|
+
chatId,
|
|
19144
|
+
senderId,
|
|
19145
|
+
msgType: resolveTextMsgType(payload.text),
|
|
19146
|
+
content: JSON.stringify({ content: payload.text }),
|
|
19147
|
+
replyToMessageId,
|
|
19148
|
+
skipEncrypt: shouldSkipEncrypt
|
|
19149
|
+
});
|
|
19150
|
+
log14.info("\u{1F4E4} AI \u6587\u672C\u56DE\u590D\u5DF2\u53D1\u9001", {
|
|
19151
|
+
chatId,
|
|
19152
|
+
\u957F\u5EA6: payload.text.length,
|
|
19153
|
+
\u56DE\u590D\u9884\u89C8: payload.text.slice(0, 200)
|
|
19154
|
+
});
|
|
19155
|
+
} catch (err) {
|
|
19156
|
+
log14.error("\u{1F4E4} AI \u6587\u672C\u56DE\u590D\u53D1\u9001\u5931\u8D25", {
|
|
19157
|
+
chatId,
|
|
19158
|
+
error: err.message
|
|
19159
|
+
});
|
|
19160
|
+
if (!hasMedia) throw err;
|
|
19161
|
+
}
|
|
19137
19162
|
}
|
|
19138
19163
|
if (hasMedia) {
|
|
19139
19164
|
for (const mediaUrl of mediaUrls) {
|
|
@@ -19425,6 +19450,21 @@ var InboundPipeline = class {
|
|
|
19425
19450
|
stack: err.stack,
|
|
19426
19451
|
durationMs
|
|
19427
19452
|
});
|
|
19453
|
+
try {
|
|
19454
|
+
const errorTip = "\u26A0\uFE0F \u6D88\u606F\u5904\u7406\u9047\u5230\u95EE\u9898\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002\u5982\u95EE\u9898\u6301\u7EED\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002";
|
|
19455
|
+
await this.deps.messagePipe.sendMessage({
|
|
19456
|
+
chatId: msg.chatId,
|
|
19457
|
+
senderId: msg.senderId,
|
|
19458
|
+
msgType: resolveTextMsgType(errorTip),
|
|
19459
|
+
content: JSON.stringify({ content: errorTip }),
|
|
19460
|
+
skipEncrypt: true
|
|
19461
|
+
// 系统提示消息不加密,避免加密失败导致的死循环
|
|
19462
|
+
});
|
|
19463
|
+
} catch (tipErr) {
|
|
19464
|
+
log15.warn("\u26A0\uFE0F \u9519\u8BEF\u63D0\u793A\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF08\u907F\u514D\u6B7B\u5FAA\u73AF\uFF0C\u4E0D\u518D\u91CD\u8BD5\uFF09", {
|
|
19465
|
+
error: tipErr.message
|
|
19466
|
+
});
|
|
19467
|
+
}
|
|
19428
19468
|
clearInboundEncryptionStatus(msg.chatId, msg.messageId);
|
|
19429
19469
|
} finally {
|
|
19430
19470
|
semaphore.release();
|
|
@@ -20918,7 +20958,7 @@ var CallbackDataSchema = external_exports.object({
|
|
|
20918
20958
|
msgUid: external_exports.string(),
|
|
20919
20959
|
type: external_exports.string(),
|
|
20920
20960
|
content: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
20921
|
-
|
|
20961
|
+
extraContent: external_exports.string().optional()
|
|
20922
20962
|
});
|
|
20923
20963
|
var MessagePipe = class _MessagePipe {
|
|
20924
20964
|
wsClient;
|
|
@@ -21035,8 +21075,8 @@ var MessagePipe = class _MessagePipe {
|
|
|
21035
21075
|
/** 文件类消息类型集合 — 这些类型的加密消息保留原始 content(文件元数据) */
|
|
21036
21076
|
static FILE_MSG_TYPES = /* @__PURE__ */ new Set(["image", "file", "voice", "video"]);
|
|
21037
21077
|
/**
|
|
21038
|
-
* 构建文件类加密消息的
|
|
21039
|
-
* 文件消息不加密 content(需要保留 fileId 等元数据),只在
|
|
21078
|
+
* 构建文件类加密消息的 extraContent — 完整模板格式。
|
|
21079
|
+
* 文件消息不加密 content(需要保留 fileId 等元数据),只在 extraContent 中携带会话信息。
|
|
21040
21080
|
*/
|
|
21041
21081
|
static buildFileEncryptExtra(iv, keyId) {
|
|
21042
21082
|
return JSON.stringify({
|
|
@@ -21068,27 +21108,27 @@ var MessagePipe = class _MessagePipe {
|
|
|
21068
21108
|
*
|
|
21069
21109
|
* 文件类消息 (image/file/voice/video):
|
|
21070
21110
|
* - content 保留原始文件元数据(fileId、fileName、size 等)
|
|
21071
|
-
* -
|
|
21111
|
+
* - extraContent 使用完整模板格式,encryptMsg 为空
|
|
21072
21112
|
*
|
|
21073
21113
|
* 文本类消息 (text/markdown):
|
|
21074
|
-
* - content 加密后置空,密文放入
|
|
21114
|
+
* - content 加密后置空,密文放入 extraContent.encryptMsg
|
|
21075
21115
|
*/
|
|
21076
21116
|
async sendMessage(msg) {
|
|
21077
21117
|
let content = msg.content;
|
|
21078
|
-
let
|
|
21118
|
+
let extraContent = "";
|
|
21079
21119
|
const isFileMessage = _MessagePipe.FILE_MSG_TYPES.has(msg.msgType);
|
|
21080
21120
|
if (!msg.skipEncrypt && this.quantumAccount) {
|
|
21081
21121
|
if (this.encryptionMode === "quantum_only") {
|
|
21082
21122
|
if (isFileMessage && msg.encryptionMeta) {
|
|
21083
|
-
|
|
21123
|
+
extraContent = _MessagePipe.buildFileEncryptExtra(msg.encryptionMeta.iv, msg.encryptionMeta.keyId);
|
|
21084
21124
|
log25.debug("\u{1F512} \u51FA\u7AD9\u6587\u4EF6\u6D88\u606F\u5DF2\u6807\u8BB0\u52A0\u5BC6 (quantum_only)", { sessionId: msg.encryptionMeta.keyId, msgType: msg.msgType });
|
|
21085
21125
|
} else if (isFileMessage) {
|
|
21086
21126
|
const { keyId, iv } = await this.crypto.encrypt(msg.content);
|
|
21087
|
-
|
|
21127
|
+
extraContent = _MessagePipe.buildFileEncryptExtra(iv, keyId);
|
|
21088
21128
|
log25.debug("\u{1F512} \u51FA\u7AD9\u6587\u4EF6\u6D88\u606F\u5DF2\u6807\u8BB0\u52A0\u5BC6 (quantum_only, fallback)", { sessionId: keyId, msgType: msg.msgType });
|
|
21089
21129
|
} else {
|
|
21090
21130
|
const { ciphertext, keyId, iv } = await this.crypto.encrypt(msg.content);
|
|
21091
|
-
|
|
21131
|
+
extraContent = JSON.stringify({
|
|
21092
21132
|
cryptoIv: iv,
|
|
21093
21133
|
encryptMsg: ciphertext,
|
|
21094
21134
|
sessionId: keyId
|
|
@@ -21099,15 +21139,15 @@ var MessagePipe = class _MessagePipe {
|
|
|
21099
21139
|
} else {
|
|
21100
21140
|
try {
|
|
21101
21141
|
if (isFileMessage && msg.encryptionMeta) {
|
|
21102
|
-
|
|
21142
|
+
extraContent = _MessagePipe.buildFileEncryptExtra(msg.encryptionMeta.iv, msg.encryptionMeta.keyId);
|
|
21103
21143
|
log25.debug("\u{1F512} \u51FA\u7AD9\u6587\u4EF6\u6D88\u606F\u5DF2\u6807\u8BB0\u52A0\u5BC6 (quantum_and_plain)", { sessionId: msg.encryptionMeta.keyId, msgType: msg.msgType });
|
|
21104
21144
|
} else if (isFileMessage) {
|
|
21105
21145
|
const { keyId, iv } = await this.crypto.encrypt(msg.content);
|
|
21106
|
-
|
|
21146
|
+
extraContent = _MessagePipe.buildFileEncryptExtra(iv, keyId);
|
|
21107
21147
|
log25.debug("\u{1F512} \u51FA\u7AD9\u6587\u4EF6\u6D88\u606F\u5DF2\u6807\u8BB0\u52A0\u5BC6 (quantum_and_plain, fallback)", { sessionId: keyId, msgType: msg.msgType });
|
|
21108
21148
|
} else {
|
|
21109
21149
|
const { ciphertext, keyId, iv } = await this.crypto.encrypt(msg.content);
|
|
21110
|
-
|
|
21150
|
+
extraContent = JSON.stringify({
|
|
21111
21151
|
cryptoIv: iv,
|
|
21112
21152
|
encryptMsg: ciphertext,
|
|
21113
21153
|
sessionId: keyId
|
|
@@ -21136,17 +21176,19 @@ var MessagePipe = class _MessagePipe {
|
|
|
21136
21176
|
msg_type: msg.msgType,
|
|
21137
21177
|
content
|
|
21138
21178
|
};
|
|
21139
|
-
if (
|
|
21140
|
-
body.
|
|
21179
|
+
if (extraContent) {
|
|
21180
|
+
body.extraContent = extraContent;
|
|
21141
21181
|
}
|
|
21142
21182
|
if (msg.replyToMessageId) {
|
|
21143
21183
|
body.reply_msg_id = msg.replyToMessageId;
|
|
21144
21184
|
}
|
|
21145
21185
|
const result = await this.callMessageApi("/messages/v1/send", body, "outbound");
|
|
21146
|
-
if (!result)
|
|
21186
|
+
if (!result) {
|
|
21187
|
+
throw new Error(`\u6D88\u606F\u53D1\u9001\u5931\u8D25: POST ${this.messageServiceBaseUrl}/messages/v1/send \u672A\u8FD4\u56DE\u6709\u6548\u54CD\u5E94`);
|
|
21188
|
+
}
|
|
21147
21189
|
log25.info("\u{1F4E4} outbound:sent \u2192 IM \u670D\u52A1\u5668", {
|
|
21148
21190
|
chatId: msg.chatId,
|
|
21149
|
-
encrypted: Boolean(
|
|
21191
|
+
encrypted: Boolean(extraContent),
|
|
21150
21192
|
requestId: result.request_id,
|
|
21151
21193
|
body
|
|
21152
21194
|
});
|
|
@@ -21167,7 +21209,10 @@ var MessagePipe = class _MessagePipe {
|
|
|
21167
21209
|
conversation_type: ""
|
|
21168
21210
|
};
|
|
21169
21211
|
const result = await this.callMessageApi("/messages/v1/recall", body, "recall");
|
|
21170
|
-
if (!result)
|
|
21212
|
+
if (!result) {
|
|
21213
|
+
log25.warn("recall:failed \u2014 callMessageApi returned null");
|
|
21214
|
+
return;
|
|
21215
|
+
}
|
|
21171
21216
|
log25.info("recall:sent", {
|
|
21172
21217
|
messageId: params.messageId,
|
|
21173
21218
|
requestId: result.request_id
|
|
@@ -21182,6 +21227,43 @@ var MessagePipe = class _MessagePipe {
|
|
|
21182
21227
|
* @param body - 请求体
|
|
21183
21228
|
* @param logTag - 日志标签前缀 (如 'outbound' / 'recall')
|
|
21184
21229
|
*/
|
|
21230
|
+
/** 单次 HTTP 请求封装 — callMessageApi 内部使用 */
|
|
21231
|
+
async _callMessageApiOnce(url2, body, logTag) {
|
|
21232
|
+
const apiStartMs = Date.now();
|
|
21233
|
+
const token = await this.tokenFn();
|
|
21234
|
+
const resp = await fetch(url2, {
|
|
21235
|
+
method: "POST",
|
|
21236
|
+
headers: {
|
|
21237
|
+
"Authorization": `Bearer ${token}`,
|
|
21238
|
+
"Content-Type": "application/json"
|
|
21239
|
+
},
|
|
21240
|
+
body: JSON.stringify(body)
|
|
21241
|
+
});
|
|
21242
|
+
if (!resp.ok) {
|
|
21243
|
+
log25.error(`${logTag}:http-error`, {
|
|
21244
|
+
status: resp.status,
|
|
21245
|
+
statusText: resp.statusText,
|
|
21246
|
+
url: url2
|
|
21247
|
+
});
|
|
21248
|
+
return { code: -1, msg: `HTTP ${resp.status}`, _retryable: resp.status >= 500 };
|
|
21249
|
+
}
|
|
21250
|
+
const result = await resp.json();
|
|
21251
|
+
if (result.code !== 0 && result.code !== 200) {
|
|
21252
|
+
log25.error(`${logTag}:api-error`, {
|
|
21253
|
+
code: result.code,
|
|
21254
|
+
msg: result.msg,
|
|
21255
|
+
requestId: result.request_id
|
|
21256
|
+
});
|
|
21257
|
+
return null;
|
|
21258
|
+
}
|
|
21259
|
+
metrics.increment("outbound.success");
|
|
21260
|
+
metrics.recordLatency("outbound.latency", Date.now() - apiStartMs);
|
|
21261
|
+
return result;
|
|
21262
|
+
}
|
|
21263
|
+
/**
|
|
21264
|
+
* 消息服务 API 公共调用方法 — 含 1 次重试 (仅限 5xx / 网络错误)。
|
|
21265
|
+
* 失败返回 null(不抛异常),错误通过 log 记录。
|
|
21266
|
+
*/
|
|
21185
21267
|
async callMessageApi(path3, body, logTag) {
|
|
21186
21268
|
const url2 = `${this.messageServiceBaseUrl}${path3}`;
|
|
21187
21269
|
const rateLimitResult = await this.rateLimiter.acquire();
|
|
@@ -21194,44 +21276,42 @@ var MessagePipe = class _MessagePipe {
|
|
|
21194
21276
|
return null;
|
|
21195
21277
|
}
|
|
21196
21278
|
try {
|
|
21197
|
-
const
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21201
|
-
|
|
21202
|
-
|
|
21203
|
-
|
|
21204
|
-
|
|
21205
|
-
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
url: url2
|
|
21212
|
-
});
|
|
21279
|
+
const result = await this._callMessageApiOnce(url2, body, logTag);
|
|
21280
|
+
if (result && "_retryable" in result) {
|
|
21281
|
+
if (result._retryable) {
|
|
21282
|
+
log25.warn(`${logTag}:retrying after 5xx`, { url: url2 });
|
|
21283
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
21284
|
+
try {
|
|
21285
|
+
const retryResult = await this._callMessageApiOnce(url2, body, `${logTag}:retry`);
|
|
21286
|
+
if (retryResult && !("_retryable" in retryResult)) {
|
|
21287
|
+
return retryResult;
|
|
21288
|
+
}
|
|
21289
|
+
} catch (retryErr) {
|
|
21290
|
+
log25.error(`${logTag}:retry-failed`, { error: retryErr.message });
|
|
21291
|
+
}
|
|
21292
|
+
}
|
|
21213
21293
|
metrics.increment("outbound.failed");
|
|
21214
21294
|
return null;
|
|
21215
21295
|
}
|
|
21216
|
-
|
|
21217
|
-
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
|
|
21221
|
-
|
|
21296
|
+
return result;
|
|
21297
|
+
} catch (err) {
|
|
21298
|
+
log25.warn(`${logTag}:network-error, retrying`, { url: url2, error: err.message });
|
|
21299
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
21300
|
+
try {
|
|
21301
|
+
const retryResult = await this._callMessageApiOnce(url2, body, `${logTag}:retry`);
|
|
21302
|
+
if (retryResult && !("_retryable" in retryResult)) {
|
|
21303
|
+
return retryResult;
|
|
21304
|
+
}
|
|
21305
|
+
metrics.increment("outbound.failed");
|
|
21306
|
+
return null;
|
|
21307
|
+
} catch (retryErr) {
|
|
21308
|
+
metrics.increment("outbound.failed");
|
|
21309
|
+
log25.error(`${logTag}:retry-network-error`, {
|
|
21310
|
+
url: url2,
|
|
21311
|
+
error: retryErr.message
|
|
21222
21312
|
});
|
|
21223
21313
|
return null;
|
|
21224
21314
|
}
|
|
21225
|
-
metrics.increment("outbound.success");
|
|
21226
|
-
metrics.recordLatency("outbound.latency", Date.now() - apiStartMs);
|
|
21227
|
-
return result;
|
|
21228
|
-
} catch (err) {
|
|
21229
|
-
metrics.increment("outbound.failed");
|
|
21230
|
-
log25.error(`${logTag}:network-error`, {
|
|
21231
|
-
url: url2,
|
|
21232
|
-
error: err.message
|
|
21233
|
-
});
|
|
21234
|
-
return null;
|
|
21235
21315
|
}
|
|
21236
21316
|
}
|
|
21237
21317
|
/**
|
|
@@ -21298,16 +21378,16 @@ var MessagePipe = class _MessagePipe {
|
|
|
21298
21378
|
groupId: callbackData.groupId,
|
|
21299
21379
|
type: callbackData.type,
|
|
21300
21380
|
content: callbackData.content,
|
|
21301
|
-
|
|
21381
|
+
extraContent: callbackData.extraContent
|
|
21302
21382
|
});
|
|
21303
|
-
const
|
|
21383
|
+
const extraContent = callbackData.extraContent;
|
|
21304
21384
|
let isEncrypted = false;
|
|
21305
|
-
if (typeof
|
|
21385
|
+
if (typeof extraContent === "string" && extraContent.length > 0) {
|
|
21306
21386
|
try {
|
|
21307
|
-
const parsed = JSON.parse(
|
|
21387
|
+
const parsed = JSON.parse(extraContent);
|
|
21308
21388
|
isEncrypted = Boolean(parsed.encryptMsg);
|
|
21309
21389
|
} catch {
|
|
21310
|
-
log25.debug("\u2139\uFE0F
|
|
21390
|
+
log25.debug("\u2139\uFE0F extraContent \u4E0D\u662F\u6709\u6548 JSON\uFF0C\u89C6\u4E3A\u660E\u6587", { msgUid: callbackData.msgUid });
|
|
21311
21391
|
}
|
|
21312
21392
|
}
|
|
21313
21393
|
let contentObj;
|
|
@@ -21340,6 +21420,10 @@ var MessagePipe = class _MessagePipe {
|
|
|
21340
21420
|
msgUid: callbackData.msgUid,
|
|
21341
21421
|
error: err.message
|
|
21342
21422
|
});
|
|
21423
|
+
await this.sendHintMessage(
|
|
21424
|
+
callbackData,
|
|
21425
|
+
"\u26A0\uFE0F \u6D88\u606F\u89E3\u5BC6\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002\u5982\u95EE\u9898\u6301\u7EED\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002"
|
|
21426
|
+
);
|
|
21343
21427
|
return;
|
|
21344
21428
|
}
|
|
21345
21429
|
} else {
|
|
@@ -21361,6 +21445,10 @@ var MessagePipe = class _MessagePipe {
|
|
|
21361
21445
|
msgUid: callbackData.msgUid,
|
|
21362
21446
|
error: err.message
|
|
21363
21447
|
});
|
|
21448
|
+
await this.sendHintMessage(
|
|
21449
|
+
callbackData,
|
|
21450
|
+
"\u26A0\uFE0F \u6D88\u606F\u89E3\u5BC6\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002\u5982\u95EE\u9898\u6301\u7EED\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002"
|
|
21451
|
+
);
|
|
21364
21452
|
return;
|
|
21365
21453
|
}
|
|
21366
21454
|
} else {
|
|
@@ -21414,15 +21502,15 @@ var MessagePipe = class _MessagePipe {
|
|
|
21414
21502
|
}
|
|
21415
21503
|
}
|
|
21416
21504
|
/**
|
|
21417
|
-
* 解密
|
|
21505
|
+
* 解密 extraContent 中的加密内容。
|
|
21418
21506
|
* @throws 解密失败时抛出异常
|
|
21419
21507
|
*/
|
|
21420
21508
|
async decryptExtra(callbackData) {
|
|
21421
|
-
const extraData = JSON.parse(callbackData.
|
|
21509
|
+
const extraData = JSON.parse(callbackData.extraContent);
|
|
21422
21510
|
const encryptMsg = extraData.encryptMsg ?? "";
|
|
21423
21511
|
const sessionId = extraData.sessionId ?? "";
|
|
21424
21512
|
if (!encryptMsg) {
|
|
21425
|
-
log25.warn("\u26A0\uFE0F
|
|
21513
|
+
log25.warn("\u26A0\uFE0F extraContent \u4E2D encryptMsg \u4E3A\u7A7A\uFF0C\u4F7F\u7528\u539F\u59CB content", { msgUid: callbackData.msgUid });
|
|
21426
21514
|
return callbackData.content;
|
|
21427
21515
|
}
|
|
21428
21516
|
const cryptoIv = extraData.cryptoIv ?? "";
|
package/dist/index.d.cts
CHANGED
|
@@ -214,7 +214,7 @@ interface OutboundMessage {
|
|
|
214
214
|
replyToMessageId?: string;
|
|
215
215
|
/** 跳过出站加密 — 用于"思考中"等无需加密的系统提示消息 */
|
|
216
216
|
skipEncrypt?: boolean;
|
|
217
|
-
/** 文件加密元数据 — 文件已在上传前加密时传入,sendMessage 直接使用此 keyId/iv 构建
|
|
217
|
+
/** 文件加密元数据 — 文件已在上传前加密时传入,sendMessage 直接使用此 keyId/iv 构建 extraContent */
|
|
218
218
|
encryptionMeta?: {
|
|
219
219
|
keyId: string;
|
|
220
220
|
iv: string;
|
|
@@ -925,8 +925,8 @@ declare class MessagePipe {
|
|
|
925
925
|
/** 文件类消息类型集合 — 这些类型的加密消息保留原始 content(文件元数据) */
|
|
926
926
|
private static readonly FILE_MSG_TYPES;
|
|
927
927
|
/**
|
|
928
|
-
* 构建文件类加密消息的
|
|
929
|
-
* 文件消息不加密 content(需要保留 fileId 等元数据),只在
|
|
928
|
+
* 构建文件类加密消息的 extraContent — 完整模板格式。
|
|
929
|
+
* 文件消息不加密 content(需要保留 fileId 等元数据),只在 extraContent 中携带会话信息。
|
|
930
930
|
*/
|
|
931
931
|
private static buildFileEncryptExtra;
|
|
932
932
|
/**
|
|
@@ -940,10 +940,10 @@ declare class MessagePipe {
|
|
|
940
940
|
*
|
|
941
941
|
* 文件类消息 (image/file/voice/video):
|
|
942
942
|
* - content 保留原始文件元数据(fileId、fileName、size 等)
|
|
943
|
-
* -
|
|
943
|
+
* - extraContent 使用完整模板格式,encryptMsg 为空
|
|
944
944
|
*
|
|
945
945
|
* 文本类消息 (text/markdown):
|
|
946
|
-
* - content 加密后置空,密文放入
|
|
946
|
+
* - content 加密后置空,密文放入 extraContent.encryptMsg
|
|
947
947
|
*/
|
|
948
948
|
sendMessage(msg: OutboundMessage): Promise<void>;
|
|
949
949
|
/**
|
|
@@ -966,6 +966,12 @@ declare class MessagePipe {
|
|
|
966
966
|
* @param body - 请求体
|
|
967
967
|
* @param logTag - 日志标签前缀 (如 'outbound' / 'recall')
|
|
968
968
|
*/
|
|
969
|
+
/** 单次 HTTP 请求封装 — callMessageApi 内部使用 */
|
|
970
|
+
private _callMessageApiOnce;
|
|
971
|
+
/**
|
|
972
|
+
* 消息服务 API 公共调用方法 — 含 1 次重试 (仅限 5xx / 网络错误)。
|
|
973
|
+
* 失败返回 null(不抛异常),错误通过 log 记录。
|
|
974
|
+
*/
|
|
969
975
|
private callMessageApi;
|
|
970
976
|
/**
|
|
971
977
|
* 入站处理流水线 (7 步):
|
|
@@ -984,7 +990,7 @@ declare class MessagePipe {
|
|
|
984
990
|
*/
|
|
985
991
|
private sendHintMessage;
|
|
986
992
|
/**
|
|
987
|
-
* 解密
|
|
993
|
+
* 解密 extraContent 中的加密内容。
|
|
988
994
|
* @throws 解密失败时抛出异常
|
|
989
995
|
*/
|
|
990
996
|
private decryptExtra;
|