Feature/agentflow v2 (#4298)

* agent flow v2

* chat message background

* conditon agent flow

* add sticky note

* update human input dynamic prompt

* add HTTP node

* add default tool icon

* fix export duplicate agentflow v2

* add agentflow v2 marketplaces

* refractor memoization, add iteration nodes

* add agentflow v2 templates

* add agentflow generator

* add migration scripts for mysql, mariadb, posrgres and fix date filters for executions

* update agentflow chat history config

* fix get all flows error after deletion and rename

* add previous nodes from parent node

* update generator prompt

* update run time state when using iteration nodes

* prevent looping connection, prevent duplication of start node, add executeflow node, add nodes agentflow, chat history variable

* update embed

* convert form input to string

* bump openai version

* add react rewards

* add prompt generator to prediction queue

* add array schema to overrideconfig

* UI touchup

* update embedded chat version

* fix node info dialog

* update start node and loop default iteration

* update UI fixes for agentflow v2

* fix async drop down

* add export import to agentflowsv2, executions, fix UI bugs

* add default empty object to flowlisttable

* add ability to share trace link publicly, allow MCP tool use for Agent and Assistant

* add runtime message length to variable, display conditions on UI

* fix array validation

* add ability to add knowledge from vector store and embeddings for agent

* add agent tool require human input

* add ephemeral memory to start node

* update agent flow node to show vs and embeddings icons

* feat: add import chat data functionality for AgentFlowV2

* feat: set chatMessage.executionId to null if not found in import JSON file or database

* fix: MariaDB execution migration script to utf8mb4_unicode_520_ci

---------

Co-authored-by: Ong Chung Yau <33013947+chungyau97@users.noreply.github.com>
Co-authored-by: chungyau97 <chungyau97@gmail.com>
This commit is contained in:
Henry Heng
2025-05-10 10:21:26 +08:00
committed by GitHub
parent 82e6f43b5c
commit 7924fbce0d
216 changed files with 33304 additions and 5269 deletions
@@ -0,0 +1,18 @@
import { Request, Response, NextFunction } from 'express'
import agentflowv2Service from '../../services/agentflowv2-generator'
const generateAgentflowv2 = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body.question || !req.body.selectedChatModel) {
throw new Error('Question and selectedChatModel are required')
}
const apiResponse = await agentflowv2Service.generateAgentflowv2(req.body.question, req.body.selectedChatModel)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
generateAgentflowv2
}
@@ -0,0 +1,114 @@
import { Request, Response, NextFunction } from 'express'
import executionsService from '../../services/executions'
import { ExecutionState } from '../../Interface'
const getExecutionById = async (req: Request, res: Response, next: NextFunction) => {
try {
const executionId = req.params.id
const execution = await executionsService.getExecutionById(executionId)
return res.json(execution)
} catch (error) {
next(error)
}
}
const getPublicExecutionById = async (req: Request, res: Response, next: NextFunction) => {
try {
const executionId = req.params.id
const execution = await executionsService.getPublicExecutionById(executionId)
return res.json(execution)
} catch (error) {
next(error)
}
}
const updateExecution = async (req: Request, res: Response, next: NextFunction) => {
try {
const executionId = req.params.id
const execution = await executionsService.updateExecution(executionId, req.body)
return res.json(execution)
} catch (error) {
next(error)
}
}
const getAllExecutions = async (req: Request, res: Response, next: NextFunction) => {
try {
// Extract all possible filters from query params
const filters: any = {}
// ID filter
if (req.query.id) filters.id = req.query.id as string
// Flow and session filters
if (req.query.agentflowId) filters.agentflowId = req.query.agentflowId as string
if (req.query.sessionId) filters.sessionId = req.query.sessionId as string
// State filter
if (req.query.state) {
const stateValue = req.query.state as string
if (['INPROGRESS', 'FINISHED', 'ERROR', 'TERMINATED', 'TIMEOUT', 'STOPPED'].includes(stateValue)) {
filters.state = stateValue as ExecutionState
}
}
// Date filters
if (req.query.startDate) {
filters.startDate = new Date(req.query.startDate as string)
}
if (req.query.endDate) {
filters.endDate = new Date(req.query.endDate as string)
}
// Pagination
if (req.query.page) {
filters.page = parseInt(req.query.page as string, 10)
}
if (req.query.limit) {
filters.limit = parseInt(req.query.limit as string, 10)
}
const apiResponse = await executionsService.getAllExecutions(filters)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
/**
* Delete multiple executions by their IDs
* If a single ID is provided in the URL params, it will delete that execution
* If an array of IDs is provided in the request body, it will delete all those executions
*/
const deleteExecutions = async (req: Request, res: Response, next: NextFunction) => {
try {
let executionIds: string[] = []
// Check if we're deleting a single execution from URL param
if (req.params.id) {
executionIds = [req.params.id]
}
// Check if we're deleting multiple executions from request body
else if (req.body.executionIds && Array.isArray(req.body.executionIds)) {
executionIds = req.body.executionIds
} else {
return res.status(400).json({ success: false, message: 'No execution IDs provided' })
}
const result = await executionsService.deleteExecutions(executionIds)
return res.json(result)
} catch (error) {
next(error)
}
}
export default {
getAllExecutions,
deleteExecutions,
getExecutionById,
getPublicExecutionById,
updateExecution
}
@@ -0,0 +1,24 @@
import { Request, Response, NextFunction } from 'express'
import validationService from '../../services/validation'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
const checkFlowValidation = async (req: Request, res: Response, next: NextFunction) => {
try {
const flowId = req.params?.id as string | undefined
if (!flowId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: validationController.checkFlowValidation - id not provided!`
)
}
const apiResponse = await validationService.checkFlowValidation(flowId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
checkFlowValidation
}