@kyan-du/agent-wechat-openclaw 0.14.0 → 0.14.2
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.js +197 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5296,6 +5296,14 @@ var openChatResultSchema = external_exports.object({
|
|
|
5296
5296
|
errorCode: external_exports.string().optional(),
|
|
5297
5297
|
error: external_exports.string().optional()
|
|
5298
5298
|
});
|
|
5299
|
+
var downloadFileParamsSchema = external_exports.object({
|
|
5300
|
+
chatId: external_exports.string().min(1),
|
|
5301
|
+
filename: external_exports.string().min(1).optional(),
|
|
5302
|
+
executionTimeoutMs: external_exports.number().int().positive().optional()
|
|
5303
|
+
});
|
|
5304
|
+
var downloadFileResultSchema = openChatResultSchema.extend({
|
|
5305
|
+
clicked: external_exports.boolean().optional()
|
|
5306
|
+
});
|
|
5299
5307
|
var idempotencyKeySchema = external_exports.string().min(1).max(128).regex(/^[A-Za-z0-9._:-]+$/);
|
|
5300
5308
|
var forwardedMessageNodeSchema = external_exports.lazy(() => external_exports.object({
|
|
5301
5309
|
sender: external_exports.string().optional(),
|
|
@@ -5482,11 +5490,12 @@ var WeChatClient = class {
|
|
|
5482
5490
|
await throwHttpError(res);
|
|
5483
5491
|
return res.json();
|
|
5484
5492
|
}
|
|
5485
|
-
async post(path, body) {
|
|
5493
|
+
async post(path, body, signal) {
|
|
5486
5494
|
const res = await fetch(`${this.base}${path}`, {
|
|
5487
5495
|
method: "POST",
|
|
5488
5496
|
headers: this.headers,
|
|
5489
|
-
body: body != null ? JSON.stringify(body) : void 0
|
|
5497
|
+
body: body != null ? JSON.stringify(body) : void 0,
|
|
5498
|
+
signal
|
|
5490
5499
|
});
|
|
5491
5500
|
if (!res.ok)
|
|
5492
5501
|
await throwHttpError(res);
|
|
@@ -5531,8 +5540,11 @@ var WeChatClient = class {
|
|
|
5531
5540
|
async markChatRead(chatId) {
|
|
5532
5541
|
return this.post(`/api/chats/${encodeURIComponent(chatId)}/mark-read`);
|
|
5533
5542
|
}
|
|
5534
|
-
async openChat(chatId, clearUnreads) {
|
|
5535
|
-
return this.post(`/api/chats/${encodeURIComponent(chatId)}/open${qs({ clearUnreads })}
|
|
5543
|
+
async openChat(chatId, clearUnreads, signal, executionTimeoutMs) {
|
|
5544
|
+
return this.post(`/api/chats/${encodeURIComponent(chatId)}/open${qs({ clearUnreads, executionTimeoutMs })}`, void 0, signal);
|
|
5545
|
+
}
|
|
5546
|
+
async downloadFile(chatId, filename, signal, executionTimeoutMs) {
|
|
5547
|
+
return this.post(`/api/chats/${encodeURIComponent(chatId)}/download-file${qs({ filename, executionTimeoutMs })}`, void 0, signal);
|
|
5536
5548
|
}
|
|
5537
5549
|
async listGroupMembersPage(groupId, limit, cursor) {
|
|
5538
5550
|
const page = groupMembersPageSchema.parse(await this.get(`/api/groups/${encodeURIComponent(groupId)}/members${qs({ limit, cursor })}`));
|
|
@@ -6785,27 +6797,113 @@ var RETRYABLE_MEDIA_ERRORS = /* @__PURE__ */ new Set([
|
|
|
6785
6797
|
"VOICE_NOT_DOWNLOADED",
|
|
6786
6798
|
"IMAGE_NOT_STABLE"
|
|
6787
6799
|
]);
|
|
6788
|
-
var DEFAULT_MEDIA_POLL_ATTEMPTS =
|
|
6789
|
-
var DEFAULT_MEDIA_POLL_INTERVAL_MS =
|
|
6800
|
+
var DEFAULT_MEDIA_POLL_ATTEMPTS = 6;
|
|
6801
|
+
var DEFAULT_MEDIA_POLL_INTERVAL_MS = 500;
|
|
6802
|
+
var IMAGE_MATERIALIZATION_OPEN_CHAT_TIMEOUT_MS = 400;
|
|
6803
|
+
var FILE_MATERIALIZATION_CLICK_TIMEOUT_MS = 8e3;
|
|
6804
|
+
function shouldTriggerMediaMaterialization(result) {
|
|
6805
|
+
return result.type === "image" || result.type === "file" || result.type === "pending";
|
|
6806
|
+
}
|
|
6807
|
+
function isFileMaterialization(result) {
|
|
6808
|
+
return result.type === "file" || result.errorCode === "FILE_NOT_DOWNLOADED" || result.errorCode === "FILE_NOT_STABLE";
|
|
6809
|
+
}
|
|
6810
|
+
async function triggerImageOpenChat(client, chatId, timeoutMs, result, attempt, options) {
|
|
6811
|
+
options?.log?.info?.(
|
|
6812
|
+
`[wechat:media] triggering chat reopen for ${result.type} attempt=${attempt} skipOpen=${options?.skipOpen === true}`
|
|
6813
|
+
);
|
|
6814
|
+
const controller = new AbortController();
|
|
6815
|
+
const opened = Promise.resolve(client.openChat(chatId, true, controller.signal, timeoutMs));
|
|
6816
|
+
void opened.catch(() => void 0);
|
|
6817
|
+
try {
|
|
6818
|
+
await raceWithTimeout(opened, timeoutMs);
|
|
6819
|
+
} finally {
|
|
6820
|
+
controller.abort();
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
6823
|
+
function triggerFileBubbleClick(client, chatId, result, attempt, options) {
|
|
6824
|
+
const filename = result.filename?.trim() || void 0;
|
|
6825
|
+
const timeoutMs = options?.timeoutMs ?? FILE_MATERIALIZATION_CLICK_TIMEOUT_MS;
|
|
6826
|
+
options?.log?.info?.(
|
|
6827
|
+
`[wechat:media] triggering file bubble click attempt=${attempt} filename=${filename ?? ""} skipOpen=${options?.skipOpen === true}`
|
|
6828
|
+
);
|
|
6829
|
+
if (!client.downloadFile) {
|
|
6830
|
+
throw Object.assign(new Error("FILE_DOWNLOAD_TRIGGER_UNAVAILABLE"), {
|
|
6831
|
+
code: "FILE_DOWNLOAD_TRIGGER_UNAVAILABLE"
|
|
6832
|
+
});
|
|
6833
|
+
}
|
|
6834
|
+
const clicked = Promise.resolve(client.downloadFile(chatId, filename, void 0, timeoutMs));
|
|
6835
|
+
void clicked.catch(() => void 0);
|
|
6836
|
+
}
|
|
6837
|
+
function createMediaMaterializationTrigger(client, chatId, options) {
|
|
6838
|
+
const timeoutMs = options?.timeoutMs ?? IMAGE_MATERIALIZATION_OPEN_CHAT_TIMEOUT_MS;
|
|
6839
|
+
return async (result, attempt) => {
|
|
6840
|
+
if (!shouldTriggerMediaMaterialization(result)) return;
|
|
6841
|
+
if (isFileMaterialization(result)) {
|
|
6842
|
+
triggerFileBubbleClick(client, chatId, result, attempt, options);
|
|
6843
|
+
return;
|
|
6844
|
+
}
|
|
6845
|
+
await triggerImageOpenChat(client, chatId, timeoutMs, result, attempt, options);
|
|
6846
|
+
};
|
|
6847
|
+
}
|
|
6848
|
+
function mediaMaterializationTriggerForMessage(opts) {
|
|
6849
|
+
const baseType = opts.messageType & 2147483647;
|
|
6850
|
+
if (baseType !== 3 && baseType !== 49) return void 0;
|
|
6851
|
+
return createMediaMaterializationTrigger(opts.client, opts.chatId, {
|
|
6852
|
+
log: opts.log,
|
|
6853
|
+
timeoutMs: opts.timeoutMs,
|
|
6854
|
+
skipOpen: opts.skipOpen
|
|
6855
|
+
});
|
|
6856
|
+
}
|
|
6857
|
+
function raceWithTimeout(promise, timeoutMs) {
|
|
6858
|
+
return new Promise((resolve, reject) => {
|
|
6859
|
+
const timer = setTimeout(() => {
|
|
6860
|
+
reject(Object.assign(new Error("IMAGE_MATERIALIZATION_OPEN_CHAT_TIMEOUT"), {
|
|
6861
|
+
code: "IMAGE_MATERIALIZATION_OPEN_CHAT_TIMEOUT"
|
|
6862
|
+
}));
|
|
6863
|
+
}, timeoutMs);
|
|
6864
|
+
promise.then(
|
|
6865
|
+
(value) => {
|
|
6866
|
+
clearTimeout(timer);
|
|
6867
|
+
resolve(value);
|
|
6868
|
+
},
|
|
6869
|
+
(error) => {
|
|
6870
|
+
clearTimeout(timer);
|
|
6871
|
+
reject(error);
|
|
6872
|
+
}
|
|
6873
|
+
);
|
|
6874
|
+
});
|
|
6875
|
+
}
|
|
6790
6876
|
function isRetryable(result) {
|
|
6791
6877
|
if (result.data !== void 0) return false;
|
|
6792
6878
|
if (result.errorCode !== void 0) return RETRYABLE_MEDIA_ERRORS.has(result.errorCode);
|
|
6793
6879
|
return result.type === "pending";
|
|
6794
6880
|
}
|
|
6795
|
-
async function pollMedia(client, chatId, localId, log, maxAttempts = DEFAULT_MEDIA_POLL_ATTEMPTS, intervalMs = DEFAULT_MEDIA_POLL_INTERVAL_MS) {
|
|
6881
|
+
async function pollMedia(client, chatId, localId, log, maxAttempts = DEFAULT_MEDIA_POLL_ATTEMPTS, intervalMs = DEFAULT_MEDIA_POLL_INTERVAL_MS, onRetryTrigger) {
|
|
6796
6882
|
let lastResult;
|
|
6883
|
+
let triggerUsed = false;
|
|
6797
6884
|
const startedAt = Date.now();
|
|
6798
6885
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6799
6886
|
const result = await client.getMedia(chatId, localId);
|
|
6800
6887
|
lastResult = result;
|
|
6801
6888
|
if (result.type === "unsupported") return result;
|
|
6802
6889
|
if (result.data || !isRetryable(result)) return result;
|
|
6890
|
+
if (!triggerUsed && onRetryTrigger) {
|
|
6891
|
+
triggerUsed = true;
|
|
6892
|
+
try {
|
|
6893
|
+
await onRetryTrigger(result, attempt);
|
|
6894
|
+
log?.info?.(`[wechat:media] download trigger completed attempt=${attempt}`);
|
|
6895
|
+
} catch {
|
|
6896
|
+
log?.info?.(`[wechat:media] download trigger failed attempt=${attempt} code=MEDIA_DOWNLOAD_TRIGGER_FAILED`);
|
|
6897
|
+
}
|
|
6898
|
+
}
|
|
6803
6899
|
if (attempt < maxAttempts) {
|
|
6804
6900
|
log?.info?.(`[wechat:media] pending attempt=${attempt}/${maxAttempts} elapsedMs=${Date.now() - startedAt}`);
|
|
6805
6901
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
6806
6902
|
}
|
|
6807
6903
|
}
|
|
6808
|
-
log?.info?.(
|
|
6904
|
+
log?.info?.(
|
|
6905
|
+
`[wechat:media] retry exhausted attempts=${maxAttempts} elapsedMs=${Date.now() - startedAt} code=${lastResult?.errorCode ?? "MEDIA_NOT_DOWNLOADED"}`
|
|
6906
|
+
);
|
|
6809
6907
|
return lastResult ?? null;
|
|
6810
6908
|
}
|
|
6811
6909
|
|
|
@@ -7392,13 +7490,54 @@ function shouldBypassNewsappAuthorization(chat) {
|
|
|
7392
7490
|
return isNewsappChat(chat);
|
|
7393
7491
|
}
|
|
7394
7492
|
|
|
7493
|
+
// src/monitor-skip.ts
|
|
7494
|
+
var SYSTEM_SERVICE_USERNAMES = /* @__PURE__ */ new Set([
|
|
7495
|
+
"qmessage",
|
|
7496
|
+
"floatbottle",
|
|
7497
|
+
"medianote",
|
|
7498
|
+
"notifymessage",
|
|
7499
|
+
"weixin",
|
|
7500
|
+
"fmessage",
|
|
7501
|
+
"filehelper",
|
|
7502
|
+
"newsapp",
|
|
7503
|
+
"tmessage",
|
|
7504
|
+
"mphelper",
|
|
7505
|
+
"qqmail",
|
|
7506
|
+
"weixingongzhong",
|
|
7507
|
+
"qqsafe",
|
|
7508
|
+
"exmail_tool",
|
|
7509
|
+
"lbsapp",
|
|
7510
|
+
"pc_qq"
|
|
7511
|
+
]);
|
|
7512
|
+
var EMPTY_UNREAD_BACKOFF_MS = 5e3;
|
|
7513
|
+
var EMPTY_UNREAD_BACKOFF_MAX_MS = 6e4;
|
|
7514
|
+
function isOfficialAccount(chatId) {
|
|
7515
|
+
return chatId.startsWith("gh_") || SYSTEM_SERVICE_USERNAMES.has(chatId);
|
|
7516
|
+
}
|
|
7517
|
+
function isEmptyUnreadBackoffActive(backoff, chatId, now = Date.now()) {
|
|
7518
|
+
const entry = backoff.get(chatId);
|
|
7519
|
+
return entry !== void 0 && now < entry.nextRetryAt;
|
|
7520
|
+
}
|
|
7521
|
+
function applyEmptyUnreadSkip(chatId, opts) {
|
|
7522
|
+
if (opts.unreadCount <= 0) return null;
|
|
7523
|
+
const now = opts.now ?? Date.now();
|
|
7524
|
+
const seededLastSeen = opts.firstPoll && !opts.lastSeenId.has(chatId);
|
|
7525
|
+
if (seededLastSeen) {
|
|
7526
|
+
opts.lastSeenId.set(chatId, opts.prevLastSeen);
|
|
7527
|
+
}
|
|
7528
|
+
const retryCount = (opts.backoff.get(chatId)?.retryCount ?? 0) + 1;
|
|
7529
|
+
const backoffMs = Math.min(
|
|
7530
|
+
EMPTY_UNREAD_BACKOFF_MAX_MS,
|
|
7531
|
+
EMPTY_UNREAD_BACKOFF_MS * 2 ** Math.min(retryCount - 1, 6)
|
|
7532
|
+
);
|
|
7533
|
+
opts.backoff.set(chatId, { nextRetryAt: now + backoffMs, retryCount });
|
|
7534
|
+
return { seededLastSeen, backoffMs };
|
|
7535
|
+
}
|
|
7536
|
+
|
|
7395
7537
|
// src/monitor.ts
|
|
7396
7538
|
var MEDIA_TYPES = /* @__PURE__ */ new Set([3, 34, 43]);
|
|
7397
7539
|
var HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
|
|
7398
7540
|
var CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
|
|
7399
|
-
function isOfficialAccount(chatId) {
|
|
7400
|
-
return chatId.startsWith("gh_");
|
|
7401
|
-
}
|
|
7402
7541
|
function sleep(ms, signal) {
|
|
7403
7542
|
return new Promise((resolve) => {
|
|
7404
7543
|
const timer = setTimeout(resolve, ms);
|
|
@@ -7428,6 +7567,7 @@ async function startWeChatMonitor(opts) {
|
|
|
7428
7567
|
const pendingMessageScans = loadPendingResetRetries(account.accountId);
|
|
7429
7568
|
const inboundLedger = loadInboundEventLedger(account.accountId);
|
|
7430
7569
|
const mediaPipeline = loadMediaPipeline(account.accountId);
|
|
7570
|
+
const emptyUnreadBackoff = /* @__PURE__ */ new Map();
|
|
7431
7571
|
const cleanupMedia = async () => {
|
|
7432
7572
|
await mediaPipeline.cleanup({
|
|
7433
7573
|
olderThanMs: MEDIA_RETENTION_MS,
|
|
@@ -7546,9 +7686,13 @@ async function startWeChatMonitor(opts) {
|
|
|
7546
7686
|
}
|
|
7547
7687
|
}
|
|
7548
7688
|
}
|
|
7549
|
-
const unreadChats = chats.filter(
|
|
7550
|
-
|
|
7551
|
-
|
|
7689
|
+
const unreadChats = chats.filter((c) => {
|
|
7690
|
+
const chatId = c.username ?? c.id;
|
|
7691
|
+
if (isEmptyUnreadBackoffActive(emptyUnreadBackoff, chatId)) return false;
|
|
7692
|
+
if (c.unreadCount <= 0) return false;
|
|
7693
|
+
if (isNewsappChat(c)) return true;
|
|
7694
|
+
return !isOfficialAccount(chatId);
|
|
7695
|
+
});
|
|
7552
7696
|
for (const chat of unreadChats) {
|
|
7553
7697
|
const chatId = chat.username ?? chat.id;
|
|
7554
7698
|
if (chatScanState.initialScanComplete && !lastSeenId.has(chatId) && !startupBaselines.has(chatId)) {
|
|
@@ -7562,8 +7706,9 @@ async function startWeChatMonitor(opts) {
|
|
|
7562
7706
|
(chat) => !isNewsappChat(chat) || newsappHandled.get(chat.username ?? chat.id) !== `${chat.lastMsgLocalId ?? ""}:${chat.lastMessagePreview?.trim() ?? ""}`
|
|
7563
7707
|
);
|
|
7564
7708
|
for (const chatId of chatsToProcess.keys()) {
|
|
7565
|
-
if (isOfficialAccount(chatId) && chatId !== "newsapp")
|
|
7709
|
+
if (isOfficialAccount(chatId) && chatId !== "newsapp" || isEmptyUnreadBackoffActive(emptyUnreadBackoff, chatId)) {
|
|
7566
7710
|
chatsToProcess.delete(chatId);
|
|
7711
|
+
}
|
|
7567
7712
|
}
|
|
7568
7713
|
if (unreadChats.length > 0) {
|
|
7569
7714
|
log?.info?.(
|
|
@@ -7585,6 +7730,7 @@ async function startWeChatMonitor(opts) {
|
|
|
7585
7730
|
retryState.persist,
|
|
7586
7731
|
inboundLedger,
|
|
7587
7732
|
mediaPipeline,
|
|
7733
|
+
emptyUnreadBackoff,
|
|
7588
7734
|
account,
|
|
7589
7735
|
cfg,
|
|
7590
7736
|
log,
|
|
@@ -7615,7 +7761,7 @@ async function startWeChatMonitor(opts) {
|
|
|
7615
7761
|
for (const chat of chats) {
|
|
7616
7762
|
if (abortSignal.aborted) break;
|
|
7617
7763
|
const chatId = chat.username ?? chat.id;
|
|
7618
|
-
if (isOfficialAccount(chatId)) continue;
|
|
7764
|
+
if (isOfficialAccount(chatId) && chatId !== "newsapp" || isEmptyUnreadBackoffActive(emptyUnreadBackoff, chatId)) continue;
|
|
7619
7765
|
const prevSeen = lastSeenId.get(chatId);
|
|
7620
7766
|
if (prevSeen === void 0) continue;
|
|
7621
7767
|
if (unreadChats.some((c) => (c.username ?? c.id) === chatId)) continue;
|
|
@@ -7633,6 +7779,7 @@ async function startWeChatMonitor(opts) {
|
|
|
7633
7779
|
retryState.persist,
|
|
7634
7780
|
inboundLedger,
|
|
7635
7781
|
mediaPipeline,
|
|
7782
|
+
emptyUnreadBackoff,
|
|
7636
7783
|
account,
|
|
7637
7784
|
cfg,
|
|
7638
7785
|
log,
|
|
@@ -7677,7 +7824,7 @@ async function startWeChatMonitor(opts) {
|
|
|
7677
7824
|
connected: false
|
|
7678
7825
|
});
|
|
7679
7826
|
}
|
|
7680
|
-
async function prepareMessage(client, mediaPipeline, msg, chatId, chat, liveAccount, policy, log) {
|
|
7827
|
+
async function prepareMessage(client, mediaPipeline, msg, chatId, chat, liveAccount, policy, log, skipOpen) {
|
|
7681
7828
|
const core = getWeChatRuntime();
|
|
7682
7829
|
if (msg.isSelf) {
|
|
7683
7830
|
log?.info?.(`[wechat:${liveAccount.accountId}] Skipping self-sent msg ${msg.localId}`);
|
|
@@ -7710,7 +7857,21 @@ async function prepareMessage(client, mediaPipeline, msg, chatId, chat, liveAcco
|
|
|
7710
7857
|
if (mayHaveMedia) {
|
|
7711
7858
|
log?.info?.(`[wechat:${liveAccount.accountId}] Checking media for msg ${msg.localId} (type ${baseType})`);
|
|
7712
7859
|
try {
|
|
7713
|
-
const result = await pollMedia(
|
|
7860
|
+
const result = await pollMedia(
|
|
7861
|
+
client,
|
|
7862
|
+
chatId,
|
|
7863
|
+
msg.localId,
|
|
7864
|
+
log,
|
|
7865
|
+
void 0,
|
|
7866
|
+
void 0,
|
|
7867
|
+
mediaMaterializationTriggerForMessage({
|
|
7868
|
+
client,
|
|
7869
|
+
chatId,
|
|
7870
|
+
messageType: baseType,
|
|
7871
|
+
log,
|
|
7872
|
+
skipOpen
|
|
7873
|
+
})
|
|
7874
|
+
);
|
|
7714
7875
|
if (result && result.data && result.type !== "unsupported") {
|
|
7715
7876
|
hasMedia = true;
|
|
7716
7877
|
mediaSource = result.source;
|
|
@@ -8089,7 +8250,7 @@ function bufferGroupHistory(groupHistory, chatId, pm, limit) {
|
|
|
8089
8250
|
if (first) groupHistory.delete(first);
|
|
8090
8251
|
}
|
|
8091
8252
|
}
|
|
8092
|
-
async function processUnreadChat(client, chat, lastSeenId, equalCursorUnreadHandled, startupBaselines, pendingMessageScans, persistRetryState, inboundLedger, mediaPipeline, account, cfg, log, skipOpen, groupHistory, groupHistoryLimit, catchup) {
|
|
8253
|
+
async function processUnreadChat(client, chat, lastSeenId, equalCursorUnreadHandled, startupBaselines, pendingMessageScans, persistRetryState, inboundLedger, mediaPipeline, emptyUnreadBackoff, account, cfg, log, skipOpen, groupHistory, groupHistoryLimit, catchup) {
|
|
8093
8254
|
const core = getWeChatRuntime();
|
|
8094
8255
|
const liveAccount = resolveWeChatAccount(cfg, account.accountId) ?? account;
|
|
8095
8256
|
const chatId = chat.username ?? chat.id;
|
|
@@ -8178,7 +8339,22 @@ async function processUnreadChat(client, chat, lastSeenId, equalCursorUnreadHand
|
|
|
8178
8339
|
const fallback = newsappFallbackMessage(chat);
|
|
8179
8340
|
if (fallback) messages = [fallback];
|
|
8180
8341
|
}
|
|
8181
|
-
if (messages.length === 0)
|
|
8342
|
+
if (messages.length === 0) {
|
|
8343
|
+
const skip = applyEmptyUnreadSkip(chatId, {
|
|
8344
|
+
unreadCount: chat.unreadCount,
|
|
8345
|
+
firstPoll,
|
|
8346
|
+
prevLastSeen,
|
|
8347
|
+
lastSeenId,
|
|
8348
|
+
backoff: emptyUnreadBackoff
|
|
8349
|
+
});
|
|
8350
|
+
if (skip) {
|
|
8351
|
+
log?.info?.(
|
|
8352
|
+
`[wechat:${liveAccount.accountId}] ${chatId}: empty unread fetch, firstPoll=${firstPoll}, unreadCount=${chat.unreadCount}; seedLastSeen=${skip.seededLastSeen}, backoff=${skip.backoffMs}ms`
|
|
8353
|
+
);
|
|
8354
|
+
}
|
|
8355
|
+
return "skipped";
|
|
8356
|
+
}
|
|
8357
|
+
emptyUnreadBackoff.delete(chatId);
|
|
8182
8358
|
const enrichedBaseline = enrichStartupBaselineFromMessages(startupBaseline, messages);
|
|
8183
8359
|
if (enrichedBaseline) {
|
|
8184
8360
|
startupBaselines.set(chatId, enrichedBaseline);
|
|
@@ -8292,7 +8468,7 @@ async function processUnreadChat(client, chat, lastSeenId, equalCursorUnreadHand
|
|
|
8292
8468
|
log?.info?.(
|
|
8293
8469
|
`[wechat:${liveAccount.accountId}] Processing msg ${msg.localId}: type=${msg.type}, sender=${msg.sender}, isSelf=${msg.isSelf}, content=${(msg.content || "").slice(0, 50)}`
|
|
8294
8470
|
);
|
|
8295
|
-
const pm = await prepareMessage(client, mediaPipeline, msg, chatId, chat, liveAccount, policy, log);
|
|
8471
|
+
const pm = await prepareMessage(client, mediaPipeline, msg, chatId, chat, liveAccount, policy, log, skipOpen);
|
|
8296
8472
|
if (pm) {
|
|
8297
8473
|
processed.push(pm);
|
|
8298
8474
|
} else {
|