fix(approval): split discord and slack runtime seams

This commit is contained in:
Vincent Koc
2026-04-10 09:07:06 +01:00
parent 8ed7c95a6a
commit c3d3cf23bc
4 changed files with 60 additions and 62 deletions

View File

@@ -25,7 +25,7 @@ import type {
ExecApprovalDecision,
} from "openclaw/plugin-sdk/infra-runtime";
import { logDebug, logError, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { shouldHandleDiscordApprovalRequest } from "./approval-native.js";
import { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
import { isDiscordExecApprovalClientEnabled } from "./exec-approvals.js";
import { createDiscordClient, stripUndefinedFields } from "./send.shared.js";
import { DiscordUiContainer } from "./ui.js";

View File

@@ -1,30 +1,26 @@
import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
import type { ChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import type { DiscordExecApprovalConfig } from "openclaw/plugin-sdk/config-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "openclaw/plugin-sdk/text-runtime";
export { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
import { listDiscordAccountIds, resolveDiscordAccount } from "./accounts.js";
import {
createChannelApproverDmTargetResolver,
createChannelNativeOriginTargetResolver,
createApproverRestrictedNativeApprovalCapability,
splitChannelApprovalCapability,
doesApprovalRequestMatchChannelAccount,
isChannelExecApprovalClientEnabledFromConfig,
matchesApprovalRequestFilters,
} from "./approval-runtime.js";
import { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
import {
getDiscordExecApprovalApprovers,
isDiscordExecApprovalApprover,
isDiscordExecApprovalClientEnabled,
} from "./exec-approvals.js";
type ApprovalRequest = ExecApprovalRequest | PluginApprovalRequest;
// Legacy export kept for monitor test/support surfaces; native routing now uses
// the shared session-conversation fallback helper instead.
export function extractDiscordChannelId(sessionKey?: string | null): string | null {
@@ -80,45 +76,6 @@ function normalizeDiscordThreadId(value?: string | number | null): string | unde
return /^\d+$/.test(normalized) ? normalized : undefined;
}
export function shouldHandleDiscordApprovalRequest(params: {
cfg: OpenClawConfig;
accountId?: string | null;
request: ApprovalRequest;
configOverride?: DiscordExecApprovalConfig | null;
}): boolean {
const config =
params.configOverride ??
resolveDiscordAccount({ cfg: params.cfg, accountId: params.accountId }).config.execApprovals;
const approvers = getDiscordExecApprovalApprovers({
cfg: params.cfg,
accountId: params.accountId,
configOverride: params.configOverride,
});
if (
!doesApprovalRequestMatchChannelAccount({
cfg: params.cfg,
request: params.request,
channel: "discord",
accountId: params.accountId,
})
) {
return false;
}
if (
!isChannelExecApprovalClientEnabledFromConfig({
enabled: config?.enabled,
approverCount: approvers.length,
})
) {
return false;
}
return matchesApprovalRequestFilters({
request: params.request.request,
agentFilter: config?.agentFilter,
sessionFilter: config?.sessionFilter,
});
}
function createDiscordOriginTargetResolver(configOverride?: DiscordExecApprovalConfig | null) {
return createChannelNativeOriginTargetResolver({
channel: "discord",

View File

@@ -0,0 +1,50 @@
import { doesApprovalRequestMatchChannelAccount } from "openclaw/plugin-sdk/approval-native-runtime";
import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import { resolveDiscordAccount } from "./accounts.js";
import {
isChannelExecApprovalClientEnabledFromConfig,
matchesApprovalRequestFilters,
} from "./approval-runtime.js";
import { getDiscordExecApprovalApprovers } from "./exec-approvals.js";
type ApprovalRequest = ExecApprovalRequest | PluginApprovalRequest;
export function shouldHandleDiscordApprovalRequest(params: {
cfg: OpenClawConfig;
accountId?: string | null;
request: ApprovalRequest;
configOverride?: DiscordExecApprovalConfig | null;
}): boolean {
const config =
params.configOverride ??
resolveDiscordAccount({ cfg: params.cfg, accountId: params.accountId }).config.execApprovals;
const approvers = getDiscordExecApprovalApprovers({
cfg: params.cfg,
accountId: params.accountId,
configOverride: params.configOverride,
});
if (
!doesApprovalRequestMatchChannelAccount({
cfg: params.cfg,
request: params.request,
channel: "discord",
accountId: params.accountId,
})
) {
return false;
}
if (
!isChannelExecApprovalClientEnabledFromConfig({
enabled: config?.enabled,
approverCount: approvers.length,
})
) {
return false;
}
return matchesApprovalRequestFilters({
request: params.request.request,
agentFilter: config?.agentFilter,
sessionFilter: config?.sessionFilter,
});
}

View File

@@ -14,11 +14,10 @@ import {
type ExecApprovalRequest,
} from "openclaw/plugin-sdk/infra-runtime";
import { logError, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { slackNativeApprovalAdapter } from "./approval-native.js";
import {
isSlackExecApprovalClientEnabled,
normalizeSlackApproverId,
shouldHandleSlackExecApprovalRequest,
normalizeSlackApproverId,
} from "./exec-approvals.js";
import { resolveSlackReplyBlocks } from "./reply-blocks.js";
import { sendMessageSlack } from "./send.js";
@@ -248,19 +247,11 @@ export const slackApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdap
if (!resolved) {
return false;
}
return (
shouldHandleSlackExecApprovalRequest({
cfg: params.cfg,
accountId: resolved.accountId,
request: params.request as ExecApprovalRequest,
}) &&
slackNativeApprovalAdapter.native?.describeDeliveryCapabilities({
cfg: params.cfg,
accountId: resolved.accountId,
approvalKind: "exec",
request: params.request as ExecApprovalRequest,
}).enabled === true
);
return shouldHandleSlackExecApprovalRequest({
cfg: params.cfg,
accountId: resolved.accountId,
request: params.request as ExecApprovalRequest,
});
},
},
presentation: {