diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/output-select/output-select.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/output-select/output-select.tsx index 4e7e975ed..8decb13cf 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/output-select/output-select.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/output-select/output-select.tsx @@ -5,6 +5,7 @@ import { useMemo } from 'react' import { RepeatIcon, SplitIcon } from 'lucide-react' import { Combobox, type ComboboxOptionGroup } from '@/components/emcn' import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' import { getBlock } from '@/blocks' import { useWorkflowDiffStore } from '@/stores/workflow-diff/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' @@ -120,6 +121,8 @@ export function OutputSelect({ : `block-${block.id}` const blockConfig = getBlock(block.type) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const effectiveTriggerMode = Boolean(block.triggerMode && isTriggerCapable) let outputsToProcess: Record = {} const rawSubBlockValues = @@ -135,8 +138,8 @@ export function OutputSelect({ } outputsToProcess = getEffectiveBlockOutputs(block.type, subBlocks, { - triggerMode: Boolean(block.triggerMode), - preferToolOutputs: !block.triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) as Record if (Object.keys(outputsToProcess).length === 0) return diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx index ac63cdfd8..0c1dbc951 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx @@ -18,6 +18,7 @@ import { getEffectiveBlockOutputType, getOutputPathsFromSchema, } from '@/lib/workflows/blocks/block-outputs' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' import { TRIGGER_TYPES } from '@/lib/workflows/triggers/triggers' import { KeyboardNavigationHandler } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/components/keyboard-navigation-handler' import type { @@ -214,7 +215,8 @@ const getOutputTypeForPath = ( const subBlocks = mergedSubBlocksOverride ?? useWorkflowStore.getState().blocks[blockId]?.subBlocks - const triggerMode = Boolean(block?.triggerMode && blockConfig?.triggers?.enabled) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const triggerMode = Boolean(block?.triggerMode && isTriggerCapable) return getEffectiveBlockOutputType(block?.type ?? '', outputPath, subBlocks, { triggerMode, @@ -1074,9 +1076,12 @@ export const TagDropdown: React.FC = ({ blockTags = [normalizedBlockName] } } else { + const sourceBlockConfig = getBlock(sourceBlock.type) + const isTriggerCapable = sourceBlockConfig ? hasTriggerCapability(sourceBlockConfig) : false + const effectiveTriggerMode = Boolean(sourceBlock.triggerMode && isTriggerCapable) const outputPaths = getEffectiveBlockOutputPaths(sourceBlock.type, mergedSubBlocks, { - triggerMode: Boolean(sourceBlock.triggerMode), - preferToolOutputs: !sourceBlock.triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) const allTags = outputPaths.map((path) => `${normalizedBlockName}.${path}`) @@ -1319,9 +1324,14 @@ export const TagDropdown: React.FC = ({ blockTags = [normalizedBlockName] } } else { + const accessibleBlockConfig = getBlock(accessibleBlock.type) + const isTriggerCapable = accessibleBlockConfig + ? hasTriggerCapability(accessibleBlockConfig) + : false + const effectiveTriggerMode = Boolean(accessibleBlock.triggerMode && isTriggerCapable) const outputPaths = getEffectiveBlockOutputPaths(accessibleBlock.type, mergedSubBlocks, { - triggerMode: Boolean(accessibleBlock.triggerMode), - preferToolOutputs: !accessibleBlock.triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) const allTags = outputPaths.map((path) => `${normalizedBlockName}.${path}`) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-block-connections.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-block-connections.ts index ae3c4f0fa..a509707db 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-block-connections.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-block-connections.ts @@ -1,6 +1,8 @@ import { useShallow } from 'zustand/react/shallow' import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculator' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' +import { getBlock } from '@/blocks' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' @@ -87,10 +89,13 @@ export function useBlockConnections(blockId: string) { // Get merged subblocks for this source block const mergedSubBlocks = getMergedSubBlocks(sourceId) + const blockConfig = getBlock(sourceBlock.type) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const effectiveTriggerMode = Boolean(sourceBlock.triggerMode && isTriggerCapable) const blockOutputs = getEffectiveBlockOutputs(sourceBlock.type, mergedSubBlocks, { - triggerMode: Boolean(sourceBlock.triggerMode), - preferToolOutputs: !sourceBlock.triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) const outputFields: Field[] = Object.entries(blockOutputs).map( diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-output-fields.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-output-fields.ts index 3be40158a..b8c344783 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-output-fields.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-output-fields.ts @@ -2,6 +2,7 @@ import { useMemo } from 'react' import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' import type { SchemaField } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item' import { getBlock } from '@/blocks' import { useSubBlockStore } from '@/stores/workflows/subblock/store' @@ -139,9 +140,11 @@ export function useBlockOutputFields({ return [] } + const isTriggerCapable = hasTriggerCapability(blockConfig) + const effectiveTriggerMode = Boolean(triggerMode && isTriggerCapable) const baseOutputs = getEffectiveBlockOutputs(blockType, mergedSubBlocks, { - triggerMode: Boolean(triggerMode), - preferToolOutputs: !triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) as Record if (Object.keys(baseOutputs).length === 0) { return [] diff --git a/apps/sim/executor/utils/block-data.ts b/apps/sim/executor/utils/block-data.ts index 63cb07d60..3fe339b45 100644 --- a/apps/sim/executor/utils/block-data.ts +++ b/apps/sim/executor/utils/block-data.ts @@ -1,4 +1,6 @@ import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' +import { getBlock } from '@/blocks/registry' import { isTriggerBehavior, normalizeName } from '@/executor/constants' import type { ExecutionContext } from '@/executor/types' import type { OutputSchema } from '@/executor/utils/block-reference' @@ -36,7 +38,9 @@ function getRegistrySchema(block: SerializedBlock): OutputSchema | undefined { if (!blockType) return undefined const subBlocks = paramsToSubBlocks(block.config?.params) - const triggerMode = isTriggerBehavior(block) + const blockConfig = getBlock(blockType) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const triggerMode = Boolean(isTriggerBehavior(block) && isTriggerCapable) const outputs = getEffectiveBlockOutputs(blockType, subBlocks, { triggerMode, preferToolOutputs: !triggerMode, diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts index fccdfc57e..efd9d4c36 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts @@ -15,6 +15,8 @@ import { loadWorkflowFromNormalizedTables, } from '@/lib/workflows/persistence/utils' import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' +import { getBlock } from '@/blocks/registry' import { normalizeName } from '@/executor/constants' import type { Loop, Parallel } from '@/stores/workflows/workflow/types' import { @@ -343,7 +345,9 @@ export async function executeGetBlockOutputs( continue } - const triggerMode = Boolean(block.triggerMode) + const blockConfig = getBlock(block.type) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const triggerMode = Boolean(block.triggerMode && isTriggerCapable) const outputs = getEffectiveBlockOutputPaths(block.type, block.subBlocks, { triggerMode, preferToolOutputs: !triggerMode, @@ -489,7 +493,9 @@ export async function executeGetBlockUpstreamReferences( ? getSubflowInsidePaths(block.type, accessibleBlockId, loops, parallels) : ['results'] } else { - const triggerMode = Boolean(block.triggerMode) + const blockConfig = getBlock(block.type) + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const triggerMode = Boolean(block.triggerMode && isTriggerCapable) outputPaths = getEffectiveBlockOutputPaths(block.type, block.subBlocks, { triggerMode, preferToolOutputs: !triggerMode, diff --git a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/builders.ts b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/builders.ts index 21e71edfa..529a0bc78 100644 --- a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/builders.ts +++ b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/builders.ts @@ -3,6 +3,7 @@ import { createLogger } from '@sim/logger' import type { PermissionGroupConfig } from '@/lib/permission-groups/types' import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { buildCanonicalIndex, isCanonicalPair } from '@/lib/workflows/subblocks/visibility' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' import { getAllBlocks } from '@/blocks/registry' import type { BlockConfig } from '@/blocks/types' import { TRIGGER_RUNTIME_SUBBLOCK_IDS } from '@/triggers/constants' @@ -39,6 +40,8 @@ export function createBlockFromParams( // Determine outputs based on trigger mode const triggerMode = params.triggerMode || false + const isTriggerCapable = blockConfig ? hasTriggerCapability(blockConfig) : false + const effectiveTriggerMode = Boolean(triggerMode && isTriggerCapable) let outputs: Record if (params.outputs) { @@ -55,8 +58,8 @@ export function createBlockFromParams( }) } outputs = getEffectiveBlockOutputs(params.type, subBlocks, { - triggerMode, - preferToolOutputs: !triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) } else { outputs = {} diff --git a/apps/sim/stores/workflows/utils.ts b/apps/sim/stores/workflows/utils.ts index c63e67053..aae0f248c 100644 --- a/apps/sim/stores/workflows/utils.ts +++ b/apps/sim/stores/workflows/utils.ts @@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid' import { DEFAULT_DUPLICATE_OFFSET } from '@/lib/workflows/autolayout/constants' import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { mergeSubblockStateWithValues } from '@/lib/workflows/subblocks' +import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' import { TriggerUtils } from '@/lib/workflows/triggers/triggers' import { getBlock } from '@/blocks' import { isAnnotationOnlyBlock, normalizeName } from '@/executor/constants' @@ -188,9 +189,11 @@ export function prepareBlockState(options: PrepareBlockStateOptions): BlockState }) } + const isTriggerCapable = hasTriggerCapability(blockConfig) + const effectiveTriggerMode = Boolean(triggerMode && isTriggerCapable) const outputs = getEffectiveBlockOutputs(type, subBlocks, { - triggerMode, - preferToolOutputs: !triggerMode, + triggerMode: effectiveTriggerMode, + preferToolOutputs: !effectiveTriggerMode, }) return {