diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index b9c337eaa9..eddcd9cb71 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -46,7 +46,7 @@ const workflowActions = { } }, addEdge: { - description: "Create a connection between two blocks", + description: "Create a connection (edge) between two blocks", parameters: { type: "object", required: ["sourceId", "targetId"], @@ -81,7 +81,7 @@ const workflowActions = { } }, removeEdge: { - description: "Remove a connection between blocks", + description: "Remove a connection (edge) between blocks", parameters: { type: "object", required: ["id"], diff --git a/stores/chat/store.ts b/stores/chat/store.ts index 440afca01c..4e2551ed82 100644 --- a/stores/chat/store.ts +++ b/stores/chat/store.ts @@ -3,7 +3,7 @@ import { devtools } from 'zustand/middleware' import { useWorkflowStore } from '../workflow/store' import { useEnvironmentStore } from '../environment/store' import { ChatStore, ChatMessage } from './types' -import { getNextBlockNumber } from './utils' +import { getNextBlockNumber, calculateBlockPosition } from './utils' export const useChatStore = create()( devtools( @@ -73,25 +73,36 @@ export const useChatStore = create()( // Handle any actions returned from the API if (data.actions) { - for (const action of data.actions) { + // Process all block additions first to properly calculate positions + const blockActions = data.actions.filter( + (action: any) => action.name === 'addBlock' + ) + + blockActions.forEach((action: any, index: number) => { + const { type, name } = action.parameters + const id = crypto.randomUUID() + + // Calculate position based on current blocks and action index + const position = calculateBlockPosition( + workflowStore.blocks, + index + ) + + // Generate name if not provided + const blockName = name || `${type} ${getNextBlockNumber(workflowStore.blocks, type)}` + + workflowStore.addBlock(id, type, blockName, position) + }) + + // Handle other actions (edges, removals, etc.) + const otherActions = data.actions.filter( + (action: any) => action.name !== 'addBlock' + ) + + otherActions.forEach((action: any) => { switch (action.name) { - case 'addBlock': { - const { type, name, position } = action.parameters - const id = crypto.randomUUID() - const defaultPosition = position || { - x: Object.keys(workflowStore.blocks).length * 250, - y: 100 - } - - // Generate name if not provided - const blockName = name || `${type} ${getNextBlockNumber(workflowStore.blocks, type)}` - - workflowStore.addBlock(id, type, blockName, defaultPosition) - break - } case 'addEdge': { const { sourceId, targetId, sourceHandle, targetHandle } = action.parameters - workflowStore.addEdge({ id: crypto.randomUUID(), source: sourceId, @@ -111,7 +122,7 @@ export const useChatStore = create()( break } } - } + }) } // Add assistant's response to chat diff --git a/stores/chat/utils.ts b/stores/chat/utils.ts index 2f5be39e72..3b0b107ac4 100644 --- a/stores/chat/utils.ts +++ b/stores/chat/utils.ts @@ -9,4 +9,25 @@ export const getNextBlockNumber = (blocks: Record, type: string) => const maxNumber = Math.max(0, ...typeBlocks) return maxNumber + 1 +} + +// Calculate block position based on existing blocks and current action index +export const calculateBlockPosition = ( + existingBlocks: Record, + index: number, + startX = 100, + startY = 100, + xSpacing = 500, + ySpacing = 150 +) => { + const blocksCount = Object.keys(existingBlocks).length + + // Calculate position based on existing blocks and current action index + const row = Math.floor((blocksCount + index) / 5) // 5 blocks per row + const col = (blocksCount + index) % 5 + + return { + x: startX + (col * xSpacing), + y: startY + (row * ySpacing) + } } \ No newline at end of file