diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/index.ts
index 4cc36a67d..0cfc45369 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/index.ts
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/index.ts
@@ -34,3 +34,4 @@ export { Text } from './text/text'
export { TimeInput } from './time-input/time-input'
export { ToolInput } from './tool-input/tool-input'
export { VariablesInput } from './variables-input/variables-input'
+export { WorkflowSelectorInput } from './workflow-selector/workflow-selector-input'
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-selector/workflow-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-selector/workflow-selector-input.tsx
new file mode 100644
index 000000000..5771e9f89
--- /dev/null
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-selector/workflow-selector-input.tsx
@@ -0,0 +1,45 @@
+'use client'
+
+import { useMemo } from 'react'
+import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
+import type { SubBlockConfig } from '@/blocks/types'
+import type { SelectorContext } from '@/hooks/selectors/types'
+import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
+
+interface WorkflowSelectorInputProps {
+ blockId: string
+ subBlock: SubBlockConfig
+ disabled?: boolean
+ isPreview?: boolean
+ previewValue?: string | null
+}
+
+export function WorkflowSelectorInput({
+ blockId,
+ subBlock,
+ disabled = false,
+ isPreview = false,
+ previewValue,
+}: WorkflowSelectorInputProps) {
+ const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId)
+
+ const context: SelectorContext = useMemo(
+ () => ({
+ excludeWorkflowId: activeWorkflowId ?? undefined,
+ }),
+ [activeWorkflowId]
+ )
+
+ return (
+
+ )
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx
index 2ea7cb557..274bba15b 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx
@@ -40,6 +40,7 @@ import {
TimeInput,
ToolInput,
VariablesInput,
+ WorkflowSelectorInput,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components'
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
import type { SubBlockConfig } from '@/blocks/types'
@@ -90,7 +91,6 @@ const isFieldRequired = (config: SubBlockConfig, subBlockValues?: Record
)
+ case 'workflow-selector':
+ return (
+
+ )
+
case 'mcp-server-selector':
return (
=> {
- try {
- const { workflows, activeWorkflowId } = useWorkflowRegistry.getState()
-
- // Filter out the current workflow to prevent recursion
- const availableWorkflows = Object.entries(workflows)
- .filter(([id]) => id !== activeWorkflowId)
- .map(([id, workflow]) => ({
- label: workflow.name || `Workflow ${id.slice(0, 8)}`,
- id: id,
- }))
- .sort((a, b) => a.label.localeCompare(b.label))
-
- return availableWorkflows
- } catch (error) {
- logger.error('Error getting available workflows:', error)
- return []
- }
-}
export const WorkflowBlock: BlockConfig = {
type: 'workflow',
@@ -38,8 +13,7 @@ export const WorkflowBlock: BlockConfig = {
{
id: 'workflowId',
title: 'Select Workflow',
- type: 'combobox',
- options: getAvailableWorkflows,
+ type: 'workflow-selector',
placeholder: 'Search workflows...',
required: true,
},
diff --git a/apps/sim/blocks/blocks/workflow_input.ts b/apps/sim/blocks/blocks/workflow_input.ts
index c918ded44..16e48c4f2 100644
--- a/apps/sim/blocks/blocks/workflow_input.ts
+++ b/apps/sim/blocks/blocks/workflow_input.ts
@@ -1,18 +1,5 @@
import { WorkflowIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
-import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
-
-const getAvailableWorkflows = (): Array<{ label: string; id: string }> => {
- try {
- const { workflows, activeWorkflowId } = useWorkflowRegistry.getState()
- return Object.entries(workflows)
- .filter(([id]) => id !== activeWorkflowId)
- .map(([id, w]) => ({ label: w.name || `Workflow ${id.slice(0, 8)}`, id }))
- .sort((a, b) => a.label.localeCompare(b.label))
- } catch {
- return []
- }
-}
export const WorkflowInputBlock: BlockConfig = {
type: 'workflow_input',
@@ -25,18 +12,16 @@ export const WorkflowInputBlock: BlockConfig = {
`,
category: 'blocks',
docsLink: 'https://docs.sim.ai/blocks/workflow',
- bgColor: '#6366F1', // Indigo - modern and professional
+ bgColor: '#6366F1',
icon: WorkflowIcon,
subBlocks: [
{
id: 'workflowId',
title: 'Select Workflow',
- type: 'combobox',
- options: getAvailableWorkflows,
+ type: 'workflow-selector',
placeholder: 'Search workflows...',
required: true,
},
- // Renders dynamic mapping UI based on selected child workflow's Start trigger inputFormat
{
id: 'inputMapping',
title: 'Input Mapping',
diff --git a/apps/sim/hooks/selectors/registry.ts b/apps/sim/hooks/selectors/registry.ts
index 0a373af29..6b0674b75 100644
--- a/apps/sim/hooks/selectors/registry.ts
+++ b/apps/sim/hooks/selectors/registry.ts
@@ -6,6 +6,7 @@ import type {
SelectorOption,
SelectorQueryArgs,
} from '@/hooks/selectors/types'
+import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
const SELECTOR_STALE = 60 * 1000
@@ -853,6 +854,36 @@ const registry: Record = {
}))
},
},
+ 'sim.workflows': {
+ key: 'sim.workflows',
+ staleTime: 0, // Always fetch fresh from store
+ getQueryKey: ({ context }: SelectorQueryArgs) => [
+ 'selectors',
+ 'sim.workflows',
+ context.excludeWorkflowId ?? 'none',
+ ],
+ enabled: () => true,
+ fetchList: async ({ context }: SelectorQueryArgs): Promise => {
+ const { workflows } = useWorkflowRegistry.getState()
+ return Object.entries(workflows)
+ .filter(([id]) => id !== context.excludeWorkflowId)
+ .map(([id, workflow]) => ({
+ id,
+ label: workflow.name || `Workflow ${id.slice(0, 8)}`,
+ }))
+ .sort((a, b) => a.label.localeCompare(b.label))
+ },
+ fetchById: async ({ detailId }: SelectorQueryArgs): Promise => {
+ if (!detailId) return null
+ const { workflows } = useWorkflowRegistry.getState()
+ const workflow = workflows[detailId]
+ if (!workflow) return null
+ return {
+ id: detailId,
+ label: workflow.name || `Workflow ${detailId.slice(0, 8)}`,
+ }
+ },
+ },
}
export function getSelectorDefinition(key: SelectorKey): SelectorDefinition {
diff --git a/apps/sim/hooks/selectors/types.ts b/apps/sim/hooks/selectors/types.ts
index d42340f58..b884a4719 100644
--- a/apps/sim/hooks/selectors/types.ts
+++ b/apps/sim/hooks/selectors/types.ts
@@ -29,6 +29,7 @@ export type SelectorKey =
| 'webflow.sites'
| 'webflow.collections'
| 'webflow.items'
+ | 'sim.workflows'
export interface SelectorOption {
id: string
@@ -52,6 +53,7 @@ export interface SelectorContext {
siteId?: string
collectionId?: string
spreadsheetId?: string
+ excludeWorkflowId?: string
}
export interface SelectorQueryArgs {