(
newChatFlow: ChatFlow,
orgId: string,
workspaceId: string,
subscriptionId: string,
usageCacheManager: UsageCacheManager
)
| 345 | } |
| 346 | |
| 347 | const saveChatflow = async ( |
| 348 | newChatFlow: ChatFlow, |
| 349 | orgId: string, |
| 350 | workspaceId: string, |
| 351 | subscriptionId: string, |
| 352 | usageCacheManager: UsageCacheManager |
| 353 | ): Promise<any> => { |
| 354 | validateChatflowType(newChatFlow.type) |
| 355 | const appServer = getRunningExpressApp() |
| 356 | |
| 357 | let dbResponse: ChatFlow |
| 358 | if (containsBase64File(newChatFlow)) { |
| 359 | // we need a 2-step process, as we need to save the chatflow first and then update the file paths |
| 360 | // this is because we need the chatflow id to create the file paths |
| 361 | |
| 362 | // step 1 - save with empty flowData |
| 363 | const incomingFlowData = newChatFlow.flowData |
| 364 | newChatFlow.flowData = JSON.stringify({}) |
| 365 | const chatflow = appServer.AppDataSource.getRepository(ChatFlow).create(newChatFlow) |
| 366 | const step1Results = await appServer.AppDataSource.getRepository(ChatFlow).save(chatflow) |
| 367 | |
| 368 | // step 2 - convert base64 to file paths and update the chatflow |
| 369 | step1Results.flowData = await updateFlowDataWithFilePaths( |
| 370 | step1Results.id, |
| 371 | incomingFlowData, |
| 372 | orgId, |
| 373 | workspaceId, |
| 374 | subscriptionId, |
| 375 | usageCacheManager |
| 376 | ) |
| 377 | await _checkAndUpdateDocumentStoreUsage(step1Results, newChatFlow.workspaceId) |
| 378 | dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).save(step1Results) |
| 379 | } else { |
| 380 | const chatflow = appServer.AppDataSource.getRepository(ChatFlow).create(newChatFlow) |
| 381 | dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).save(chatflow) |
| 382 | } |
| 383 | |
| 384 | // Check if the flow is agentflow and if it has a schedule node, if yes then notify the beat to sync the schedule |
| 385 | if (dbResponse.type === EnumChatflowType.AGENTFLOW) { |
| 386 | /*** Get chatflows and prepare data ***/ |
| 387 | const flowData = dbResponse.flowData |
| 388 | const parsedFlowData: IReactFlowObject = JSON.parse(flowData) |
| 389 | const nodes = (parsedFlowData.nodes || []).filter((node) => node.data.name !== 'stickyNoteAgentflow') |
| 390 | const startNode = nodes.find((node) => node.data.name === 'startAgentflow') |
| 391 | const startInputType = startNode?.data?.inputs?.startInputType as StartInputType | undefined |
| 392 | if (startInputType === 'scheduleInput') { |
| 393 | const scheduleInputMode = startNode?.data?.inputs?.scheduleInputMode as ScheduleInputMode | undefined |
| 394 | if (!scheduleInputMode) { |
| 395 | throw new InternalFlowiseError( |
| 396 | StatusCodes.BAD_REQUEST, |
| 397 | 'Schedule Input Mode is required on the Start node when Start Input Type is Schedule.' |
| 398 | ) |
| 399 | } |
| 400 | const resolvedCron = scheduleService.resolveScheduleCron(startNode?.data?.inputs || {}) |
| 401 | const scheduleTimezone = startNode?.data?.inputs?.scheduleTimezone || 'UTC' |
| 402 | const scheduleDefaultInput = startNode?.data?.inputs?.scheduleDefaultInput || '' |
| 403 | const scheduleFormDefaultsRaw = startNode?.data?.inputs?.scheduleFormDefaults |
| 404 | const scheduleFormDefaults = |
nothing calls this directly
no test coverage detected