@@ -4,6 +4,7 @@ import { devtools } from 'zustand/middleware'
44import { createLogger } from '@/lib/logs/console/logger'
55import { getBlockOutputs } from '@/lib/workflows/block-outputs'
66import { getBlock } from '@/blocks'
7+ import type { SubBlockConfig } from '@/blocks/types'
78import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
89import { useSubBlockStore } from '@/stores/workflows/subblock/store'
910import {
@@ -21,6 +22,72 @@ import { generateLoopBlocks, generateParallelBlocks } from '@/stores/workflows/w
2122
2223const logger = createLogger ( 'WorkflowStore' )
2324
25+ /**
26+ * Creates a deep clone of an initial sub-block value to avoid shared references.
27+ *
28+ * @param value - The value to clone.
29+ * @returns A cloned value suitable for initializing sub-block state.
30+ */
31+ function cloneInitialSubblockValue ( value : unknown ) : unknown {
32+ if ( Array . isArray ( value ) ) {
33+ return value . map ( ( item ) => cloneInitialSubblockValue ( item ) )
34+ }
35+
36+ if ( value && typeof value === 'object' ) {
37+ return Object . entries ( value as Record < string , unknown > ) . reduce < Record < string , unknown > > (
38+ ( acc , [ key , entry ] ) => {
39+ acc [ key ] = cloneInitialSubblockValue ( entry )
40+ return acc
41+ } ,
42+ { }
43+ )
44+ }
45+
46+ return value ?? null
47+ }
48+
49+ /**
50+ * Resolves the initial value for a sub-block based on its configuration.
51+ *
52+ * @param config - The sub-block configuration.
53+ * @returns The resolved initial value or null when no defaults are defined.
54+ */
55+ function resolveInitialSubblockValue ( config : SubBlockConfig ) : unknown {
56+ if ( typeof config . value === 'function' ) {
57+ try {
58+ const resolved = config . value ( { } )
59+ return cloneInitialSubblockValue ( resolved )
60+ } catch ( error ) {
61+ logger . warn ( 'Failed to resolve dynamic sub-block default value' , {
62+ subBlockId : config . id ,
63+ error : error instanceof Error ? error . message : String ( error ) ,
64+ } )
65+ }
66+ }
67+
68+ if ( config . defaultValue !== undefined ) {
69+ return cloneInitialSubblockValue ( config . defaultValue )
70+ }
71+
72+ if ( config . type === 'input-format' ) {
73+ return [
74+ {
75+ id : crypto . randomUUID ( ) ,
76+ name : '' ,
77+ type : 'string' ,
78+ value : '' ,
79+ collapsed : false ,
80+ } ,
81+ ]
82+ }
83+
84+ if ( config . type === 'table' ) {
85+ return [ ]
86+ }
87+
88+ return null
89+ }
90+
2491const initialState = {
2592 blocks : { } ,
2693 edges : [ ] ,
@@ -106,12 +173,38 @@ export const useWorkflowStore = create<WorkflowStore>()(
106173 }
107174
108175 const subBlocks : Record < string , SubBlockState > = { }
176+ const subBlockStore = useSubBlockStore . getState ( )
177+ const activeWorkflowId = useWorkflowRegistry . getState ( ) . activeWorkflowId
178+
109179 blockConfig . subBlocks . forEach ( ( subBlock ) => {
110180 const subBlockId = subBlock . id
181+ const initialValue = resolveInitialSubblockValue ( subBlock )
182+ const normalizedValue =
183+ initialValue !== undefined && initialValue !== null ? initialValue : null
184+
111185 subBlocks [ subBlockId ] = {
112186 id : subBlockId ,
113187 type : subBlock . type ,
114- value : null ,
188+ value : normalizedValue as SubBlockState [ 'value' ] ,
189+ }
190+
191+ if ( activeWorkflowId ) {
192+ try {
193+ const valueToStore =
194+ initialValue !== undefined ? cloneInitialSubblockValue ( initialValue ) : null
195+ subBlockStore . setValue ( id , subBlockId , valueToStore )
196+ } catch ( error ) {
197+ logger . warn ( 'Failed to seed sub-block store value during block creation' , {
198+ blockId : id ,
199+ subBlockId,
200+ error : error instanceof Error ? error . message : String ( error ) ,
201+ } )
202+ }
203+ } else {
204+ logger . warn ( 'Cannot seed sub-block store value: activeWorkflowId not available' , {
205+ blockId : id ,
206+ subBlockId,
207+ } )
115208 }
116209 } )
117210
0 commit comments