@@ -21,7 +21,7 @@ import {
2121 updateCanonicalModesForInputs ,
2222} from './builders'
2323import { VALID_LOOP_TYPES , VALID_PARALLEL_TYPES } from './container-types'
24- import type { EditWorkflowOperation , OperationContext } from './types'
24+ import type { EditWorkflowOperation , OperationContext , SkippedItem } from './types'
2525import { logSkippedItem } from './types'
2626import {
2727 findBlockWithDuplicateNormalizedName ,
@@ -31,6 +31,36 @@ import {
3131
3232const logger = createLogger ( 'EditWorkflowServerTool' )
3333
34+ /**
35+ * Refuses a new block of a sunset (`legacy` / `deprecated`) type and names its
36+ * successor. Placed instances keep executing and stay editable.
37+ *
38+ * @returns whether the placement was refused
39+ */
40+ function refuseSunsetPlacement (
41+ skippedItems : SkippedItem [ ] ,
42+ placement : {
43+ blockType : string | undefined
44+ operationType : string
45+ blockId : string
46+ outcome : string
47+ details ?: Record < string , unknown >
48+ }
49+ ) : boolean {
50+ const { blockType, operationType, blockId, outcome, details } = placement
51+ const sunset = blockType ? getBlock ( blockType ) ?. sunset : undefined
52+ if ( ! sunset ) return false
53+ const successor = sunset . replacedBy ? ` - use "${ sunset . replacedBy } " instead` : ''
54+ logSkippedItem ( skippedItems , {
55+ type : 'block_not_allowed' ,
56+ operationType,
57+ blockId,
58+ reason : `Block type "${ blockType } " is ${ sunset . status } ${ successor } - ${ outcome } ` ,
59+ details : { requestedType : blockType , replacedBy : sunset . replacedBy , ...details } ,
60+ } )
61+ return true
62+ }
63+
3464/**
3565 * Applies loop/parallel container config from `inputs` onto a block state (data.loopType, etc.).
3666 */
@@ -104,6 +134,18 @@ function processNestedNodesForParent(
104134 return
105135 }
106136
137+ if (
138+ refuseSunsetPlacement ( skippedItems , {
139+ blockType : childBlock . type ,
140+ operationType : 'add_nested_node' ,
141+ blockId : childId ,
142+ outcome : 'child block skipped' ,
143+ details : { parentBlockId } ,
144+ } )
145+ ) {
146+ return
147+ }
148+
107149 const childBlockState = createBlockFromParams (
108150 childId ,
109151 childBlock ,
@@ -283,6 +325,18 @@ function mergeNestedNodesForParent(
283325 return
284326 }
285327
328+ if (
329+ refuseSunsetPlacement ( skippedItems , {
330+ blockType : childBlock . type ,
331+ operationType : 'add_nested_node' ,
332+ blockId : childId ,
333+ outcome : 'child block skipped' ,
334+ details : { parentBlockId } ,
335+ } )
336+ ) {
337+ return
338+ }
339+
286340 const childBlockState = createBlockFromParams (
287341 childId ,
288342 childBlock ,
@@ -607,7 +661,15 @@ export function handleEditOperation(op: EditWorkflowOperation, ctx: OperationCon
607661 reason : `Block type "${ params . type } " is unavailable in this deployment or blocked by access control - type change skipped` ,
608662 details : { requestedType : params . type } ,
609663 } )
610- } else {
664+ } else if (
665+ params . type === block . type ||
666+ ! refuseSunsetPlacement ( skippedItems , {
667+ blockType : params . type ,
668+ operationType : 'edit' ,
669+ blockId : block_id ,
670+ outcome : 'type change skipped' ,
671+ } )
672+ ) {
611673 block . type = params . type
612674 }
613675 }
@@ -791,6 +853,17 @@ export function handleAddOperation(op: EditWorkflowOperation, ctx: OperationCont
791853 return
792854 }
793855
856+ if (
857+ refuseSunsetPlacement ( skippedItems , {
858+ blockType : params . type ,
859+ operationType : 'add' ,
860+ blockId : block_id ,
861+ outcome : 'block not added' ,
862+ } )
863+ ) {
864+ return
865+ }
866+
794867 const triggerIssue = TriggerUtils . getTriggerAdditionIssue ( modifiedState . blocks , params . type )
795868 if ( triggerIssue ) {
796869 logSkippedItem ( skippedItems , {
@@ -1022,6 +1095,18 @@ export function handleInsertIntoSubflowOperation(
10221095 return
10231096 }
10241097
1098+ if (
1099+ refuseSunsetPlacement ( skippedItems , {
1100+ blockType : params . type ,
1101+ operationType : 'insert_into_subflow' ,
1102+ blockId : block_id ,
1103+ outcome : 'block not inserted into subflow' ,
1104+ details : { subflowId } ,
1105+ } )
1106+ ) {
1107+ return
1108+ }
1109+
10251110 const newBlock = createBlockFromParams (
10261111 block_id ,
10271112 params ,
0 commit comments