From a484d08f5c75e3bcdfbfb9af3e2192c090df0fd9 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 6 Apr 2026 18:05:19 +0100 Subject: [PATCH] refactor: dedupe discord thread binding session helpers --- .../src/monitor/thread-bindings.lifecycle.ts | 58 ++--------------- .../monitor/thread-bindings.session-shared.ts | 59 +++++++++++++++++ .../thread-bindings.session-updates.ts | 63 ++----------------- 3 files changed, 69 insertions(+), 111 deletions(-) create mode 100644 extensions/discord/src/monitor/thread-bindings.session-shared.ts diff --git a/extensions/discord/src/monitor/thread-bindings.lifecycle.ts b/extensions/discord/src/monitor/thread-bindings.lifecycle.ts index 230a9cd7273..d0fac6a3e58 100644 --- a/extensions/discord/src/monitor/thread-bindings.lifecycle.ts +++ b/extensions/discord/src/monitor/thread-bindings.lifecycle.ts @@ -1,6 +1,5 @@ import { readAcpSessionEntry, type AcpSessionStoreEntry } from "openclaw/plugin-sdk/acp-runtime"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { normalizeAccountId } from "openclaw/plugin-sdk/routing"; import { parseDiscordTarget } from "../targets.js"; import { resolveChannelIdForBinding } from "./thread-bindings.discord-api.js"; import { getThreadBindingManager } from "./thread-bindings.manager.js"; @@ -8,17 +7,19 @@ import { resolveThreadBindingIntroText, resolveThreadBindingThreadName, } from "./thread-bindings.messages.js"; +import { + normalizeNonNegativeMs, + resolveBindingIdsForTargetSession, + updateBindingsForTargetSession, +} from "./thread-bindings.session-shared.js"; import { BINDINGS_BY_THREAD_ID, MANAGERS_BY_ACCOUNT_ID, - ensureBindingsLoaded, getThreadBindingToken, normalizeThreadId, rememberRecentUnboundWebhookEcho, removeBindingRecord, - resolveBindingIdsForSession, saveBindingsToDisk, - setBindingRecord, shouldPersistBindingMutations, } from "./thread-bindings.state.js"; import type { ThreadBindingRecord, ThreadBindingTargetKind } from "./thread-bindings.types.js"; @@ -73,55 +74,6 @@ async function mapWithConcurrency(params: { return params.items.map((_item, index) => resultsByIndex.get(index)!); } -function normalizeNonNegativeMs(raw: number): number { - if (!Number.isFinite(raw)) { - return 0; - } - return Math.max(0, Math.floor(raw)); -} - -function resolveBindingIdsForTargetSession(params: { - targetSessionKey: string; - accountId?: string; - targetKind?: ThreadBindingTargetKind; -}) { - ensureBindingsLoaded(); - const targetSessionKey = params.targetSessionKey.trim(); - if (!targetSessionKey) { - return []; - } - const accountId = params.accountId ? normalizeAccountId(params.accountId) : undefined; - return resolveBindingIdsForSession({ - targetSessionKey, - accountId, - targetKind: params.targetKind, - }); -} - -function updateBindingsForTargetSession( - ids: string[], - update: (existing: ThreadBindingRecord, now: number) => ThreadBindingRecord, -) { - if (ids.length === 0) { - return []; - } - const now = Date.now(); - const updated: ThreadBindingRecord[] = []; - for (const bindingKey of ids) { - const existing = BINDINGS_BY_THREAD_ID.get(bindingKey); - if (!existing) { - continue; - } - const nextRecord = update(existing, now); - setBindingRecord(nextRecord); - updated.push(nextRecord); - } - if (updated.length > 0 && shouldPersistBindingMutations()) { - saveBindingsToDisk({ force: true }); - } - return updated; -} - export function listThreadBindingsForAccount(accountId?: string): ThreadBindingRecord[] { const manager = getThreadBindingManager(accountId); if (!manager) { diff --git a/extensions/discord/src/monitor/thread-bindings.session-shared.ts b/extensions/discord/src/monitor/thread-bindings.session-shared.ts new file mode 100644 index 00000000000..fc0ec47f214 --- /dev/null +++ b/extensions/discord/src/monitor/thread-bindings.session-shared.ts @@ -0,0 +1,59 @@ +import { normalizeAccountId } from "openclaw/plugin-sdk/routing"; +import { + BINDINGS_BY_THREAD_ID, + ensureBindingsLoaded, + resolveBindingIdsForSession, + saveBindingsToDisk, + setBindingRecord, + shouldPersistBindingMutations, +} from "./thread-bindings.state.js"; +import type { ThreadBindingRecord, ThreadBindingTargetKind } from "./thread-bindings.types.js"; + +export function normalizeNonNegativeMs(raw: number): number { + if (!Number.isFinite(raw)) { + return 0; + } + return Math.max(0, Math.floor(raw)); +} + +export function resolveBindingIdsForTargetSession(params: { + targetSessionKey: string; + accountId?: string; + targetKind?: ThreadBindingTargetKind; +}) { + ensureBindingsLoaded(); + const targetSessionKey = params.targetSessionKey.trim(); + if (!targetSessionKey) { + return []; + } + const accountId = params.accountId ? normalizeAccountId(params.accountId) : undefined; + return resolveBindingIdsForSession({ + targetSessionKey, + accountId, + targetKind: params.targetKind, + }); +} + +export function updateBindingsForTargetSession( + ids: string[], + update: (existing: ThreadBindingRecord, now: number) => ThreadBindingRecord, +) { + if (ids.length === 0) { + return []; + } + const now = Date.now(); + const updated: ThreadBindingRecord[] = []; + for (const bindingKey of ids) { + const existing = BINDINGS_BY_THREAD_ID.get(bindingKey); + if (!existing) { + continue; + } + const nextRecord = update(existing, now); + setBindingRecord(nextRecord); + updated.push(nextRecord); + } + if (updated.length > 0 && shouldPersistBindingMutations()) { + saveBindingsToDisk({ force: true }); + } + return updated; +} diff --git a/extensions/discord/src/monitor/thread-bindings.session-updates.ts b/extensions/discord/src/monitor/thread-bindings.session-updates.ts index 09945f5efe0..266294b56e9 100644 --- a/extensions/discord/src/monitor/thread-bindings.session-updates.ts +++ b/extensions/discord/src/monitor/thread-bindings.session-updates.ts @@ -1,62 +1,9 @@ -import { normalizeAccountId } from "openclaw/plugin-sdk/routing"; import { - BINDINGS_BY_THREAD_ID, - ensureBindingsLoaded, - resolveBindingIdsForSession, - saveBindingsToDisk, - setBindingRecord, - shouldPersistBindingMutations, -} from "./thread-bindings.state.js"; -import type { ThreadBindingRecord, ThreadBindingTargetKind } from "./thread-bindings.types.js"; - -function normalizeNonNegativeMs(raw: number): number { - if (!Number.isFinite(raw)) { - return 0; - } - return Math.max(0, Math.floor(raw)); -} - -function resolveBindingIdsForTargetSession(params: { - targetSessionKey: string; - accountId?: string; - targetKind?: ThreadBindingTargetKind; -}) { - ensureBindingsLoaded(); - const targetSessionKey = params.targetSessionKey.trim(); - if (!targetSessionKey) { - return []; - } - const accountId = params.accountId ? normalizeAccountId(params.accountId) : undefined; - return resolveBindingIdsForSession({ - targetSessionKey, - accountId, - targetKind: params.targetKind, - }); -} - -function updateBindingsForTargetSession( - ids: string[], - update: (existing: ThreadBindingRecord, now: number) => ThreadBindingRecord, -) { - if (ids.length === 0) { - return []; - } - const now = Date.now(); - const updated: ThreadBindingRecord[] = []; - for (const bindingKey of ids) { - const existing = BINDINGS_BY_THREAD_ID.get(bindingKey); - if (!existing) { - continue; - } - const nextRecord = update(existing, now); - setBindingRecord(nextRecord); - updated.push(nextRecord); - } - if (updated.length > 0 && shouldPersistBindingMutations()) { - saveBindingsToDisk({ force: true }); - } - return updated; -} + normalizeNonNegativeMs, + resolveBindingIdsForTargetSession, + updateBindingsForTargetSession, +} from "./thread-bindings.session-shared.js"; +import type { ThreadBindingRecord } from "./thread-bindings.types.js"; export function setThreadBindingIdleTimeoutBySessionKey(params: { targetSessionKey: string;