mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-21 05:32:53 +00:00
refactor: dedupe reply routing readers
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { getActivePluginChannelRegistry } from "../../plugins/runtime.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
type CommandSurfaceParams = {
|
||||
ctx: {
|
||||
@@ -32,13 +33,11 @@ export function resolveCommandSurfaceChannel(params: CommandSurfaceParams): stri
|
||||
params.command.channel ??
|
||||
params.ctx.Surface ??
|
||||
params.ctx.Provider;
|
||||
return String(channel ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
return normalizeOptionalString(channel)?.toLowerCase() ?? "";
|
||||
}
|
||||
|
||||
export function resolveChannelAccountId(params: ChannelAccountParams): string {
|
||||
const accountId = typeof params.ctx.AccountId === "string" ? params.ctx.AccountId.trim() : "";
|
||||
const accountId = normalizeOptionalString(params.ctx.AccountId) ?? "";
|
||||
if (accountId) {
|
||||
return accountId;
|
||||
}
|
||||
@@ -46,6 +45,6 @@ export function resolveChannelAccountId(params: ChannelAccountParams): string {
|
||||
const plugin = getActivePluginChannelRegistry()?.channels.find(
|
||||
(entry) => entry.plugin.id === channel,
|
||||
)?.plugin;
|
||||
const configuredDefault = plugin?.config.defaultAccountId?.(params.cfg)?.trim();
|
||||
const configuredDefault = normalizeOptionalString(plugin?.config.defaultAccountId?.(params.cfg));
|
||||
return configuredDefault || "default";
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
removeChannelAllowFromStoreEntry,
|
||||
} from "../../pairing/pairing-store.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeOptionalAccountId } from "../../routing/session-key.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { normalizeStringEntries } from "../../shared/string-normalization.js";
|
||||
import {
|
||||
rejectNonOwnerCommand,
|
||||
@@ -65,7 +66,9 @@ function resolveAllowlistAccountId(params: {
|
||||
return explicitAccountId;
|
||||
}
|
||||
const plugin = getChannelPlugin(params.channelId);
|
||||
const configuredDefaultAccountId = plugin?.config.defaultAccountId?.(params.cfg)?.trim();
|
||||
const configuredDefaultAccountId = normalizeOptionalString(
|
||||
plugin?.config.defaultAccountId?.(params.cfg),
|
||||
);
|
||||
const ctxAccountId = normalizeOptionalAccountId(params.ctxAccountId);
|
||||
return configuredDefaultAccountId || ctxAccountId || DEFAULT_ACCOUNT_ID;
|
||||
}
|
||||
@@ -126,8 +129,8 @@ function parseAllowlistCommand(raw: string): AllowlistCommand | null {
|
||||
}
|
||||
const kv = token.split("=");
|
||||
if (kv.length === 2) {
|
||||
const key = kv[0]?.trim().toLowerCase();
|
||||
const value = kv[1]?.trim();
|
||||
const key = normalizeOptionalString(kv[0])?.toLowerCase();
|
||||
const value = normalizeOptionalString(kv[1]);
|
||||
if (key === "channel") {
|
||||
if (value) {
|
||||
channel = value;
|
||||
@@ -280,7 +283,7 @@ export const handleAllowlistCommand: CommandHandler = async (params, allowTextCo
|
||||
reply: { text: "⚠️ Unknown channel. Add channel=<id> to the command." },
|
||||
};
|
||||
}
|
||||
if (parsed.account?.trim() && !normalizeOptionalAccountId(parsed.account)) {
|
||||
if (normalizeOptionalString(parsed.account) && !normalizeOptionalAccountId(parsed.account)) {
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import type { CommandHandler } from "./commands-types.js";
|
||||
import { stripMentions, stripStructuralPrefixes } from "./mentions.js";
|
||||
|
||||
@@ -31,7 +32,7 @@ function extractCompactInstructions(params: {
|
||||
}
|
||||
|
||||
function isCompactionSkipReason(reason?: string): boolean {
|
||||
const text = reason?.trim().toLowerCase() ?? "";
|
||||
const text = normalizeOptionalString(reason)?.toLowerCase() ?? "";
|
||||
return (
|
||||
text.includes("nothing to compact") ||
|
||||
text.includes("below threshold") ||
|
||||
@@ -41,7 +42,7 @@ function isCompactionSkipReason(reason?: string): boolean {
|
||||
}
|
||||
|
||||
function formatCompactionReason(reason?: string): string | undefined {
|
||||
const text = reason?.trim();
|
||||
const text = normalizeOptionalString(reason);
|
||||
if (!text) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ensureAuthProfileStore } from "../../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
export function resolveProfileOverride(params: {
|
||||
rawProfile?: string;
|
||||
@@ -7,7 +8,7 @@ export function resolveProfileOverride(params: {
|
||||
cfg: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
}): { profileId?: string; error?: string } {
|
||||
const raw = params.rawProfile?.trim();
|
||||
const raw = normalizeOptionalString(params.rawProfile);
|
||||
if (!raw) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
} from "../../plugins/conversation-binding.js";
|
||||
import { getGlobalHookRunner, getGlobalPluginRegistry } from "../../plugins/hook-runner-global.js";
|
||||
import { resolveSendPolicy } from "../../sessions/send-policy.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { normalizeTtsAutoMode, resolveConfiguredTtsMode } from "../../tts/tts-config.js";
|
||||
import { normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||
import type { FinalizedMsgContext } from "../templating.js";
|
||||
@@ -95,7 +96,8 @@ async function maybeApplyTtsToReplyPayload(
|
||||
|
||||
const AUDIO_PLACEHOLDER_RE = /^<media:audio>(\s*\([^)]*\))?$/i;
|
||||
const AUDIO_HEADER_RE = /^\[Audio\b/i;
|
||||
const normalizeMediaType = (value: string): string => value.split(";")[0]?.trim().toLowerCase();
|
||||
const normalizeMediaType = (value: string): string =>
|
||||
normalizeOptionalString(value.split(";")[0])?.toLowerCase() ?? "";
|
||||
|
||||
const isInboundAudioContext = (ctx: FinalizedMsgContext): boolean => {
|
||||
const rawTypes = [
|
||||
@@ -136,8 +138,10 @@ const resolveSessionStoreLookup = (
|
||||
entry?: SessionEntry;
|
||||
} => {
|
||||
const targetSessionKey =
|
||||
ctx.CommandSource === "native" ? ctx.CommandTargetSessionKey?.trim() : undefined;
|
||||
const sessionKey = (targetSessionKey ?? ctx.SessionKey)?.trim();
|
||||
ctx.CommandSource === "native"
|
||||
? normalizeOptionalString(ctx.CommandTargetSessionKey)
|
||||
: undefined;
|
||||
const sessionKey = normalizeOptionalString(targetSessionKey ?? ctx.SessionKey);
|
||||
if (!sessionKey) {
|
||||
return {};
|
||||
}
|
||||
@@ -742,13 +746,13 @@ export async function dispatchReplyFromConfig(params: {
|
||||
message?: string;
|
||||
}) => {
|
||||
if (payload.status === "pending") {
|
||||
if (payload.command?.trim()) {
|
||||
if (normalizeOptionalString(payload.command)) {
|
||||
return normalizeWorkingLabel(`awaiting approval: ${payload.command}`);
|
||||
}
|
||||
return "awaiting approval";
|
||||
}
|
||||
if (payload.status === "unavailable") {
|
||||
if (payload.message?.trim()) {
|
||||
if (normalizeOptionalString(payload.message)) {
|
||||
return normalizeWorkingLabel(payload.message);
|
||||
}
|
||||
return "approval unavailable";
|
||||
@@ -756,10 +760,10 @@ export async function dispatchReplyFromConfig(params: {
|
||||
return "";
|
||||
};
|
||||
const summarizePatchLabel = (payload: { summary?: string; title?: string }) => {
|
||||
if (payload.summary?.trim()) {
|
||||
if (normalizeOptionalString(payload.summary)) {
|
||||
return normalizeWorkingLabel(payload.summary);
|
||||
}
|
||||
if (payload.title?.trim()) {
|
||||
if (normalizeOptionalString(payload.title)) {
|
||||
return normalizeWorkingLabel(payload.title);
|
||||
}
|
||||
return "";
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { SessionEntry } from "../../config/sessions.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { generateSecureToken } from "../../infra/secure-random.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { resolveGatewayMessageChannel } from "../../utils/message-channel.js";
|
||||
import {
|
||||
listReservedChatSlashCommandNames,
|
||||
@@ -57,12 +58,12 @@ function resolveSlashCommandName(commandBodyNormalized: string): string | null {
|
||||
return null;
|
||||
}
|
||||
const match = trimmed.match(/^\/([^\s:]+)(?::|\s|$)/);
|
||||
const name = match?.[1]?.trim().toLowerCase() ?? "";
|
||||
const name = normalizeOptionalString(match?.[1])?.toLowerCase() ?? "";
|
||||
return name ? name : null;
|
||||
}
|
||||
|
||||
function expandBundleCommandPromptTemplate(template: string, args?: string): string {
|
||||
const normalizedArgs = args?.trim() || "";
|
||||
const normalizedArgs = normalizeOptionalString(args) || "";
|
||||
const rendered = template.includes("$ARGUMENTS")
|
||||
? template.replaceAll("$ARGUMENTS", normalizedArgs)
|
||||
: template;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { resolveSessionParentSessionKey } from "../../channels/plugins/session-c
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import { applyModelOverrideToSessionEntry } from "../../sessions/model-overrides.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import type { ThinkLevel } from "./directives.js";
|
||||
|
||||
export type ModelDirectiveSelection = {
|
||||
@@ -148,7 +149,7 @@ function resolveParentSessionKeyCandidate(params: {
|
||||
sessionKey?: string;
|
||||
parentSessionKey?: string;
|
||||
}): string | null {
|
||||
const explicit = params.parentSessionKey?.trim();
|
||||
const explicit = normalizeOptionalString(params.parentSessionKey);
|
||||
if (explicit && explicit !== params.sessionKey) {
|
||||
return explicit;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { resolveEmbeddedSessionLane } from "../../../agents/pi-embedded-runner/lanes.js";
|
||||
import { clearCommandLane } from "../../../process/command-queue.js";
|
||||
import { normalizeOptionalString } from "../../../shared/string-coerce.js";
|
||||
import { clearFollowupDrainCallback } from "./drain.js";
|
||||
import { clearFollowupQueue } from "./state.js";
|
||||
|
||||
@@ -57,7 +58,7 @@ export function clearSessionQueues(keys: Array<string | undefined>): ClearSessio
|
||||
const clearLane = resolveQueueCleanupLaneClearer();
|
||||
|
||||
for (const key of keys) {
|
||||
const cleaned = key?.trim();
|
||||
const cleaned = normalizeOptionalString(key);
|
||||
if (!cleaned || seen.has(cleaned)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getChannelPlugin } from "../../../channels/plugins/index.js";
|
||||
import type { InboundDebounceByProvider } from "../../../config/types.messages.js";
|
||||
import { normalizeOptionalString } from "../../../shared/string-coerce.js";
|
||||
import { normalizeQueueDropPolicy, normalizeQueueMode } from "./normalize.js";
|
||||
import { DEFAULT_QUEUE_CAP, DEFAULT_QUEUE_DEBOUNCE_MS, DEFAULT_QUEUE_DROP } from "./state.js";
|
||||
import type { QueueMode, QueueSettings, ResolveQueueSettingsParams } from "./types.js";
|
||||
@@ -30,7 +31,7 @@ function resolvePluginDebounce(channelKey: string | undefined): number | undefin
|
||||
}
|
||||
|
||||
export function resolveQueueSettings(params: ResolveQueueSettingsParams): QueueSettings {
|
||||
const channelKey = params.channel?.trim().toLowerCase();
|
||||
const channelKey = normalizeOptionalString(params.channel)?.toLowerCase();
|
||||
const queueCfg = params.cfg.messages?.queue;
|
||||
const providerModeRaw =
|
||||
channelKey && queueCfg?.byChannel
|
||||
|
||||
@@ -10,6 +10,7 @@ import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import { updateSessionStore } from "../../config/sessions.js";
|
||||
import { applyModelOverrideToSessionEntry } from "../../sessions/model-overrides.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import type { MsgContext, TemplateContext } from "../templating.js";
|
||||
import { resolveModelDirectiveSelection, type ModelDirectiveSelection } from "./model-selection.js";
|
||||
|
||||
@@ -104,7 +105,7 @@ export async function applyResetModelOverride(params: {
|
||||
if (!params.resetTriggered) {
|
||||
return {};
|
||||
}
|
||||
const rawBody = params.bodyStripped?.trim();
|
||||
const rawBody = normalizeOptionalString(params.bodyStripped);
|
||||
if (!rawBody) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user