Skip to content

feat(workflow): slack trigger node, trigger workflow from slack#1204

Open
Sithaarth24 wants to merge 8 commits intomainfrom
feat/workflow-slack-trigger
Open

feat(workflow): slack trigger node, trigger workflow from slack#1204
Sithaarth24 wants to merge 8 commits intomainfrom
feat/workflow-slack-trigger

Conversation

@Sithaarth24
Copy link
Contributor

@Sithaarth24 Sithaarth24 commented Nov 10, 2025

Summary by CodeRabbit

  • New Features
    • Slack integration in the workflow builder: create/edit Slack triggers and Slack message steps.
    • New "Slack Message" action to post messages from workflows to channels.
    • Slack trigger configuration UI (app mentions & direct messages) and channel selector UI.
    • /workflows Slack command to list and run configured workflows.
    • Workflow execution can post to Slack and fetch channel metadata for selection.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds Slack trigger and message support across frontend and backend: UI components and icons, API endpoints and client helpers, DB query for Slack-triggered workflows, server workflow execution helpers, and request/route wiring for Slack metadata and message posting.

Changes

Cohort / File(s) Summary
Frontend: Builder & icons
frontend/src/components/workflow/WorkflowBuilder.tsx, frontend/src/components/workflow/WorkflowIcons.tsx
Integrates SlackIcon and wires SlackTriggerConfigUI / SlackMessageConfigUI into the builder UI and triggers sidebar; adjusts node rendering to support Slack trigger/message nodes.
Frontend: Slack UI components
frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx, frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx, frontend/src/components/workflow/slack/SlackChannlesInput.tsx
Adds Slack trigger and message configuration UIs and a channel selector with pagination, types, validation, save/back/close flows, and builder integration.
Frontend: Node & actions
frontend/src/components/workflow/WorkflowNode.tsx, frontend/src/components/workflow/WhatHappensNextUI.tsx
Adds WorkflowNode component (configured/unconfigured rendering) and registers the "Slack Message" action.
Frontend: API & routes
frontend/src/components/workflow/api/ApiHandlers.ts, frontend/src/routes/_authenticated/workflow.tsx
Adds workflowToolsAPI.fetchSlackMetadata (paginated) and removes a debug console.log from the workflow route.
Frontend: Builder wiring (detailed)
frontend/src/components/workflow/WorkflowBuilder.tsx, frontend/src/components/workflow/WorkflowNode.tsx
Wires Slack UIs into builder surfaces (isVisible/onBack/onClose/onSave/initialConfig/toolId/builder) and implements create/update flows for Slack nodes and edges.
Backend: Types & enums
server/types/workflowTypes.ts, server/integrations/slack/types.ts
Adds ToolType members SLACK_TRIGGER and SLACK_MESSAGE; introduces SlackTriggerTool interface.
Backend: DB layer
server/db/workflowTool.ts
Adds getSlackTriggersInWorkflows(txn, userId, workspaceId, channel) to query workflow templates with Slack triggers; updates imports/exports and uses sql/or.
Backend: Slack client & commands
server/integrations/slack/client.ts, server/integrations/slack/types.ts
Adds command handlers for workflows, router changes to prioritize workflows, and exports listSlackChannels and postSlackMessage.
Backend: Workflow execution
server/integrations/slack/workflowSlackUtils.ts
Adds executeWorkflowWithSlackTrigger, plus execution context/result types, to create executions/step records and run the workflow chain for Slack-triggered workflows.
Backend: API endpoints & server wiring
server/api/workflow.ts, server/server.ts
Adds getSlackMetadataApi and registers GET /workflow/tools/slack/metadata; extends execution to handle slack_message via postSlackMessage.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Slack as Slack
    participant SlackClient as Slack Client
    participant DB as Database
    participant WorkflowSvc as Workflow Utils
    participant Engine as Workflow Engine

    User->>Slack: Trigger (slash/mention)
    Slack->>SlackClient: Event/command
    SlackClient->>DB: getSlackTriggersInWorkflows(...)
    DB-->>SlackClient: matching workflow(s)
    SlackClient->>WorkflowSvc: executeWorkflowWithSlackTrigger(context)
    WorkflowSvc->>DB: create workflowExecution & stepExecutions
    WorkflowSvc->>Engine: executeWorkflowChain(root step)
    Engine-->>WorkflowSvc: step results
    WorkflowSvc->>DB: finalize statuses
    WorkflowSvc-->>SlackClient: execution summary
    SlackClient->>Slack: post result message
Loading
sequenceDiagram
    actor User
    participant Builder as Frontend Builder
    participant SlackUI as Slack Config UI
    participant API as Backend API
    participant DB as Database

    User->>Builder: Add Slack node
    Builder->>SlackUI: open SlackTriggerConfigUI / SlackMessageConfigUI
    SlackUI->>API: fetchSlackMetadata()
    API->>DB: listSlackChannels()
    DB-->>API: channels
    API-->>SlackUI: channels
    User->>SlackUI: Save config
    SlackUI->>API: save node config (create/update)
    API->>DB: create/update node & edges
    DB-->>API: success
    API-->>Builder: node created/updated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Files/areas needing extra attention:
    • server/integrations/slack/workflowSlackUtils.ts — transaction boundaries, step execution ordering, status finalization.
    • server/integrations/slack/client.ts — command routing precedence, DM vs channel messaging, error feedback.
    • server/db/workflowTool.ts — correctness of joins/permission filters and channel filtering.
    • Frontend Slack UIs (SlackTriggerConfigUI, SlackMessageConfigUI, SlackChannlesInput) — validation rules, pagination, "all" channel semantics, and builder save flows.
    • server/api/workflow.ts — placeholder replacement and aggregation when posting Slack messages.

Possibly related PRs

Suggested reviewers

  • zereraz
  • junaid-shirur
  • kalpadhwaryu
  • shivamashtikar

Poem

🐰 I hopped through code with tiny paws,
Slack bells chimed and opened doors,
Channels picked and messages sent,
Steps queued up with joyful intent,
Tiny rabbit smiles — workflows soar. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding a Slack trigger node and workflow triggering capability from Slack.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/workflow-slack-trigger

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Sithaarth24, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new capability: triggering workflows directly from Slack. It provides a comprehensive solution, encompassing a new frontend UI for configuring Slack-based triggers within the workflow builder, visual representation of these triggers, and robust backend logic to listen for and respond to specific Slack commands. This allows users to seamlessly initiate automated processes by interacting with a bot in Slack, enhancing workflow accessibility and integration with communication channels.

Highlights

  • New Slack Trigger UI: Introduced a dedicated React component (SlackTriggerConfigUI.tsx) for configuring Slack workflow triggers, allowing users to define trigger types (app mention, direct message, message in channel), channel IDs, titles, and descriptions.
  • Workflow Builder Integration: The workflow builder (WorkflowBuilder.tsx) now supports adding and displaying Slack Trigger nodes, including a new Slack icon in the triggers sidebar and specific rendering logic for these nodes.
  • Backend Workflow Trigger Retrieval: Added a new database function (getSlackTriggersInWorkflows in workflowTool.ts) to efficiently query and retrieve workflow templates that are configured with Slack triggers.
  • Slack Command Handling: Enhanced the Slack integration client (slack/client.ts) to process /workflows commands (to list available Slack-triggered workflows) and custom /{workflow-name} commands (to trigger specific workflows).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Sithaarth24, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature enabling workflows to be triggered directly from Slack. It encompasses a full-stack implementation, from a new frontend UI for configuring Slack triggers within the workflow builder, to backend database queries for managing these triggers, and finally, updates to the Slack integration to listen for and respond to specific commands to list and execute these workflows.

