123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- type IterationInfo = { iterationId: string; iterationIndex: number }
- type NodePlain = { nodeType: 'plain'; nodeId: string; } & Partial<IterationInfo>
- type NodeComplex = { nodeType: string; nodeId: string; params: (NodePlain | (NodeComplex & Partial<IterationInfo>) | Node[] | number)[] } & Partial<IterationInfo>
- type Node = NodePlain | NodeComplex
- function parseDSL(dsl: string): NodeData[] {
- return convertToNodeData(parseTopLevelFlow(dsl).map(nodeStr => parseNode(nodeStr)))
- }
- function parseTopLevelFlow(dsl: string): string[] {
- const segments: string[] = []
- let buffer = ''
- let nested = 0
- for (let i = 0; i < dsl.length; i++) {
- const char = dsl[i]
- if (char === '(') nested++
- if (char === ')') nested--
- if (char === '-' && dsl[i + 1] === '>' && nested === 0) {
- segments.push(buffer.trim())
- buffer = ''
- i++
- }
- else {
- buffer += char
- }
- }
- if (buffer.trim())
- segments.push(buffer.trim())
- return segments
- }
- function parseNode(nodeStr: string, parentIterationId?: string): Node {
-
- if (nodeStr.startsWith('(') && nodeStr.endsWith(')')) {
- const innerContent = nodeStr.slice(1, -1).trim()
- let nested = 0
- let buffer = ''
- const parts: string[] = []
-
- for (let i = 0; i < innerContent.length; i++) {
- const char = innerContent[i]
- if (char === '(') nested++
- if (char === ')') nested--
- if (char === ',' && nested === 0) {
- parts.push(buffer.trim())
- buffer = ''
- }
- else {
- buffer += char
- }
- }
- parts.push(buffer.trim())
-
- const [nodeType, nodeId, ...paramsRaw] = parts
- const params = parseParams(paramsRaw, nodeType === 'iteration' ? nodeId.trim() : parentIterationId)
- const complexNode = {
- nodeType: nodeType.trim(),
- nodeId: nodeId.trim(),
- params,
- }
- if (parentIterationId) {
- (complexNode as any).iterationId = parentIterationId;
- (complexNode as any).iterationIndex = 0
- }
- return complexNode
- }
-
- const plainNode: NodePlain = { nodeType: 'plain', nodeId: nodeStr.trim() }
- if (parentIterationId) {
- plainNode.iterationId = parentIterationId
- plainNode.iterationIndex = 0
- }
- return plainNode
- }
- function parseParams(paramParts: string[], iterationId?: string): (Node | Node[] | number)[] {
- return paramParts.map((part) => {
- if (part.includes('->')) {
-
- return parseTopLevelFlow(part).map(node => parseNode(node, iterationId))
- }
- else if (part.startsWith('(')) {
-
- return parseNode(part, iterationId)
- }
- else if (!Number.isNaN(Number(part.trim()))) {
-
- return Number(part.trim())
- }
- else {
-
- return parseNode(part, iterationId)
- }
- })
- }
- type NodeData = {
- id: string;
- node_id: string;
- title: string;
- node_type?: string;
- execution_metadata: Record<string, any>;
- status: string;
- }
- function convertPlainNode(node: Node): NodeData[] {
- return [
- {
- id: node.nodeId,
- node_id: node.nodeId,
- title: node.nodeId,
- execution_metadata: {},
- status: 'succeeded',
- },
- ]
- }
- function convertRetryNode(node: Node): NodeData[] {
- const { nodeId, iterationId, iterationIndex, params } = node as NodeComplex
- const retryCount = params ? Number.parseInt(params[0] as unknown as string, 10) : 0
- const result: NodeData[] = [
- {
- id: nodeId,
- node_id: nodeId,
- title: nodeId,
- execution_metadata: {},
- status: 'succeeded',
- },
- ]
- for (let i = 0; i < retryCount; i++) {
- result.push({
- id: nodeId,
- node_id: nodeId,
- title: nodeId,
- execution_metadata: iterationId ? {
- iteration_id: iterationId,
- iteration_index: iterationIndex || 0,
- } : {},
- status: 'retry',
- })
- }
- return result
- }
- function convertIterationNode(node: Node): NodeData[] {
- const { nodeId, params } = node as NodeComplex
- const result: NodeData[] = [
- {
- id: nodeId,
- node_id: nodeId,
- title: nodeId,
- node_type: 'iteration',
- status: 'succeeded',
- execution_metadata: {},
- },
- ]
- params?.forEach((param: any) => {
- if (Array.isArray(param)) {
- param.forEach((childNode: Node) => {
- const childData = convertToNodeData([childNode])
- childData.forEach((data) => {
- data.execution_metadata = {
- ...data.execution_metadata,
- iteration_id: nodeId,
- iteration_index: 0,
- }
- })
- result.push(...childData)
- })
- }
- })
- return result
- }
- function convertParallelNode(node: Node, parentParallelId?: string, parentStartNodeId?: string): NodeData[] {
- const { nodeId, params } = node as NodeComplex
- const result: NodeData[] = [
- {
- id: nodeId,
- node_id: nodeId,
- title: nodeId,
- execution_metadata: {
- parallel_id: nodeId,
- },
- status: 'succeeded',
- },
- ]
- params?.forEach((param) => {
- if (Array.isArray(param)) {
- const startNodeId = param[0]?.nodeId
- param.forEach((childNode: Node) => {
- const childData = convertToNodeData([childNode])
- childData.forEach((data) => {
- data.execution_metadata = {
- ...data.execution_metadata,
- parallel_id: nodeId,
- parallel_start_node_id: startNodeId,
- ...(parentParallelId && {
- parent_parallel_id: parentParallelId,
- parent_parallel_start_node_id: parentStartNodeId,
- }),
- }
- })
- result.push(...childData)
- })
- }
- else if (param && typeof param === 'object') {
- const startNodeId = param.nodeId
- const childData = convertToNodeData([param])
- childData.forEach((data) => {
- data.execution_metadata = {
- ...data.execution_metadata,
- parallel_id: nodeId,
- parallel_start_node_id: startNodeId,
- ...(parentParallelId && {
- parent_parallel_id: parentParallelId,
- parent_parallel_start_node_id: parentStartNodeId,
- }),
- }
- })
- result.push(...childData)
- }
- })
- return result
- }
- function convertToNodeData(nodes: Node[], parentParallelId?: string, parentStartNodeId?: string): NodeData[] {
- const result: NodeData[] = []
- nodes.forEach((node) => {
- switch (node.nodeType) {
- case 'plain':
- result.push(...convertPlainNode(node))
- break
- case 'retry':
- result.push(...convertRetryNode(node))
- break
- case 'iteration':
- result.push(...convertIterationNode(node))
- break
- case 'parallel':
- result.push(...convertParallelNode(node, parentParallelId, parentStartNodeId))
- break
- default:
- throw new Error(`Unknown nodeType: ${node.nodeType}`)
- }
- })
- return result
- }
- export default parseDSL
|