Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slack Block Builder do not update static select value in modal #2184

Open
mister-good-deal opened this issue Aug 4, 2024 · 4 comments
Open
Labels
question M-T: User needs support to use the project

Comments

@mister-good-deal
Copy link

On "@slack/bolt": "^3.19.0", I got a strange bug where a static_select element from Block Builder do not display the initial_option correctly in my Slack app.

I'm using "slack-block-builder": "^2.8.0" to generate the JSON output that updates the following Modal view.

{
  "callback_id": "assistantConfigurationModalCallback",
  "title": {
    "type": "plain_text",
    "text": "AI Assistant"
  },
  "submit": {
    "type": "plain_text",
    "text": "Submit"
  },
  "close": {
    "type": "plain_text",
    "text": "Cancel"
  },
  "blocks": [
    {
      "text": {
        "type": "mrkdwn",
        "text": "Create an AI assistant bound to a public channel."
      },
      "type": "section"
    },
    {
      "type": "divider"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Create or edit Assistant"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Select assistant"
        },
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "Create new assistant"
            },
            "value": "-1"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-test"
            },
            "value": "1"
          }
        ],
        "initial_option": {
          "text": {
            "type": "plain_text",
            "text": "mistral-test"
          },
          "value": "1"
        },
        "action_id": "select_assistant_action",
        "type": "static_select"
      },
      "dispatch_action": true,
      "block_id": "select_assistant_action_block_id",
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Assistant name"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Enter the assistant name"
        },
        "initial_value": "mistral-test",
        "action_id": "assistant_name_text_input_action",
        "type": "plain_text_input"
      },
      "block_id": "assistant_name_block_id",
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Assistant description"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Enter the assistant description"
        },
        "multiline": true,
        "initial_value": "Mistral AI test API call",
        "action_id": "assistant_description_text_input_action",
        "type": "plain_text_input"
      },
      "block_id": "assistant_description_block_id",
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Assistant instructions"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Enter the assistant instructions"
        },
        "multiline": true,
        "initial_value": "You are a helpful assistant helping user in a Slack channel",
        "action_id": "assistant_instructions_text_input_action",
        "type": "plain_text_input"
      },
      "block_id": "assistant_instructions_block_id",
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Public channel name"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Enter the public channel name"
        },
        "initial_value": "mistral-test",
        "action_id": "assistant_channel_name_text_input_action",
        "type": "plain_text_input"
      },
      "block_id": "assistant_channel_name_block_id",
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "AI service"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Select AI service"
        },
        "action_id": "select_ai_service_action",
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "OPENAI"
            },
            "value": "OPENAI"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "MISTRAL_AI"
            },
            "value": "MISTRAL_AI"
          }
        ],
        "initial_option": {
          "text": {
            "type": "plain_text",
            "text": "MISTRAL_AI"
          },
          "value": "MISTRAL_AI"
        },
        "type": "static_select"
      },
      "block_id": "select_ai_service_block_id",
      "dispatch_action": true,
      "type": "input"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Model"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Select AI model"
        },
        "action_id": "select_ai_model_action",
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "open-mistral-7b"
            },
            "value": "open-mistral-7b"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-tiny"
            },
            "value": "mistral-tiny"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-tiny-2312"
            },
            "value": "mistral-tiny-2312"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-mistral-nemo"
            },
            "value": "open-mistral-nemo"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-mistral-nemo-2407"
            },
            "value": "open-mistral-nemo-2407"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-tiny-2407"
            },
            "value": "mistral-tiny-2407"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-tiny-latest"
            },
            "value": "mistral-tiny-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-mixtral-8x7b"
            },
            "value": "open-mixtral-8x7b"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-small"
            },
            "value": "mistral-small"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-small-2312"
            },
            "value": "mistral-small-2312"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-mixtral-8x22b"
            },
            "value": "open-mixtral-8x22b"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-mixtral-8x22b-2404"
            },
            "value": "open-mixtral-8x22b-2404"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-small-2402"
            },
            "value": "mistral-small-2402"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-small-latest"
            },
            "value": "mistral-small-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-medium-2312"
            },
            "value": "mistral-medium-2312"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-medium"
            },
            "value": "mistral-medium"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-medium-latest"
            },
            "value": "mistral-medium-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-large-2402"
            },
            "value": "mistral-large-2402"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-large-2407"
            },
            "value": "mistral-large-2407"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-large-latest"
            },
            "value": "mistral-large-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "codestral-2405"
            },
            "value": "codestral-2405"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "codestral-latest"
            },
            "value": "codestral-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "codestral-mamba-2407"
            },
            "value": "codestral-mamba-2407"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "open-codestral-mamba"
            },
            "value": "open-codestral-mamba"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "codestral-mamba-latest"
            },
            "value": "codestral-mamba-latest"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "mistral-embed"
            },
            "value": "mistral-embed"
          }
        ],
        "initial_option": {
          "text": {
            "type": "plain_text",
            "text": "open-mistral-nemo"
          },
          "value": "open-mistral-nemo"
        },
        "type": "static_select"
      },
      "block_id": "select_ai_model_block_id",
      "type": "input"
    },
    {
      "text": {
        "type": "mrkdwn",
        "text": "_See different models purpose and features in <https://docs.mistral.ai/guides/model-selection|Mistral models>_"
      },
      "type": "section"
    },
    {
      "label": {
        "type": "plain_text",
        "text": "Functions"
      },
      "element": {
        "placeholder": {
          "type": "plain_text",
          "text": "Select the functions assistant can use"
        },
        "action_id": "select_assistant_functions_action",
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "storeFileInSlackFromString"
            },
            "value": "storeFileInSlackFromString"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "createGitlabIssue"
            },
            "value": "createGitlabIssue"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "listGitlabLabels"
            },
            "value": "listGitlabLabels"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "createGitlabLabel"
            },
            "value": "createGitlabLabel"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "removeGitlabLabel"
            },
            "value": "removeGitlabLabel"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectsInformation"
            },
            "value": "getGitlabProjectsInformation"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectInformation"
            },
            "value": "getGitlabProjectInformation"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectIssues"
            },
            "value": "getGitlabProjectIssues"
          }
        ],
        "initial_options": [
          {
            "text": {
              "type": "plain_text",
              "text": "createGitlabIssue"
            },
            "value": "createGitlabIssue"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "listGitlabLabels"
            },
            "value": "listGitlabLabels"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "createGitlabLabel"
            },
            "value": "createGitlabLabel"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "removeGitlabLabel"
            },
            "value": "removeGitlabLabel"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectsInformation"
            },
            "value": "getGitlabProjectsInformation"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectInformation"
            },
            "value": "getGitlabProjectInformation"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "getGitlabProjectIssues"
            },
            "value": "getGitlabProjectIssues"
          }
        ],
        "type": "multi_static_select"
      },
      "block_id": "select_assistant_functions_block_id",
      "type": "input"
    },
    {
      "text": {
        "type": "mrkdwn",
        "text": "_The selected functions will be available for the assistant._"
      },
      "type": "section"
    }
  ],
  "type": "modal"
}

