@meet-im/meet 3.4.1 → 3.4.3
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const MEET_PLUGIN_VERSION = "3.4.
|
|
1
|
+
export declare const MEET_PLUGIN_VERSION = "3.4.3";
|
|
2
2
|
export declare const MEET_OPENCLAW_VERSION = "2026.5.18";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const MEET_PLUGIN_VERSION = "3.4.
|
|
1
|
+
export const MEET_PLUGIN_VERSION = "3.4.3";
|
|
2
2
|
export const MEET_OPENCLAW_VERSION = "2026.5.18";
|
package/dist/src/monitor.js
CHANGED
|
@@ -3,6 +3,7 @@ import { resolveMeetAccount, listEnabledMeetAccounts } from "./accounts.js";
|
|
|
3
3
|
import { createMeetClient, closeMeetClient, closeAllMeetClients, getPollingOptions } from "./client.js";
|
|
4
4
|
import { handleMeetMessage } from "./bot.js";
|
|
5
5
|
import { msgContentToContext, enrichContextWithUserNames } from "./sdk-bridge.js";
|
|
6
|
+
const activeMonitors = new Map();
|
|
6
7
|
export async function monitorMeetProvider(opts = {}) {
|
|
7
8
|
const cfg = opts.config;
|
|
8
9
|
if (!cfg) {
|
|
@@ -38,13 +39,32 @@ async function monitorSingleAccount(params) {
|
|
|
38
39
|
const { accountId } = account;
|
|
39
40
|
const log = runtime?.log ?? console.log;
|
|
40
41
|
const error = runtime?.error ?? console.error;
|
|
42
|
+
const existingMonitor = activeMonitors.get(accountId);
|
|
43
|
+
if (existingMonitor) {
|
|
44
|
+
if (abortSignal) {
|
|
45
|
+
const stopExistingMonitor = () => {
|
|
46
|
+
existingMonitor.stop();
|
|
47
|
+
};
|
|
48
|
+
if (abortSignal.aborted) {
|
|
49
|
+
stopExistingMonitor();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
abortSignal.addEventListener("abort", stopExistingMonitor, { once: true });
|
|
53
|
+
void existingMonitor.promise.finally(() => {
|
|
54
|
+
abortSignal.removeEventListener("abort", stopExistingMonitor);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return existingMonitor.promise;
|
|
59
|
+
}
|
|
41
60
|
const pollTimeoutMs = account.config.pollTimeout ?? 30000;
|
|
42
61
|
log(`[${accountId}]: starting with pollTimeout=${pollTimeoutMs}ms`);
|
|
43
62
|
const bot = createMeetClient(account);
|
|
44
63
|
const botUserId = extractBotUserId(account.apiToken ?? "");
|
|
45
64
|
const groupHistories = new Map();
|
|
46
65
|
const messageQueue = new KeyedAsyncQueue();
|
|
47
|
-
|
|
66
|
+
let stopMonitor = () => { };
|
|
67
|
+
const monitorPromise = new Promise((resolve, reject) => {
|
|
48
68
|
let isCleaningUp = false;
|
|
49
69
|
const cleanup = () => {
|
|
50
70
|
if (isCleaningUp)
|
|
@@ -53,6 +73,7 @@ async function monitorSingleAccount(params) {
|
|
|
53
73
|
bot.stopPolling();
|
|
54
74
|
closeMeetClient(accountId);
|
|
55
75
|
};
|
|
76
|
+
stopMonitor = cleanup;
|
|
56
77
|
const handleAbort = () => {
|
|
57
78
|
log(`[${accountId}]: abort signal received, stopping`);
|
|
58
79
|
cleanup();
|
|
@@ -151,6 +172,17 @@ async function monitorSingleAccount(params) {
|
|
|
151
172
|
reject(err);
|
|
152
173
|
});
|
|
153
174
|
});
|
|
175
|
+
activeMonitors.set(accountId, {
|
|
176
|
+
promise: monitorPromise,
|
|
177
|
+
stop: () => {
|
|
178
|
+
stopMonitor();
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
return monitorPromise.finally(() => {
|
|
182
|
+
if (activeMonitors.get(accountId)?.promise === monitorPromise) {
|
|
183
|
+
activeMonitors.delete(accountId);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
154
186
|
}
|
|
155
187
|
export function stopMeetMonitor(accountId) {
|
|
156
188
|
if (accountId) {
|
|
@@ -4,6 +4,14 @@ import { createTypingCallbacks } from "openclaw/plugin-sdk/channel-message";
|
|
|
4
4
|
import { getMeetRuntime } from "./runtime.js";
|
|
5
5
|
import { sendMessageMeet, sendMediaMeet } from "./send.js";
|
|
6
6
|
import { sendTypingMeet, stopTypingMeet } from "./typing.js";
|
|
7
|
+
function normalizeVisibleTextForDedup(text) {
|
|
8
|
+
return normalizeStatusTextForDedup(text.replace(/\r\n/g, "\n").trim());
|
|
9
|
+
}
|
|
10
|
+
function normalizeStatusTextForDedup(text) {
|
|
11
|
+
return text
|
|
12
|
+
.replace(/(⏱️\s*Uptime:\s*gateway\s+)\d+s(\s*·\s*system\s+)/g, "$1<secs>$2")
|
|
13
|
+
.replace(/(⏱️\s*Uptime:\s*gateway\s+[^·\n]+·\s*system\s+)\d+s(\b)/g, "$1<secs>$2");
|
|
14
|
+
}
|
|
7
15
|
function resolveMeetConversationType(chatId) {
|
|
8
16
|
if (chatId.startsWith("channel:")) {
|
|
9
17
|
return "group";
|
|
@@ -91,6 +99,7 @@ export async function createMeetReplyDispatcher(opts) {
|
|
|
91
99
|
: undefined;
|
|
92
100
|
const shouldAutoMentionSender = chatType === "channel" && mentionedBot === true && !!senderId;
|
|
93
101
|
const senderMentionText = shouldAutoMentionSender ? `<@${senderId}>` : undefined;
|
|
102
|
+
let lastDeliveredVisibleText;
|
|
94
103
|
// 创建 typing callbacks(如果配置了 typing 且有必要参数)
|
|
95
104
|
const hasTypingParams = typingMode && typingMode !== "none" && sessionInfo && apiToken;
|
|
96
105
|
// stop 请求需要等待最后一个 start 完成,避免乱序
|
|
@@ -170,6 +179,18 @@ export async function createMeetReplyDispatcher(opts) {
|
|
|
170
179
|
opts.runtime.log?.(`[${accountId}]: reply deliver kind=${_info.kind} text_len=${payload.text?.length ?? 0} media_count=${payload.mediaUrls?.length ?? (payload.mediaUrl ? 1 : 0)} reasoning=${payload.isReasoning === true} error=${payload.isError === true}`);
|
|
171
180
|
const text = payload.text ?? "";
|
|
172
181
|
const mediaUrls = payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : []);
|
|
182
|
+
if (mediaUrls.length === 0) {
|
|
183
|
+
const normalizedVisibleText = normalizeVisibleTextForDedup(text);
|
|
184
|
+
if (_info.kind === "final" &&
|
|
185
|
+
normalizedVisibleText &&
|
|
186
|
+
normalizedVisibleText === lastDeliveredVisibleText) {
|
|
187
|
+
opts.runtime.log?.(`[${accountId}]: suppress duplicate final visible text for ${chatId}`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (normalizedVisibleText) {
|
|
191
|
+
lastDeliveredVisibleText = normalizedVisibleText;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
173
194
|
// 如果既没有文本也没有媒体,直接返回
|
|
174
195
|
if (!text.trim() && mediaUrls.length === 0) {
|
|
175
196
|
return;
|