diff --git a/src/auto-reply/reply/slack-directives.ts b/src/auto-reply/reply/slack-directives.ts index 79fa11eeb32..fe58f0c5961 100644 --- a/src/auto-reply/reply/slack-directives.ts +++ b/src/auto-reply/reply/slack-directives.ts @@ -1,4 +1,5 @@ import { parseSlackBlocksInput } from "../../slack/blocks-input.js"; +import { truncateSlackText } from "../../slack/truncate.js"; import type { ReplyPayload } from "../types.js"; const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button"; @@ -21,17 +22,6 @@ type SlackChoice = { value: string; }; -function truncateSlackText(value: string, max: number): string { - const trimmed = value.trim(); - if (trimmed.length <= max) { - return trimmed; - } - if (max <= 1) { - return trimmed.slice(0, max); - } - return `${trimmed.slice(0, max - 1)}…`; -} - function parseChoice(raw: string): SlackChoice | null { const trimmed = raw.trim(); if (!trimmed) { diff --git a/src/slack/monitor/events/interactions.ts b/src/slack/monitor/events/interactions.ts index deca761dd52..b82c30d8571 100644 --- a/src/slack/monitor/events/interactions.ts +++ b/src/slack/monitor/events/interactions.ts @@ -1,6 +1,7 @@ import type { SlackActionMiddlewareArgs } from "@slack/bolt"; import type { Block, KnownBlock } from "@slack/web-api"; import { enqueueSystemEvent } from "../../../infra/system-events.js"; +import { truncateSlackText } from "../../truncate.js"; import { authorizeSlackSystemEventSender } from "../auth.js"; import type { SlackMonitorContext } from "../context.js"; import { escapeSlackMrkdwn } from "../mrkdwn.js"; @@ -53,17 +54,6 @@ type InteractionSummary = InteractionSelectionFields & { threadTs?: string; }; -function truncateInteractionString( - value: string, - max = SLACK_INTERACTION_STRING_MAX_CHARS, -): string { - const trimmed = value.trim(); - if (trimmed.length <= max) { - return trimmed; - } - return `${trimmed.slice(0, max - 1)}…`; -} - function sanitizeSlackInteractionPayloadValue(value: unknown, key?: string): unknown { if (value === undefined) { return undefined; @@ -75,7 +65,7 @@ function sanitizeSlackInteractionPayloadValue(value: unknown, key?: string): unk return REDACTED_INTERACTION_VALUE; } if (typeof value === "string") { - return truncateInteractionString(value); + return truncateSlackText(value, SLACK_INTERACTION_STRING_MAX_CHARS); } if (Array.isArray(value)) { const sanitized = value diff --git a/src/slack/monitor/slash.ts b/src/slack/monitor/slash.ts index 7d3b1839deb..f8b030e59ca 100644 --- a/src/slack/monitor/slash.ts +++ b/src/slack/monitor/slash.ts @@ -10,6 +10,7 @@ import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "../../ import { danger, logVerbose } from "../../globals.js"; import { chunkItems } from "../../utils/chunk-items.js"; import type { ResolvedSlackAccount } from "../accounts.js"; +import { truncateSlackText } from "../truncate.js"; import { resolveSlackAllowListMatch, resolveSlackUserAllowed } from "./allow-list.js"; import { resolveSlackEffectiveAllowFrom } from "./auth.js"; import { resolveSlackChannelConfig, type SlackChannelConfigResolved } from "./channel-config.js"; @@ -62,17 +63,6 @@ function loadSlashSkillCommandsRuntime() { type EncodedMenuChoice = SlackExternalArgMenuChoice; const slackExternalArgMenuStore = createSlackExternalArgMenuStore(); -function truncatePlainText(value: string, max: number): string { - const trimmed = value.trim(); - if (trimmed.length <= max) { - return trimmed; - } - if (max <= 1) { - return trimmed.slice(0, max); - } - return `${trimmed.slice(0, max - 1)}…`; -} - function buildSlackArgMenuConfirm(params: { command: string; arg: string }) { const command = escapeSlackMrkdwn(params.command); const arg = escapeSlackMrkdwn(params.arg); @@ -255,12 +245,12 @@ function buildSlackCommandArgMenuBlocks(params: { ], }), ); - const headerText = truncatePlainText( + const headerText = truncateSlackText( `/${params.command}: choose ${params.arg}`, SLACK_HEADER_TEXT_MAX, ); - const sectionText = truncatePlainText(params.title, 3000); - const contextText = truncatePlainText( + const sectionText = truncateSlackText(params.title, 3000); + const contextText = truncateSlackText( `Select one option to continue /${params.command} (${params.arg})`, 3000, ); diff --git a/src/slack/truncate.ts b/src/slack/truncate.ts new file mode 100644 index 00000000000..d7c387f63ae --- /dev/null +++ b/src/slack/truncate.ts @@ -0,0 +1,10 @@ +export function truncateSlackText(value: string, max: number): string { + const trimmed = value.trim(); + if (trimmed.length <= max) { + return trimmed; + } + if (max <= 1) { + return trimmed.slice(0, max); + } + return `${trimmed.slice(0, max - 1)}…`; +}