It is displaying fine on Slack builder kit preview in https://app.slack.com/block-kit-builder.

But in my Slack app, the initial option open-mistral-nemo in the Model static select input is displaying the 1st element open-mistral-7b instead.

Others static selects or multi static selects display initial options fine.

My workflow is :

  • The modal is opened by a button trigger in Home Page
  • The modal values are refreshed based on the 1st input
  • I'm using the client.views.update to update the view like in the following function
import logger from "../../logger/winston.ts";
import prisma from "../../prisma/client.ts";
import { feedback } from "../../utilities/slack.ts";
import {
    assistantConfigurationModal,
    loadModalInputsFromView,
    loadModalInputsFromAssistant,
    NONE_SELECTED
} from "../views/assistant-configuration-modal.ts";

import type { Assistant } from "@prisma/client";
import type { AllMiddlewareArgs, BlockAction, SlackActionMiddlewareArgs, StaticSelectAction } from "@slack/bolt";

type ActionEventArgs = AllMiddlewareArgs & SlackActionMiddlewareArgs<BlockAction>;

async function loadAssistant(assistantId: number, teamId: string): Promise<Assistant | undefined> {
    if (assistantId === NONE_SELECTED) return undefined;
    return await prisma.assistant.findUniqueOrThrow({ where: { id: assistantId, SlackTeamId: teamId } });
}

export async function selectAssistantActionCallback({ ack, body, client, payload }: ActionEventArgs) {
    try {
        await ack();
        // Type guard for typescript completion
        if (body.type !== "block_actions" || !body.view) return;

        const payloadTyped = payload as StaticSelectAction;
        const assistantId = parseInt(payloadTyped.selected_option.value);
        // Update the configuration modal with the selected assistant values
        await client.views.update({
            user_id: body.user.id,
            view_id: body.view.id,
            hash: body.view.hash,
            view: await assistantConfigurationModal(
                body.user.team_id!,
                loadModalInputsFromAssistant(await loadAssistant(assistantId, body.user.team_id!))
            )
        });
    } catch (error) {
        logger.error(error);
        await feedback(client, body, "An error occurred while selecting the assistant. Please try again.");
    }
}

That is really strange as the block kit builder is displaying the initial option correctly...

@seratch seratch added question M-T: User needs support to use the project needs info An issue that is claimed to be a bug and hasn't been reproduced, or otherwise needs more info and removed untriaged needs info An issue that is claimed to be a bug and hasn't been reproduced, or otherwise needs more info labels Aug 5, 2024
@seratch
Copy link
Member

seratch commented Aug 5, 2024

Hi @mister-good-deal, thanks for asking the question!

Indeed, this can be unintuitive, but when you set dispatch_action: true for an input block, overriding the selected option by setting initial_option does not work. In other words, you don't need to set initial_option for a block, which already has its selected item. The item you've selected will be kept if you don't pass initial_option. By contrast, if you add new blocks to the modal in response to the block_actions event, those new blocks can have initial_option. Hope this clarifies.

FYI, here is a simple working example demonstrating what I said above:

import { App, BlockAction } from "@slack/bolt";

export function registerListeners(app: App) {
  app.event("message", async ({ say }) => {
    await say({
      text: "hi!",
      blocks: [
        {
          type: "actions",
          elements: [
            {
              type: "button",
              action_id: "test",
              text: { type: "plain_text", text: "Click Me" },
              value: "click_me_123",
            },
          ],
        },
      ],
    });
  });
  app.action<BlockAction>("test", async ({ body, client, ack }) => {
    await ack();
    await client.views.open({
      trigger_id: body.trigger_id,
      view: {
        type: "modal",
        callback_id: "assistantConfigurationModalCallback",
        title: { type: "plain_text", text: "AI Assistant" },
        blocks: [
          {
            label: { type: "plain_text", text: "Create or edit Assistant" },
            element: {
              placeholder: { type: "plain_text", text: "Select assistant" },
              options: [
                {
                  text: {
                    type: "plain_text",
                    text: "Create new assistant",
                  },
                  value: "-1",
                },
                {
                  text: { type: "plain_text", text: "mistral-test" },
                  value: "1",
                },
              ],
              action_id: "select_assistant_action",
              type: "static_select",
            },
            dispatch_action: true,
            block_id: "select_assistant_action_block_id",
            type: "input",
          },
        ],
      },
    });
  });
  app.action<BlockAction>(
    "select_assistant_action",
    async ({ ack, client, body }) => {
      await ack();
      if (body.view) {
        await client.views.update({
          view_id: body.view.id,
          view: {
            type: "modal",
            callback_id: "assistantConfigurationModalCallback",
            title: { type: "plain_text", text: "AI Assistant" },
            blocks: [
              {
                label: { type: "plain_text", text: "Create or edit Assistant" },
                element: {
                  placeholder: { type: "plain_text", text: "Select assistant" },
                  options: [
                    {
                      text: {
                        type: "plain_text",
                        text: "Create new assistant",
                      },
                      value: "-1",
                    },
                    {
                      text: { type: "plain_text", text: "mistral-test" },
                      value: "1",
                    },
                  ],
                  // No need to set the initial_option again
                  // initial_option: {
                  //   text: { type: "plain_text", text: "mistral-test" },
                  //   value: "1",
                  // },
                  action_id: "select_assistant_action",
                  type: "static_select",
                },
                dispatch_action: true,
                block_id: "select_assistant_action_block_id",
                type: "input",
              },
            ],
          },
        });
      }
    }
  );
}

@mister-good-deal
Copy link
Author

Ok that's clear, so what is the way to load an initial value from an input which is interactive (ie have dispatch_action: true)?

Is there an event I can send programmatically to set an input and trigger its dispatch_action event?

Copy link

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

@mister-good-deal
Copy link
Author

I rephrase it, how to load previously saved data in a modal when it opens?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question M-T: User needs support to use the project
Projects
None yet
Development

No branches or pull requests

2 participants