@agent-wechat/wechat 0.4.0 → 0.5.0
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 +72 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1118,9 +1118,6 @@ function getWeChatRuntime() {
|
|
|
1118
1118
|
return runtime;
|
|
1119
1119
|
}
|
|
1120
1120
|
|
|
1121
|
-
// src/monitor.ts
|
|
1122
|
-
import { execSync } from "node:child_process";
|
|
1123
|
-
|
|
1124
1121
|
// ../shared/dist/client.js
|
|
1125
1122
|
function normalizeUrl(base) {
|
|
1126
1123
|
const url = base.startsWith("http") ? base : `http://${base}`;
|
|
@@ -5553,18 +5550,12 @@ function enqueueWeChatSystemEvent(text, contextKey) {
|
|
|
5553
5550
|
} catch {
|
|
5554
5551
|
}
|
|
5555
5552
|
}
|
|
5556
|
-
function enqueueAndWakeSystemEvent(text, contextKey, log) {
|
|
5557
|
-
enqueueWeChatSystemEvent(text, contextKey);
|
|
5558
|
-
try {
|
|
5559
|
-
execSync("openclaw system event --mode now", { timeout: 5e3, stdio: "ignore" });
|
|
5560
|
-
} catch {
|
|
5561
|
-
log?.info?.("Failed to trigger heartbeat wake \u2014 agent will see event on next prompt");
|
|
5562
|
-
}
|
|
5563
|
-
}
|
|
5564
5553
|
async function startWeChatMonitor(opts) {
|
|
5565
5554
|
const { account, abortSignal, setStatus, log } = opts;
|
|
5566
5555
|
const client = new WeChatClient({ baseUrl: account.serverUrl, token: account.token });
|
|
5567
5556
|
const lastSeenId = /* @__PURE__ */ new Map();
|
|
5557
|
+
const groupHistory = /* @__PURE__ */ new Map();
|
|
5558
|
+
const GROUP_HISTORY_LIMIT = 50;
|
|
5568
5559
|
let lastAuthCheck = 0;
|
|
5569
5560
|
let prevStatus = void 0;
|
|
5570
5561
|
setStatus({
|
|
@@ -5591,12 +5582,11 @@ async function startWeChatMonitor(opts) {
|
|
|
5591
5582
|
});
|
|
5592
5583
|
if (prevStatus === "logged_in" && !isLinked) {
|
|
5593
5584
|
const msg = auth.status === "app_not_running" ? "[WeChat] Application stopped. It will restart automatically \u2014 credentials may be cached, so you can try reconnecting using the wechat_login tool." : "[WeChat] Session ended. You can try reconnecting using the wechat_login tool \u2014 if credentials are cached, login may complete automatically.";
|
|
5594
|
-
|
|
5585
|
+
enqueueWeChatSystemEvent(msg, "wechat:auth_lost");
|
|
5595
5586
|
} else if (prevStatus === void 0 && !isLinked) {
|
|
5596
|
-
|
|
5587
|
+
enqueueWeChatSystemEvent(
|
|
5597
5588
|
"[WeChat] Not logged in. Use the wechat_login tool to authenticate \u2014 if credentials are cached from a previous session, login may complete automatically.",
|
|
5598
|
-
"wechat:auth_required"
|
|
5599
|
-
log
|
|
5589
|
+
"wechat:auth_required"
|
|
5600
5590
|
);
|
|
5601
5591
|
}
|
|
5602
5592
|
prevStatus = auth.status;
|
|
@@ -5614,10 +5604,9 @@ async function startWeChatMonitor(opts) {
|
|
|
5614
5604
|
lastError: String(err)
|
|
5615
5605
|
});
|
|
5616
5606
|
if (prevStatus === "logged_in") {
|
|
5617
|
-
|
|
5607
|
+
enqueueWeChatSystemEvent(
|
|
5618
5608
|
"[WeChat] Cannot reach agent-wechat server. The container may have stopped.",
|
|
5619
|
-
"wechat:server_unreachable"
|
|
5620
|
-
log
|
|
5609
|
+
"wechat:server_unreachable"
|
|
5621
5610
|
);
|
|
5622
5611
|
}
|
|
5623
5612
|
prevStatus = void 0;
|
|
@@ -5655,7 +5644,10 @@ async function startWeChatMonitor(opts) {
|
|
|
5655
5644
|
lastSeenId,
|
|
5656
5645
|
account,
|
|
5657
5646
|
cfg,
|
|
5658
|
-
log
|
|
5647
|
+
log,
|
|
5648
|
+
void 0,
|
|
5649
|
+
groupHistory,
|
|
5650
|
+
GROUP_HISTORY_LIMIT
|
|
5659
5651
|
);
|
|
5660
5652
|
}
|
|
5661
5653
|
}
|
|
@@ -5670,7 +5662,7 @@ async function startWeChatMonitor(opts) {
|
|
|
5670
5662
|
log?.info?.(
|
|
5671
5663
|
`[wechat:${account.accountId}] Catch-up: ${chatId} lastMsgLocalId=${chat.lastMsgLocalId} > lastSeenId=${prevSeen}`
|
|
5672
5664
|
);
|
|
5673
|
-
await processUnreadChat(client, chat, lastSeenId, account, cfg, log, true);
|
|
5665
|
+
await processUnreadChat(client, chat, lastSeenId, account, cfg, log, true, groupHistory, GROUP_HISTORY_LIMIT);
|
|
5674
5666
|
}
|
|
5675
5667
|
} catch (err) {
|
|
5676
5668
|
log?.error?.(
|
|
@@ -5802,7 +5794,7 @@ function buildSegments(processed) {
|
|
|
5802
5794
|
}
|
|
5803
5795
|
return segments;
|
|
5804
5796
|
}
|
|
5805
|
-
async function dispatchSegment(segment, client, chatId, chat, liveAccount, cfg, log, remainingSegments) {
|
|
5797
|
+
async function dispatchSegment(segment, client, chatId, chat, liveAccount, cfg, log, remainingSegments, groupHistory) {
|
|
5806
5798
|
const core = getWeChatRuntime();
|
|
5807
5799
|
const lastMsg = segment[segment.length - 1];
|
|
5808
5800
|
const { isGroup, senderId, senderName, timestamp, rawBody, msg } = lastMsg;
|
|
@@ -6013,13 +6005,29 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, cfg,
|
|
|
6013
6005
|
direction: "inbound",
|
|
6014
6006
|
at: timestamp
|
|
6015
6007
|
});
|
|
6008
|
+
if (isGroup && groupHistory) {
|
|
6009
|
+
groupHistory.set(chatId, []);
|
|
6010
|
+
}
|
|
6016
6011
|
} catch (err) {
|
|
6017
6012
|
log?.error?.(
|
|
6018
6013
|
`[wechat:${liveAccount.accountId}] Failed to dispatch segment (last msg ${msg.localId}): ${err}`
|
|
6019
6014
|
);
|
|
6020
6015
|
}
|
|
6021
6016
|
}
|
|
6022
|
-
|
|
6017
|
+
function bufferGroupHistory(groupHistory, chatId, pm, limit) {
|
|
6018
|
+
const history = groupHistory.get(chatId) ?? [];
|
|
6019
|
+
history.push(pm);
|
|
6020
|
+
while (history.length > limit) {
|
|
6021
|
+
history.shift();
|
|
6022
|
+
}
|
|
6023
|
+
groupHistory.delete(chatId);
|
|
6024
|
+
groupHistory.set(chatId, history);
|
|
6025
|
+
if (groupHistory.size > 1e3) {
|
|
6026
|
+
const first = groupHistory.keys().next().value;
|
|
6027
|
+
if (first) groupHistory.delete(first);
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
async function processUnreadChat(client, chat, lastSeenId, account, cfg, log, skipOpen, groupHistory, groupHistoryLimit) {
|
|
6023
6031
|
const liveAccount = resolveWeChatAccount(cfg, account.accountId) ?? account;
|
|
6024
6032
|
const chatId = chat.username ?? chat.id;
|
|
6025
6033
|
if (!skipOpen) {
|
|
@@ -6084,6 +6092,47 @@ async function processUnreadChat(client, chat, lastSeenId, account, cfg, log, sk
|
|
|
6084
6092
|
processed.push(pm);
|
|
6085
6093
|
}
|
|
6086
6094
|
}
|
|
6095
|
+
const isGroup = chatId.includes("@chatroom");
|
|
6096
|
+
if (isGroup && groupHistory) {
|
|
6097
|
+
const wechatCfg = cfg?.channels?.wechat;
|
|
6098
|
+
const groupEntry = wechatCfg?.groups?.[chatId];
|
|
6099
|
+
const defaultEntry = wechatCfg?.groups?.["*"];
|
|
6100
|
+
const requireMention = groupEntry?.requireMention ?? defaultEntry?.requireMention ?? true;
|
|
6101
|
+
if (requireMention) {
|
|
6102
|
+
const hasMention = processed.some((pm) => pm.isMentioned);
|
|
6103
|
+
if (!hasMention) {
|
|
6104
|
+
const limit = groupHistoryLimit ?? 50;
|
|
6105
|
+
for (const pm of processed) {
|
|
6106
|
+
bufferGroupHistory(groupHistory, chatId, pm, limit);
|
|
6107
|
+
}
|
|
6108
|
+
log?.info?.(`[wechat:${liveAccount.accountId}] Buffered ${processed.length} msg(s) for group history in ${chatId}`);
|
|
6109
|
+
const maxId2 = Math.max(...newMessages.map((m) => m.localId));
|
|
6110
|
+
lastSeenId.set(chatId, maxId2);
|
|
6111
|
+
return;
|
|
6112
|
+
}
|
|
6113
|
+
const buffered = groupHistory.get(chatId) ?? [];
|
|
6114
|
+
if (buffered.length > 0) {
|
|
6115
|
+
for (const pm of buffered) {
|
|
6116
|
+
pm.isMentioned = true;
|
|
6117
|
+
}
|
|
6118
|
+
processed.unshift(...buffered);
|
|
6119
|
+
groupHistory.set(chatId, []);
|
|
6120
|
+
log?.info?.(`[wechat:${liveAccount.accountId}] Injected ${buffered.length} buffered msg(s) as history in ${chatId}`);
|
|
6121
|
+
}
|
|
6122
|
+
let latestMediaIdx = -1;
|
|
6123
|
+
for (let i = processed.length - 1; i >= 0; i--) {
|
|
6124
|
+
if (processed[i].mediaPath) {
|
|
6125
|
+
latestMediaIdx = i;
|
|
6126
|
+
break;
|
|
6127
|
+
}
|
|
6128
|
+
}
|
|
6129
|
+
for (let i = 0; i < processed.length; i++) {
|
|
6130
|
+
if (processed[i].mediaPath && i !== latestMediaIdx) {
|
|
6131
|
+
processed[i] = { ...processed[i], mediaPath: void 0, mediaMime: void 0, hasMedia: false };
|
|
6132
|
+
}
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
6135
|
+
}
|
|
6087
6136
|
if (processed.length > 0) {
|
|
6088
6137
|
const segments = buildSegments(processed);
|
|
6089
6138
|
log?.info?.(
|
|
@@ -6091,7 +6140,7 @@ async function processUnreadChat(client, chat, lastSeenId, account, cfg, log, sk
|
|
|
6091
6140
|
);
|
|
6092
6141
|
for (let i = 0; i < segments.length; i++) {
|
|
6093
6142
|
const remaining = segments.length - i - 1;
|
|
6094
|
-
await dispatchSegment(segments[i], client, chatId, chat, liveAccount, cfg, log, remaining);
|
|
6143
|
+
await dispatchSegment(segments[i], client, chatId, chat, liveAccount, cfg, log, remaining, groupHistory);
|
|
6095
6144
|
}
|
|
6096
6145
|
}
|
|
6097
6146
|
const maxId = Math.max(...newMessages.map((m) => m.localId));
|