Highlights

  • New Slack Trigger UI: A new React component, SlackTriggerConfigUI.tsx, has been added to provide a dedicated user interface for configuring Slack workflow triggers within the application.
  • Workflow Builder Integration: The workflow builder (WorkflowBuilder.tsx) now supports a new 'Slack Trigger' node type, allowing users to visually add and configure Slack-based triggers directly in their workflows. This includes custom rendering for the Slack trigger node and integration with its configuration sidebar.
  • Backend Support for Slack Triggers: The backend now includes a new getSlackTriggersInWorkflows function in workflowTool.ts to retrieve workflows configured with Slack triggers. The ToolType enum has been extended to include SLACK_TRIGGER.
  • Slack Command Handling: The Slack integration (slack/client.ts) has been enhanced to process new commands: /workflows to list available workflows with Slack triggers, and /{workflow-name} to trigger a specific workflow execution directly from Slack. A new SlackTriggerTool interface was also introduced.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant new feature: a Slack trigger for workflows. The implementation is comprehensive, covering the frontend UI for configuration, the workflow builder canvas rendering, and backend logic to handle Slack commands for listing and triggering workflows. The code is generally well-structured. I've identified one high-severity bug in the UI where a trigger option is missing, along with a few medium-severity suggestions to remove debug code, improve type safety, and enhance performance. Overall, this is a solid contribution that greatly expands the platform's integration capabilities.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new Slack Trigger feature, allowing workflows to be initiated directly from Slack. The changes include a new UI component for configuring Slack triggers, updates to the workflow builder to integrate this new trigger type, and backend logic to handle Slack commands and retrieve relevant workflows. The implementation looks solid, with good separation of concerns between frontend and backend components. The new getSlackTriggersInWorkflows function is a valuable addition for dynamic workflow discovery in Slack. The UI for configuring the trigger is intuitive, and the integration into the workflow builder is seamless. The command handling in Slack client is well-structured to support both listing workflows and triggering them. Overall, this is a well-executed feature.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7dba401 and 4692fef.

📒 Files selected for processing (7)
  • frontend/src/components/workflow/SlackTriggerConfigUI.tsx (1 hunks)
  • frontend/src/components/workflow/WorkflowBuilder.tsx (14 hunks)
  • frontend/src/components/workflow/WorkflowIcons.tsx (1 hunks)
  • server/db/workflowTool.ts (3 hunks)
  • server/integrations/slack/client.ts (5 hunks)
  • server/integrations/slack/types.ts (1 hunks)
  • server/types/workflowTypes.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-10-28T07:51:03.144Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1127
File: server/db/schema/workflows.ts:320-320
Timestamp: 2025-10-28T07:51:03.144Z
Learning: In the workflow template architecture, the API layer handles conversion between external UUIDs (used by frontend) and internal integer IDs (used in database). Frontend types expect UUID strings for workflow template IDs, while internal schemas like createWorkflowStepTemplateSchema expect integers. The publicWorkflowTemplateSchema maps external_id → id for API responses.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-09-02T16:41:31.729Z
Learnt from: devesh-juspay
Repo: xynehq/xyne PR: 758
File: server/db/schema/workflowTools.ts:9-14
Timestamp: 2025-09-02T16:41:31.729Z
Learning: In the workflowTools.ts schema, the user prefers to add notNull() constraint to the type field but does not want onDelete cascade behavior for the workflowTemplateId foreign key reference.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-11-06T09:49:42.236Z
Learnt from: Asrani-Aman
Repo: xynehq/xyne PR: 1163
File: server/api/chat/agents.ts:3941-3991
Timestamp: 2025-11-06T09:49:42.236Z
Learning: In server/api/chat/agents.ts dual RAG path and similar agent message flows, when `agentForDb.appIntegrations` is parsed, the outer function (agents.ts) only needs to extract high-level routing info like `agentAppEnums`. The detailed per-app selections (`selectedItems`) are intentionally extracted inside the inner RAG functions (`generateAnswerFromDualRag`, `UnderstandMessageAndAnswer` in chat.ts) by parsing the `agentPrompt` parameter. This is the established architectural pattern: outer function handles routing, inner function handles detailed selection parsing via `parseAppSelections(agentPromptData.appIntegrations)` and passes `selectedItem` to `searchVespaAgent` for per-app item scoping.

Applied to files:

  • server/integrations/slack/client.ts
🧬 Code graph analysis (4)
server/db/workflowTool.ts (2)
server/types.ts (1)
  • TxnOrClient (320-320)
server/db/schema/workflows.ts (3)
  • workflowTemplate (63-87)
  • workflowTool (115-133)
  • workflowStepTemplate (90-112)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (1)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
server/integrations/slack/client.ts (2)
server/integrations/slack/types.ts (2)
  • DbUser (23-31)
  • SlackTriggerTool (70-77)
server/db/workflowTool.ts (1)
  • getSlackTriggersInWorkflows (82-129)
frontend/src/components/workflow/WorkflowBuilder.tsx (2)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (2)
  • SlackTriggerConfig (4-9)
  • SlackTriggerConfigUI (39-355)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
server/db/workflowTool.ts (1)

155-159: Remove the per-user filter on workspace triggers

eq(workflowTemplate.userId, userId) means a Slack user will only ever see workflows they personally authored. That breaks the core use case of listing workspace-wide Slack triggers (and it’s the same issue we called out earlier). Please drop the userId predicate—or replace it with the real permission check—so members can run team workflows from Slack.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4692fef and b9b293f.

📒 Files selected for processing (2)
  • frontend/src/components/workflow/WorkflowBuilder.tsx (14 hunks)
  • server/db/workflowTool.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-28T07:51:03.144Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1127
File: server/db/schema/workflows.ts:320-320
Timestamp: 2025-10-28T07:51:03.144Z
Learning: In the workflow template architecture, the API layer handles conversion between external UUIDs (used by frontend) and internal integer IDs (used in database). Frontend types expect UUID strings for workflow template IDs, while internal schemas like createWorkflowStepTemplateSchema expect integers. The publicWorkflowTemplateSchema maps external_id → id for API responses.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-09-02T16:41:31.729Z
Learnt from: devesh-juspay
Repo: xynehq/xyne PR: 758
File: server/db/schema/workflowTools.ts:9-14
Timestamp: 2025-09-02T16:41:31.729Z
Learning: In the workflowTools.ts schema, the user prefers to add notNull() constraint to the type field but does not want onDelete cascade behavior for the workflowTemplateId foreign key reference.

Applied to files:

  • server/db/workflowTool.ts
🧬 Code graph analysis (2)
server/db/workflowTool.ts (2)
server/types.ts (1)
  • TxnOrClient (340-340)
server/db/schema/workflows.ts (3)
  • workflowTemplate (65-89)
  • workflowTool (117-135)
  • workflowStepTemplate (92-114)
frontend/src/components/workflow/WorkflowBuilder.tsx (2)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (2)
  • SlackTriggerConfig (4-9)
  • SlackTriggerConfigUI (39-355)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (3)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (2)

105-132: Validate and render channels for both “app_mention” and “message_in_channel”

If you plan to support “message_in_channel”, require channels in validation and show the channel selector for both types.

