-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Slack v2 components #18744
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
base: master
Are you sure you want to change the base?
Slack v2 components #18744
Changes from all commits
e68de1f
2f2719a
e5597ae
3aa0773
2126d8e
8eb39ec
ce6dba8
8b99a4e
2476e2c
074b23e
ccc2353
8717ff3
325a164
18a1e8f
2df5de6
42e6bb2
2ae0dcb
fc32b4b
5dbafa7
135030d
cfeb6ed
97ed7f6
f417859
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import slack from "../../slack.app.mjs"; | ||
|
||
export default { | ||
key: "slack_v2-add-emoji-reaction", | ||
name: "Add Emoji Reaction", | ||
description: "Add an emoji reaction to a message. [See the documentation](https://api.slack.com/methods/reactions.add)", | ||
version: "0.0.17", | ||
annotations: { | ||
destructiveHint: false, | ||
openWorldHint: true, | ||
readOnlyHint: false, | ||
}, | ||
type: "action", | ||
props: { | ||
slack, | ||
conversation: { | ||
propDefinition: [ | ||
slack, | ||
"conversation", | ||
], | ||
description: "Channel where the message to add reaction to was posted.", | ||
}, | ||
timestamp: { | ||
propDefinition: [ | ||
slack, | ||
"messageTs", | ||
], | ||
description: "Timestamp of the message to add reaction to. e.g. `1403051575.000407`.", | ||
}, | ||
icon_emoji: { | ||
propDefinition: [ | ||
slack, | ||
"icon_emoji", | ||
], | ||
description: "Provide an emoji to use as the icon for this reaction. E.g. `fire`", | ||
optional: false, | ||
}, | ||
}, | ||
async run({ $ }) { | ||
const response = await this.slack.addReactions({ | ||
channel: this.conversation, | ||
timestamp: this.timestamp, | ||
name: this.icon_emoji, | ||
}); | ||
$.export("$summary", `Successfully added ${this.icon_emoji} emoji reaction.`); | ||
return response; | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import slack from "../../slack_v2.app.mjs"; | ||
import constants from "../../common/constants.mjs"; | ||
|
||
export default { | ||
key: "slack_v2-approve-workflow", | ||
name: "Approve Workflow", | ||
description: "Suspend the workflow until approved by a Slack message. [See the documentation](https://pipedream.com/docs/code/nodejs/rerun#flowsuspend)", | ||
version: "0.0.6", | ||
annotations: { | ||
destructiveHint: false, | ||
openWorldHint: true, | ||
readOnlyHint: false, | ||
}, | ||
type: "action", | ||
props: { | ||
slack, | ||
channelType: { | ||
type: "string", | ||
label: "Channel Type", | ||
description: "The type of channel to send to. User/Direct Message (im), Group (mpim), Private Channel or Public Channel", | ||
async options() { | ||
return constants.CHANNEL_TYPE_OPTIONS; | ||
}, | ||
}, | ||
conversation: { | ||
propDefinition: [ | ||
slack, | ||
"conversation", | ||
(c) => ({ | ||
types: c.channelType === "Channels" | ||
? [ | ||
constants.CHANNEL_TYPE.PUBLIC, | ||
constants.CHANNEL_TYPE.PRIVATE, | ||
] | ||
: [ | ||
c.channelType, | ||
], | ||
}), | ||
], | ||
}, | ||
message: { | ||
type: "string", | ||
label: "Message", | ||
description: "Text to include with the Approve and Cancel Buttons", | ||
}, | ||
}, | ||
async run({ $ }) { | ||
const { | ||
resume_url, cancel_url, | ||
} = $.flow.suspend(); | ||
|
||
const response = await this.slack.postChatMessage({ | ||
text: "Click here to approve or cancel workflow", | ||
blocks: [ | ||
{ | ||
type: "section", | ||
text: { | ||
type: "mrkdwn", | ||
text: this.message, | ||
}, | ||
}, | ||
{ | ||
type: "actions", | ||
elements: [ | ||
{ | ||
type: "button", | ||
text: { | ||
type: "plain_text", | ||
text: "Approve", | ||
}, | ||
style: "primary", | ||
url: resume_url, | ||
}, | ||
{ | ||
type: "button", | ||
text: { | ||
type: "plain_text", | ||
text: "Cancel", | ||
}, | ||
style: "danger", | ||
url: cancel_url, | ||
}, | ||
], | ||
}, | ||
], | ||
channel: this.conversation, | ||
}); | ||
|
||
$.export("$summary", "Successfully sent message"); | ||
return response; | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import slack from "../../slack_v2.app.mjs"; | ||
import constants from "../../common/constants.mjs"; | ||
|
||
export default { | ||
key: "slack_v2-archive-channel", | ||
name: "Archive Channel", | ||
description: "Archive a channel. [See the documentation](https://api.slack.com/methods/conversations.archive)", | ||
version: "0.0.25", | ||
annotations: { | ||
destructiveHint: true, | ||
openWorldHint: true, | ||
readOnlyHint: false, | ||
}, | ||
type: "action", | ||
props: { | ||
slack, | ||
conversation: { | ||
propDefinition: [ | ||
slack, | ||
"conversation", | ||
() => ({ | ||
types: [ | ||
constants.CHANNEL_TYPE.PUBLIC, | ||
constants.CHANNEL_TYPE.PRIVATE, | ||
constants.CHANNEL_TYPE.MPIM, | ||
], | ||
}), | ||
], | ||
}, | ||
}, | ||
async run({ $ }) { | ||
const response = await this.slack.archiveConversations({ | ||
channel: this.conversation, | ||
}); | ||
$.export("$summary", "Successfully archived channel."); | ||
return response; | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,182 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
import common from "./send-message.mjs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
export default { | ||||||||||||||||||||||||||||||||||||||||||||||||||
props: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
passArrayOrConfigure: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Add Blocks - Reference Existing Blocks Array or Configure Manually?", | ||||||||||||||||||||||||||||||||||||||||||||||||||
description: "Would you like to reference an array of blocks from a previous step (for example, `{{steps.blocks.$return_value}}`), or configure them in this action?", | ||||||||||||||||||||||||||||||||||||||||||||||||||
options: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Reference an array of blocks", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "array", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Configure blocks individually (maximum 5 blocks)", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "configure", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||
optional: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
reloadProps: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
methods: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
// This adds a visual separator in the props form between each block | ||||||||||||||||||||||||||||||||||||||||||||||||||
separator() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return ` | ||||||||||||||||||||||||||||||||||||||||||||||||||
--- | ||||||||||||||||||||||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
createBlockProp(type, label, description) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type, | ||||||||||||||||||||||||||||||||||||||||||||||||||
label, | ||||||||||||||||||||||||||||||||||||||||||||||||||
description: `${description} ${this.separator()}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
createBlock(type, text) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (type === "section") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "section", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "mrkdwn", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (type === "context") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const elements = Array.isArray(text) | ||||||||||||||||||||||||||||||||||||||||||||||||||
? text.map((t) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "mrkdwn", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text: t, | ||||||||||||||||||||||||||||||||||||||||||||||||||
})) | ||||||||||||||||||||||||||||||||||||||||||||||||||
: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "mrkdwn", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "context", | ||||||||||||||||||||||||||||||||||||||||||||||||||
elements, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (type === "link_button") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const buttons = Object.keys(text).map((buttonText) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "button", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "plain_text", | ||||||||||||||||||||||||||||||||||||||||||||||||||
text: buttonText, | ||||||||||||||||||||||||||||||||||||||||||||||||||
emoji: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
url: text[buttonText], // Access the URL using buttonText as the key | ||||||||||||||||||||||||||||||||||||||||||||||||||
action_id: `actionId-${Math.random().toString(36) | ||||||||||||||||||||||||||||||||||||||||||||||||||
.substr(2, 9)}`, // Generates a random action_id | ||||||||||||||||||||||||||||||||||||||||||||||||||
})); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+65
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate
- } else if (type === "link_button") {
- const buttons = Object.keys(text).map((buttonText) => ({
+ } else if (type === "link_button") {
+ if (!text || typeof text !== "object" || Array.isArray(text)) {
+ throw new Error("Link Button expects an object mapping button text → URL");
+ }
+ const buttons = Object.keys(text).map((buttonText) => ({
type: "button",
@@
- action_id: `actionId-${Math.random().toString(36)
- .substr(2, 9)}`, // Generates a random action_id
+ action_id: `actionId-${Math.random().toString(36).slice(2, 11)}`, // Generates a random action_id
})); 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "actions", | ||||||||||||||||||||||||||||||||||||||||||||||||||
elements: buttons, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
async additionalProps(existingProps) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
await common.additionalProps.call(this, existingProps); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const props = {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const sectionDescription = "Add a **section** block to your message and configure with plain text or mrkdwn. See [Slack's docs](https://api.slack.com/reference/block-kit/blocks?ref=bk#section) for more info."; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const contextDescription = "Add a **context** block to your message and configure with plain text or mrkdwn. Define multiple items if you'd like multiple elements in the context block. See [Slack's docs](https://api.slack.com/reference/block-kit/blocks?ref=bk#context) for more info."; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const linkButtonDescription = "Add a **link button** to your message. Enter the button text as the key and the link URL as the value. Configure multiple buttons in the array to render them inline, or add additional Button Link blocks to render them vertically. See [Slack's docs](https://api.slack.com/reference/block-kit/blocks?ref=bk#actions) for more info."; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const propsSection = this.createBlockProp("string", "Section Block Text", sectionDescription); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const propsContext = this.createBlockProp("string[]", "Context Block Text", contextDescription); | ||||||||||||||||||||||||||||||||||||||||||||||||||
const propsLinkButton = this.createBlockProp("object", "Link Button", linkButtonDescription); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (!this.passArrayOrConfigure) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return props; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (this.passArrayOrConfigure == "array") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
props.blocks = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: common.props.slack.propDefinitions.blocks.type, | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: common.props.slack.propDefinitions.blocks.label, | ||||||||||||||||||||||||||||||||||||||||||||||||||
description: common.props.slack.propDefinitions.blocks.description, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+97
to
+103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use strict equality for mode checks. Avoid coercion. Switch to - if (this.passArrayOrConfigure == "array") {
+ if (this.passArrayOrConfigure === "array") {
props.blocks = {
@@
- if (this.passArrayOrConfigure == "array") {
- blocks = this.blocks;
+ if (this.passArrayOrConfigure === "array") {
+ blocks = this.blocks;
} else { Also applies to: 160-164 🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||
props.blockType = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Block Type", | ||||||||||||||||||||||||||||||||||||||||||||||||||
description: "Select the type of block to add. Refer to [Slack's docs](https://api.slack.com/reference/block-kit/blocks) for more info.", | ||||||||||||||||||||||||||||||||||||||||||||||||||
options: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Section", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "section", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Context", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "context", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Link Button", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "link_button", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||
reloadProps: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
};} | ||||||||||||||||||||||||||||||||||||||||||||||||||
let currentBlockType = this.blockType; | ||||||||||||||||||||||||||||||||||||||||||||||||||
for (let i = 1; i <= 5; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (currentBlockType === "section") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
props[`section${i}`] = propsSection; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (currentBlockType === "context") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
props[`context${i}`] = propsContext; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (currentBlockType === "link_button") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
props[`linkButton${i}`] = propsLinkButton; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (i < 5 && currentBlockType) { // Check if currentBlockType is set before adding nextBlockType | ||||||||||||||||||||||||||||||||||||||||||||||||||
props[`nextBlockType${i}`] = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Next Block Type", | ||||||||||||||||||||||||||||||||||||||||||||||||||
options: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Section", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "section", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Context", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "context", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
label: "Link Button", | ||||||||||||||||||||||||||||||||||||||||||||||||||
value: "link_button", | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||
optional: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
reloadProps: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
currentBlockType = this[`nextBlockType${i}`]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return props; | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
async run() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
let blocks = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (this.passArrayOrConfigure == "array") { | ||||||||||||||||||||||||||||||||||||||||||||||||||
blocks = this.blocks; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||
for (let i = 1; i <= 5; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (this[`section${i}`]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
blocks.push(this.createBlock("section", this[`section${i}`])); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (this[`context${i}`]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
blocks.push(this.createBlock("context", this[`context${i}`])); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (this[`linkButton${i}`]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
blocks.push(this.createBlock("link_button", this[`linkButton${i}`])); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return blocks; | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect import path.
This file imports from
"../../slack.app.mjs"
while all other Slack v2 actions import from"../../slack_v2.app.mjs"
. This inconsistency will likely cause a module resolution error since this is a Slack v2 component.Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents