diff --git a/json-logs/samples/api/views.open.json b/json-logs/samples/api/views.open.json index 731b3ea0c..f8b4ed226 100644 --- a/json-logs/samples/api/views.open.json +++ b/json-logs/samples/api/views.open.json @@ -2598,7 +2598,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, "dispatch_action": false, "hint": { @@ -3205,7 +3208,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, { "type": "workflow_button", diff --git a/json-logs/samples/api/views.publish.json b/json-logs/samples/api/views.publish.json index 731b3ea0c..f8b4ed226 100644 --- a/json-logs/samples/api/views.publish.json +++ b/json-logs/samples/api/views.publish.json @@ -2598,7 +2598,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, "dispatch_action": false, "hint": { @@ -3205,7 +3208,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, { "type": "workflow_button", diff --git a/json-logs/samples/api/views.push.json b/json-logs/samples/api/views.push.json index 731b3ea0c..f8b4ed226 100644 --- a/json-logs/samples/api/views.push.json +++ b/json-logs/samples/api/views.push.json @@ -2598,7 +2598,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, "dispatch_action": false, "hint": { @@ -3205,7 +3208,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, { "type": "workflow_button", diff --git a/json-logs/samples/api/views.update.json b/json-logs/samples/api/views.update.json index 731b3ea0c..f8b4ed226 100644 --- a/json-logs/samples/api/views.update.json +++ b/json-logs/samples/api/views.update.json @@ -2598,7 +2598,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, "dispatch_action": false, "hint": { @@ -3205,7 +3208,10 @@ }, "style": "" }, - "accessibility_label": "" + "accessibility_label": "", + "agent_prompt": "", + "agent_prompt_display": "", + "visible_to_user_ids": [] }, { "type": "workflow_button", diff --git a/slack-api-model-kotlin-extension/src/main/kotlin/com/slack/api/model/kotlin_extension/block/element/ButtonElementBuilder.kt b/slack-api-model-kotlin-extension/src/main/kotlin/com/slack/api/model/kotlin_extension/block/element/ButtonElementBuilder.kt index 2ddcbbc55..af5d5a4e6 100644 --- a/slack-api-model-kotlin-extension/src/main/kotlin/com/slack/api/model/kotlin_extension/block/element/ButtonElementBuilder.kt +++ b/slack-api-model-kotlin-extension/src/main/kotlin/com/slack/api/model/kotlin_extension/block/element/ButtonElementBuilder.kt @@ -17,6 +17,9 @@ class ButtonElementBuilder : Builder { private var style: String? = null private var confirm: ConfirmationDialogObject? = null private var accessibilityLabel: String? = null + private var agentPrompt: String? = null + private var agentPromptDisplay: String? = null + private var visibleToUserIds: List? = null /** * An identifier for this action. You can use this when you receive an interaction payload to identify the source @@ -103,6 +106,44 @@ class ButtonElementBuilder : Builder { this.accessibilityLabel = accessibilityLabel } + /** + * A prompt sent to Slackbot when the button is clicked, if Slackbot AI is available to the user. + * Maximum length for this field is 4000 characters. + * + * @see Button element documentation + */ + fun agentPrompt(agentPrompt: String) { + this.agentPrompt = agentPrompt + } + + /** + * Short text shown instead of the full agent_prompt in the user's Slackbot message. + * Requires agent_prompt and defaults to the button's text. + * + * @see Button element documentation + */ + fun agentPromptDisplay(agentPromptDisplay: String) { + this.agentPromptDisplay = agentPromptDisplay + } + + /** + * An array of user IDs for which the button appears. If not provided, the button is visible to all users. + * + * @see Button element documentation + */ + fun visibleToUserIds(visibleToUserIds: List) { + this.visibleToUserIds = visibleToUserIds + } + + /** + * An array of user IDs for which the button appears. If not provided, the button is visible to all users. + * + * @see Button element documentation + */ + fun visibleToUserIds(vararg visibleToUserIds: String) { + this.visibleToUserIds = visibleToUserIds.toList() + } + override fun build(): ButtonElement { return ButtonElement.builder() .actionId(actionId) @@ -112,6 +153,9 @@ class ButtonElementBuilder : Builder { .style(style) .confirm(confirm) .accessibilityLabel(accessibilityLabel) + .agentPrompt(agentPrompt) + .agentPromptDisplay(agentPromptDisplay) + .visibleToUserIds(visibleToUserIds) .build() } } \ No newline at end of file diff --git a/slack-api-model-kotlin-extension/src/test/kotlin/test_locally/block/ActionsBlockTest.kt b/slack-api-model-kotlin-extension/src/test/kotlin/test_locally/block/ActionsBlockTest.kt index 2eb9d931b..2c0d339a0 100644 --- a/slack-api-model-kotlin-extension/src/test/kotlin/test_locally/block/ActionsBlockTest.kt +++ b/slack-api-model-kotlin-extension/src/test/kotlin/test_locally/block/ActionsBlockTest.kt @@ -31,6 +31,25 @@ class ActionsBlockTest { assertEquals(expected, result) } + @Test + fun buttonWithAgentPrompt() { + val gson = GsonFactory.createSnakeCase() + val blocks = withBlocks { + actions { + button { + actionId("summarize_incident") + text("Summarize with Slackbot") + agentPrompt("Summarize this incident and suggest next steps.") + agentPromptDisplay("Summarize this incident") + visibleToUserIds("U123456") + } + } + } + val result = gson.toJson(blocks) + val expected = """[{"type":"actions","elements":[{"type":"button","text":{"type":"plain_text","text":"Summarize with Slackbot"},"action_id":"summarize_incident","agent_prompt":"Summarize this incident and suggest next steps.","agent_prompt_display":"Summarize this incident","visible_to_user_ids":["U123456"]}]}]""" + assertEquals(expected, result) + } + @Test fun `multi-selects`() { val gson = GsonFactory.createSnakeCase() diff --git a/slack-api-model/src/main/java/com/slack/api/model/block/element/ButtonElement.java b/slack-api-model/src/main/java/com/slack/api/model/block/element/ButtonElement.java index 5ac173064..9835509e3 100644 --- a/slack-api-model/src/main/java/com/slack/api/model/block/element/ButtonElement.java +++ b/slack-api-model/src/main/java/com/slack/api/model/block/element/ButtonElement.java @@ -4,6 +4,8 @@ import com.slack.api.model.block.composition.PlainTextObject; import lombok.*; +import java.util.List; + /** * https://docs.slack.dev/reference/block-kit/block-elements/button-element */ @@ -68,4 +70,21 @@ public class ButtonElement extends BlockElement { * Maximum length for this field is 75 characters. */ private String accessibilityLabel; + + /** + * A prompt sent to Slackbot when the button is clicked, if Slackbot AI is available to the user. + * Maximum length for this field is 4000 characters. + */ + private String agentPrompt; + + /** + * Short text shown instead of the full agent_prompt in the user's Slackbot message. + * Requires agent_prompt and defaults to the button's text. + */ + private String agentPromptDisplay; + + /** + * An array of user IDs for which the button appears. If not provided, the button is visible to all users. + */ + private List visibleToUserIds; } diff --git a/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java b/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java index 8ad28d305..5c6722a1c 100644 --- a/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java +++ b/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java @@ -1313,6 +1313,35 @@ public void parseContextActionsBlock() { assertEquals(Arrays.asList("USLACKBOT", "U0123456789"), iconButton.getVisibleToUserIds()); } + @Test + public void parseButtonWithAgentPrompt() { + String json = "{\n" + + " \"type\": \"actions\",\n" + + " \"elements\": [\n" + + " {\n" + + " \"type\": \"button\",\n" + + " \"text\": {\n" + + " \"type\": \"plain_text\",\n" + + " \"text\": \"Summarize with Slackbot\"\n" + + " },\n" + + " \"action_id\": \"summarize_incident\",\n" + + " \"agent_prompt\": \"Summarize this incident and suggest next steps.\",\n" + + " \"agent_prompt_display\": \"Summarize this incident\",\n" + + " \"visible_to_user_ids\": [\"U123456\"]\n" + + " }\n" + + " ]\n" + + "}"; + ActionsBlock block = GsonFactory.createSnakeCase().fromJson(json, ActionsBlock.class); + ButtonElement button = (ButtonElement) block.getElements().get(0); + assertEquals("Summarize this incident and suggest next steps.", button.getAgentPrompt()); + assertEquals("Summarize this incident", button.getAgentPromptDisplay()); + assertEquals(Arrays.asList("U123456"), button.getVisibleToUserIds()); + String serialized = GsonFactory.createSnakeCase().toJson(block); + assertThat(serialized, containsString("\"agent_prompt\":\"Summarize this incident and suggest next steps.\"")); + assertThat(serialized, containsString("\"agent_prompt_display\":\"Summarize this incident\"")); + assertThat(serialized, containsString("\"visible_to_user_ids\":[\"U123456\"]")); + } + String richTextSkinTone = "{ \"blocks\": [\n" + " {\n" + " \"type\": \"rich_text\",\n" +