mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-30 01:06:11 +00:00
Slack: add header and context blocks to arg menus
This commit is contained in:
@@ -167,6 +167,12 @@ function encodeValue(parts: { command: string; arg: string; value: string; userI
|
||||
].join("|");
|
||||
}
|
||||
|
||||
function findFirstActionsBlock(payload: { blocks?: Array<{ type: string }> }) {
|
||||
return payload.blocks?.find((block) => block.type === "actions") as
|
||||
| { type: string; elements?: Array<{ type?: string; action_id?: string }> }
|
||||
| undefined;
|
||||
}
|
||||
|
||||
function createArgMenusHarness() {
|
||||
const commands = new Map<string, (args: unknown) => Promise<void>>();
|
||||
const actions = new Map<string, (args: unknown) => Promise<void>>();
|
||||
@@ -281,10 +287,11 @@ describe("Slack native command argument menus", () => {
|
||||
|
||||
expect(respond).toHaveBeenCalledTimes(1);
|
||||
const payload = respond.mock.calls[0]?.[0] as { blocks?: Array<{ type: string }> };
|
||||
expect(payload.blocks?.[0]?.type).toBe("section");
|
||||
expect(payload.blocks?.[1]?.type).toBe("actions");
|
||||
const elementType = (payload.blocks?.[1] as { elements?: Array<{ type?: string }> } | undefined)
|
||||
?.elements?.[0]?.type;
|
||||
expect(payload.blocks?.[0]?.type).toBe("header");
|
||||
expect(payload.blocks?.[1]?.type).toBe("section");
|
||||
expect(payload.blocks?.[2]?.type).toBe("context");
|
||||
const actions = findFirstActionsBlock(payload);
|
||||
const elementType = actions?.elements?.[0]?.type;
|
||||
expect(elementType).toBe("button");
|
||||
});
|
||||
|
||||
@@ -307,11 +314,11 @@ describe("Slack native command argument menus", () => {
|
||||
|
||||
expect(respond).toHaveBeenCalledTimes(1);
|
||||
const payload = respond.mock.calls[0]?.[0] as { blocks?: Array<{ type: string }> };
|
||||
expect(payload.blocks?.[0]?.type).toBe("section");
|
||||
expect(payload.blocks?.[1]?.type).toBe("actions");
|
||||
const element = (
|
||||
payload.blocks?.[1] as { elements?: Array<{ type?: string; action_id?: string }> } | undefined
|
||||
)?.elements?.[0];
|
||||
expect(payload.blocks?.[0]?.type).toBe("header");
|
||||
expect(payload.blocks?.[1]?.type).toBe("section");
|
||||
expect(payload.blocks?.[2]?.type).toBe("context");
|
||||
const actions = findFirstActionsBlock(payload);
|
||||
const element = actions?.elements?.[0];
|
||||
expect(element?.type).toBe("static_select");
|
||||
expect(element?.action_id).toBe("openclaw_cmdarg");
|
||||
});
|
||||
@@ -335,10 +342,8 @@ describe("Slack native command argument menus", () => {
|
||||
|
||||
expect(respond).toHaveBeenCalledTimes(1);
|
||||
const payload = respond.mock.calls[0]?.[0] as { blocks?: Array<{ type: string }> };
|
||||
expect(payload.blocks?.[1]?.type).toBe("actions");
|
||||
const firstElement = (
|
||||
payload.blocks?.[1] as { elements?: Array<{ type?: string }> } | undefined
|
||||
)?.elements?.[0];
|
||||
const actions = findFirstActionsBlock(payload);
|
||||
const firstElement = actions?.elements?.[0];
|
||||
expect(firstElement?.type).toBe("button");
|
||||
});
|
||||
|
||||
@@ -361,10 +366,8 @@ describe("Slack native command argument menus", () => {
|
||||
|
||||
expect(respond).toHaveBeenCalledTimes(1);
|
||||
const payload = respond.mock.calls[0]?.[0] as { blocks?: Array<{ type: string }> };
|
||||
expect(payload.blocks?.[1]?.type).toBe("actions");
|
||||
const element = (
|
||||
payload.blocks?.[1] as { elements?: Array<{ type?: string; action_id?: string }> } | undefined
|
||||
)?.elements?.[0];
|
||||
const actions = findFirstActionsBlock(payload);
|
||||
const element = actions?.elements?.[0];
|
||||
expect(element?.type).toBe("overflow");
|
||||
expect(element?.action_id).toBe("openclaw_cmdarg");
|
||||
});
|
||||
|
||||
@@ -34,6 +34,18 @@ const SLACK_COMMAND_ARG_OVERFLOW_MIN = 3;
|
||||
const SLACK_COMMAND_ARG_OVERFLOW_MAX = 5;
|
||||
const SLACK_COMMAND_ARG_SELECT_OPTIONS_MAX = 100;
|
||||
const SLACK_COMMAND_ARG_SELECT_OPTION_VALUE_MAX = 75;
|
||||
const SLACK_HEADER_TEXT_MAX = 150;
|
||||
|
||||
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)}…`;
|
||||
}
|
||||
|
||||
type CommandsRegistry = typeof import("../../auto-reply/commands-registry.js");
|
||||
let commandsRegistry: CommandsRegistry | undefined;
|
||||
@@ -164,10 +176,27 @@ function buildSlackCommandArgMenuBlocks(params: {
|
||||
},
|
||||
],
|
||||
}));
|
||||
const headerText = truncatePlainText(
|
||||
`/${params.command}: choose ${params.arg}`,
|
||||
SLACK_HEADER_TEXT_MAX,
|
||||
);
|
||||
const sectionText = truncatePlainText(params.title, 3000);
|
||||
const contextText = truncatePlainText(
|
||||
`Select one option to continue /${params.command} (${params.arg})`,
|
||||
3000,
|
||||
);
|
||||
return [
|
||||
{
|
||||
type: "header",
|
||||
text: { type: "plain_text", text: headerText },
|
||||
},
|
||||
{
|
||||
type: "section",
|
||||
text: { type: "mrkdwn", text: params.title },
|
||||
text: { type: "mrkdwn", text: sectionText },
|
||||
},
|
||||
{
|
||||
type: "context",
|
||||
elements: [{ type: "mrkdwn", text: contextText }],
|
||||
},
|
||||
...rows,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user