diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000..95efa798fa --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..3a8d5a9735 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,37 @@ +# Build output +.next +out +dist +build + +# Dependencies +node_modules + +# Cache +.cache +.npm + +# Misc +.DS_Store +*.pem + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Local env files +.env*.local +.env + +# Vercel +.vercel + +# Coverage +coverage + +# PWA files +**/public/sw.js +**/public/workbox-*.js +**/public/worker-*.js +**/public/fallback-*.js \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000000..41708aec7a --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,22 @@ +module.exports = { + semi: false, + singleQuote: true, + tabWidth: 2, + trailingComma: 'es5', + printWidth: 100, + bracketSpacing: true, + arrowParens: 'always', + endOfLine: 'lf', + plugins: ['prettier-plugin-tailwindcss', '@trivago/prettier-plugin-sort-imports'], + importOrder: [ + '^(react/(.*)$)|^(react$)', + '^(next/(.*)$)|^(next$)', + '', + '^@/components/(.*)$', + '^@/lib/(.*)$', + '^@/stores/(.*)$', + '^@/(.*)$', + '^[./]', + ], + importOrderSortSpecifiers: true, +} diff --git a/README.md b/README.md index d2141d0aea..5bc14ee449 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ All icons are available as React components and can be imported from `components import { ApiIcon, CodeIcon, ErrorIcon } from '@/components/icons' // Usage + ; ``` diff --git a/app/api/proxy/route.ts b/app/api/proxy/route.ts index cfebe278b9..dd1aec4656 100644 --- a/app/api/proxy/route.ts +++ b/app/api/proxy/route.ts @@ -1,14 +1,14 @@ import { NextResponse } from 'next/server' -import { getTool } from '@/tools' import { anthropicProvider } from '@/providers/anthropic' +import { googleProvider } from '@/providers/google' import { openaiProvider } from '@/providers/openai' import { ProviderConfig } from '@/providers/types' -import { googleProvider } from '@/providers/google' +import { getTool } from '@/tools' const providers: Record = { 'anthropic/chat': anthropicProvider, 'openai/chat': openaiProvider, - 'google/chat': googleProvider + 'google/chat': googleProvider, } export async function POST(request: Request) { @@ -26,7 +26,7 @@ export async function POST(request: Request) { const response = await fetch(provider.baseUrl, { method: 'POST', headers: provider.headers(apiKey), - body: JSON.stringify(restParams) + body: JSON.stringify(restParams), }) if (!response.ok) { @@ -36,7 +36,7 @@ export async function POST(request: Request) { return NextResponse.json({ success: true, - output: await response.json() + output: await response.json(), }) } @@ -62,10 +62,10 @@ export async function POST(request: Request) { const externalResponse = await fetch(url, { method, headers, body }) if (!externalResponse.ok) { - const errorContent = await externalResponse.json().catch(() => ({ - message: externalResponse.statusText + const errorContent = await externalResponse.json().catch(() => ({ + message: externalResponse.statusText, })) - + // Use the tool's error transformer or a default message const error = tool.transformError ? tool.transformError(errorContent) @@ -84,9 +84,7 @@ export async function POST(request: Request) { if (!result.success) { throw new Error( - tool.transformError - ? tool.transformError(result) - : 'Tool returned an error' + tool.transformError ? tool.transformError(result) : 'Tool returned an error' ) } @@ -97,7 +95,7 @@ export async function POST(request: Request) { } catch (error: any) { return NextResponse.json({ success: false, - error: error.message || 'Unknown error' + error: error.message || 'Unknown error', }) } -} \ No newline at end of file +} diff --git a/app/layout.tsx b/app/layout.tsx index 1579049bfd..60d4844e67 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -4,15 +4,10 @@ import { ZoomPrevention } from './zoom-prevention' export const metadata: Metadata = { title: 'Sim Studio', - description: - 'Drag and drop agents to create workflows. Powered by Simplicity', + description: 'Drag and drop agents to create workflows. Powered by Simplicity', } -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { +export default function RootLayout({ children }: { children: React.ReactNode }) { return ( diff --git a/app/w/[id]/components/custom-edge/custom-edge.tsx b/app/w/[id]/components/custom-edge/custom-edge.tsx index 2bbdb0624c..f07bca46a4 100644 --- a/app/w/[id]/components/custom-edge/custom-edge.tsx +++ b/app/w/[id]/components/custom-edge/custom-edge.tsx @@ -1,9 +1,8 @@ -import { EdgeProps, getSmoothStepPath } from 'reactflow' import { X } from 'lucide-react' +import { EdgeProps, getSmoothStepPath } from 'reactflow' export const CustomEdge = (props: EdgeProps) => { - const isHorizontal = - props.sourcePosition === 'right' || props.sourcePosition === 'left' + const isHorizontal = props.sourcePosition === 'right' || props.sourcePosition === 'left' // For horizontal handles, we'll add a minimum extension to ensure the path // always goes outward before going up/down diff --git a/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx b/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx index b575fc5d1c..d0400c44c6 100644 --- a/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx +++ b/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx @@ -1,20 +1,8 @@ +import { ArrowLeftRight, ArrowUpDown, Circle, CircleOff, Copy, Play, Trash2 } from 'lucide-react' import { Button } from '@/components/ui/button' -import { - Trash2, - Play, - Circle, - CircleOff, - Copy, - ArrowLeftRight, - ArrowUpDown, -} from 'lucide-react' -import { useWorkflowStore } from '@/stores/workflow/store' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/components/ui/tooltip' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { cn } from '@/lib/utils' +import { useWorkflowStore } from '@/stores/workflow/store' interface ActionBarProps { blockId: string @@ -22,16 +10,10 @@ interface ActionBarProps { export function ActionBar({ blockId }: ActionBarProps) { const removeBlock = useWorkflowStore((state) => state.removeBlock) - const toggleBlockEnabled = useWorkflowStore( - (state) => state.toggleBlockEnabled - ) - const toggleBlockHandles = useWorkflowStore( - (state) => state.toggleBlockHandles - ) + const toggleBlockEnabled = useWorkflowStore((state) => state.toggleBlockEnabled) + const toggleBlockHandles = useWorkflowStore((state) => state.toggleBlockHandles) const duplicateBlock = useWorkflowStore((state) => state.duplicateBlock) - const isEnabled = useWorkflowStore( - (state) => state.blocks[blockId]?.enabled ?? true - ) + const isEnabled = useWorkflowStore((state) => state.blocks[blockId]?.enabled ?? true) const horizontalHandles = useWorkflowStore( (state) => state.blocks[blockId]?.horizontalHandles ?? false ) @@ -63,16 +45,10 @@ export function ActionBar({ blockId }: ActionBarProps) { onClick={() => toggleBlockEnabled(blockId)} className="text-gray-500" > - {isEnabled ? ( - - ) : ( - - )} + {isEnabled ? : } - - {isEnabled ? 'Disable Block' : 'Enable Block'} - + {isEnabled ? 'Disable Block' : 'Enable Block'} diff --git a/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx index e13d341569..a7b90fcf5b 100644 --- a/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx +++ b/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx @@ -1,17 +1,13 @@ -import { useBlockConnections } from '@/app/w/hooks/use-block-connections' import { Card } from '@/components/ui/card' +import { useBlockConnections } from '@/app/w/hooks/use-block-connections' interface ConnectionBlocksProps { blockId: string setIsConnecting: (isConnecting: boolean) => void } -export function ConnectionBlocks({ - blockId, - setIsConnecting, -}: ConnectionBlocksProps) { - const { incomingConnections, hasIncomingConnections } = - useBlockConnections(blockId) +export function ConnectionBlocks({ blockId, setIsConnecting }: ConnectionBlocksProps) { + const { incomingConnections, hasIncomingConnections } = useBlockConnections(blockId) if (!hasIncomingConnections) return null @@ -51,9 +47,7 @@ export function ConnectionBlocks({ {connection.name.replace(/\s+/g, '').toLowerCase()} - - .{connection.outputType} - + .{connection.outputType} ))} diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx index 22ba6abcda..5576560a46 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx @@ -1,7 +1,7 @@ -import { Label } from '@/components/ui/label' import { Checkbox } from '@/components/ui/checkbox' -import { useSubBlockValue } from '../hooks/use-sub-block-value' +import { Label } from '@/components/ui/label' import { cn } from '@/lib/utils' +import { useSubBlockValue } from '../hooks/use-sub-block-value' interface CheckboxListProps { blockId: string @@ -11,21 +11,9 @@ interface CheckboxListProps { layout?: 'full' | 'half' } -export function CheckboxList({ - blockId, - subBlockId, - title, - options, - layout, -}: CheckboxListProps) { +export function CheckboxList({ blockId, subBlockId, title, options, layout }: CheckboxListProps) { return ( -
+
{options.map((option) => { const [value, setValue] = useSubBlockValue(blockId, option.id) return ( diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx index 027ba5db53..16c8b7e25a 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx @@ -1,11 +1,11 @@ -import { useState, useRef, useEffect } from 'react' -import Editor from 'react-simple-code-editor' +import { useEffect, useRef, useState } from 'react' import { highlight, languages } from 'prismjs' import 'prismjs/components/prism-javascript' import 'prismjs/themes/prism.css' +import Editor from 'react-simple-code-editor' +import { TagDropdown, checkTagTrigger } from '@/components/ui/tag-dropdown' import { cn } from '@/lib/utils' import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { TagDropdown, checkTagTrigger } from '@/components/ui/tag-dropdown' interface CodeProps { blockId: string @@ -19,9 +19,7 @@ export function Code({ blockId, subBlockId, isConnecting }: CodeProps) { const [lineCount, setLineCount] = useState(1) const [showTags, setShowTags] = useState(false) const [cursorPosition, setCursorPosition] = useState(0) - const [activeSourceBlockId, setActiveSourceBlockId] = useState( - null - ) + const [activeSourceBlockId, setActiveSourceBlockId] = useState(null) const editorRef = useRef(null) // Add new state for tracking visual line heights @@ -93,10 +91,7 @@ export function Code({ blockId, subBlockId, isConnecting }: CodeProps) { document.body.removeChild(container) setVisualLineHeights(newVisualLineHeights) - const totalVisualLines = newVisualLineHeights.reduce( - (sum, height) => sum + height, - 0 - ) + const totalVisualLines = newVisualLineHeights.reduce((sum, height) => sum + height, 0) setLineCount(totalVisualLines) } @@ -146,8 +141,7 @@ export function Code({ blockId, subBlockId, isConnecting }: CodeProps) { const dropPosition = textarea?.selectionStart ?? code.length // Insert '<' at drop position to trigger the dropdown - const newValue = - code.slice(0, dropPosition) + '<' + code.slice(dropPosition) + const newValue = code.slice(0, dropPosition) + '<' + code.slice(dropPosition) setCode(newValue) setStoreValue(newValue) @@ -216,9 +210,7 @@ export function Code({ blockId, subBlockId, isConnecting }: CodeProps) { } } }} - highlight={(code) => - highlight(code, languages.javascript, 'javascript') - } + highlight={(code) => highlight(code, languages.javascript, 'javascript')} padding={12} style={{ fontFamily: 'inherit', diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx index b31d8c4344..b3fdc352cc 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx @@ -1,3 +1,4 @@ +import { useEffect } from 'react' import { Select, SelectContent, @@ -6,7 +7,6 @@ import { SelectValue, } from '@/components/ui/select' import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { useEffect } from 'react' interface DropdownProps { options: string[] @@ -15,12 +15,7 @@ interface DropdownProps { subBlockId: string } -export function Dropdown({ - options, - defaultValue, - blockId, - subBlockId, -}: DropdownProps) { +export function Dropdown({ options, defaultValue, blockId, subBlockId }: DropdownProps) { const [value, setValue] = useSubBlockValue(blockId, subBlockId) // Set the value to the first option if it's not set diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx index 878628873b..da01423e54 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx @@ -1,15 +1,12 @@ -import { Textarea } from '@/components/ui/textarea' -import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { cn } from '@/lib/utils' -import { useState, useRef } from 'react' -import { SubBlockConfig } from '@/blocks/types' +import { useRef, useState } from 'react' +import { EnvVarDropdown, checkEnvVarTrigger } from '@/components/ui/env-var-dropdown' import { formatDisplayText } from '@/components/ui/formatted-text' -import { - EnvVarDropdown, - checkEnvVarTrigger, -} from '@/components/ui/env-var-dropdown' import { TagDropdown, checkTagTrigger } from '@/components/ui/tag-dropdown' +import { Textarea } from '@/components/ui/textarea' +import { cn } from '@/lib/utils' import { useWorkflowStore } from '@/stores/workflow/store' +import { SubBlockConfig } from '@/blocks/types' +import { useSubBlockValue } from '../hooks/use-sub-block-value' interface LongInputProps { placeholder?: string @@ -33,9 +30,7 @@ export function LongInput({ const [cursorPosition, setCursorPosition] = useState(0) const textareaRef = useRef(null) const overlayRef = useRef(null) - const [activeSourceBlockId, setActiveSourceBlockId] = useState( - null - ) + const [activeSourceBlockId, setActiveSourceBlockId] = useState(null) // Handle input changes const handleChange = (e: React.ChangeEvent) => { @@ -77,15 +72,11 @@ export function LongInput({ if (data.type !== 'connectionBlock') return // Get current cursor position or append to end - const dropPosition = - textareaRef.current?.selectionStart ?? value?.toString().length ?? 0 + const dropPosition = textareaRef.current?.selectionStart ?? value?.toString().length ?? 0 // Insert '<' at drop position to trigger the dropdown const currentValue = value?.toString() ?? '' - const newValue = - currentValue.slice(0, dropPosition) + - '<' + - currentValue.slice(dropPosition) + const newValue = currentValue.slice(0, dropPosition) + '<' + currentValue.slice(dropPosition) // Focus the textarea first textareaRef.current?.focus() diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx index d75e05eb5c..2925d6a8dd 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx @@ -1,14 +1,11 @@ +import { useEffect, useRef, useState } from 'react' +import { EnvVarDropdown, checkEnvVarTrigger } from '@/components/ui/env-var-dropdown' +import { formatDisplayText } from '@/components/ui/formatted-text' import { Input } from '@/components/ui/input' -import { useState, useRef, useEffect } from 'react' -import { useSubBlockValue } from '../hooks/use-sub-block-value' +import { TagDropdown, checkTagTrigger } from '@/components/ui/tag-dropdown' import { cn } from '@/lib/utils' import { SubBlockConfig } from '@/blocks/types' -import { formatDisplayText } from '@/components/ui/formatted-text' -import { - EnvVarDropdown, - checkEnvVarTrigger, -} from '@/components/ui/env-var-dropdown' -import { TagDropdown, checkTagTrigger } from '@/components/ui/tag-dropdown' +import { useSubBlockValue } from '../hooks/use-sub-block-value' interface ShortInputProps { placeholder?: string @@ -39,9 +36,7 @@ export function ShortInput({ const [cursorPosition, setCursorPosition] = useState(0) const inputRef = useRef(null) const overlayRef = useRef(null) - const [activeSourceBlockId, setActiveSourceBlockId] = useState( - null - ) + const [activeSourceBlockId, setActiveSourceBlockId] = useState(null) // Use either controlled or uncontrolled value const value = propValue !== undefined ? propValue : storeValue @@ -104,15 +99,11 @@ export function ShortInput({ if (data.type !== 'connectionBlock') return // Get current cursor position or append to end - const dropPosition = - inputRef.current?.selectionStart ?? value?.toString().length ?? 0 + const dropPosition = inputRef.current?.selectionStart ?? value?.toString().length ?? 0 // Insert '<' at drop position to trigger the dropdown const currentValue = value?.toString() ?? '' - const newValue = - currentValue.slice(0, dropPosition) + - '<' + - currentValue.slice(dropPosition) + const newValue = currentValue.slice(0, dropPosition) + '<' + currentValue.slice(dropPosition) // Focus the input first inputRef.current?.focus() @@ -151,9 +142,7 @@ export function ShortInput({ // Value display logic const displayValue = - password && !isFocused - ? '•'.repeat(value?.toString().length ?? 0) - : value?.toString() ?? '' + password && !isFocused ? '•'.repeat(value?.toString().length ?? 0) : (value?.toString() ?? '') // Modify the EnvVarDropdown to use the correct setter const handleEnvVarSelect = (newValue: string) => { diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx index f26a3de554..29c5368d8d 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx @@ -32,9 +32,7 @@ export function SliderInput({
{ const percentage = ((Number(sliderValue) - min) / (max - min)) * 100 const bias = -25 * Math.sin((percentage * Math.PI) / 50) diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx index b32996aced..1011ce8367 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx @@ -1,6 +1,6 @@ +import { Label } from '@/components/ui/label' import { Switch as UISwitch } from '@/components/ui/switch' import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { Label } from '@/components/ui/label' interface SwitchProps { blockId: string @@ -16,10 +16,7 @@ export function Switch({ blockId, subBlockId, title }: SwitchProps) { - setValue(checked)} - /> + setValue(checked)} />
) } 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 852297157c..eabb6000c7 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,9 +1,9 @@ +import { useEffect, useRef } from 'react' import { Trash2 } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { cn } from '@/lib/utils' import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { useRef, useEffect } from 'react' interface TableProps { columns: string[] @@ -18,9 +18,7 @@ interface TableRow { export function Table({ columns, blockId, subBlockId }: TableProps) { const [value, setValue] = useSubBlockValue(blockId, subBlockId) - const activePositionRef = useRef<{ rowIndex: number; column: string } | null>( - null - ) + const activePositionRef = useRef<{ rowIndex: number; column: string } | null>(null) const inputRefs = useRef>(new Map()) useEffect(() => { @@ -57,11 +55,7 @@ export function Table({ columns, blockId, subBlockId }: TableProps) { }, ] - const handleCellChange = ( - rowIndex: number, - column: string, - value: string - ) => { + const handleCellChange = (rowIndex: number, column: string, value: string) => { const updatedRows = rows.map((row, idx) => idx === rowIndex ? { @@ -111,10 +105,7 @@ export function Table({ columns, blockId, subBlockId }: TableProps) { {columns.map((column, cellIndex) => ( { @@ -128,9 +119,7 @@ export function Table({ columns, blockId, subBlockId }: TableProps) { data-column={column} value={row.cells[column] || ''} placeholder={column} - onChange={(e) => - handleCellChange(rowIndex, column, e.target.value) - } + onChange={(e) => handleCellChange(rowIndex, column, e.target.value)} onFocus={() => { activePositionRef.current = { rowIndex, column } }} diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input.tsx index 72bdd8c685..f53a7fb23b 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' -import { Button } from '@/components/ui/button' import { PlusIcon, XIcon } from 'lucide-react' +import { Button } from '@/components/ui/button' import { Command, CommandEmpty, @@ -9,15 +9,11 @@ import { CommandItem, CommandList, } from '@/components/ui/command' -import { - Popover, - PopoverContent, - PopoverTrigger, -} from '@/components/ui/popover' -import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { getAllBlocks } from '@/blocks' +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { cn } from '@/lib/utils' +import { getAllBlocks } from '@/blocks' import { getTool } from '@/tools' +import { useSubBlockValue } from '../hooks/use-sub-block-value' import { ShortInput } from './short-input' interface ToolInputProps { @@ -82,9 +78,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { const [value, setValue] = useSubBlockValue(blockId, subBlockId) const [open, setOpen] = useState(false) - const toolBlocks = getAllBlocks().filter( - (block) => block.toolbar.category === 'tools' - ) + const toolBlocks = getAllBlocks().filter((block) => block.toolbar.category === 'tools') const selectedTools: StoredTool[] = Array.isArray(value) && value.length > 0 && typeof value[0] === 'object' @@ -112,11 +106,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { setValue(selectedTools.filter((tool) => tool.type !== toolType)) } - const handleParamChange = ( - toolType: string, - paramId: string, - paramValue: string - ) => { + const handleParamChange = (toolType: string, paramId: string, paramValue: string) => { setValue( selectedTools.map((tool) => tool.type === toolType @@ -132,13 +122,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { ) } - const IconComponent = ({ - icon: Icon, - className, - }: { - icon: any - className?: string - }) => { + const IconComponent = ({ icon: Icon, className }: { icon: any; className?: string }) => { if (!Icon) return null return } @@ -177,10 +161,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { className="flex items-center justify-center w-6 h-6 rounded" style={{ backgroundColor: block.toolbar.bgColor }} > - +
{block.toolbar.title} @@ -193,9 +174,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { ) : (
{selectedTools.map((tool) => { - const toolBlock = toolBlocks.find( - (block) => block.type === tool.type - ) + const toolBlock = toolBlocks.find((block) => block.type === tool.type) const toolId = getToolIdFromBlock(tool.type) const requiredParams = toolId ? getRequiredToolParams(toolId) : [] @@ -235,10 +214,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { blockId={blockId} subBlockId={`${subBlockId}-param`} placeholder={param.description} - password={ - param.id.toLowerCase().replace(/\s+/g, '') === - 'apikey' - } + password={param.id.toLowerCase().replace(/\s+/g, '') === 'apikey'} isConnecting={false} config={{ id: `${subBlockId}-param`, @@ -246,9 +222,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { title: param.id, }} value={tool.params[param.id] || ''} - onChange={(value) => - handleParamChange(tool.type, param.id, value) - } + onChange={(value) => handleParamChange(tool.type, param.id, value)} />
@@ -286,10 +260,7 @@ export function ToolInput({ blockId, subBlockId }: ToolInputProps) { className="flex items-center justify-center w-6 h-6 rounded" style={{ backgroundColor: block.toolbar.bgColor }} > - + {block.toolbar.title} 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 ccc1436c59..910b5313dd 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,11 +1,10 @@ -import { useWorkflowStore } from '@/stores/workflow/store' import { useCallback } from 'react' +import { useWorkflowStore } from '@/stores/workflow/store' export function useSubBlockValue(blockId: string, subBlockId: string) { const value = useWorkflowStore( useCallback( - (state) => - (state.blocks[blockId]?.subBlocks[subBlockId]?.value) ?? null, + (state) => state.blocks[blockId]?.subBlocks[subBlockId]?.value ?? null, [blockId, subBlockId] ) ) @@ -20,4 +19,4 @@ export function useSubBlockValue(blockId: string, subBlockId: string) { ) return [value, setValue] as const -} \ No newline at end of file +} diff --git a/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx b/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx index fb003ba9de..e3e06034fc 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx @@ -1,14 +1,14 @@ -import { SubBlockConfig } from '../../../../../../../blocks/types' import { Label } from '@/components/ui/label' -import { ShortInput } from './components/short-input' -import { LongInput } from './components/long-input' -import { Dropdown } from './components/dropdown' -import { SliderInput } from './components/slider-input' -import { Table } from './components/table' -import { Code } from './components/code' -import { Switch } from './components/switch' -import { ToolInput } from './components/tool-input' +import { SubBlockConfig } from '../../../../../../../blocks/types' import { CheckboxList } from './components/checkbox-list' +import { Code } from './components/code' +import { Dropdown } from './components/dropdown' +import { LongInput } from './components/long-input' +import { ShortInput } from './components/short-input' +import { SliderInput } from './components/slider-input' +import { Switch } from './components/switch' +import { Table } from './components/table' +import { ToolInput } from './components/tool-input' interface SubBlockProps { blockId: string @@ -65,35 +65,15 @@ export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) { subBlockId={config.id} min={config.min} max={config.max} - defaultValue={ - (config.min || 0) + ((config.max || 100) - (config.min || 0)) / 2 - } + defaultValue={(config.min || 0) + ((config.max || 100) - (config.min || 0)) / 2} /> ) case 'table': - return ( - - ) + return
case 'code': - return ( - - ) + return case 'switch': - return ( - - ) + return case 'tool-input': return case 'checkbox-list': diff --git a/app/w/[id]/components/workflow-block/workflow-block.tsx b/app/w/[id]/components/workflow-block/workflow-block.tsx index c46b6e9922..803b93c595 100644 --- a/app/w/[id]/components/workflow-block/workflow-block.tsx +++ b/app/w/[id]/components/workflow-block/workflow-block.tsx @@ -1,14 +1,14 @@ -import { Card } from '@/components/ui/card' -import { BlockConfig, SubBlockConfig } from '../../../../../blocks/types' -import { SubBlock } from './components/sub-block/sub-block' +import { useEffect, useRef, useState } from 'react' import { Handle, Position } from 'reactflow' +import { useUpdateNodeInternals } from 'reactflow' +import { Badge } from '@/components/ui/badge' +import { Card } from '@/components/ui/card' import { cn } from '@/lib/utils' +import { useWorkflowStore } from '@/stores/workflow/store' +import { BlockConfig, SubBlockConfig } from '../../../../../blocks/types' import { ActionBar } from './components/action-bar/action-bar' import { ConnectionBlocks } from './components/connection-blocks/connection-blocks' -import { useState, useEffect, useRef } from 'react' -import { useWorkflowStore } from '@/stores/workflow/store' -import { Badge } from '@/components/ui/badge' -import { useUpdateNodeInternals } from 'reactflow' +import { SubBlock } from './components/sub-block/sub-block' interface WorkflowBlockProps { id: string @@ -24,19 +24,11 @@ interface SubBlockPosition { top: number } -export function WorkflowBlock({ - id, - type, - config, - name, - selected, -}: WorkflowBlockProps) { +export function WorkflowBlock({ id, type, config, name, selected }: WorkflowBlockProps) { const { toolbar, workflow } = config // Dragging connection state const [isConnecting, setIsConnecting] = useState(false) - const isEnabled = useWorkflowStore( - (state) => state.blocks[id]?.enabled ?? true - ) + const isEnabled = useWorkflowStore((state) => state.blocks[id]?.enabled ?? true) const horizontalHandles = useWorkflowStore( (state) => state.blocks[id]?.horizontalHandles ?? false ) @@ -44,9 +36,7 @@ export function WorkflowBlock({ const [editedName, setEditedName] = useState('') const updateBlockName = useWorkflowStore((state) => state.updateBlockName) const blockRef = useRef(null) - const [subBlockPositions, setSubBlockPositions] = useState< - SubBlockPosition[] - >([]) + const [subBlockPositions, setSubBlockPositions] = useState([]) const updateNodeInternals = useUpdateNodeInternals() // Calculate subblock positions when the component mounts or updates @@ -198,10 +188,7 @@ export function WorkflowBlock({ )} {!isEnabled && ( - + Disabled )} @@ -213,16 +200,10 @@ export function WorkflowBlock({ {row.map((subBlock, blockIndex) => (
- +
))} diff --git a/app/w/[id]/components/workflow-canvas/workflow-canvas.tsx b/app/w/[id]/components/workflow-canvas/workflow-canvas.tsx index 8ac8e77948..839b4013e3 100644 --- a/app/w/[id]/components/workflow-canvas/workflow-canvas.tsx +++ b/app/w/[id]/components/workflow-canvas/workflow-canvas.tsx @@ -3,19 +3,19 @@ import { useCallback, useEffect, useState } from 'react' import ReactFlow, { Background, - NodeTypes, - EdgeTypes, - useReactFlow, ConnectionLineType, + EdgeTypes, + NodeTypes, + useReactFlow, } from 'reactflow' -import { getBlock } from '../../../../../blocks' -import { useWorkflowStore } from '@/stores/workflow/store' import { useNotificationStore } from '@/stores/notifications/store' -import { useWorkflowExecution } from '../../../hooks/use-workflow-execution' -import { NotificationList } from '@/app/w/components/notifications/notifications' -import { WorkflowNode } from '../workflow-node/workflow-node' -import { CustomEdge } from '../custom-edge/custom-edge' import { initializeStateLogger } from '@/stores/workflow/logger' +import { useWorkflowStore } from '@/stores/workflow/store' +import { NotificationList } from '@/app/w/components/notifications/notifications' +import { getBlock } from '../../../../../blocks' +import { useWorkflowExecution } from '../../../hooks/use-workflow-execution' +import { CustomEdge } from '../custom-edge/custom-edge' +import { WorkflowNode } from '../workflow-node/workflow-node' // Define custom node and edge types for ReactFlow const nodeTypes: NodeTypes = { @@ -29,8 +29,7 @@ export function WorkflowCanvas() { const [selectedEdgeId, setSelectedEdgeId] = useState(null) // Store references and state management hooks - const { isExecuting, executionResult, handleRunWorkflow } = - useWorkflowExecution() + const { isExecuting, executionResult, handleRunWorkflow } = useWorkflowExecution() const { blocks, edges, @@ -152,10 +151,7 @@ export function WorkflowCanvas() { // Handle keyboard shortcuts for edge deletion useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { - if ( - (event.key === 'Delete' || event.key === 'Backspace') && - selectedEdgeId - ) { + if ((event.key === 'Delete' || event.key === 'Backspace') && selectedEdgeId) { removeEdge(selectedEdgeId) setSelectedEdgeId(null) } diff --git a/app/w/[id]/components/workflow-node/workflow-node.tsx b/app/w/[id]/components/workflow-node/workflow-node.tsx index f835b42453..7bde3cff7c 100644 --- a/app/w/[id]/components/workflow-node/workflow-node.tsx +++ b/app/w/[id]/components/workflow-node/workflow-node.tsx @@ -1,6 +1,6 @@ import { NodeProps } from 'reactflow' -import { WorkflowBlock } from '../workflow-block/workflow-block' import { BlockConfig } from '../../../../../blocks/types' +import { WorkflowBlock } from '../workflow-block/workflow-block' interface WorkflowNodeData { type: string @@ -8,13 +8,7 @@ interface WorkflowNodeData { name: string } -export const WorkflowNode = ({ - data, - id, - xPos, - yPos, - selected, -}: NodeProps) => ( +export const WorkflowNode = ({ data, id, xPos, yPos, selected }: NodeProps) => ( - !entry.error && !entry.warning && setIsExpanded(!isExpanded) - } + onClick={() => !entry.error && !entry.warning && setIsExpanded(!isExpanded)} >
= 400 - ? 'flex items-center justify-between' - : 'grid gap-4 grid-cols-1' + consoleWidth >= 400 ? 'flex items-center justify-between' : 'grid gap-4 grid-cols-1' }`} > {entry.blockName && ( @@ -113,9 +100,7 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) {
Warning
-
-                  {entry.warning}
-                
+
{entry.warning}
)} diff --git a/app/w/components/console/components/json-view/json-view.tsx b/app/w/components/console/components/json-view/json-view.tsx index 1a3e9b8725..2cc05c46fe 100644 --- a/app/w/components/console/components/json-view/json-view.tsx +++ b/app/w/components/console/components/json-view/json-view.tsx @@ -1,5 +1,5 @@ -import { useState, useEffect } from 'react' -import { ChevronRight, ChevronDown } from 'lucide-react' +import { useEffect, useState } from 'react' +import { ChevronDown, ChevronRight } from 'lucide-react' import { Button } from '@/components/ui/button' interface JSONViewProps { @@ -40,11 +40,7 @@ const copyToClipboard = (data: any) => { navigator.clipboard.writeText(stringified) } -export const JSONView = ({ - data, - level = 0, - initiallyExpanded = false, -}: JSONViewProps) => { +export const JSONView = ({ data, level = 0, initiallyExpanded = false }: JSONViewProps) => { const [isCollapsed, setIsCollapsed] = useState(!initiallyExpanded) const [contextMenuPosition, setContextMenuPosition] = useState<{ x: number @@ -74,15 +70,9 @@ export const JSONView = ({ return ( - {typeof data === 'string' ? ( - - ) : ( - stringValue - )} + {typeof data === 'string' ? : stringValue} {contextMenuPosition && (
{isArray ? '[]' : '{}'} - ) + return {isArray ? '[]' : '{}'} } return ( @@ -119,9 +107,7 @@ export const JSONView = ({ setIsCollapsed(!isCollapsed) }} > - - {isCollapsed ? '▶' : '▼'} - + {isCollapsed ? '▶' : '▼'} {isArray ? '[' : '{'} {isCollapsed ? '...' : ''} diff --git a/app/w/components/console/console.tsx b/app/w/components/console/console.tsx index 34e609ae69..f9ec157a7e 100644 --- a/app/w/components/console/console.tsx +++ b/app/w/components/console/console.tsx @@ -1,15 +1,11 @@ 'use client' -import { useState, useMemo, useEffect } from 'react' +import { useEffect, useMemo, useState } from 'react' import { PanelLeftClose, Terminal } from 'lucide-react' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/components/ui/tooltip' -import { useConsoleStore } from '@/stores/console/store' -import { ScrollArea } from '@/components/ui/scroll-area' import { Button } from '@/components/ui/button' +import { ScrollArea } from '@/components/ui/scroll-area' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { useConsoleStore } from '@/stores/console/store' import { useWorkflowRegistry } from '@/stores/workflow/registry' import { ConsoleEntry } from './components/console-entry/console-entry' diff --git a/app/w/components/control-bar/components/history-dropdown-item.tsx b/app/w/components/control-bar/components/history-dropdown-item.tsx index 33d2640a38..158699fbb1 100644 --- a/app/w/components/control-bar/components/history-dropdown-item.tsx +++ b/app/w/components/control-bar/components/history-dropdown-item.tsx @@ -31,10 +31,7 @@ export function HistoryDropdownItem({ onClick={onClick} >
@@ -58,12 +55,7 @@ export function HistoryDropdownItem({ )}
-

+

{action}

diff --git a/app/w/components/control-bar/components/notification-dropdown-item.tsx b/app/w/components/control-bar/components/notification-dropdown-item.tsx index 44e16bfd51..2fd2262abf 100644 --- a/app/w/components/control-bar/components/notification-dropdown-item.tsx +++ b/app/w/components/control-bar/components/notification-dropdown-item.tsx @@ -1,14 +1,11 @@ +import { useEffect, useState } from 'react' import { formatDistanceToNow } from 'date-fns' -import { Terminal, AlertCircle } from 'lucide-react' -import { DropdownMenuItem } from '@/components/ui/dropdown-menu' -import { - NotificationType, - NotificationStore, -} from '@/stores/notifications/types' -import { useNotificationStore } from '@/stores/notifications/store' -import { cn } from '@/lib/utils' +import { AlertCircle, Terminal } from 'lucide-react' import { ErrorIcon } from '@/components/icons' -import { useState, useEffect } from 'react' +import { DropdownMenuItem } from '@/components/ui/dropdown-menu' +import { cn } from '@/lib/utils' +import { useNotificationStore } from '@/stores/notifications/store' +import { NotificationStore, NotificationType } from '@/stores/notifications/types' interface NotificationDropdownItemProps { id: string @@ -46,8 +43,7 @@ export function NotificationDropdownItem({ const timeAgo = formatDistanceToNow(timestamp, { addSuffix: true }) // Truncate message if it's too long - const truncatedMessage = - message.length > 50 ? `${message.slice(0, 50)}...` : message + const truncatedMessage = message.length > 50 ? `${message.slice(0, 50)}...` : message return (
- - {type === 'error' ? 'Error' : 'Console'} - + {type === 'error' ? 'Error' : 'Console'} {timeAgo}

{truncatedMessage}

diff --git a/app/w/components/control-bar/control-bar.tsx b/app/w/components/control-bar/control-bar.tsx index 9243d7e23f..069c90155d 100644 --- a/app/w/components/control-bar/control-bar.tsx +++ b/app/w/components/control-bar/control-bar.tsx @@ -1,27 +1,9 @@ 'use client' -import { Button } from '@/components/ui/button' -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from '@/components/ui/dropdown-menu' -import { History, Bell, Play, Trash2, MessageSquare } from 'lucide-react' -import { useNotificationStore } from '@/stores/notifications/store' -import { NotificationDropdownItem } from './components/notification-dropdown-item' -import { useWorkflowStore } from '@/stores/workflow/store' -import { HistoryDropdownItem } from './components/history-dropdown-item' -import { formatDistanceToNow } from 'date-fns' import { useEffect, useState } from 'react' -import { useWorkflowExecution } from '../../hooks/use-workflow-execution' -import { useWorkflowRegistry } from '@/stores/workflow/registry' import { useRouter } from 'next/navigation' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/components/ui/tooltip' +import { formatDistanceToNow } from 'date-fns' +import { Bell, History, MessageSquare, Play, Trash2 } from 'lucide-react' import { AlertDialog, AlertDialogAction, @@ -33,14 +15,27 @@ import { AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' +import { Button } from '@/components/ui/button' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { useNotificationStore } from '@/stores/notifications/store' +import { useWorkflowRegistry } from '@/stores/workflow/registry' +import { useWorkflowStore } from '@/stores/workflow/store' +import { useWorkflowExecution } from '../../hooks/use-workflow-execution' +import { HistoryDropdownItem } from './components/history-dropdown-item' +import { NotificationDropdownItem } from './components/notification-dropdown-item' export function ControlBar() { const { notifications, getWorkflowNotifications } = useNotificationStore() const { history, undo, redo, revertToHistoryState } = useWorkflowStore() const [isEditing, setIsEditing] = useState(false) const [editedName, setEditedName] = useState('') - const { workflows, updateWorkflow, activeWorkflowId, removeWorkflow } = - useWorkflowRegistry() + const { workflows, updateWorkflow, activeWorkflowId, removeWorkflow } = useWorkflowRegistry() const [, forceUpdate] = useState({}) const { isExecuting, handleRunWorkflow } = useWorkflowExecution() const router = useRouter() @@ -167,8 +162,7 @@ export function ControlBar() { Delete Workflow - Are you sure you want to delete this workflow? This action - cannot be undone. + Are you sure you want to delete this workflow? This action cannot be undone. @@ -198,10 +192,7 @@ export function ControlBar() { ) : ( - + <> {[...history.future].reverse().map((entry, index) => ( revertToHistoryState( - history.past.length + - 1 + - (history.future.length - 1 - index) + history.past.length + 1 + (history.future.length - 1 - index) ) } isFuture={true} @@ -230,9 +219,7 @@ export function ControlBar() { key={`past-${entry.timestamp}-${index}`} action={entry.action} timestamp={entry.timestamp} - onClick={() => - revertToHistoryState(history.past.length - 1 - index) - } + onClick={() => revertToHistoryState(history.past.length - 1 - index)} /> ))} @@ -255,17 +242,11 @@ export function ControlBar() { ) : ( - + {[...workflowNotifications] .sort((a, b) => b.timestamp - a.timestamp) .map((notification) => ( - + ))} )} diff --git a/app/w/components/notifications/notifications.tsx b/app/w/components/notifications/notifications.tsx index e607fcd4f2..6fa80bd1ba 100644 --- a/app/w/components/notifications/notifications.tsx +++ b/app/w/components/notifications/notifications.tsx @@ -1,9 +1,9 @@ import { useEffect, useState } from 'react' import { AlertCircle, Terminal } from 'lucide-react' -import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' -import { useNotificationStore } from '@/stores/notifications/store' -import { cn } from '@/lib/utils' import { ErrorIcon } from '@/components/icons' +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' +import { cn } from '@/lib/utils' +import { useNotificationStore } from '@/stores/notifications/store' const NOTIFICATION_TIMEOUT = 4000 const FADE_DURATION = 300 @@ -22,9 +22,7 @@ const NotificationColors = { export function NotificationList() { const { notifications, hideNotification } = useNotificationStore() - const [fadingNotifications, setFadingNotifications] = useState>( - new Set() - ) + const [fadingNotifications, setFadingNotifications] = useState>(new Set()) // Only show visible notifications in the display const visibleNotifications = notifications.filter((n) => n.isVisible) @@ -74,9 +72,7 @@ export function NotificationList() { key={notification.id} className={cn( 'transition-all duration-300 ease-in-out opacity-0 translate-y-[-100%]', - isFading - ? 'animate-notification-fade-out' - : 'animate-notification-slide', + isFading ? 'animate-notification-fade-out' : 'animate-notification-slide', NotificationColors[notification.type] )} > @@ -89,9 +85,7 @@ export function NotificationList() { {notification.type === 'error' ? 'Error' : 'Console'} - - {notification.message} - + {notification.message} ) })} diff --git a/app/w/components/sidebar/components/nav-item/nav-item.tsx b/app/w/components/sidebar/components/nav-item/nav-item.tsx index a06e1b72ea..064f670352 100644 --- a/app/w/components/sidebar/components/nav-item/nav-item.tsx +++ b/app/w/components/sidebar/components/nav-item/nav-item.tsx @@ -1,13 +1,9 @@ 'use client' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/components/ui/tooltip' -import clsx from 'clsx' import Link from 'next/link' import { usePathname } from 'next/navigation' +import clsx from 'clsx' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' export function NavItem({ href, diff --git a/app/w/components/sidebar/components/settings-modal/settings-modal.tsx b/app/w/components/sidebar/components/settings-modal/settings-modal.tsx index bc2ff44a34..12e09f8b87 100644 --- a/app/w/components/sidebar/components/settings-modal/settings-modal.tsx +++ b/app/w/components/sidebar/components/settings-modal/settings-modal.tsx @@ -1,11 +1,6 @@ 'use client' -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog' +import { useEffect, useMemo, useRef, useState } from 'react' import { AlertDialog, AlertDialogAction, @@ -16,10 +11,10 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' -import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' -import { useState, useRef, useEffect, useMemo } from 'react' import { useEnvironmentStore } from '@/stores/environment/store' import { EnvironmentVariable as StoreEnvironmentVariable } from '@/stores/environment/types' @@ -39,9 +34,7 @@ const INITIAL_ENV_VAR: UIEnvironmentVariable = { key: '', value: '' } export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { const { variables, setVariable, removeVariable } = useEnvironmentStore() const [envVars, setEnvVars] = useState([]) - const [focusedValueIndex, setFocusedValueIndex] = useState( - null - ) + const [focusedValueIndex, setFocusedValueIndex] = useState(null) const [showUnsavedChanges, setShowUnsavedChanges] = useState(false) const scrollContainerRef = useRef(null) const pendingClose = useRef(false) @@ -111,15 +104,11 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { useEffect(() => { if (scrollContainerRef.current) { - scrollContainerRef.current.scrollTop = - scrollContainerRef.current.scrollHeight + scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight } }, [envVars]) - const handleValueFocus = ( - index: number, - e: React.FocusEvent - ) => { + const handleValueFocus = (index: number, e: React.FocusEvent) => { setFocusedValueIndex(index) // Always scroll to the start of the input e.target.scrollLeft = 0 @@ -137,10 +126,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { } } - const handlePaste = ( - e: React.ClipboardEvent, - index: number - ) => { + const handlePaste = (e: React.ClipboardEvent, index: number) => { const text = e.clipboardData.getData('text').trim() if (!text) return @@ -149,9 +135,9 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { e.preventDefault() - const inputType = (e.target as HTMLInputElement).getAttribute( - 'data-input-type' - ) as 'key' | 'value' + const inputType = (e.target as HTMLInputElement).getAttribute('data-input-type') as + | 'key' + | 'value' const containsKeyValuePair = text.includes('=') // Handle single value paste into specific field @@ -164,11 +150,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { handleKeyValuePaste(lines) } - const handleSingleValuePaste = ( - text: string, - index: number, - inputType: 'key' | 'value' - ) => { + const handleSingleValuePaste = (text: string, index: number, inputType: 'key' | 'value') => { const newEnvVars = [...envVars] newEnvVars[index][inputType] = text setEnvVars(newEnvVars) @@ -182,14 +164,14 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { return { key: key.trim(), value, - id: Date.now() + Math.random() + id: Date.now() + Math.random(), } }) .filter(({ key, value }) => key && value) if (parsedVars.length > 0) { // Merge existing vars with new ones, removing any empty rows at the end - const existingVars = envVars.filter(v => v.key || v.value) + const existingVars = envVars.filter((v) => v.key || v.value) setEnvVars([...existingVars, ...parsedVars]) } } @@ -200,11 +182,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { setEnvVars([...envVars, newVar]) } - const updateEnvVar = ( - index: number, - field: 'key' | 'value', - value: string - ) => { + const updateEnvVar = (index: number, field: 'key' | 'value', value: string) => { const newEnvVars = [...envVars] newEnvVars[index][field] = value setEnvVars(newEnvVars) @@ -254,12 +232,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { placeholder="Enter value" className="allow-scroll" /> -
@@ -309,10 +282,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { - + Unsaved Changes @@ -321,12 +291,8 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { - - Discard Changes - - - Save Changes - + Discard Changes + Save Changes diff --git a/app/w/components/sidebar/sidebar.tsx b/app/w/components/sidebar/sidebar.tsx index 0710edef56..9db8aaef1e 100644 --- a/app/w/components/sidebar/sidebar.tsx +++ b/app/w/components/sidebar/sidebar.tsx @@ -1,28 +1,18 @@ 'use client' -import Link from 'next/link' -import { NavItem } from './components/nav-item/nav-item' -import { Settings, Plus } from 'lucide-react' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/components/ui/tooltip' -import { AgentIcon } from '@/components/icons' -import { useWorkflowRegistry } from '@/stores/workflow/registry' -import { useRouter } from 'next/navigation' -import { Button } from '@/components/ui/button' import { useState } from 'react' +import Link from 'next/link' +import { useRouter } from 'next/navigation' +import { Plus, Settings } from 'lucide-react' +import { AgentIcon } from '@/components/icons' +import { Button } from '@/components/ui/button' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { useWorkflowRegistry } from '@/stores/workflow/registry' +import { NavItem } from './components/nav-item/nav-item' import { SettingsModal } from './components/settings-modal/settings-modal' export function Sidebar() { - const WORKFLOW_COLORS = [ - '#3972F6', - '#F639DD', - '#F6B539', - '#8139F6', - '#F64439', - ] + const WORKFLOW_COLORS = ['#3972F6', '#F639DD', '#F6B539', '#8139F6', '#F64439'] const { workflows, addWorkflow } = useWorkflowRegistry() const router = useRouter() const [showSettings, setShowSettings] = useState(false) @@ -33,9 +23,7 @@ export function Sidebar() { const lastWorkflow = workflowArray[workflowArray.length - 1] // Find the index of the last used color, defaulting to first color if undefined - const lastColorIndex = lastWorkflow?.color - ? WORKFLOW_COLORS.indexOf(lastWorkflow.color) - : -1 + const lastColorIndex = lastWorkflow?.color ? WORKFLOW_COLORS.indexOf(lastWorkflow.color) : -1 // Get next color index, wrapping around to 0 if we reach the end const nextColorIndex = (lastColorIndex + 1) % WORKFLOW_COLORS.length @@ -83,11 +71,7 @@ export function Sidebar() {