@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.
Files changed (2) hide show
  1. package/dist/index.js +72 -23
  2. 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
- enqueueAndWakeSystemEvent(msg, "wechat:auth_lost", log);
5585
+ enqueueWeChatSystemEvent(msg, "wechat:auth_lost");
5595
5586
  } else if (prevStatus === void 0 && !isLinked) {
5596
- enqueueAndWakeSystemEvent(
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
- enqueueAndWakeSystemEvent(
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
- async function processUnreadChat(client, chat, lastSeenId, account, cfg, log, skipOpen) {
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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-wechat/wechat",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",