- export interface SlackTriggerConfig {
-   triggerType: "app_mention" | "direct_message" 
+ export interface SlackTriggerConfig {
+   triggerType: "app_mention" | "direct_message" | "message_in_channel"
@@
-  if (config.triggerType === "app_mention") {
+  if (config.triggerType === "app_mention" || config.triggerType === "message_in_channel") {
     if (!config.channelIds || config.channelIds.length === 0) {
       validationErrors.push(
         "At least one channel is required for 'App Mention' trigger",
       )
     }
   }
@@
-{config.triggerType === "app_mention" && (
+{(config.triggerType === "app_mention" || config.triggerType === "message_in_channel") && (

Also applies to: 341-346


28-39: Expose “Message in Channel” in the dropdown

Add the missing option to keep UI, types, and validator consistent.

 const triggerTypeOptions = [
   {
     value: "app_mention" as const,
     label: "App Mention",
     description: "When bot/app is mentioned in channel with @botname",
   },
   {
     value: "direct_message" as const,
     label: "Direct Message (DM)",
     description: "When a user sends a direct message to the bot",
   },
+  {
+    value: "message_in_channel" as const,
+    label: "Message in Channel",
+    description: "When a message is posted in specified channel(s)",
+  },
 ]
frontend/src/components/workflow/WorkflowBuilder.tsx (1)

2293-2302: Populate Slack config before opening the editor

When clicking an existing Slack Trigger node, the code only toggles the sidebar visibility but doesn't populate slackTriggerInitialConfig or slackTriggerToolId. This causes the editor to show defaults instead of the node's saved settings, potentially wiping previous configuration on update.

This issue was previously flagged in past review comments for lines 2293-2297.

Apply this diff to hydrate the config before opening:

        case "slack_trigger":
-          // Open Slack Trigger config sidebar 
-          setShowSlackTriggerConfigUI(true)
-          setSelectedSlackTriggerNodeId(node.id)
-          break
+          {
+            // Open Slack Trigger config sidebar 
+            const slackTools = (node.data?.tools as Tool[] | undefined) || []
+            const slackTool = slackTools[0]
+            const slackConfig =
+              (slackTool?.config as SlackTriggerConfig | undefined) ||
+              (slackTool?.val as SlackTriggerConfig | undefined) ||
+              ((step as any)?.config as SlackTriggerConfig | undefined)
+
+            setSlackTriggerInitialConfig(slackConfig)
+            setSlackTriggerToolId(slackTool?.id)
+            setShowSlackTriggerConfigUI(true)
+            setSelectedSlackTriggerNodeId(node.id)
+            break
+          }

        case "slack_message":
-          setShowSlackMessageConfigUI(true)
-          setSelectedSlackMessageNodeId(node.id)
-          break
+          {
+            const slackMsgTools = (node.data?.tools as Tool[] | undefined) || []
+            const slackMsgTool = slackMsgTools[0]
+            const slackMsgConfig =
+              (slackMsgTool?.config as SlackMessageConfig | undefined) ||
+              (slackMsgTool?.val as SlackMessageConfig | undefined) ||
+              ((step as any)?.config as SlackMessageConfig | undefined)
+
+            // Populate initial config for Slack Message if editing existing node
+            setShowSlackMessageConfigUI(true)
+            setSelectedSlackMessageNodeId(node.id)
+            break
+          }

Note: For Slack Message, you'll also need to pass the config to SlackMessageConfigUI via an initialConfig prop (currently the component accepts it but WorkflowBuilder doesn't pass it).

🧹 Nitpick comments (7)
frontend/src/components/workflow/WhatHappensNextUI.tsx (1)

123-127: Consider refactoring the condition for better maintainability.

The condition now has five action IDs checked with OR operators, making it lengthy and harder to maintain when adding new actions.

Consider refactoring to:

+            const clickableActions = ["ai_agent", "email", "http_request", "select_agents", "slack_message"]
             onClick={() => {
-              if (action.id === "ai_agent" || action.id === "email" || action.id === "http_request" || action.id === "select_agents" || action.id === "slack_message") {
+              if (clickableActions.includes(action.id)) {
                 // For AI Agent, Email, HTTP Request, Select Agents, and Slack Message, trigger custom event to open respective ConfigUI
                 onSelectAction(action.id)
                 onClose() // Close WhatHappensNextUI
               }
             }}
frontend/src/components/workflow/WorkflowNode.tsx (1)

81-85: Add type guard for icon prop to prevent runtime errors.

The React.cloneElement call assumes icon is a valid React element. If the icon prop is not a proper ReactElement, this will throw a runtime error.

Consider adding a type guard:

-                        {React.cloneElement(icon as React.ReactElement, {
+                        {React.isValidElement(icon) && React.cloneElement(icon, {
                             width: iconSizeUnconfigured,
                             height: iconSizeUnconfigured,
                             color: iconColor
                         })}

Apply the same fix at line 177 in the configured state.

server/api/workflow.ts (1)

5826-5841: Consider GET for metadata endpoint (optional)

Fetching metadata is semantically a GET, not POST. If routing allows, expose GET /workflow/tools/slack/metadata for idempotent caching at CDN/proxy.

server/integrations/slack/client.ts (2)

1597-1652: Avoid DB hit on every “/” command; cache workflow triggers briefly

Fetching workflow triggers on each command adds latency and load. Cache per (workspaceId,userId) with a short TTL (e.g., 30–60s).

// module scope
const wfCache = new Map<string, { expires: number; data: SlackTriggerTool[] }>()
const wfKey = (u: number, w: number) => `${w}:${u}`
const getWf = async (u: number, w: number) => {
  const k = wfKey(u, w)
  const hit = wfCache.get(k)
  const now = Date.now()
  if (hit && hit.expires > now) return hit.data
  const data = await getSlackTriggersInWorkflows(db, u, w)
  wfCache.set(k, { expires: now + 60_000, data })
  return data
}
// replace direct getSlackTriggersInWorkflows(...) with: await getWf(dbUser.id, dbUser.workspaceId)

1504-1583: Workflow execution path is a stub (“DUMMY EXECUTION”)

If this is intentional for the first cut, please track a follow-up to call the actual workflow execution API, pass the mapped tool/workflow IDs, and surface the executionId back to Slack.

frontend/src/components/workflow/SlackMessageConfigUI.tsx (1)

132-142: Consider revising channel clearing logic

The current implementation clears the selected channel whenever the input value is empty. This could be problematic if a user clicks into the input field (perhaps to search for a different channel) – any typing would immediately clear their current selection before they've actually chosen a replacement.

Consider only clearing the selection explicitly via the X button (lines 239-244) and not automatically when the user types into the search input.

  const handleChannelInputChange = (value: string) => {
    setChannelInput(value)
-    
-    // If input is cleared, clear the selected channel
-    if (!value.trim()) {
-      setConfig({
-        ...config,
-        channelId: ""
-      })
-    }
  }
frontend/src/components/workflow/WorkflowBuilder.tsx (1)

707-711: Simplify config extraction to improve type safety

The config extraction pattern uses multiple fallbacks with any type assertions, which was flagged in previous review comments as complex and not ideal for type safety. Consider simplifying this to be more explicit and type-safe.

Based on learnings

-    const config =
-      (step as any).config ||
-      (hasSlackTriggerTool && tools?.[0]?.config) ||
-      (hasSlackTriggerTool && tools?.[0]?.val) ||
-      {}
+    const stepWithConfig = step as Step & { config?: Partial<SlackTriggerConfig> }
+    const toolConfig = (hasSlackTriggerTool && (tools?.[0]?.config || tools?.[0]?.val)) as Partial<SlackTriggerConfig> | undefined
+    const config: Partial<SlackTriggerConfig> = stepWithConfig.config || toolConfig || {}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9b293f and 5356005.

📒 Files selected for processing (12)
  • frontend/src/components/workflow/SlackMessageConfigUI.tsx (1 hunks)
  • frontend/src/components/workflow/SlackTriggerConfigUI.tsx (1 hunks)
  • frontend/src/components/workflow/WhatHappensNextUI.tsx (3 hunks)
  • frontend/src/components/workflow/WorkflowBuilder.tsx (19 hunks)
  • frontend/src/components/workflow/WorkflowNode.tsx (1 hunks)
  • frontend/src/components/workflow/api/ApiHandlers.ts (1 hunks)
  • frontend/src/routes/_authenticated/workflow.tsx (0 hunks)
  • server/api/workflow.ts (3 hunks)
  • server/db/workflowTool.ts (3 hunks)
  • server/integrations/slack/client.ts (7 hunks)
  • server/server.ts (2 hunks)
  • server/types/workflowTypes.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/routes/_authenticated/workflow.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/types/workflowTypes.ts
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-05-28T10:47:41.020Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 484
File: server/integrations/google/sync.ts:222-222
Timestamp: 2025-05-28T10:47:41.020Z
Learning: The functions `handleGoogleDriveChange` and `getDriveChanges` in `server/integrations/google/sync.ts` are intentionally exported for future changes, even though they are not currently being imported by other modules.

Applied to files:

  • server/server.ts
📚 Learning: 2025-06-10T05:40:04.427Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 525
File: frontend/src/routes/_authenticated/admin/integrations/slack.tsx:141-148
Timestamp: 2025-06-10T05:40:04.427Z
Learning: In frontend/src/routes/_authenticated/admin/integrations/slack.tsx, the ConnectAction enum and related connectAction state (lines 141-148, 469-471) are intentionally kept for future development, even though they appear unused in the current implementation.

Applied to files:

  • frontend/src/components/workflow/WhatHappensNextUI.tsx
  • frontend/src/components/workflow/SlackMessageConfigUI.tsx
📚 Learning: 2025-07-28T12:07:13.546Z
Learnt from: vipul-maheshwari
Repo: xynehq/xyne PR: 686
File: server/utils/chainUtils.ts:65-69
Timestamp: 2025-07-28T12:07:13.546Z
Learning: In the chainUtils.ts file, the correct type for message parameters is `SelectMessage[]` rather than `Message[]` when working with conversation message arrays.

Applied to files:

  • frontend/src/components/workflow/SlackTriggerConfigUI.tsx
📚 Learning: 2025-09-08T16:18:07.128Z
Learnt from: Aayushjshah
Repo: xynehq/xyne PR: 787
File: server/api/chat/mapper.ts:631-636
Timestamp: 2025-09-08T16:18:07.128Z
Learning: In server/api/chat/mapper.ts, the filter_query parameter for getSlackThreads should remain required: false (optional) in the mapper definition, even if it differs from the AgentTool definition in server/api/chat/tools.ts. This is an intentional design decision where parameter requirements can differ between the mapper and tool layers.

Applied to files:

  • server/integrations/slack/client.ts
📚 Learning: 2025-08-08T10:58:41.288Z
Learnt from: MayankBansal2004
Repo: xynehq/xyne PR: 719
File: server/api/chat/agents.ts:2056-2058
Timestamp: 2025-08-08T10:58:41.288Z
Learning: In server/db/schema/messages.ts, the messages table defines tokensUsed as integer and cost as numeric. Due to Drizzle’s numeric mapping, cost is handled as a string at the TypeScript layer, while tokensUsed remains a number. Therefore, insertMessage should persist cost as a string and tokensUsed as a number across server/api/chat/agents.ts.

Applied to files:

  • server/integrations/slack/client.ts
📚 Learning: 2025-11-06T09:49:42.236Z
Learnt from: Asrani-Aman
Repo: xynehq/xyne PR: 1163
File: server/api/chat/agents.ts:3941-3991
Timestamp: 2025-11-06T09:49:42.236Z
Learning: In server/api/chat/agents.ts dual RAG path and similar agent message flows, when `agentForDb.appIntegrations` is parsed, the outer function (agents.ts) only needs to extract high-level routing info like `agentAppEnums`. The detailed per-app selections (`selectedItems`) are intentionally extracted inside the inner RAG functions (`generateAnswerFromDualRag`, `UnderstandMessageAndAnswer` in chat.ts) by parsing the `agentPrompt` parameter. This is the established architectural pattern: outer function handles routing, inner function handles detailed selection parsing via `parseAppSelections(agentPromptData.appIntegrations)` and passes `selectedItem` to `searchVespaAgent` for per-app item scoping.

Applied to files:

  • server/integrations/slack/client.ts
📚 Learning: 2025-09-02T16:41:31.729Z
Learnt from: devesh-juspay
Repo: xynehq/xyne PR: 758
File: server/db/schema/workflowTools.ts:9-14
Timestamp: 2025-09-02T16:41:31.729Z
Learning: In the workflowTools.ts schema, the user prefers to add notNull() constraint to the type field but does not want onDelete cascade behavior for the workflowTemplateId foreign key reference.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-10-28T07:51:03.144Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1127
File: server/db/schema/workflows.ts:320-320
Timestamp: 2025-10-28T07:51:03.144Z
Learning: In the workflow template architecture, the API layer handles conversion between external UUIDs (used by frontend) and internal integer IDs (used in database). Frontend types expect UUID strings for workflow template IDs, while internal schemas like createWorkflowStepTemplateSchema expect integers. The publicWorkflowTemplateSchema maps external_id → id for API responses.

Applied to files:

  • server/db/workflowTool.ts
🧬 Code graph analysis (8)
server/api/workflow.ts (2)
server/db/schema/channels.ts (1)
  • channels (32-69)
server/integrations/slack/client.ts (1)
  • listSlackChannels (2378-2395)
server/server.ts (1)
server/api/workflow.ts (1)
  • getSlackMetadataApi (5829-5841)
frontend/src/components/workflow/SlackMessageConfigUI.tsx (1)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (2)
frontend/src/components/workflow/api/ApiHandlers.ts (1)
  • workflowToolsAPI (396-1090)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
server/integrations/slack/client.ts (2)
server/integrations/slack/types.ts (2)
  • DbUser (23-31)
  • SlackTriggerTool (70-77)
server/db/workflowTool.ts (1)
  • getSlackTriggersInWorkflows (125-179)
frontend/src/components/workflow/api/ApiHandlers.ts (1)
frontend/src/api.ts (1)
  • api (5-5)
frontend/src/components/workflow/WorkflowBuilder.tsx (3)
frontend/src/components/workflow/WorkflowIcons.tsx (3)
  • WebhookIcon (167-185)
  • FormDocumentIcon (318-337)
  • SlackIcon (494-526)
frontend/src/components/workflow/SlackTriggerConfigUI.tsx (2)
  • SlackTriggerConfig (6-11)
  • SlackTriggerConfigUI (41-512)
frontend/src/components/workflow/SlackMessageConfigUI.tsx (2)
  • SlackMessageConfig (6-11)
  • SlackMessageConfigUI (29-397)
server/db/workflowTool.ts (3)
server/types.ts (1)
  • TxnOrClient (340-340)
server/db/schema/workflows.ts (3)
  • workflowTemplate (65-89)
  • workflowTool (117-135)
  • workflowStepTemplate (92-114)
server/db/schema/userWorkflowPermissions.ts (1)
  • userWorkflowPermissions (23-54)
🔇 Additional comments (14)
frontend/src/components/workflow/WhatHappensNextUI.tsx (1)

11-11: LGTM! Slack Message action properly integrated.

The MessageSquare icon import and slack_message action definition follow the established pattern and integrate cleanly with the existing action list.

Also applies to: 50-55

server/db/workflowTool.ts (2)

147-154: LGTM! Join condition uses idiomatic Drizzle ORM.

The inArray(workflowTool.id, workflowStepTemplate.toolIds) join condition is the proper Drizzle ORM approach for array containment checks, providing good type safety.


125-179: No actionable changes required.

The permission model is correct and consistent throughout the codebase. Slack trigger workflows are properly scoped:

  • Public workflows (isPublic=true) → accessible to all workspace members
  • Private workflows → accessible only to users with explicit permission entries

This pattern is used consistently across getSlackTriggersInWorkflows, getWorkflows, and related functions. The leftJoin + OR condition correctly implements this two-tier access model. If workspace-wide access is desired for a trigger, mark it public; otherwise, use permission entries to control visibility. The implementation is secure and intentional.

frontend/src/components/workflow/WorkflowNode.tsx (3)

4-29: LGTM! Well-structured interface with clear documentation.

The WorkflowNodeProps interface is comprehensive and well-documented, making the component easy to use.


111-141: LGTM! Add Next Step button properly implemented.

The button correctly handles events (stopPropagation + preventDefault) and uses conditional rendering appropriately.


148-265: LGTM! Configured state renders properly with all required elements.

The configured state rendering includes all necessary UI elements (icon, title, description, handles, optional button) and maintains consistency with the unconfigured state.

server/server.ts (1)

327-327: LGTM! Slack metadata route properly integrated.

The import and route follow the established pattern for workflow tool metadata endpoints, maintaining consistency with similar Jira routes.

Also applies to: 1510-1510

frontend/src/components/workflow/api/ApiHandlers.ts (2)

1086-1088: LGTM! Error handling is consistent.

Error logging and re-throwing follows the established pattern in this file.


1065-1089: ****

The review comment is based on a false premise. The server-side getSlackMetadataApi calls listSlackChannels(), which already returns an array of objects with { id: string; name: string } structure. The endpoint wraps this as { success: true, data: { channels } }. The frontend code correctly extracts result.data?.channels, which is already in the expected format—no transformation is needed. The misleading comment should be removed or clarified to reflect that the channels are already properly formatted.

Likely an incorrect or invalid review comment.

frontend/src/components/workflow/SlackMessageConfigUI.tsx (2)

55-72: Good pattern: fetching channels on visibility

The effect correctly fetches Slack channels when the component becomes visible, with proper error handling and loading states. This ensures fresh data for each configuration session.


89-116: Validation logic is thorough

The validation function properly checks all required fields and enforces appropriate length limits (message: 4000, title: 100, description: 500), providing clear error messages for users.

frontend/src/components/workflow/WorkflowBuilder.tsx (3)

3959-4093: Slack Message follows correct pattern

The handleSlackMessageConfigSave implementation correctly follows the pattern of other "What Happens Next" actions (AI Agent, Email, HTTP Request) by creating/updating local node state without backend API calls. These action nodes are persisted when the entire workflow template is saved, which is appropriate for workflow steps rather than trigger configurations.


1379-1385: Slack Trigger successfully integrated into triggers list

The Slack Trigger entry is properly added to the TriggersSidebar with appropriate icon, description, and enabled state. This makes it discoverable to users alongside other trigger types.


4728-4770: UI components properly wired with correct props

Both SlackTriggerConfigUI and SlackMessageConfigUI are correctly integrated with all necessary props (isVisible, onBack, onClose, onSave, initialConfig, toolId, showBackButton, builder) following the established patterns from other configuration sidebars.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (5)
frontend/src/components/workflow/WorkflowBuilder.tsx (3)

3539-3544: Remove console.log in production UI flow.

Replace with the existing Snackbar/logger pattern to avoid noisy console output.

-          console.log("Webhook saved to backend:", savedWebhookData)
+          // saved to backend; update UI below
...
-          console.log("Webhook updated in backend:", savedWebhookData)
+          // updated in backend; update UI below

Also applies to: 3602-3605


707-711: Simplify Slack Trigger config source selection.

Prefer a single clear source-of-truth order: step.config, then tools[0].config. Dropping tools[0].val reduces confusion.

-    const config =
-      (step as any).config ||
-      (hasSlackTriggerTool && tools?.[0]?.config) ||
-      (hasSlackTriggerTool && tools?.[0]?.val) ||
-      {}
+    const config =
+      (step as any).config ||
+      (hasSlackTriggerTool && tools?.[0]?.config) ||
+      {}

2293-2303: Hydrate Slack Trigger editor on node click to avoid wiping saved config.

Opening an existing Slack Trigger sets the sidebar flags but does not set slackTriggerInitialConfig or slackTriggerToolId, so the editor shows defaults and edits overwrite existing settings. Hydrate from node.data.tools[0] (fallback to step.config) before opening.

-        case "slack_trigger":
-          // Open Slack Trigger config sidebar 
-          setShowSlackTriggerConfigUI(true)
-          setSelectedSlackTriggerNodeId(node.id)
-          break
+        case "slack_trigger": {
+          const slackTools = (node.data?.tools as Tool[] | undefined) || []
+          const slackTool = slackTools[0]
+          const slackConfig =
+            (slackTool?.config as SlackTriggerConfig | undefined) ||
+            (slackTool?.value as SlackTriggerConfig | undefined) ||
+            ((step as any)?.config as SlackTriggerConfig | undefined)
+          setSlackTriggerInitialConfig(slackConfig)
+          setSlackTriggerToolId(slackTool?.id)
+          setSelectedSlackTriggerNodeId(node.id)
+          setShowSlackTriggerConfigUI(true)
+          break
+        }

Based on learnings

server/integrations/slack/client.ts (2)

1667-1700: Avoid repeated DB scans; add short‑TTL cache for workflow triggers.

getSlackTriggersInWorkflows is called on every slash. Cache by workspaceId+channel for a few seconds to reduce load.

+// simple in-memory cache { key: { data, expiresAt } }
+const wfCache = new Map<string, { data: SlackTriggerTool[]; expiresAt: number }>()
@@
-    const workflowTriggers: SlackTriggerTool[] = await getSlackTriggersInWorkflows(
+    const cacheKey = `${dbUser.workspaceId}:${channel}`
+    const cached = wfCache.get(cacheKey)
+    const now = Date.now()
+    const workflowTriggers: SlackTriggerTool[] = cached && cached.expiresAt > now
+      ? cached.data
+      : await getSlackTriggersInWorkflows(
         db,
         dbUser.id,
         dbUser.workspaceId,
         channel
-    )
+      ).then(res => {
+        wfCache.set(cacheKey, { data: res, expiresAt: now + 5_000 })
+        return res
+      })

2427-2466: Guard against missing client and paginate conversations.list.

webClient! can be null and only one page is fetched. Add a null check, iterate cursors, and exclude archived.

-export const listSlackChannels = async (
+export const listSlackChannels = async (
   options: {
     cursor?: string,
     limit?: number
   } = {}
 ): Promise<{
   channels: {
     id: string,
     name: string, 
   }[],
   hasMore: boolean,
   nextCursor?: string
 }> => {
-  const { cursor, limit = 200 } = options
-  
-  const response = await webClient!.conversations.list({
-    cursor,
-    limit,
-    exclude_archived: true,
-    types: 'public_channel,private_channel'
-  })
-  
-  if (!response.channels) {
-    Logger.error("channels not received from conversations")
-    throw new Error("Channels absent in conversation response")
-  }
-  
-  const channels = response.channels
-    .filter(ch => (ch.name && ch.id))
-    .map(ch => ({
-      id: ch.id!,
-      name: ch.name! 
-    }))
-
-  return {
-    channels,
-    hasMore: !!response.response_metadata?.next_cursor,
-    nextCursor: response.response_metadata?.next_cursor
-  }
+  if (!webClient) {
+    Logger.warn("Slack client not initialized for listSlackChannels")
+    throw new Error("Slack integration is not configured")
+  }
+  const { limit = 200 } = options
+  const out: Array<{ id: string; name: string }> = []
+  let cursor = options.cursor
+  do {
+    const resp = await webClient.conversations.list({
+      cursor,
+      limit,
+      exclude_archived: true,
+      types: "public_channel,private_channel",
+    } as any)
+    const page = (resp.channels || [])
+      .filter((ch: any) => ch?.id && ch?.name)
+      .map((ch: any) => ({ id: ch.id as string, name: ch.name as string }))
+    out.push(...page)
+    cursor = (resp.response_metadata as any)?.next_cursor || undefined
+  } while (cursor)
+  return { channels: out, hasMore: false, nextCursor: undefined }
🧹 Nitpick comments (9)
server/integrations/slack/workflowSlackUtils.ts (3)

45-83: Consider wrapping workflowExecution + stepExecution creation in a DB transaction

Right now the template lookup, workflowExecution insert, stepExecution inserts, and rootWorkflowStepExeId update (Lines 53–61, 66–83, 95–133) run as separate statements on db. If anything fails mid‑way, you can end up with an execution record without all its steps, or steps without rootWorkflowStepExeId set.

Using db.transaction for this block would keep the execution and its steps consistent (all‑or‑nothing) before you call executeWorkflowChain, while still letting the chain use the committed state.

Also applies to: 95-133


161-180: Avoid duplicating workflow completion logic already handled in executeWorkflowChain

After executeWorkflowChain returns, you re‑query all step executions and, if all are COMPLETED, explicitly mark the workflowExecution as COMPLETED (Lines 161–180). Per the existing executeWorkflowChain behaviour, it already rechecks all steps and marks the workflowExecution as COMPLETED when appropriate.

This duplication is harmless but adds extra queries and another place to maintain completion rules. You can rely on executeWorkflowChain for status updates and here only read status (and step counts) for reporting, or drop the completion update here entirely.


135-137: Optional: de‑duplicate toolIds before querying workflow tools

When building allToolIds (Lines 135–136), the same toolId can appear in multiple steps. Passing duplicates into getWorkflowToolsByIds is functionally fine (the DB IN clause will dedupe), but you can reduce query payload slightly by doing Array.from(new Set(allToolIds)) first.

frontend/src/components/workflow/api/ApiHandlers.ts (1)

1065-1105: Reuse extractResponseData and tighten typing for Slack metadata helper

The implementation correctly builds query params and parses { success, data } from /workflow/tools/slack/metadata (Lines 1068–1100). Two small improvements:

  • You can reuse extractResponseData to keep response‑handling consistent across APIs, e.g.:
const data = await extractResponseData<{
  channels: Array<{ id: string; name: string }>
  hasMore: boolean
  nextCursor?: string
}>(response)

return {
  channels: data.channels ?? [],
  hasMore: data.hasMore ?? false,
  nextCursor: data.nextCursor,
}
  • Instead of const query: any = {}, type it as Record<string, string> for better inference and to match how other APIs build query objects.
frontend/src/components/workflow/WorkflowBuilder.tsx (1)

3854-3864: Use stable id for Slack Trigger node (optional).

Other triggers use fixed ids ("form-submission", "webhook-trigger", "jira-trigger"). Consider "slack-trigger" for consistency and easier lookups.

-          const newNodeId = String(nodeCounter + 1)
-          setNodeCounter(nodeCounter + 1)
+          const newNodeId = "slack-trigger"
+          setNodeCounter(prev => prev + 1)
server/integrations/slack/client.ts (4)

1-1: Remove unused type import.

ConversationsListResponse isn’t used.

-import { WebClient, type ConversationsListResponse } from "@slack/web-api"
+import { WebClient } from "@slack/web-api"

1424-1500: Validate workspace before listing workflows and handle empty access early.

Mirror the guards used in /agents to avoid confusing errors.

   const handleWorkflowsCommand = async (
@@
 ) => {
   try {
+    if (!dbUser.workspaceId || dbUser.workspaceId <= 0) {
+      const msg = "There's an issue with your workspace configuration. Please contact your administrator."
+      return isDM
+        ? client.chat.postMessage({ channel, text: msg })
+        : client.chat.postEphemeral({ channel, user, text: msg, thread_ts })
+    }
     const workflowTriggers = await getSlackTriggersInWorkflows(

1505-1631: Slug matching robustness.

workflowName normalization uses “replace(/-/g, ' ')” on the command but equality check uses raw db name lowercased. To avoid false negatives, compare using a shared slugify.

-    const matchedTrigger = workflowTriggers.find((wf) => wf.workflowName.toLowerCase() === workflowName)
+    const slug = (s: string) => s.trim().toLowerCase().replace(/\s+/g, "-")
+    const matchedTrigger = workflowTriggers.find((wf) => slug(wf.workflowName) === slug(workflowName))

2492-2528: Return consistent errors from postSlackMessage and consider username support.

Current implementation is fine; optional: document that username may be ignored for bot tokens. No code change required.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5356005 and 5e6b967.

📒 Files selected for processing (10)
  • frontend/src/components/workflow/WorkflowBuilder.tsx (19 hunks)
  • frontend/src/components/workflow/api/ApiHandlers.ts (1 hunks)
  • frontend/src/components/workflow/slack/SlackChannlesInput.tsx (1 hunks)
  • frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx (1 hunks)
  • frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx (1 hunks)
  • server/api/workflow.ts (4 hunks)
  • server/db/workflowTool.ts (3 hunks)
  • server/integrations/slack/client.ts (8 hunks)
  • server/integrations/slack/workflowSlackUtils.ts (1 hunks)
  • server/server.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/db/workflowTool.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).
📚 Learning: 2025-08-11T14:10:56.008Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 725
File: server/server.ts:784-811
Timestamp: 2025-08-11T14:10:56.008Z
Learning: In the xyne application (server/server.ts), the following endpoints are intentionally accessible to regular authenticated users (not just admins):
- POST /oauth/create - allows users to create OAuth providers
- POST /slack/ingest_more_channel - allows users to ingest Slack channels
- POST /slack/start_ingestion - allows users to start Slack ingestion
- DELETE /oauth/connector/delete - allows users to delete OAuth connectors
- POST /connector/update_status - allows users to update connector status
- GET /connectors/all - allows users to view all connectors
- GET /oauth/global-slack-provider - allows users to check for global Slack provider
These endpoints enable self-service integration management for users.

Applied to files:

  • server/server.ts
📚 Learning: 2025-11-12T06:07:09.854Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).

Applied to files:

  • server/server.ts
  • frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx
  • server/integrations/slack/client.ts
  • frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx
  • frontend/src/components/workflow/WorkflowBuilder.tsx
📚 Learning: 2025-07-28T12:07:13.546Z
Learnt from: vipul-maheshwari
Repo: xynehq/xyne PR: 686
File: server/utils/chainUtils.ts:65-69
Timestamp: 2025-07-28T12:07:13.546Z
Learning: In the chainUtils.ts file, the correct type for message parameters is `SelectMessage[]` rather than `Message[]` when working with conversation message arrays.

Applied to files:

  • frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx
📚 Learning: 2025-09-08T16:18:07.128Z
Learnt from: Aayushjshah
Repo: xynehq/xyne PR: 787
File: server/api/chat/mapper.ts:631-636
Timestamp: 2025-09-08T16:18:07.128Z
Learning: In server/api/chat/mapper.ts, the filter_query parameter for getSlackThreads should remain required: false (optional) in the mapper definition, even if it differs from the AgentTool definition in server/api/chat/tools.ts. This is an intentional design decision where parameter requirements can differ between the mapper and tool layers.

Applied to files:

  • server/integrations/slack/client.ts
📚 Learning: 2025-08-08T10:58:41.288Z
Learnt from: MayankBansal2004
Repo: xynehq/xyne PR: 719
File: server/api/chat/agents.ts:2056-2058
Timestamp: 2025-08-08T10:58:41.288Z
Learning: In server/db/schema/messages.ts, the messages table defines tokensUsed as integer and cost as numeric. Due to Drizzle’s numeric mapping, cost is handled as a string at the TypeScript layer, while tokensUsed remains a number. Therefore, insertMessage should persist cost as a string and tokensUsed as a number across server/api/chat/agents.ts.

Applied to files:

  • server/integrations/slack/client.ts
📚 Learning: 2025-11-06T09:49:42.273Z
Learnt from: Asrani-Aman
Repo: xynehq/xyne PR: 1163
File: server/api/chat/agents.ts:3941-3991
Timestamp: 2025-11-06T09:49:42.273Z
Learning: In server/api/chat/agents.ts dual RAG path and similar agent message flows, when `agentForDb.appIntegrations` is parsed, the outer function (agents.ts) only needs to extract high-level routing info like `agentAppEnums`. The detailed per-app selections (`selectedItems`) are intentionally extracted inside the inner RAG functions (`generateAnswerFromDualRag`, `UnderstandMessageAndAnswer` in chat.ts) by parsing the `agentPrompt` parameter. This is the established architectural pattern: outer function handles routing, inner function handles detailed selection parsing via `parseAppSelections(agentPromptData.appIntegrations)` and passes `selectedItem` to `searchVespaAgent` for per-app item scoping.

Applied to files:

  • server/integrations/slack/client.ts
🧬 Code graph analysis (9)
frontend/src/components/workflow/api/ApiHandlers.ts (1)
frontend/src/api.ts (1)
  • api (5-5)
server/integrations/slack/workflowSlackUtils.ts (4)
server/logger/index.ts (2)
  • getLogger (36-93)
  • Subsystem (15-15)
server/db/schema/workflows.ts (4)
  • workflowTemplate (65-89)
  • workflowExecution (138-163)
  • workflowStepTemplate (92-114)
  • workflowStepExecution (166-192)
server/db/workflowTool.ts (1)
  • getWorkflowToolsByIds (108-120)
server/api/workflow.ts (1)
  • executeWorkflowChain (1158-1710)
server/server.ts (1)
server/api/workflow.ts (1)
  • getSlackMetadataApi (5937-5955)
frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx (2)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
frontend/src/components/workflow/slack/SlackChannlesInput.tsx (1)
  • SlackChannelInput (18-240)
server/integrations/slack/client.ts (3)
server/integrations/slack/types.ts (2)
  • DbUser (23-31)
  • SlackTriggerTool (70-77)
server/db/workflowTool.ts (1)
  • getSlackTriggersInWorkflows (125-186)
server/integrations/slack/workflowSlackUtils.ts (1)
  • executeWorkflowWithSlackTrigger (45-199)
frontend/src/components/workflow/slack/SlackChannlesInput.tsx (1)
frontend/src/components/workflow/api/ApiHandlers.ts (1)
  • workflowToolsAPI (396-1106)
frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx (2)
frontend/src/components/workflow/WorkflowIcons.tsx (1)
  • SlackIcon (494-526)
frontend/src/components/workflow/slack/SlackChannlesInput.tsx (1)
  • SlackChannelInput (18-240)
server/api/workflow.ts (1)
server/integrations/slack/client.ts (2)
  • postSlackMessage (2492-2528)
  • listSlackChannels (2427-2466)
frontend/src/components/workflow/WorkflowBuilder.tsx (3)
frontend/src/components/workflow/WorkflowIcons.tsx (3)
  • WebhookIcon (167-185)
  • FormDocumentIcon (318-337)
  • SlackIcon (494-526)
frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx (2)
  • SlackTriggerConfig (6-11)
  • SlackTriggerConfigUI (41-370)
frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx (2)
  • SlackMessageConfig (5-10)
  • SlackMessageConfigUI (28-269)
🔇 Additional comments (3)
server/integrations/slack/workflowSlackUtils.ts (1)

144-157: Initial previousResults shape looks reasonable for Slack trigger payload

The initial previousResults you pass into executeWorkflowChain (Lines 144–157) includes the Slack trigger payload under the root step’s name, along with a toolType: 'slack_trigger'. This aligns with how downstream tools typically consume accumulated results and should be sufficient for Slack‑aware tools to pick up the trigger context.

server/server.ts (1)

327-328: Slack metadata endpoint wiring looks consistent and correct

The getSlackMetadataApi import and .get("/workflow/tools/slack/metadata", getSlackMetadataApi) route (Lines 327–328, 1510–1511) align with the Hono client path (api.workflow.tools.slack.metadata) and sit behind the existing AuthMiddleware, matching the pattern of other workflow tool routes.

Also applies to: 1510-1511

frontend/src/components/workflow/WorkflowBuilder.tsx (1)

4727-4750: Pass initialConfig/toolId to Slack Trigger UI.

The state variables exist but are never set on edit without the hydration above. Ensure props are wired; after applying the node-click hydration, these props work as intended. No code change needed here beyond the hydration fix.

@debojyoti-git
Copy link

Can you please add a demo?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
server/api/workflow.ts (1)

5972-5993: Return proper HTTP errors for Slack metadata and gate on Slack being enabled

This handler currently logs and returns a generic JSON error:

export const getSlackMetadataApi = async (c: Context) => {
  try {
    const cursor = c.req.query("cursor") || undefined
    const limit = Number(c.req.query("limit")) || 200

    const result = await listSlackChannels({ cursor, limit })
    return c.json({ success: true, data: result })
  } catch (error) {
    Logger.error(error, "Failed to get slack metadata")
    return c.json({
      success: false,
      error: "Failed to get slack metadata"
    }, 500)
  }
}

Issues:

  • It doesn’t fail fast when Slack isn’t configured (e.g., missing token/client).
  • It diverges from the rest of this file, which typically throws an HTTPException with getErrorMessage(error) in catch blocks.

You can align it with other APIs and make failure modes clearer by:

  • Using an isSlackEnabled() guard from the Slack client (if available).
  • Throwing HTTPException instead of returning ad‑hoc JSON from the catch.

For example:

-import { listSlackChannels, postSlackMessage } from "@/integrations/slack/client"
+import { listSlackChannels, postSlackMessage, isSlackEnabled } from "@/integrations/slack/client"
@@
 export const getSlackMetadataApi = async (c: Context) => {
   try {
+    if (!isSlackEnabled()) {
+      throw new HTTPException(503, { message: "Slack integration is not configured" })
+    }
+
     const cursor = c.req.query("cursor") || undefined
     const limit = Number(c.req.query("limit")) || 200

     const result = await listSlackChannels({ cursor, limit })
     
     return c.json({
       success: true,
       data: result
     })
   } catch (error) {
     Logger.error(error, "Failed to get slack metadata")
-    return c.json({
-      success: false,
-      error: "Failed to get slack metadata"
-    }, 500)
+    throw new HTTPException(500, {
+      message: getErrorMessage(error),
+    })
   }
 }

This matches the surrounding API style and guarantees callers always get a consistent HTTP‑level error.

🧹 Nitpick comments (1)
server/db/workflowTool.ts (1)

122-183: Reconfirm owner access & channel config assumptions in Slack trigger query

The query looks good overall, but two edge cases are worth double‑checking:

  1. Owner access without explicit permission rows
    The access predicate is:

    and(
      eq(workflowTool.type, ToolType.SLACK_TRIGGER),
      eq(workflowTemplate.workspaceId, workspaceId),
      or(
        eq(workflowTemplate.isPublic, true),
        eq(userWorkflowPermissions.userId, userId),
      ),
    )

    This will surface:

    • Public workflows in the workspace, and
    • Workflows where the user has an entry in userWorkflowPermissions.

    If owners don’t always get a userWorkflowPermissions row for their own private workflows, their own non‑public Slack triggers won’t appear here. If that situation is possible, consider extending the or with eq(workflowTemplate.userId, userId) to guarantee owners see their own triggers as well.

  2. Channel IDs shape assumptions
    The final filter assumes toolConfig.channelIds is a string[]:

    const channelIds = ((wf.toolConfig as any).channelIds as string[]) || []

    If this is ever mis‑shaped (single string, null, etc.), the result will silently drop that workflow. A small guard like Array.isArray(...) ? ... : [] (and/or returning an explicit config error upstream) would make this more robust.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e6b967 and 8ba9967.

📒 Files selected for processing (4)
  • frontend/src/components/workflow/slack/SlackChannlesInput.tsx (1 hunks)
  • server/api/workflow.ts (4 hunks)
  • server/db/workflowTool.ts (3 hunks)
  • server/integrations/slack/workflowSlackUtils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/workflow/slack/SlackChannlesInput.tsx
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).
📚 Learning: 2025-11-12T06:07:09.854Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).

Applied to files:

  • server/integrations/slack/workflowSlackUtils.ts
📚 Learning: 2025-07-04T07:00:46.837Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 638
File: server/integrations/slack/index.ts:793-824
Timestamp: 2025-07-04T07:00:46.837Z
Learning: In server/integrations/slack/index.ts, the dual IngestionState instances follow a specific pattern: `ingestionState` stores the current state that gets updated during processing, while `ingestionOldState` stores the old/previously saved state used for resumption logic when restarting ingestion.

Applied to files:

  • server/integrations/slack/workflowSlackUtils.ts
📚 Learning: 2025-09-08T16:18:07.128Z
Learnt from: Aayushjshah
Repo: xynehq/xyne PR: 787
File: server/api/chat/mapper.ts:631-636
Timestamp: 2025-09-08T16:18:07.128Z
Learning: In server/api/chat/mapper.ts, the filter_query parameter for getSlackThreads should remain required: false (optional) in the mapper definition, even if it differs from the AgentTool definition in server/api/chat/tools.ts. This is an intentional design decision where parameter requirements can differ between the mapper and tool layers.

Applied to files:

  • server/api/workflow.ts
📚 Learning: 2025-05-28T10:47:41.020Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 484
File: server/integrations/google/sync.ts:222-222
Timestamp: 2025-05-28T10:47:41.020Z
Learning: The functions `handleGoogleDriveChange` and `getDriveChanges` in `server/integrations/google/sync.ts` are intentionally exported for future changes, even though they are not currently being imported by other modules.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-10-28T07:51:03.144Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1127
File: server/db/schema/workflows.ts:320-320
Timestamp: 2025-10-28T07:51:03.144Z
Learning: In the workflow template architecture, the API layer handles conversion between external UUIDs (used by frontend) and internal integer IDs (used in database). Frontend types expect UUID strings for workflow template IDs, while internal schemas like createWorkflowStepTemplateSchema expect integers. The publicWorkflowTemplateSchema maps external_id → id for API responses.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-09-02T16:41:31.729Z
Learnt from: devesh-juspay
Repo: xynehq/xyne PR: 758
File: server/db/schema/workflowTools.ts:9-14
Timestamp: 2025-09-02T16:41:31.729Z
Learning: In the workflowTools.ts schema, the user prefers to add notNull() constraint to the type field but does not want onDelete cascade behavior for the workflowTemplateId foreign key reference.

Applied to files:

  • server/db/workflowTool.ts
🧬 Code graph analysis (3)
server/integrations/slack/workflowSlackUtils.ts (3)
server/logger/index.ts (2)
  • getLogger (36-93)
  • Subsystem (15-15)
server/db/workflowTool.ts (1)
  • getWorkflowToolsByIds (108-120)
server/api/workflow.ts (1)
  • executeWorkflowChain (1158-1710)
server/api/workflow.ts (1)
server/integrations/slack/client.ts (2)
  • postSlackMessage (2492-2528)
  • listSlackChannels (2427-2466)
server/db/workflowTool.ts (3)
server/types.ts (1)
  • TxnOrClient (340-340)
server/db/schema/workflows.ts (3)
  • workflowTemplate (65-89)
  • workflowTool (117-135)
  • workflowStepTemplate (92-114)
server/db/schema/userWorkflowPermissions.ts (1)
  • userWorkflowPermissions (23-54)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
frontend/src/components/workflow/WorkflowBuilder.tsx (3)

718-720: Fix channel field mismatch in Slack Trigger rendering.

Lines 718 and 720 use config.channelId (singular), but SlackTriggerConfig defines channelIds: string[] (plural array). This prevents channel information from ever displaying in the node.

Apply this fix:

-    const isConfigured = Boolean(config.title || step.name || config.triggerType || config.description)
+    const isConfigured = Boolean(
+      config.title || 
+      step.name || 
+      config.triggerType || 
+      config.description || 
+      (config.channelIds && config.channelIds.length > 0)
+    )
     const triggerLabel = config.triggerType ? triggerTypeLabels[config.triggerType as keyof typeof triggerTypeLabels] : "Slack Trigger"
-    const channelInfo = config.channelId ? ` in ${config.channelId}` : ""
+    const channelInfo = 
+      Array.isArray(config.channelIds) && config.channelIds.length > 0
+        ? ` in ${config.channelIds.length === 1 ? config.channelIds[0] : config.channelIds.join(", ")}`
+        : ""

753-759: Fix channel field mismatch in Slack Message rendering.

Lines 753 and 759 use config.channel (singular), but SlackMessageConfig defines channelIds: string[] (plural array). This prevents channel information from displaying correctly.

Apply this fix:

-    const isConfigured = Boolean(config.title || step.name || config.message || config.channel)
+    const isConfigured = Boolean(
+      config.title || 
+      step.name || 
+      config.message || 
+      (config.channelIds && config.channelIds.length > 0)
+    )

     return (
       <WorkflowNode
         icon={<SlackIcon />}
         title={config.title || step.name || "Slack Message"}
-        description={config.description || `Send message to Slack${config.channel ? ` in ${config.channel}` : ""}`}
+        description={
+          config.description || 
+          `Send message to Slack${
+            Array.isArray(config.channelIds) && config.channelIds.length > 0
+              ? ` in ${config.channelIds.length === 1 ? config.channelIds[0] : config.channelIds.join(", ")}`
+              : ""
+          }`
+        }

2293-2297: Populate Slack Trigger config before opening the editor.

When clicking an existing Slack Trigger node, the editor opens with blank values because slackTriggerInitialConfig and slackTriggerToolId are not populated. This causes users to lose their previous configuration when editing.

Apply this fix (following the pattern used for Jira at lines 2258-2291):

         case "slack_trigger":
-          // Open Slack Trigger config sidebar 
+          // Open Slack Trigger config sidebar - fetch config from node
+          const slackTriggerTools = node?.data?.tools as any[]
+          const slackTriggerTool = slackTriggerTools?.[0] as any
+          if (slackTriggerTool?.id) {
+            // Populate config from node data
+            setSlackTriggerInitialConfig({
+              ...slackTriggerTool?.config,
+              ...slackTriggerTool?.value,
+            })
+            setSlackTriggerToolId(slackTriggerTool.id)
+          } else {
+            // No tool ID yet (shouldn't happen for existing nodes)
+            setSlackTriggerInitialConfig(undefined)
+            setSlackTriggerToolId(undefined)
+          }
           setShowSlackTriggerConfigUI(true)
           setSelectedSlackTriggerNodeId(node.id)
           break
🧹 Nitpick comments (2)
server/db/workflowTool.ts (1)

122-137: Consider defining a named type for the return value.

While the explicit return type is helpful, defining a named interface or type (e.g., SlackTriggerWorkflow) would improve code reusability and maintainability, especially since this structure is likely used in other parts of the codebase (e.g., SlackTriggerTool in server/integrations/slack/types.ts).

Example:

export type SlackTriggerWorkflow = {
  workflowId: string
  workflowName: string
  workflowDescription: string | null
  toolId: string
  toolConfig: any
  toolValue: any
}

export const getSlackTriggersInWorkflows = async (
  txn: TxnOrClient,
  userId: number,
  workspaceId: number,
  channel: string
): Promise<SlackTriggerWorkflow[]> => {
  // ...
}
frontend/src/components/workflow/WorkflowBuilder.tsx (1)

707-711: Optional: Simplify config extraction with better typing.

The multiple fallback logic with type assertions could be made clearer and type-safe. Consider extracting this pattern into a helper function or using a more structured approach:

const getSlackTriggerConfig = (step: Step, tools?: Tool[]): Partial<SlackTriggerConfig> => {
  const stepConfig = (step as any).config as Partial<SlackTriggerConfig> | undefined
  const toolConfig = tools?.[0]?.config as Partial<SlackTriggerConfig> | undefined
  const toolVal = tools?.[0]?.val as Partial<SlackTriggerConfig> | undefined
  return stepConfig || toolConfig || toolVal || {}
}

const config = getSlackTriggerConfig(step, hasSlackTriggerTool ? tools : undefined)

This makes the intent clearer and avoids repeated type assertions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba9967 and 20536fa.

📒 Files selected for processing (5)
  • frontend/src/components/workflow/WorkflowBuilder.tsx (19 hunks)
  • server/api/workflow.ts (5 hunks)
  • server/db/workflowTool.ts (3 hunks)
  • server/integrations/slack/workflowSlackUtils.ts (1 hunks)
  • server/server.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • server/server.ts
  • server/integrations/slack/workflowSlackUtils.ts
  • server/api/workflow.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).
📚 Learning: 2025-05-28T10:47:41.020Z
Learnt from: naSim087
Repo: xynehq/xyne PR: 484
File: server/integrations/google/sync.ts:222-222
Timestamp: 2025-05-28T10:47:41.020Z
Learning: The functions `handleGoogleDriveChange` and `getDriveChanges` in `server/integrations/google/sync.ts` are intentionally exported for future changes, even though they are not currently being imported by other modules.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-10-28T07:51:03.144Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1127
File: server/db/schema/workflows.ts:320-320
Timestamp: 2025-10-28T07:51:03.144Z
Learning: In the workflow template architecture, the API layer handles conversion between external UUIDs (used by frontend) and internal integer IDs (used in database). Frontend types expect UUID strings for workflow template IDs, while internal schemas like createWorkflowStepTemplateSchema expect integers. The publicWorkflowTemplateSchema maps external_id → id for API responses.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-09-02T16:41:31.729Z
Learnt from: devesh-juspay
Repo: xynehq/xyne PR: 758
File: server/db/schema/workflowTools.ts:9-14
Timestamp: 2025-09-02T16:41:31.729Z
Learning: In the workflowTools.ts schema, the user prefers to add notNull() constraint to the type field but does not want onDelete cascade behavior for the workflowTemplateId foreign key reference.

Applied to files:

  • server/db/workflowTool.ts
📚 Learning: 2025-11-12T06:07:09.854Z
Learnt from: Sithaarth24
Repo: xynehq/xyne PR: 1204
File: frontend/src/components/workflow/WorkflowBuilder.tsx:3851-3938
Timestamp: 2025-11-12T06:07:09.854Z
Learning: In the WorkflowBuilder component, workflow node configurations (including Slack Trigger, AI Agent, Email, HTTP Request, Form, etc.) should only update local React state when users configure them. Backend persistence happens through a single batch save operation when the user clicks the "Save Changes" button (handleSaveChanges function). Only Jira currently has immediate backend persistence (will be changed to match this pattern).

Applied to files:

  • frontend/src/components/workflow/WorkflowBuilder.tsx
📚 Learning: 2025-07-28T12:07:13.546Z
Learnt from: vipul-maheshwari
Repo: xynehq/xyne PR: 686
File: server/utils/chainUtils.ts:65-69
Timestamp: 2025-07-28T12:07:13.546Z
Learning: In the chainUtils.ts file, the correct type for message parameters is `SelectMessage[]` rather than `Message[]` when working with conversation message arrays.

Applied to files:

  • frontend/src/components/workflow/WorkflowBuilder.tsx
📚 Learning: 2025-09-17T10:17:16.374Z
Learnt from: MayankBansal2004
Repo: xynehq/xyne PR: 853
File: frontend/src/components/ChatBox.tsx:696-726
Timestamp: 2025-09-17T10:17:16.374Z
Learning: MayankBansal2004 prefers the current model validation approach in ChatBox.tsx that validates saved models against allModelsWithO3 rather than filtering by current capability, considering this a "default mechanism thing" for the frontend that is working fine as designed.

Applied to files:

  • frontend/src/components/workflow/WorkflowBuilder.tsx
🧬 Code graph analysis (2)
server/db/workflowTool.ts (3)
server/types.ts (1)
  • TxnOrClient (340-340)
server/db/schema/workflows.ts (3)
  • workflowTemplate (65-89)
  • workflowTool (117-135)
  • workflowStepTemplate (92-114)
server/db/schema/userWorkflowPermissions.ts (1)
  • userWorkflowPermissions (23-54)
frontend/src/components/workflow/WorkflowBuilder.tsx (4)
frontend/src/components/workflow/WorkflowIcons.tsx (3)
  • WebhookIcon (167-185)
  • FormDocumentIcon (318-337)
  • SlackIcon (494-526)
frontend/src/components/workflow/slack/SlackTriggerConfigUI.tsx (2)
  • SlackTriggerConfig (6-11)
  • SlackTriggerConfigUI (41-370)
frontend/src/components/workflow/slack/SlackMessageConfigUI.tsx (2)
  • SlackMessageConfig (5-10)
  • SlackMessageConfigUI (28-269)
frontend/src/components/workflow/Types.ts (1)
  • Tool (58-63)
🔇 Additional comments (2)
server/db/workflowTool.ts (2)

1-1: LGTM!

The new imports (sql, or, workflowTemplate, workflowStepTemplate, userWorkflowPermissions) are properly added and utilized in the new getSlackTriggersInWorkflows function.

Also applies to: 10-11, 14-14


164-167: Permission logic correctly implemented.

The or() condition properly handles both public workflows and explicitly shared workflows. The left join on userWorkflowPermissions combined with the OR condition ensures that:

  • Public workflows (isPublic = true) are accessible to all workspace users
  • Private workflows are only accessible if the user has an explicit permission entry

This correctly addresses the past review concern about workspace workflow visibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants