From bb9291aeccd170aa95009a4f9c52cdca3045d537 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Tue, 8 Jul 2025 21:27:08 -0700 Subject: [PATCH] It works?? --- apps/sim/app/api/workflows/[id]/route.ts | 10 +++ .../sim/app/api/workflows/[id]/state/route.ts | 16 ++++- .../import-controls/import-controls.tsx | 23 +++---- apps/sim/lib/workflows/db-helpers.ts | 17 +++++ apps/sim/stores/workflows/registry/store.ts | 7 +++ apps/sim/stores/workflows/yaml/importer.ts | 62 +++++++++++++++---- 6 files changed, 108 insertions(+), 27 deletions(-) diff --git a/apps/sim/app/api/workflows/[id]/route.ts b/apps/sim/app/api/workflows/[id]/route.ts index 2096e99fc5..0fe25809a3 100644 --- a/apps/sim/app/api/workflows/[id]/route.ts +++ b/apps/sim/app/api/workflows/[id]/route.ts @@ -110,6 +110,16 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{ parallelsCount: Object.keys(normalizedData.parallels).length, loops: normalizedData.loops, }) + + // Debug: Log sample block data from normalized tables + const sampleBlockId = Object.keys(normalizedData.blocks)[0] + if (sampleBlockId) { + logger.debug(`[${requestId}] Sample block from normalized tables:`, { + blockId: sampleBlockId, + block: normalizedData.blocks[sampleBlockId], + subBlocks: normalizedData.blocks[sampleBlockId]?.subBlocks + }) + } // Use normalized table data - reconstruct complete state object // First get any existing state properties, then override with normalized data const existingState = diff --git a/apps/sim/app/api/workflows/[id]/state/route.ts b/apps/sim/app/api/workflows/[id]/state/route.ts index 63e83128e1..508366f8d7 100644 --- a/apps/sim/app/api/workflows/[id]/state/route.ts +++ b/apps/sim/app/api/workflows/[id]/state/route.ts @@ -85,9 +85,19 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{ return NextResponse.json({ error: 'Access denied' }, { status: 403 }) } - // Save to normalized tables + // Save to normalized tables logger.info(`[${requestId}] Saving workflow ${workflowId} state to normalized tables`) - + + // Debug: Log sample block data being received + const sampleBlockId = Object.keys(state.blocks)[0] + if (sampleBlockId) { + logger.debug(`[${requestId}] Sample block data received:`, { + blockId: sampleBlockId, + block: state.blocks[sampleBlockId], + subBlocks: state.blocks[sampleBlockId]?.subBlocks + }) + } + // Ensure all required fields are present for WorkflowState type const workflowState = { blocks: state.blocks, @@ -101,7 +111,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{ hasActiveSchedule: state.hasActiveSchedule || false, hasActiveWebhook: state.hasActiveWebhook || false, } - + const saveResult = await saveWorkflowToNormalizedTables(workflowId, workflowState) if (!saveResult.success) { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/import-controls/import-controls.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/import-controls/import-controls.tsx index 40ffa101cc..307b425633 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/import-controls/import-controls.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/import-controls/import-controls.tsx @@ -114,13 +114,9 @@ export function ImportControls({ disabled = false }: ImportControlsProps) { workspaceId, }) - // Navigate to the new workflow - router.push(`/workspace/${workspaceId}/w/${newWorkflowId}`) - - // Brief delay to ensure navigation completes - await new Promise((resolve) => setTimeout(resolve, 100)) - - // Import the YAML into the new workflow (creates complete state and saves directly to DB) + // Import the YAML into the new workflow BEFORE navigation (creates complete state and saves directly to DB) + // This avoids timing issues with workflow reload during navigation + logger.info('Importing YAML into new workflow before navigation') const result = await importWorkflowFromYaml(yamlContent, { addBlock: collaborativeAddBlock, addEdge: collaborativeAddEdge, @@ -133,11 +129,16 @@ export function ImportControls({ disabled = false }: ImportControlsProps) { collaborativeSetSubblockValue(blockId, subBlockId, value) }, getExistingBlocks: () => { - // This will be called after navigation, so we need to get blocks from the store - const { useWorkflowStore } = require('@/stores/workflows/workflow/store') - return useWorkflowStore.getState().blocks + // For a new workflow, we'll get the starter block from the server + return {} }, - }) + }, newWorkflowId) // Pass the new workflow ID to import into + + // Navigate to the new workflow AFTER import is complete + if (result.success) { + logger.info('Navigating to imported workflow') + router.push(`/workspace/${workspaceId}/w/${newWorkflowId}`) + } setImportResult(result) diff --git a/apps/sim/lib/workflows/db-helpers.ts b/apps/sim/lib/workflows/db-helpers.ts index f4c61e7cdd..cfe1b31d33 100644 --- a/apps/sim/lib/workflows/db-helpers.ts +++ b/apps/sim/lib/workflows/db-helpers.ts @@ -69,6 +69,14 @@ export async function loadWorkflowFromNormalizedTables( parentId, extent, } + + // Debug: Log sample block subBlocks from database + if (block.type === 'agent') { + logger.debug(`Loaded ${block.type} block from database:`, { + blockId: block.id, + subBlocks: block.subBlocks + }) + } }) // Convert edges to the expected format @@ -162,6 +170,15 @@ export async function saveWorkflowToNormalizedTables( extent: block.data?.extent || null, })) + // Debug: Log sample block insert data + if (blockInserts.length > 0) { + logger.debug(`Saving ${blockInserts.length} blocks. Sample block:`, { + blockId: blockInserts[0].id, + type: blockInserts[0].type, + subBlocks: blockInserts[0].subBlocks + }) + } + await tx.insert(workflowBlocks).values(blockInserts) } diff --git a/apps/sim/stores/workflows/registry/store.ts b/apps/sim/stores/workflows/registry/store.ts index 5fada790b0..10c4205b3e 100644 --- a/apps/sim/stores/workflows/registry/store.ts +++ b/apps/sim/stores/workflows/registry/store.ts @@ -474,6 +474,9 @@ export const useWorkflowRegistry = create()( }) }) + // Debug: Log what values are being extracted from the database + logger.debug(`Extracted subblock values from database for workflow ${id}:`, subblockValues) + // Update subblock store for this workflow useSubBlockStore.setState((state) => ({ workflowValues: { @@ -481,6 +484,10 @@ export const useWorkflowRegistry = create()( [id]: subblockValues, }, })) + + // Debug: Verify SubBlockStore was updated + const updatedValues = useSubBlockStore.getState().workflowValues[id] + logger.debug(`SubBlockStore updated for workflow ${id}:`, updatedValues) } else { // If no state in DB, use empty state - server should have created start block workflowState = { diff --git a/apps/sim/stores/workflows/yaml/importer.ts b/apps/sim/stores/workflows/yaml/importer.ts index 3e0d1dd109..bb1eedbf55 100644 --- a/apps/sim/stores/workflows/yaml/importer.ts +++ b/apps/sim/stores/workflows/yaml/importer.ts @@ -348,7 +348,8 @@ export async function importWorkflowFromYaml( applyAutoLayout: () => void setSubBlockValue: (blockId: string, subBlockId: string, value: any) => void getExistingBlocks: () => Record - } + }, + targetWorkflowId?: string ): Promise<{ success: boolean; errors: string[]; warnings: string[]; summary?: string }> { logger.info('Starting YAML workflow import (complete state creation)') @@ -376,7 +377,25 @@ export async function importWorkflowFromYaml( ) // Get the existing workflow state (to preserve starter blocks if they exist) - const existingBlocks = workflowActions.getExistingBlocks() + let existingBlocks: Record = {} + + if (targetWorkflowId) { + // For target workflow, fetch from API + try { + const response = await fetch(`/api/workflows/${targetWorkflowId}`) + if (response.ok) { + const workflowData = await response.json() + existingBlocks = workflowData.data?.state?.blocks || {} + logger.debug(`Fetched existing blocks for target workflow ${targetWorkflowId}:`, Object.keys(existingBlocks)) + } + } catch (error) { + logger.warn(`Failed to fetch existing blocks for workflow ${targetWorkflowId}:`, error) + } + } else { + // For active workflow, use from store + existingBlocks = workflowActions.getExistingBlocks() + } + const existingStarterBlocks = Object.values(existingBlocks).filter( (block: any) => block.type === 'starter' ) @@ -389,11 +408,13 @@ export async function importWorkflowFromYaml( // Get current workflow state const currentWorkflowState = useWorkflowStore.getState() - const activeWorkflowId = useWorkflowRegistry.getState().activeWorkflowId + const activeWorkflowId = targetWorkflowId || useWorkflowRegistry.getState().activeWorkflowId if (!activeWorkflowId) { return { success: false, errors: ['No active workflow'], warnings: [] } } + + logger.info(`Importing YAML into workflow: ${activeWorkflowId} ${targetWorkflowId ? '(specified target)' : '(active workflow)'}`) // Build complete blocks object const completeBlocks: Record = {} @@ -593,6 +614,12 @@ export async function importWorkflowFromYaml( // Save directly to database via API logger.info('Saving complete workflow state directly to database...') + logger.debug('Sample block being saved:', { + firstBlockId: Object.keys(completeBlocks)[0], + firstBlock: Object.values(completeBlocks)[0], + firstBlockSubBlocks: Object.values(completeBlocks)[0]?.subBlocks + }) + const response = await fetch(`/api/workflows/${activeWorkflowId}/state`, { method: 'PUT', headers: { @@ -614,17 +641,26 @@ export async function importWorkflowFromYaml( const saveResponse = await response.json() logger.info('Successfully saved to database:', saveResponse) - // Update local state for immediate UI display - logger.info('Updating local state for immediate display...') - useWorkflowStore.setState(completeWorkflowState) + // Update local state for immediate UI display (only if importing into active workflow) + if (!targetWorkflowId) { + logger.info('Updating local state for immediate display (active workflow)...') + useWorkflowStore.setState(completeWorkflowState) - // Set subblock values in local store - useSubBlockStore.setState((state: any) => ({ - workflowValues: { - ...state.workflowValues, - [activeWorkflowId]: completeSubBlockValues, - }, - })) + // Set subblock values in local store + logger.debug('Setting SubBlockStore with values:', completeSubBlockValues) + useSubBlockStore.setState((state: any) => ({ + workflowValues: { + ...state.workflowValues, + [activeWorkflowId]: completeSubBlockValues, + }, + })) + + // Verify SubBlockStore was updated + const subBlockStoreValues = useSubBlockStore.getState().workflowValues[activeWorkflowId] + logger.debug('SubBlockStore after update:', subBlockStoreValues) + } else { + logger.info('Skipping local state update (importing into non-active workflow)') + } // Brief delay for UI to update await new Promise((resolve) => setTimeout(resolve, 100))