import {
createChannelInboundDebouncer,
shouldDebounceTextInbound,
} from "openclaw/plugin-sdk/channel-inbound"; import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import type { ResolvedSlackAccount } from "../accounts.js"; import type { SlackMessageEvent } from "../types.js"; import { stripSlackMentionsForCommandDetection } from "./commands.js"; import type { SlackMonitorContext } from "./context.js"; import {
buildSlackDebounceKey,
buildTopLevelSlackConversationKey,
} from "./message-handler/debounce-key.js"; import { createSlackThreadTsResolver } from "./thread-resolution.js";
type SlackMessagePipeline = typeofimport("./message-handler/pipeline.runtime.js");
let slackMessagePipelinePromise: Promise<SlackMessagePipeline> | undefined;
function loadSlackMessagePipeline(): Promise<SlackMessagePipeline> {
slackMessagePipelinePromise ??= import("./message-handler/pipeline.runtime.js"); return slackMessagePipelinePromise;
}
const pruneAppMentionRetryKeys = (now: number) => { for (const [key, expiresAt] of appMentionRetryKeys) { if (expiresAt <= now) {
appMentionRetryKeys.delete(key);
}
} for (const [key, expiresAt] of appMentionDispatchedKeys) { if (expiresAt <= now) {
appMentionDispatchedKeys.delete(key);
}
}
};
const rememberAppMentionRetryKey = (key: string) => { const now = Date.now();
pruneAppMentionRetryKeys(now);
appMentionRetryKeys.set(key, now + APP_MENTION_RETRY_TTL_MS);
};
const consumeAppMentionRetryKey = (key: string) => { const now = Date.now();
pruneAppMentionRetryKeys(now); if (!appMentionRetryKeys.has(key)) { returnfalse;
}
appMentionRetryKeys.delete(key); returntrue;
};
return async (message, opts) => { if (opts.source === "message" && message.type !== "message") { return;
} if (
opts.source === "message" &&
message.subtype &&
message.subtype !== "file_share" &&
message.subtype !== "bot_message" &&
message.subtype !== "thread_broadcast"
) { return;
} const seenMessageKey = buildSeenMessageKey(message.channel, message.ts); const wasSeen = seenMessageKey ? ctx.markMessageSeen(message.channel, message.ts) : false; if (seenMessageKey && opts.source === "message" && !wasSeen) { // Prime exactly one fallback app_mention allowance immediately so a near-simultaneous // app_mention is not dropped while message handling is still in-flight.
rememberAppMentionRetryKey(seenMessageKey);
} if (seenMessageKey && wasSeen) { // Allow exactly one app_mention retry if the same ts was previously dropped // from the message stream before it reached dispatch. if (opts.source !== "app_mention" || !consumeAppMentionRetryKey(seenMessageKey)) { return;
}
}
trackEvent?.(); const resolvedMessage = await threadTsResolver.resolve({ message, source: opts.source }); const debounceKey = buildSlackDebounceKey(resolvedMessage, ctx.accountId); const conversationKey = buildTopLevelSlackConversationKey(resolvedMessage, ctx.accountId); const canDebounce = debounceMs > 0 && shouldDebounceSlackMessage(resolvedMessage, ctx.cfg); if (!canDebounce && conversationKey) { const pendingKeys = pendingTopLevelDebounceKeys.get(conversationKey); if (pendingKeys && pendingKeys.size > 0) { const keysToFlush = Array.from(pendingKeys); for (const pendingKey of keysToFlush) {
await debouncer.flushKey(pendingKey);
}
}
} if (canDebounce && debounceKey && conversationKey) { const pendingKeys = pendingTopLevelDebounceKeys.get(conversationKey) ?? new Set<string>();
pendingKeys.add(debounceKey);
pendingTopLevelDebounceKeys.set(conversationKey, pendingKeys);
}
await debouncer.enqueue({ message: resolvedMessage, opts });
};
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.