























@@ -21,6 +21,11 @@ const SLACK_ACTION_BLOCK_ELEMENTS_MAX = 25;
21212222export type SlackBlock = Block | KnownBlock;
232324+export type SlackInteractiveBlockRenderOptions = {
25+buttonIndexOffset?: number;
26+selectIndexOffset?: number;
27+};
28+2429function buildSlackReplyButtonActionId(buttonIndex: number, choiceIndex: number): string {
2530return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
2631}
@@ -45,11 +50,49 @@ function isWithinSlackLimit(value: string, maxLength: number): boolean {
4550return value.length <= maxLength;
4651}
475248-export function buildSlackInteractiveBlocks(interactive?: InteractiveReply): SlackBlock[] {
53+function readSlackBlockId(block: SlackBlock): string | undefined {
54+const value = (block as { block_id?: unknown }).block_id;
55+return typeof value === "string" ? value : undefined;
56+}
57+58+function readSlackOpenClawBlockIndex(blockId: string, prefix: string): number | undefined {
59+if (!blockId.startsWith(prefix)) {
60+return undefined;
61+}
62+const value = Number.parseInt(blockId.slice(prefix.length), 10);
63+return Number.isSafeInteger(value) && value > 0 ? value : undefined;
64+}
65+66+export function resolveSlackInteractiveBlockOffsets(
67+blocks?: readonly SlackBlock[],
68+): SlackInteractiveBlockRenderOptions {
69+let buttonIndexOffset = 0;
70+let selectIndexOffset = 0;
71+for (const block of blocks ?? []) {
72+const blockId = readSlackBlockId(block);
73+if (!blockId) {
74+continue;
75+}
76+buttonIndexOffset = Math.max(
77+buttonIndexOffset,
78+readSlackOpenClawBlockIndex(blockId, "openclaw_reply_buttons_") ?? 0,
79+);
80+selectIndexOffset = Math.max(
81+selectIndexOffset,
82+readSlackOpenClawBlockIndex(blockId, "openclaw_reply_select_") ?? 0,
83+);
84+}
85+return { buttonIndexOffset, selectIndexOffset };
86+}
87+88+export function buildSlackInteractiveBlocks(
89+interactive?: InteractiveReply,
90+options: SlackInteractiveBlockRenderOptions = {},
91+): SlackBlock[] {
4992const initialState = {
5093blocks: [] as SlackBlock[],
51-buttonIndex: 0,
52-selectIndex: 0,
94+buttonIndex: options.buttonIndexOffset ?? 0,
95+selectIndex: options.selectIndexOffset ?? 0,
5396};
5497return reduceInteractiveReply(interactive, initialState, (state, block) => {
5598if (block.type === "text") {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。