From 660a203c75b65e069882329bdb3e6c9155f21482 Mon Sep 17 00:00:00 2001 From: Emir Karabeg Date: Wed, 12 Feb 2025 11:13:38 -0800 Subject: [PATCH] Fix: table subblock input --- .../components/sub-block/components/table.tsx | 24 +++++---- .../sub-block/hooks/use-sub-block-value.ts | 11 ++-- stores/workflow/store.ts | 52 ++++++++----------- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx index eabb6000c7..c89ea9e078 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useMemo, useRef } from 'react' import { Trash2 } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' @@ -47,16 +47,22 @@ export function Table({ columns, blockId, subBlockId }: TableProps) { } }, [value]) - // Initialize with empty row if no value exists - const rows = (value as any[]) || [ - { - id: crypto.randomUUID(), - cells: Object.fromEntries(columns.map((col) => [col, ''])), - }, - ] + // Ensure value is properly typed and initialized + const rows = useMemo(() => { + if (!Array.isArray(value)) { + // Initialize with a single empty row if value is null or invalid + return [ + { + id: crypto.randomUUID(), + cells: Object.fromEntries(columns.map((col) => [col, ''])), + }, + ] + } + return value as TableRow[] + }, [value, columns]) const handleCellChange = (rowIndex: number, column: string, value: string) => { - const updatedRows = rows.map((row, idx) => + const updatedRows = [...rows].map((row, idx) => idx === rowIndex ? { ...row, diff --git a/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts b/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts index 910b5313dd..f4ec5be574 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts +++ b/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts @@ -1,7 +1,10 @@ import { useCallback } from 'react' import { useWorkflowStore } from '@/stores/workflow/store' -export function useSubBlockValue(blockId: string, subBlockId: string) { +export function useSubBlockValue( + blockId: string, + subBlockId: string +): readonly [T | null, (value: T) => void] { const value = useWorkflowStore( useCallback( (state) => state.blocks[blockId]?.subBlocks[subBlockId]?.value ?? null, @@ -12,11 +15,11 @@ export function useSubBlockValue(blockId: string, subBlockId: string) { const updateSubBlock = useWorkflowStore((state) => state.updateSubBlock) const setValue = useCallback( - (newValue: any) => { - updateSubBlock(blockId, subBlockId, newValue) + (newValue: T) => { + updateSubBlock(blockId, subBlockId, newValue as any) }, [blockId, subBlockId, updateSubBlock] ) - return [value, setValue] as const + return [value as T | null, setValue] as const } diff --git a/stores/workflow/store.ts b/stores/workflow/store.ts index c5e9dffb19..87b9bea3fe 100644 --- a/stores/workflow/store.ts +++ b/stores/workflow/store.ts @@ -38,19 +38,26 @@ export const useWorkflowStore = create()( const block = state.blocks[blockId] if (!block) return state - const blockConfig = getBlock(block.type) - if (!blockConfig) return state + const processedValue = Array.isArray(value) + ? value + : typeof value === 'string' + ? value + : JSON.stringify(value, null, 2) - // Validate responseFormat if it's the agent block's responseFormat input - if (blockConfig.type === 'agent' && subBlockId === 'responseFormat' && value) { + // Only attempt JSON parsing for agent responseFormat validation + if ( + block.type === 'agent' && + subBlockId === 'responseFormat' && + typeof processedValue === 'string' + ) { console.log('Validating responseFormat input:', { - type: typeof value, - rawValue: value, + type: typeof processedValue, + rawValue: processedValue, }) try { // Parse the input string to validate JSON but keep original string value - const parsed = JSON.parse(value) + const parsed = JSON.parse(processedValue) console.log('Parsed responseFormat:', parsed) // Simple validation of required schema structure @@ -81,35 +88,18 @@ export const useWorkflowStore = create()( } } - // Create new subBlocks state with the original value - const newSubBlocks = { - ...block.subBlocks, - [subBlockId]: { - ...block.subBlocks[subBlockId], - value: - // Keep tools as arrays - subBlockId === 'tools' && Array.isArray(value) - ? value - : // Keep responseFormat as string - subBlockId === 'responseFormat' - ? value - : // For all other values, use the previous logic of stringifying - typeof value === 'string' - ? value - : JSON.stringify(value, null, 2), - }, - } - - // Resolve new outputs - const newOutputs = resolveOutputType(blockConfig.workflow.outputs, newSubBlocks) - return { blocks: { ...state.blocks, [blockId]: { ...block, - subBlocks: newSubBlocks, - outputs: newOutputs, + subBlocks: { + ...block.subBlocks, + [subBlockId]: { + ...block.subBlocks[subBlockId], + value: processedValue, + }, + }, }, }, }