Slack: dedupe normalized interaction selections

This commit is contained in:
Colin
2026-02-16 13:08:29 -05:00
committed by Peter Steinberger
parent 6e790303df
commit 7e42408ade
2 changed files with 25 additions and 7 deletions

View File

@@ -211,12 +211,13 @@ describe("registerSlackInteractionEvents", () => {
type: "multi_conversations_select",
action_id: "openclaw:route",
selected_user: "U777",
selected_users: ["U888"],
selected_users: ["U777", "U888"],
selected_channel: "C777",
selected_channels: ["C888"],
selected_channels: ["C777", "C888"],
selected_conversation: "G777",
selected_conversations: ["G888"],
selected_conversations: ["G777", "G888"],
selected_options: [
{ text: { type: "plain_text", text: "Alpha" }, value: "alpha" },
{ text: { type: "plain_text", text: "Alpha" }, value: "alpha" },
{ text: { type: "plain_text", text: "Beta" }, value: "beta" },
],

View File

@@ -70,6 +70,23 @@ function readOptionLabels(options: unknown): string[] | undefined {
return labels.length > 0 ? labels : undefined;
}
function uniqueNonEmptyStrings(values: string[]): string[] {
const unique: string[] = [];
const seen = new Set<string>();
for (const entry of values) {
if (typeof entry !== "string") {
continue;
}
const trimmed = entry.trim();
if (!trimmed || seen.has(trimmed)) {
continue;
}
seen.add(trimmed);
unique.push(trimmed);
}
return unique;
}
function summarizeAction(
action: Record<string, unknown>,
): Omit<InteractionSummary, "actionId" | "blockId"> {
@@ -89,7 +106,7 @@ function summarizeAction(
value?: string;
};
const actionType = typed.type;
const selectedValues = [
const selectedValues = uniqueNonEmptyStrings([
...(typed.selected_option?.value ? [typed.selected_option.value] : []),
...(readOptionValues(typed.selected_options) ?? []),
...(typed.selected_user ? [typed.selected_user] : []),
@@ -98,11 +115,11 @@ function summarizeAction(
...(Array.isArray(typed.selected_channels) ? typed.selected_channels : []),
...(typed.selected_conversation ? [typed.selected_conversation] : []),
...(Array.isArray(typed.selected_conversations) ? typed.selected_conversations : []),
].filter((entry) => typeof entry === "string" && entry.trim().length > 0);
const selectedLabels = [
]);
const selectedLabels = uniqueNonEmptyStrings([
...(typed.selected_option?.text?.text ? [typed.selected_option.text.text] : []),
...(readOptionLabels(typed.selected_options) ?? []),
].filter((entry) => typeof entry === "string" && entry.trim().length > 0);
]);
return {
actionType,