Skip to content

Commit 61deb02

Browse files
authored
fix(subflows): fixed subflows not executing (#711)
1 parent 92fe353 commit 61deb02

File tree

5 files changed

+702
-18
lines changed

5 files changed

+702
-18
lines changed

apps/sim/app/chat/[subdomain]/components/voice-interface/voice-interface.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ export function VoiceInterface({
514514
const getButtonContent = () => {
515515
if (state === 'agent_speaking') {
516516
return (
517-
<svg className='w-6 h-6' viewBox='0 0 24 24' fill='currentColor'>
517+
<svg className='h-6 w-6' viewBox='0 0 24 24' fill='currentColor'>
518518
<rect x='6' y='6' width='12' height='12' rx='2' />
519519
</svg>
520520
)
@@ -534,23 +534,23 @@ export function VoiceInterface({
534534
isPlayingAudio={state === 'agent_speaking'}
535535
isStreaming={isStreaming}
536536
isMuted={isMuted}
537-
className='w-80 h-80 md:w-96 md:h-96'
537+
className='h-80 w-80 md:h-96 md:w-96'
538538
/>
539539
</div>
540540

541541
{/* Live transcript - subtitle style */}
542-
<div className='mb-16 h-24 flex items-center justify-center'>
542+
<div className='mb-16 flex h-24 items-center justify-center'>
543543
{currentTranscript && (
544544
<div className='max-w-2xl px-8'>
545-
<p className='text-xl text-gray-700 text-center leading-relaxed overflow-hidden'>
545+
<p className='overflow-hidden text-center text-gray-700 text-xl leading-relaxed'>
546546
{currentTranscript}
547547
</p>
548548
</div>
549549
)}
550550
</div>
551551

552552
{/* Status */}
553-
<p className='text-lg text-gray-600 mb-8 text-center'>
553+
<p className='mb-8 text-center text-gray-600 text-lg'>
554554
{getStatusText()}
555555
{isMuted && <span className='ml-2 text-gray-400 text-sm'>(Muted)</span>}
556556
</p>

apps/sim/executor/routing/routing.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ describe('Routing', () => {
8989
})
9090

9191
describe('shouldSkipConnection', () => {
92-
it.concurrent('should skip flow control blocks', () => {
93-
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(true)
94-
expect(Routing.shouldSkipConnection('source', BlockType.LOOP)).toBe(true)
92+
it.concurrent('should allow regular connections to flow control blocks', () => {
93+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
94+
expect(Routing.shouldSkipConnection('source', BlockType.LOOP)).toBe(false)
9595
})
9696

9797
it.concurrent('should skip flow control specific connections', () => {
@@ -107,9 +107,9 @@ describe('Routing', () => {
107107
expect(Routing.shouldSkipConnection(undefined, BlockType.API)).toBe(false)
108108
})
109109

110-
it.concurrent('should not skip routing connections', () => {
111-
expect(Routing.shouldSkipConnection('condition-test-if', BlockType.FUNCTION)).toBe(false)
112-
expect(Routing.shouldSkipConnection('condition-test-else', BlockType.AGENT)).toBe(false)
110+
it.concurrent('should skip condition-specific connections during selective activation', () => {
111+
expect(Routing.shouldSkipConnection('condition-test-if', BlockType.FUNCTION)).toBe(true)
112+
expect(Routing.shouldSkipConnection('condition-test-else', BlockType.AGENT)).toBe(true)
113113
})
114114

115115
it.concurrent('should handle empty/undefined types', () => {

apps/sim/executor/routing/routing.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,27 @@ export class Routing {
7979
* Checks if a connection should be skipped during selective activation
8080
*/
8181
static shouldSkipConnection(sourceHandle: string | undefined, targetBlockType: string): boolean {
82-
// Skip flow control blocks
83-
if (Routing.shouldSkipInSelectiveActivation(targetBlockType)) {
84-
return true
85-
}
86-
87-
// Skip flow control specific connections
82+
// Skip flow control specific connections (internal flow control handles)
8883
const flowControlHandles = [
8984
'parallel-start-source',
9085
'parallel-end-source',
9186
'loop-start-source',
9287
'loop-end-source',
9388
]
9489

95-
return flowControlHandles.includes(sourceHandle || '')
90+
if (flowControlHandles.includes(sourceHandle || '')) {
91+
return true
92+
}
93+
94+
// Skip condition-specific connections during selective activation
95+
// These should only be activated when the condition makes a specific decision
96+
if (sourceHandle?.startsWith('condition-')) {
97+
return true
98+
}
99+
100+
// For regular connections (no special source handle), allow activation of flow control blocks
101+
// This enables regular blocks (like agents) to activate parallel/loop blocks
102+
// The flow control blocks themselves will handle active path checking
103+
return false
96104
}
97105
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { BlockType } from '@/executor/consts'
3+
import { Routing } from '@/executor/routing/routing'
4+
5+
describe('Parallel Activation Integration - shouldSkipConnection behavior', () => {
6+
describe('Regular blocks can activate parallel/loop blocks', () => {
7+
it('should allow Agent → Parallel connections', () => {
8+
// This was the original bug - agent couldn't activate parallel
9+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
10+
expect(Routing.shouldSkipConnection('source', BlockType.PARALLEL)).toBe(false)
11+
})
12+
13+
it('should allow Function → Parallel connections', () => {
14+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
15+
expect(Routing.shouldSkipConnection('source', BlockType.PARALLEL)).toBe(false)
16+
})
17+
18+
it('should allow API → Loop connections', () => {
19+
expect(Routing.shouldSkipConnection(undefined, BlockType.LOOP)).toBe(false)
20+
expect(Routing.shouldSkipConnection('source', BlockType.LOOP)).toBe(false)
21+
})
22+
23+
it('should allow all regular blocks to activate parallel/loop', () => {
24+
const regularBlocks = [
25+
BlockType.FUNCTION,
26+
BlockType.AGENT,
27+
BlockType.API,
28+
BlockType.EVALUATOR,
29+
BlockType.RESPONSE,
30+
BlockType.WORKFLOW,
31+
]
32+
33+
regularBlocks.forEach((sourceBlockType) => {
34+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
35+
expect(Routing.shouldSkipConnection(undefined, BlockType.LOOP)).toBe(false)
36+
})
37+
})
38+
})
39+
40+
describe('✅ Still works: Router and Condition blocks can activate parallel/loop', () => {
41+
it('should allow Router → Parallel connections', () => {
42+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
43+
})
44+
45+
it('should allow Condition → Parallel connections', () => {
46+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
47+
})
48+
})
49+
50+
describe('✅ Still blocked: Internal flow control connections', () => {
51+
it('should block parallel-start-source connections during selective activation', () => {
52+
expect(Routing.shouldSkipConnection('parallel-start-source', BlockType.FUNCTION)).toBe(true)
53+
expect(Routing.shouldSkipConnection('parallel-start-source', BlockType.AGENT)).toBe(true)
54+
})
55+
56+
it('should block parallel-end-source connections during selective activation', () => {
57+
expect(Routing.shouldSkipConnection('parallel-end-source', BlockType.FUNCTION)).toBe(true)
58+
expect(Routing.shouldSkipConnection('parallel-end-source', BlockType.AGENT)).toBe(true)
59+
})
60+
61+
it('should block loop-start-source connections during selective activation', () => {
62+
expect(Routing.shouldSkipConnection('loop-start-source', BlockType.FUNCTION)).toBe(true)
63+
expect(Routing.shouldSkipConnection('loop-start-source', BlockType.AGENT)).toBe(true)
64+
})
65+
66+
it('should block loop-end-source connections during selective activation', () => {
67+
expect(Routing.shouldSkipConnection('loop-end-source', BlockType.FUNCTION)).toBe(true)
68+
expect(Routing.shouldSkipConnection('loop-end-source', BlockType.AGENT)).toBe(true)
69+
})
70+
})
71+
72+
describe('✅ Still blocked: Condition-specific connections during selective activation', () => {
73+
it('should block condition-specific connections during selective activation', () => {
74+
expect(Routing.shouldSkipConnection('condition-test-if', BlockType.FUNCTION)).toBe(true)
75+
expect(Routing.shouldSkipConnection('condition-test-else', BlockType.AGENT)).toBe(true)
76+
expect(Routing.shouldSkipConnection('condition-some-id', BlockType.PARALLEL)).toBe(true)
77+
})
78+
})
79+
80+
describe('✅ Still works: Regular connections', () => {
81+
it('should allow regular connections between regular blocks', () => {
82+
expect(Routing.shouldSkipConnection(undefined, BlockType.FUNCTION)).toBe(false)
83+
expect(Routing.shouldSkipConnection('source', BlockType.AGENT)).toBe(false)
84+
expect(Routing.shouldSkipConnection('output', BlockType.API)).toBe(false)
85+
})
86+
87+
it('should allow regular connections with any source handle (except blocked ones)', () => {
88+
expect(Routing.shouldSkipConnection('result', BlockType.FUNCTION)).toBe(false)
89+
expect(Routing.shouldSkipConnection('output', BlockType.AGENT)).toBe(false)
90+
expect(Routing.shouldSkipConnection('data', BlockType.PARALLEL)).toBe(false)
91+
})
92+
})
93+
})
94+
95+
describe('Real-world workflow scenarios', () => {
96+
describe('✅ Working: User workflows', () => {
97+
it('should support: Start → Agent → Parallel → Agent pattern', () => {
98+
// This is the user's exact workflow pattern that was broken
99+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
100+
})
101+
102+
it('should support: Start → Function → Loop → Function pattern', () => {
103+
expect(Routing.shouldSkipConnection(undefined, BlockType.LOOP)).toBe(false)
104+
})
105+
106+
it('should support: Start → API → Parallel → Multiple Agents pattern', () => {
107+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
108+
})
109+
110+
it('should support: Start → Evaluator → Parallel → Response pattern', () => {
111+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
112+
})
113+
})
114+
115+
describe('✅ Working: Complex routing patterns', () => {
116+
it('should support: Start → Router → Parallel → Function (existing working pattern)', () => {
117+
// This already worked before the fix
118+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
119+
})
120+
121+
it('should support: Start → Condition → Parallel → Agent (existing working pattern)', () => {
122+
// This already worked before the fix
123+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
124+
})
125+
126+
it('should support: Start → Router → Function → Parallel → Agent (new working pattern)', () => {
127+
// Router selects function, function activates parallel
128+
expect(Routing.shouldSkipConnection(undefined, BlockType.PARALLEL)).toBe(false)
129+
})
130+
})
131+
})

0 commit comments

Comments
 (0)