Skip to content

Commit 35683dd

Browse files
committed
fix(resolver): add both new and old workflow blocks for backwards compat
1 parent 02229f0 commit 35683dd

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

apps/sim/executor/variables/resolvers/block.test.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,112 @@ describe('BlockResolver', () => {
817817
expect(resolver.resolve('<workflow1.childWorkflowName>', ctx)).toBe('vibrant-cliff')
818818
}
819819
)
820+
821+
it.concurrent(
822+
'real-world scenario: accessing entire response object via <workflow1.result.response> (workflow type)',
823+
() => {
824+
const workflow = createTestWorkflow([
825+
{ id: 'workflow-block', name: 'Workflow 1', type: 'workflow' },
826+
])
827+
const resolver = new BlockResolver(workflow)
828+
829+
// Child Response block output (new format - no wrapper)
830+
const ctx = createTestContext('current', {
831+
'workflow-block': {
832+
success: true,
833+
childWorkflowName: 'response-workflow-child-editor',
834+
result: {
835+
data: {
836+
s: 'example string',
837+
nums: [1, 2, 3],
838+
n: 42,
839+
obj: { key1: 'value1', key2: 'value2' },
840+
},
841+
status: 206,
842+
headers: { 'Content-Type': 'application/json', apple: 'banana' },
843+
},
844+
},
845+
})
846+
847+
// OLD reference: <workflow1.result.response> should return the entire result object
848+
// This is used when the user wants to get data, status, headers all at once
849+
const response = resolver.resolve('<workflow1.result.response>', ctx)
850+
expect(response).toEqual({
851+
data: {
852+
s: 'example string',
853+
nums: [1, 2, 3],
854+
n: 42,
855+
obj: { key1: 'value1', key2: 'value2' },
856+
},
857+
status: 206,
858+
headers: { 'Content-Type': 'application/json', apple: 'banana' },
859+
})
860+
861+
// Verify individual fields can be accessed from the returned object
862+
expect(response.status).toBe(206)
863+
expect(response.headers.apple).toBe('banana')
864+
expect(response.data.s).toBe('example string')
865+
expect(response.data.n).toBe(42)
866+
expect(response.data.nums).toEqual([1, 2, 3])
867+
expect(response.data.obj.key1).toBe('value1')
868+
}
869+
)
870+
871+
it.concurrent(
872+
'real-world scenario: workflow_input type block with <workflow1.result.response>',
873+
() => {
874+
/**
875+
* CRITICAL: Workflow blocks can have type 'workflow' OR 'workflow_input'.
876+
* Both must support backwards compatibility.
877+
*
878+
* This test uses 'workflow_input' which is the actual type in production.
879+
*/
880+
const workflow = createTestWorkflow([
881+
{ id: 'workflow-block', name: 'Workflow 1', type: 'workflow_input' },
882+
])
883+
const resolver = new BlockResolver(workflow)
884+
885+
const ctx = createTestContext('current', {
886+
'workflow-block': {
887+
success: true,
888+
childWorkflowName: 'response-workflow-child-editor',
889+
result: {
890+
data: {
891+
s: 'example string',
892+
nums: [1, 2, 3],
893+
n: 42,
894+
obj: { key1: 'value1', key2: 'value2' },
895+
},
896+
status: 206,
897+
headers: { 'Content-Type': 'application/json', apple: 'banana' },
898+
},
899+
},
900+
})
901+
902+
// OLD reference: <workflow1.result.response> should return the entire result object
903+
const response = resolver.resolve('<workflow1.result.response>', ctx)
904+
expect(response).toEqual({
905+
data: {
906+
s: 'example string',
907+
nums: [1, 2, 3],
908+
n: 42,
909+
obj: { key1: 'value1', key2: 'value2' },
910+
},
911+
status: 206,
912+
headers: { 'Content-Type': 'application/json', apple: 'banana' },
913+
})
914+
915+
// Also test drilling into specific fields
916+
expect(resolver.resolve('<workflow1.result.response.data>', ctx)).toEqual({
917+
s: 'example string',
918+
nums: [1, 2, 3],
919+
n: 42,
920+
obj: { key1: 'value1', key2: 'value2' },
921+
})
922+
expect(resolver.resolve('<workflow1.result.response.status>', ctx)).toBe(206)
923+
expect(resolver.resolve('<workflow1.result.response.data.s>', ctx)).toBe('example string')
924+
}
925+
)
820926
})
821927

822928
describe('edge cases', () => {

apps/sim/executor/variables/resolvers/block.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ export class BlockResolver implements Resolver {
9090
// Workflow block backwards compatibility:
9191
// Old: <workflowBlock.result.response.data> -> New: <workflowBlock.result.data>
9292
// Only apply fallback if:
93-
// 1. Block type is 'workflow'
93+
// 1. Block type is 'workflow' or 'workflow_input'
9494
// 2. Path starts with 'result.response.'
9595
// 3. output.result.response doesn't exist (confirming child used new format)
96+
const isWorkflowBlock =
97+
block?.metadata?.id === 'workflow' || block?.metadata?.id === 'workflow_input'
9698
if (
97-
block?.metadata?.id === 'workflow' &&
99+
isWorkflowBlock &&
98100
pathParts[0] === 'result' &&
99101
pathParts[1] === 'response' &&
100102
output?.result?.response === undefined

0 commit comments

Comments
 (0)