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,60 @@ 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+ if ( underscoreIndex > 0 ) {
200+ const maybeUuid = outputId . substring ( 0 , underscoreIndex )
201+ if ( uuidValidate ( maybeUuid ) ) {
202+ return outputId
203+ }
204+ }
205+
206+ if ( dotIndex > 0 ) {
207+ const maybeUuid = outputId . substring ( 0 , dotIndex )
208+ if ( uuidValidate ( maybeUuid ) ) {
209+ return `${ outputId . substring ( 0 , dotIndex ) } _${ outputId . substring ( dotIndex + 1 ) } `
210+ }
211+ }
212+
213+ if ( uuidValidate ( outputId ) ) {
214+ return outputId
215+ }
216+
217+ if ( dotIndex === - 1 ) {
218+ logger . warn ( `Invalid output ID format (missing dot): ${ outputId } ` )
219+ return outputId
220+ }
221+
222+ const blockName = outputId . substring ( 0 , dotIndex )
223+ const path = outputId . substring ( dotIndex + 1 )
224+
225+ const normalizedBlockName = blockName . toLowerCase ( ) . replace ( / \s + / g, '' )
226+ const block = Object . values ( blocks ) . find ( ( b : any ) => {
227+ const normalized = ( b . name || '' ) . toLowerCase ( ) . replace ( / \s + / g, '' )
228+ return normalized === normalizedBlockName
229+ } )
230+
231+ if ( ! block ) {
232+ logger . warn ( `Block not found for name: ${ blockName } (from output ID: ${ outputId } )` )
233+ return outputId
234+ }
235+
236+ const resolvedId = `${ block . id } _${ path } `
237+ logger . debug ( `Resolved output ID: ${ outputId } -> ${ resolvedId } ` )
238+ return resolvedId
239+ } )
240+ }
241+
187242/**
188243 * POST /api/workflows/[id]/execute
189244 *
@@ -425,7 +480,32 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
425480 }
426481 }
427482
428- logger . info ( `[${ requestId } ] Using SSE execution (streaming response)` )
483+ if ( shouldUseDraftState ) {
484+ logger . info ( `[${ requestId } ] Using SSE console log streaming (manual execution)` )
485+ } else {
486+ logger . info ( `[${ requestId } ] Using streaming API response` )
487+ const deployedData = await loadDeployedWorkflowState ( workflowId )
488+ const resolvedSelectedOutputs = resolveOutputIds ( selectedOutputs , deployedData ?. blocks || { } )
489+ const stream = await createStreamingResponse ( {
490+ requestId,
491+ workflow,
492+ input : processedInput ,
493+ executingUserId : userId ,
494+ streamConfig : {
495+ selectedOutputs : resolvedSelectedOutputs ,
496+ isSecureMode : false ,
497+ workflowTriggerType : triggerType === 'chat' ? 'chat' : 'api' ,
498+ } ,
499+ createFilteredResult,
500+ executionId,
501+ } )
502+
503+ return new NextResponse ( stream , {
504+ status : 200 ,
505+ headers : SSE_HEADERS ,
506+ } )
507+ }
508+
429509 const encoder = new TextEncoder ( )
430510 let executorInstance : any = null
431511 let isStreamClosed = false
0 commit comments