refactor(plugin): extract turn bootstrap/cache helpers into core module

This commit is contained in:
2026-03-08 05:25:53 +00:00
parent 05b902c0b2
commit f9ac401877
2 changed files with 44 additions and 61 deletions

View File

@@ -0,0 +1,43 @@
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
import { initTurnOrder } from "../turn-manager.js";
const channelSeenAccounts = new Map<string, Set<string>>();
function getAllBotAccountIds(api: OpenClawPluginApi): string[] {
const root = (api.config as Record<string, unknown>) || {};
const bindings = root.bindings as Array<Record<string, unknown>> | undefined;
if (!Array.isArray(bindings)) return [];
const ids: string[] = [];
for (const b of bindings) {
const match = b.match as Record<string, unknown> | undefined;
if (match?.channel === "discord" && typeof match.accountId === "string") {
ids.push(match.accountId);
}
}
return ids;
}
function getChannelBotAccountIds(api: OpenClawPluginApi, channelId: string): string[] {
const allBots = new Set(getAllBotAccountIds(api));
const seen = channelSeenAccounts.get(channelId);
if (!seen) return [];
return [...seen].filter((id) => allBots.has(id));
}
export function recordChannelAccount(channelId: string, accountId: string): boolean {
let seen = channelSeenAccounts.get(channelId);
if (!seen) {
seen = new Set();
channelSeenAccounts.set(channelId, seen);
}
if (seen.has(accountId)) return false;
seen.add(accountId);
return true;
}
export function ensureTurnOrder(api: OpenClawPluginApi, channelId: string): void {
const botAccounts = getChannelBotAccountIds(api, channelId);
if (botAccounts.length > 0) {
initTurnOrder(channelId, botAccounts);
}
}

View File

@@ -3,7 +3,6 @@ import path from "node:path";
import { spawn, type ChildProcess } from "node:child_process";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
import type { Decision, DirigentConfig } from "./rules.js";
import { initTurnOrder } from "./turn-manager.js";
import { startModeratorPresence, stopModeratorPresence } from "./moderator-presence.js";
import { registerMessageReceivedHook } from "./hooks/message-received.js";
import { registerBeforeModelResolveHook } from "./hooks/before-model-resolve.js";
@@ -16,6 +15,7 @@ import { getLivePluginConfig } from "./core/live-config.js";
import { ensurePolicyStateLoaded, persistPolicies, policyState } from "./policy/store.js";
import { buildAgentIdentity, buildUserIdToAccountIdMap, resolveAccountId } from "./core/identity.js";
import { extractMentionedUserIds, getModeratorUserId } from "./core/mentions.js";
import { ensureTurnOrder, recordChannelAccount } from "./core/turn-bootstrap.js";
// ── No-Reply API child process lifecycle ──────────────────────────────
let noReplyProcess: ChildProcess | null = null;
@@ -110,66 +110,6 @@ function pruneDecisionMap(now = Date.now()) {
}
}
/**
* Get all Discord bot accountIds from config bindings.
*/
function getAllBotAccountIds(api: OpenClawPluginApi): string[] {
const root = (api.config as Record<string, unknown>) || {};
const bindings = root.bindings as Array<Record<string, unknown>> | undefined;
if (!Array.isArray(bindings)) return [];
const ids: string[] = [];
for (const b of bindings) {
const match = b.match as Record<string, unknown> | undefined;
if (match?.channel === "discord" && typeof match.accountId === "string") {
ids.push(match.accountId);
}
}
return ids;
}
/**
* Track which bot accountIds have been seen in each channel via message_received.
* Key: channelId, Value: Set of accountIds seen.
*/
const channelSeenAccounts = new Map<string, Set<string>>();
/**
* Record a bot accountId seen in a channel.
* Returns true if this is a new account for this channel (turn order should be updated).
*/
function recordChannelAccount(channelId: string, accountId: string): boolean {
let seen = channelSeenAccounts.get(channelId);
if (!seen) {
seen = new Set();
channelSeenAccounts.set(channelId, seen);
}
if (seen.has(accountId)) return false;
seen.add(accountId);
return true;
}
/**
* Get the list of bot accountIds seen in a channel.
* Only returns accounts that are also in the global bindings (actual bots).
*/
function getChannelBotAccountIds(api: OpenClawPluginApi, channelId: string): string[] {
const allBots = new Set(getAllBotAccountIds(api));
const seen = channelSeenAccounts.get(channelId);
if (!seen) return [];
return [...seen].filter(id => allBots.has(id));
}
/**
* Ensure turn order is initialized for a channel.
* Uses only bot accounts that have been seen in this channel.
*/
function ensureTurnOrder(api: OpenClawPluginApi, channelId: string): void {
const botAccounts = getChannelBotAccountIds(api, channelId);
if (botAccounts.length > 0) {
initTurnOrder(channelId, botAccounts);
}
}
// --- Moderator bot helpers ---
/** Extract Discord user ID from a bot token (base64-encoded in first segment) */