11import { type NextRequest , NextResponse } from 'next/server'
2- import { v4 as uuidv4 } from 'uuid'
2+ import { validate as uuidValidate , v4 as uuidv4 } from 'uuid'
33import { checkHybridAuth } from '@/lib/auth/hybrid'
44import { checkServerSideUsageLimits } from '@/lib/billing'
55import { processInputFileFields } from '@/lib/execution/files'
@@ -13,6 +13,7 @@ import {
1313import { executeWorkflowCore } from '@/lib/workflows/executor/execution-core'
1414import { type ExecutionEvent , encodeSSEEvent } from '@/lib/workflows/executor/execution-events'
1515import { PauseResumeManager } from '@/lib/workflows/executor/pause-resume-manager'
16+ import { createStreamingResponse } from '@/lib/workflows/streaming'
1617import { validateWorkflowAccess } from '@/app/api/workflows/middleware'
1718import { type ExecutionMetadata , ExecutionSnapshot } from '@/executor/execution/snapshot'
1819import type { StreamingExecution } from '@/executor/types'
@@ -184,6 +185,63 @@ export function createFilteredResult(result: any) {
184185 }
185186}
186187
188+ function resolveOutputIds (
189+ selectedOutputs : string [ ] | undefined ,
190+ blocks : Record < string , any >
191+ ) : string [ ] | undefined {
192+ if ( ! selectedOutputs || selectedOutputs . length === 0 ) {
193+ return selectedOutputs
194+ }
195+
196+ return selectedOutputs . map ( ( outputId ) => {
197+ const underscoreIndex = outputId . indexOf ( '_' )
198+ const dotIndex = outputId . indexOf ( '.' )
199+
200+ // Check if starts with UUID followed by separator
201+ if ( underscoreIndex > 0 ) {
202+ const maybeUuid = outputId . substring ( 0 , underscoreIndex )
203+ if ( uuidValidate ( maybeUuid ) ) {
204+ return outputId
205+ }
206+ }
207+
208+ if ( dotIndex > 0 ) {
209+ const maybeUuid = outputId . substring ( 0 , dotIndex )
210+ if ( uuidValidate ( maybeUuid ) ) {
211+ // Convert to underscore format for consistency
212+ return outputId . substring ( 0 , dotIndex ) + '_' + outputId . substring ( dotIndex + 1 )
213+ }
214+ }
215+
216+ if ( uuidValidate ( outputId ) ) {
217+ return outputId
218+ }
219+
220+ if ( dotIndex === - 1 ) {
221+ logger . warn ( `Invalid output ID format (missing dot): ${ outputId } ` )
222+ return outputId
223+ }
224+
225+ const blockName = outputId . substring ( 0 , dotIndex )
226+ const path = outputId . substring ( dotIndex + 1 )
227+
228+ const normalizedBlockName = blockName . toLowerCase ( ) . replace ( / \s + / g, '' )
229+ const block = Object . values ( blocks ) . find ( ( b : any ) => {
230+ const normalized = ( b . name || '' ) . toLowerCase ( ) . replace ( / \s + / g, '' )
231+ return normalized === normalizedBlockName
232+ } )
233+
234+ if ( ! block ) {
235+ logger . warn ( `Block not found for name: ${ blockName } (from output ID: ${ outputId } )` )
236+ return outputId
237+ }
238+
239+ const resolvedId = `${ block . id } _${ path } `
240+ logger . debug ( `Resolved output ID: ${ outputId } -> ${ resolvedId } ` )
241+ return resolvedId
242+ } )
243+ }
244+
187245/**
188246 * POST /api/workflows/[id]/execute
189247 *
@@ -425,7 +483,32 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
425483 }
426484 }
427485
428- logger . info ( `[${ requestId } ] Using SSE execution (streaming response)` )
486+ if ( shouldUseDraftState ) {
487+ logger . info ( `[${ requestId } ] Using SSE console log streaming (manual execution)` )
488+ } else {
489+ logger . info ( `[${ requestId } ] Using streaming API response` )
490+ const deployedData = await loadDeployedWorkflowState ( workflowId )
491+ const resolvedSelectedOutputs = resolveOutputIds ( selectedOutputs , deployedData ?. blocks || { } )
492+ const stream = await createStreamingResponse ( {
493+ requestId,
494+ workflow,
495+ input : processedInput ,
496+ executingUserId : userId ,
497+ streamConfig : {
498+ selectedOutputs : resolvedSelectedOutputs ,
499+ isSecureMode : false ,
500+ workflowTriggerType : triggerType === 'chat' ? 'chat' : 'api' ,
501+ } ,
502+ createFilteredResult,
503+ executionId,
504+ } )
505+
506+ return new NextResponse ( stream , {
507+ status : 200 ,
508+ headers : SSE_HEADERS ,
509+ } )
510+ }
511+
429512 const encoder = new TextEncoder ( )
430513 let executorInstance : any = null
431514 let isStreamClosed = false
0 commit comments