mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 01:50:22 +00:00
refactor: dedupe approval and routing readers
This commit is contained in:
@@ -8,6 +8,7 @@ import type {
|
||||
PluginHookMessageReceivedEvent,
|
||||
PluginHookMessageSentEvent,
|
||||
} from "../plugins/types.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type {
|
||||
MessagePreprocessedHookContext,
|
||||
MessageReceivedHookContext,
|
||||
@@ -194,8 +195,8 @@ function resolveInboundConversation(canonical: CanonicalInboundMessageHookContex
|
||||
: null;
|
||||
if (pluginResolved) {
|
||||
return {
|
||||
conversationId: pluginResolved.conversationId?.trim() || undefined,
|
||||
parentConversationId: pluginResolved.parentConversationId?.trim() || undefined,
|
||||
conversationId: normalizeOptionalString(pluginResolved.conversationId),
|
||||
parentConversationId: normalizeOptionalString(pluginResolved.parentConversationId),
|
||||
};
|
||||
}
|
||||
const baseConversationId = stripChannelPrefix(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { parseAgentSessionKey } from "../routing/session-key.js";
|
||||
import { compileSafeRegex, testRegexWithBoundedInput } from "../security/safe-regex.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export type ApprovalRequestFilterInput = {
|
||||
agentId?: string | null;
|
||||
@@ -26,7 +27,7 @@ export function matchesApprovalRequestFilters(params: {
|
||||
fallbackAgentIdFromSessionKey?: boolean;
|
||||
}): boolean {
|
||||
if (params.agentFilter?.length) {
|
||||
const explicitAgentId = params.request.agentId?.trim() || undefined;
|
||||
const explicitAgentId = normalizeOptionalString(params.request.agentId);
|
||||
const sessionAgentId = params.fallbackAgentIdFromSessionKey
|
||||
? (parseAgentSessionKey(params.request.sessionKey)?.agentId ?? undefined)
|
||||
: undefined;
|
||||
@@ -37,7 +38,7 @@ export function matchesApprovalRequestFilters(params: {
|
||||
}
|
||||
|
||||
if (params.sessionFilter?.length) {
|
||||
const sessionKey = params.request.sessionKey?.trim();
|
||||
const sessionKey = normalizeOptionalString(params.request.sessionKey);
|
||||
if (!sessionKey || !matchesApprovalRequestSessionFilter(sessionKey, params.sessionFilter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
buildPluginApprovalPendingReplyPayload,
|
||||
buildPluginApprovalResolvedReplyPayload,
|
||||
} from "../plugin-sdk/approval-renderers.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
isDeliverableMessageChannel,
|
||||
normalizeMessageChannel,
|
||||
@@ -312,8 +313,8 @@ function defaultResolveSessionTarget(params: {
|
||||
cfg: params.cfg,
|
||||
request: params.request,
|
||||
turnSourceChannel: normalizeTurnSourceChannel(params.request.request.turnSourceChannel),
|
||||
turnSourceTo: params.request.request.turnSourceTo?.trim() || undefined,
|
||||
turnSourceAccountId: params.request.request.turnSourceAccountId?.trim() || undefined,
|
||||
turnSourceTo: normalizeOptionalString(params.request.request.turnSourceTo),
|
||||
turnSourceAccountId: normalizeOptionalString(params.request.request.turnSourceAccountId),
|
||||
turnSourceThreadId: params.request.request.turnSourceThreadId ?? undefined,
|
||||
});
|
||||
if (!resolvedTarget?.channel || !resolvedTarget.to) {
|
||||
|
||||
@@ -263,8 +263,8 @@ export function getExecApprovalReplyMetadata(
|
||||
return null;
|
||||
}
|
||||
const record = execApproval as Record<string, unknown>;
|
||||
const approvalId = typeof record.approvalId === "string" ? record.approvalId.trim() : "";
|
||||
const approvalSlug = typeof record.approvalSlug === "string" ? record.approvalSlug.trim() : "";
|
||||
const approvalId = normalizeOptionalString(record.approvalId) ?? "";
|
||||
const approvalSlug = normalizeOptionalString(record.approvalSlug) ?? "";
|
||||
if (!approvalId || !approvalSlug) {
|
||||
return null;
|
||||
}
|
||||
@@ -275,10 +275,8 @@ export function getExecApprovalReplyMetadata(
|
||||
value === "allow-once" || value === "allow-always" || value === "deny",
|
||||
)
|
||||
: undefined;
|
||||
const agentId =
|
||||
typeof record.agentId === "string" ? record.agentId.trim() || undefined : undefined;
|
||||
const sessionKey =
|
||||
typeof record.sessionKey === "string" ? record.sessionKey.trim() || undefined : undefined;
|
||||
const agentId = normalizeOptionalString(record.agentId);
|
||||
const sessionKey = normalizeOptionalString(record.sessionKey);
|
||||
return {
|
||||
approvalId,
|
||||
approvalSlug,
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
resolveChannelApprovalCapability,
|
||||
} from "../channels/plugins/index.js";
|
||||
import { loadConfig, type OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
INTERNAL_MESSAGE_CHANNEL,
|
||||
isDeliverableMessageChannel,
|
||||
@@ -41,7 +42,7 @@ export function resolveExecApprovalInitiatingSurfaceState(params: {
|
||||
}): ExecApprovalInitiatingSurfaceState {
|
||||
const channel = normalizeMessageChannel(params.channel);
|
||||
const channelLabel = labelForChannel(channel);
|
||||
const accountId = params.accountId?.trim() || undefined;
|
||||
const accountId = normalizeOptionalString(params.accountId);
|
||||
if (!channel || channel === INTERNAL_MESSAGE_CHANNEL || channel === "tui") {
|
||||
return { kind: "enabled", channel, channelLabel, accountId };
|
||||
}
|
||||
@@ -78,7 +79,7 @@ export function listNativeExecApprovalClientLabels(params?: {
|
||||
return listChannelPlugins()
|
||||
.filter((plugin) => plugin.id !== excludeChannel)
|
||||
.filter((plugin) => hasNativeExecApprovalCapability(plugin.id))
|
||||
.map((plugin) => plugin.meta.label?.trim())
|
||||
.map((plugin) => normalizeOptionalString(plugin.meta.label))
|
||||
.filter((label): label is string => Boolean(label))
|
||||
.toSorted((a, b) => a.localeCompare(b));
|
||||
}
|
||||
@@ -92,8 +93,8 @@ export function describeNativeExecApprovalClientSetup(params: {
|
||||
if (!channel || channel === INTERNAL_MESSAGE_CHANNEL || channel === "tui") {
|
||||
return null;
|
||||
}
|
||||
const channelLabel = params.channelLabel?.trim() || labelForChannel(channel);
|
||||
const accountId = params.accountId?.trim() || undefined;
|
||||
const channelLabel = normalizeOptionalString(params.channelLabel) ?? labelForChannel(channel);
|
||||
const accountId = normalizeOptionalString(params.accountId);
|
||||
return (
|
||||
resolveChannelApprovalCapability(getChannelPlugin(channel))?.describeExecApprovalSetup?.({
|
||||
channel,
|
||||
|
||||
@@ -2,7 +2,7 @@ import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
|
||||
import { readStringValue } from "../shared/string-coerce.js";
|
||||
import { normalizeOptionalString, readStringValue } from "../shared/string-coerce.js";
|
||||
import { resolveAllowAlwaysPatternEntries } from "./exec-approvals-allowlist.js";
|
||||
import type { ExecCommandSegment } from "./exec-approvals-analysis.js";
|
||||
import { expandHomePrefix } from "./home-dir.js";
|
||||
@@ -852,7 +852,7 @@ export function addAllowlistEntry(
|
||||
if (!trimmed) {
|
||||
return;
|
||||
}
|
||||
const trimmedArgPattern = options?.argPattern?.trim() || undefined;
|
||||
const trimmedArgPattern = normalizeOptionalString(options?.argPattern);
|
||||
const existingEntry = allowlist.find(
|
||||
(entry) => entry.pattern === trimmed && (entry.argPattern ?? undefined) === trimmedArgPattern,
|
||||
);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
function normalizeConversationId(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed || undefined;
|
||||
return normalizeOptionalString(value);
|
||||
}
|
||||
|
||||
function resolveExplicitConversationTargetId(target: string): string | undefined {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/ind
|
||||
import type { ChannelDirectoryEntryKind, ChannelId } from "../../channels/plugins/types.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { getActivePluginChannelRegistryVersion } from "../../plugins/runtime.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
export function normalizeChannelTargetInput(raw: string): string {
|
||||
return raw.trim();
|
||||
@@ -42,14 +43,13 @@ export function normalizeTargetForProvider(provider: string, raw?: string): stri
|
||||
if (!raw) {
|
||||
return undefined;
|
||||
}
|
||||
const fallback = raw.trim() || undefined;
|
||||
const fallback = normalizeOptionalString(raw);
|
||||
if (!fallback) {
|
||||
return undefined;
|
||||
}
|
||||
const providerId = normalizeChannelId(provider);
|
||||
const normalizer = providerId ? resolveTargetNormalizer(providerId) : undefined;
|
||||
const normalized = normalizer?.(raw) ?? fallback;
|
||||
return normalized || undefined;
|
||||
return normalizeOptionalString(normalizer?.(raw) ?? fallback);
|
||||
}
|
||||
|
||||
export type TargetResolveKindLike = ChannelDirectoryEntryKind | "channel";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
export function normalizeOutboundThreadId(value?: string | number | null): string | undefined {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
@@ -8,6 +10,5 @@ export function normalizeOutboundThreadId(value?: string | number | null): strin
|
||||
}
|
||||
return String(Math.trunc(value));
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
return normalizeOptionalString(value);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export type InlineDirectiveParseResult = {
|
||||
text: string;
|
||||
audioAsVoice: boolean;
|
||||
@@ -185,7 +187,7 @@ export function parseInlineDirectives(
|
||||
cleaned = normalizeDirectiveWhitespace(cleaned);
|
||||
|
||||
const replyToId =
|
||||
lastExplicitId ?? (sawCurrent ? currentMessageId?.trim() || undefined : undefined);
|
||||
lastExplicitId ?? (sawCurrent ? normalizeOptionalString(currentMessageId) : undefined);
|
||||
|
||||
return {
|
||||
text: cleaned,
|
||||
|
||||
Reference in New Issue
Block a user